[
  {
    "path": ".gitignore",
    "content": "/..config*\n/.config*\n/build/\n/defconfig\n"
  },
  {
    "path": ".travis.yml",
    "content": "---\ndist: bionic\n\nlanguage: c\n\nmatrix:\n  include:\n    - addons:\n        apt:\n          packages:\n            - codespell\n      env:\n        - MAKEFLAGS=-j$(nproc)\n      install:\n        - git clone --depth 1 -b uncrustify-0.72.0\n            https://github.com/uncrustify/uncrustify\n        - mkdir -p uncrustify/build\n        - (cd uncrustify/build && cmake -DCMAKE_INSTALL_PREFIX=$PWD\n            -DCMAKE_C_COMPILER=gcc-7 -DCMAKE_CXX_COMPILER=g++-7 ..)\n        - make -C uncrustify/build\n        - export PATH=$PATH:$PWD/uncrustify/build\n        - uncrustify --version\n      name: Run source code checks\n      script:\n        - make check-format\n        - codespell -i 0 -q 4 $(git ls-files)\n    - addons:\n        apt:\n          packages:\n            - doxygen\n            - gcc-aarch64-linux-gnu\n            - graphviz\n            - libc6-dev-arm64-cross\n      env:\n        - CONFIGS=\"allnoconfig allyesconfig defconfig\n                   bananapi_m2_plus_h3_defconfig\n                   beelink_x2_defconfig\n                   libretech_all_h3_cc_h3_defconfig\n                   libretech_all_h3_cc_h5_defconfig\n                   orangepi_3_defconfig\n                   orangepi_one_defconfig\n                   orangepi_pc2_defconfig\n                   orangepi_plus2e_defconfig\n                   orangepi_win_defconfig\n                   orangepi_zero_plus_defconfig\n                   pine64_plus_defconfig\n                   pine_h64_defconfig\n                   pinebook_defconfig\n                   pinephone_defconfig\n                   tanix_tx6_defconfig\n                   tbs_a711_defconfig\n                   randconfig randconfig randconfig\"\n        - GCC_VER=9.1.1-20190507\n        - HOST_COMPILE=aarch64-linux-gnu-\n        - MAKEFLAGS=-j$(nproc)\n      install:\n        - curl -LSs https://github.com/stffrdhrn/gcc/releases/download/or1k-$GCC_VER/or1k-linux-musl-$GCC_VER.tar.xz |\n            tar xJf -\n        - export PATH=$PATH:$PWD/or1k-linux-musl/bin\n      name: Build all configs\n      script:\n        - |-\n          set -e\n          cd /tmp\n          ln -s $TRAVIS_BUILD_DIR/Makefile .\n          cat > all.config << 'EOF'\n          CONFIG_COMPILE_TEST=y\n          EOF\n          for config in ${CONFIGS}; do\n            echo ========== begin $config ==========\n            make SRC=$TRAVIS_BUILD_DIR KCONFIG_ALLCONFIG=1 V=1 \"$config\"\n            make SRC=$TRAVIS_BUILD_DIR TGT=\"\\$(OBJ)/$config\" V=1 all check\n            or1k-linux-musl-size build/$config/scp.elf\n            grep __bss_end build/$config/scp.map\n            sha256sum -b build/$config/scp.bin\n            echo =========== end $config ===========\n          done\n          make SRC=$TRAVIS_BUILD_DIR V=1 html tools\n...\n"
  },
  {
    "path": ".uncrustify",
    "content": "align_asm_colon                 = false\nalign_assign_span               = 1\nalign_assign_thresh             = 8\nalign_enum_equ_span             = 3\nalign_enum_equ_thresh           = 0\nalign_func_params               = false\nalign_func_params_gap           = 0\nalign_func_params_span          = 0\nalign_func_params_thresh        = 0\nalign_func_proto_gap            = 0\nalign_func_proto_span           = 0\nalign_keep_extra_space          = true\nalign_keep_tabs                 = false\nalign_left_shift                = true\nalign_mix_var_proto             = false\nalign_nl_cont                   = false\nalign_number_right              = false\nalign_oc_decl_colon             = false\nalign_oc_msg_colon_first        = false\nalign_oc_msg_colon_span         = 0\nalign_oc_msg_spec_span          = 0\nalign_on_operator               = false\nalign_on_tabstop                = false\nalign_pp_define_gap             = 0\nalign_pp_define_span            = 3\nalign_pp_define_together        = true\nalign_right_cmt_at_col          = 0\nalign_right_cmt_gap             = 0\nalign_right_cmt_mix             = false\nalign_right_cmt_span            = 2\nalign_same_func_call_params     = false\nalign_single_line_brace         = false\nalign_single_line_brace_gap     = 0\nalign_single_line_func          = false\nalign_struct_init_span          = 0\nalign_typedef_amp_style         = 2\nalign_typedef_func              = 2\nalign_typedef_gap               = 0\nalign_typedef_span              = 3\nalign_typedef_star_style        = 2\nalign_var_class_gap             = 0\nalign_var_class_span            = 0\nalign_var_class_thresh          = 0\nalign_var_def_amp_style         = 2\nalign_var_def_attribute         = true\nalign_var_def_colon             = false\nalign_var_def_colon_gap         = 0\nalign_var_def_gap               = 0\nalign_var_def_inline            = true\nalign_var_def_span              = 1\nalign_var_def_star_style        = 2\nalign_var_def_thresh            = 1\nalign_var_struct_gap            = 0\nalign_var_struct_span           = 3\nalign_var_struct_thresh         = 0\nalign_with_tabs                 = false\ncmt_c_group                     = false\ncmt_c_nl_end                    = false\ncmt_c_nl_start                  = false\ncmt_convert_tab_to_spaces       = false\ncmt_cpp_group                   = false\ncmt_cpp_nl_end                  = false\ncmt_cpp_nl_start                = false\ncmt_cpp_to_c                    = true\ncmt_indent_multi                = true\ncmt_insert_before_ctor_dtor     = false\ncmt_insert_before_inlines       = true\ncmt_insert_before_preproc       = false\ncmt_insert_class_header         = \"\"\ncmt_insert_file_footer          = \"\"\ncmt_insert_file_header          = \"\"\ncmt_insert_func_header          = \"\"\ncmt_insert_oc_msg_header        = \"\"\ncmt_multi_check_last            = true\ncmt_multi_first_len_minimum     = 4\ncmt_reflow_mode                 = 0\ncmt_sp_after_star_cont          = 0\ncmt_sp_before_star_cont         = 0\ncmt_star_cont                   = true\ncmt_width                       = 79\ncode_width                      = 79\ndisable_processing_cmt          = \"format off\"\neat_blanks_after_open_brace     = true\neat_blanks_before_close_brace   = true\nenable_digraphs                 = false\nenable_processing_cmt           = \"format on\"\nforce_tab_after_define          = false\ninclude_category_0              = \"<[^/]*>\"\ninclude_category_1              = \"<(?!platform/).*/.*>\"\ninclude_category_2              = \"<.*>\"\nindent_access_spec              = 1\nindent_access_spec_body         = false\nindent_align_assign             = true\nindent_align_string             = true\nindent_bool_paren               = 0\nindent_brace                    = 0\nindent_brace_parent             = false\nindent_braces                   = false\nindent_braces_no_class          = false\nindent_braces_no_func           = false\nindent_braces_no_struct         = false\nindent_case_brace               = 0\nindent_case_shift               = 0\nindent_class                    = false\nindent_class_colon              = false\nindent_class_on_colon           = false\nindent_cmt_with_tabs            = false\nindent_col1_comment             = false\nindent_columns                  = 8\nindent_comma_paren              = 0\nindent_constr_colon             = false\nindent_continue                 = 0\nindent_cpp_lambda_body          = false\nindent_cs_delegate_brace        = false\nindent_ctor_init                = 0\nindent_ctor_init_leading        = 2\nindent_else_if                  = false\nindent_extern                   = false\nindent_first_bool_expr          = false\nindent_func_call_param          = false\nindent_func_class_param         = false\nindent_func_const               = 0\nindent_func_ctor_var_param      = false\nindent_func_def_force_col1      = false\nindent_func_def_param           = false\nindent_func_param_double        = false\nindent_func_proto_param         = false\nindent_func_throw               = 0\nindent_ignore_asm_block         = true\nindent_label                    = 1\nindent_member                   = 0\nindent_min_vbrace_open          = 0\nindent_namespace                = false\nindent_namespace_level          = 0\nindent_namespace_limit          = 0\nindent_namespace_single_indent  = false\nindent_oc_block                 = false\nindent_oc_block_msg             = 0\nindent_oc_block_msg_from_brace  = false\nindent_oc_block_msg_from_caret  = false\nindent_oc_block_msg_from_colon  = false\nindent_oc_block_msg_from_keyword = false\nindent_oc_block_msg_xcode_style = false\nindent_oc_msg_colon             = 0\nindent_oc_msg_prioritize_first_colon = true\nindent_param                    = 0\nindent_paren_after_func_call    = false\nindent_paren_after_func_decl    = false\nindent_paren_after_func_def     = false\nindent_paren_close              = 2\nindent_paren_nl                 = false\nindent_paren_open_brace         = false\nindent_preserve_sql             = false\nindent_relative_single_line_comments = false\nindent_shift                    = 0\nindent_single_line_comments_before = 0\nindent_square_nl                = false\nindent_switch_case              = 0\nindent_switch_pp                = true\nindent_template_param           = false\nindent_ternary_operator         = 2\nindent_token_after_brace        = true\nindent_using_block              = true\nindent_var_def_blk              = 0\nindent_var_def_cont             = false\nindent_vbrace_open_on_tabstop   = false\nindent_with_tabs                = 1\nindent_xml_string               = 0\ninput_tab_size                  = 8\nls_code_width                   = false\nls_for_split_full               = false\nls_func_split_full              = false\nmod_add_long_class_closebrace_comment = 0\nmod_add_long_function_closebrace_comment = 0\nmod_add_long_ifdef_else_comment = 0\nmod_add_long_ifdef_endif_comment = 0\nmod_add_long_namespace_closebrace_comment = 0\nmod_add_long_switch_closebrace_comment = 0\nmod_case_brace                  = remove\nmod_full_brace_do               = force\nmod_full_brace_for              = remove\nmod_full_brace_function         = ignore\nmod_full_brace_if               = remove\nmod_full_brace_if_chain         = 1\nmod_full_brace_if_chain_only    = false\nmod_full_brace_nl               = 2\nmod_full_brace_nl_block_rem_mlcond = false\nmod_full_brace_using            = ignore\nmod_full_brace_while            = remove\nmod_full_paren_if_bool          = false\nmod_move_case_break             = false\nmod_paren_on_return             = remove\nmod_pawn_semicolon              = false\nmod_remove_empty_return         = false\nmod_remove_extra_semicolon      = true\nmod_sort_import                 = false\nmod_sort_include                = true\nmod_sort_oc_properties          = false\nmod_sort_oc_property_class_weight = 0\nmod_sort_oc_property_getter_weight = 0\nmod_sort_oc_property_nullability_weight = 0\nmod_sort_oc_property_readwrite_weight = 0\nmod_sort_oc_property_reference_weight = 0\nmod_sort_oc_property_setter_weight = 0\nmod_sort_oc_property_thread_safe_weight = 0\nmod_sort_using                  = false\nnewlines                        = lf\nnl_after_access_spec            = 0\nnl_after_annotation             = ignore\nnl_after_brace_close            = true\nnl_after_brace_open             = true\nnl_after_brace_open_cmt         = false\nnl_after_case                   = true\nnl_after_class                  = 0\nnl_after_do                     = ignore\nnl_after_for                    = ignore\nnl_after_func_body              = 2\nnl_after_func_body_class        = 0\nnl_after_func_body_one_liner    = 2\nnl_after_func_class_proto       = 0\nnl_after_func_class_proto_group = 0\nnl_after_func_proto             = 0\nnl_after_func_proto_group       = 2\nnl_after_if                     = ignore\nnl_after_label_colon            = true\nnl_after_multiline_comment      = true\nnl_after_return                 = false\nnl_after_semicolon              = true\nnl_after_square_assign          = ignore\nnl_after_struct                 = 2\nnl_after_switch                 = ignore\nnl_after_synchronized           = ignore\nnl_after_try_catch_finally      = 0\nnl_after_vbrace_close           = false\nnl_after_vbrace_open            = true\nnl_after_vbrace_open_empty      = true\nnl_after_while                  = ignore\nnl_around_cs_property           = 0\nnl_assign_brace                 = remove\nnl_assign_leave_one_liners      = true\nnl_assign_square                = ignore\nnl_before_access_spec           = 0\nnl_before_block_comment         = 0\nnl_before_c_comment             = 0\nnl_before_case                  = false\nnl_before_class                 = 0\nnl_before_cpp_comment           = 0\nnl_before_do                    = ignore\nnl_before_for                   = ignore\nnl_before_func_body_def         = 0\nnl_before_func_body_proto       = 0\nnl_before_func_class_def        = 0\nnl_before_func_class_proto      = 0\nnl_before_if                    = ignore\nnl_before_if_closing_paren      = remove\nnl_before_return                = false\nnl_before_switch                = ignore\nnl_before_synchronized          = ignore\nnl_before_throw                 = ignore\nnl_before_while                 = ignore\nnl_between_annotation           = ignore\nnl_between_get_set              = 0\nnl_brace_brace                  = ignore\nnl_brace_catch                  = ignore\nnl_brace_else                   = remove\nnl_brace_finally                = ignore\nnl_brace_fparen                 = remove\nnl_brace_square                 = ignore\nnl_brace_struct_var             = remove\nnl_brace_while                  = remove\nnl_case_colon_brace             = remove\nnl_catch_brace                  = ignore\nnl_class_brace                  = ignore\nnl_class_colon                  = ignore\nnl_class_init_args              = ignore\nnl_class_leave_one_liners       = false\nnl_collapse_empty_body          = false\nnl_comment_func_def             = 1\nnl_constr_colon                 = ignore\nnl_constr_init_args             = ignore\nnl_cpp_lambda_leave_one_liners  = false\nnl_cpp_ldef_brace               = ignore\nnl_create_for_one_liner         = false\nnl_create_if_one_liner          = false\nnl_create_while_one_liner       = false\nnl_define_macro                 = true\nnl_do_brace                     = remove\nnl_ds_struct_enum_close_brace   = true\nnl_ds_struct_enum_cmt           = false\nnl_else_brace                   = remove\nnl_else_if                      = remove\nnl_elseif_brace                 = ignore\nnl_end_of_file                  = force\nnl_end_of_file_min              = 1\nnl_enum_brace                   = remove\nnl_enum_class                   = ignore\nnl_enum_class_identifier        = ignore\nnl_enum_colon_type              = ignore\nnl_enum_identifier_colon        = ignore\nnl_enum_leave_one_liners        = false\nnl_enum_own_lines               = ignore\nnl_fcall_brace                  = remove\nnl_fdef_brace                   = force\nnl_finally_brace                = ignore\nnl_for_brace                    = remove\nnl_func_call_args_multi_line    = false\nnl_func_call_empty              = remove\nnl_func_call_end_multi_line     = false\nnl_func_call_paren              = remove\nnl_func_call_paren_empty        = ignore\nnl_func_call_start_multi_line   = false\nnl_func_class_scope             = ignore\nnl_func_decl_args               = ignore\nnl_func_decl_args_multi_line    = false\nnl_func_decl_empty              = remove\nnl_func_decl_end                = remove\nnl_func_decl_end_multi_line     = false\nnl_func_decl_end_single         = ignore\nnl_func_decl_start              = remove\nnl_func_decl_start_multi_line   = false\nnl_func_decl_start_single       = ignore\nnl_func_def_args                = ignore\nnl_func_def_args_multi_line     = false\nnl_func_def_empty               = remove\nnl_func_def_end                 = remove\nnl_func_def_end_multi_line      = false\nnl_func_def_end_single          = ignore\nnl_func_def_paren               = remove\nnl_func_def_paren_empty         = ignore\nnl_func_def_start               = remove\nnl_func_def_start_multi_line    = false\nnl_func_def_start_single        = ignore\nnl_func_leave_one_liners        = false\nnl_func_paren                   = remove\nnl_func_paren_empty             = ignore\nnl_func_proto_type_name         = remove\nnl_func_scope_name              = ignore\nnl_func_type_name               = force\nnl_func_type_name_class         = ignore\nnl_func_var_def_blk             = 1\nnl_getset_brace                 = ignore\nnl_getset_leave_one_liners      = false\nnl_if_brace                     = remove\nnl_if_leave_one_liners          = false\nnl_max                          = 2\nnl_max_blank_in_func            = 2\nnl_multi_line_cond              = false\nnl_multi_line_define            = false\nnl_namespace_brace              = ignore\nnl_oc_block_brace               = ignore\nnl_oc_msg_args                  = false\nnl_oc_msg_leave_one_liner       = false\nnl_paren_dbrace_open            = ignore\nnl_property_brace               = ignore\nnl_remove_extra_newlines        = 0\nnl_return_expr                  = remove\nnl_scope_brace                  = ignore\nnl_split_for_one_liner          = true\nnl_split_if_one_liner           = true\nnl_split_while_one_liner        = true\nnl_squeeze_ifdef                = false\nnl_squeeze_ifdef_top_level      = false\nnl_start_of_file                = remove\nnl_start_of_file_min            = 0\nnl_struct_brace                 = remove\nnl_switch_brace                 = remove\nnl_synchronized_brace           = ignore\nnl_template_class               = ignore\nnl_try_brace                    = ignore\nnl_type_brace_init_lst          = ignore\nnl_type_brace_init_lst_close    = ignore\nnl_type_brace_init_lst_open     = ignore\nnl_typedef_blk_end              = 0\nnl_typedef_blk_in               = 0\nnl_typedef_blk_start            = 0\nnl_union_brace                  = remove\nnl_unittest_brace               = ignore\nnl_using_brace                  = ignore\nnl_var_def_blk_end              = 0\nnl_var_def_blk_in               = 2\nnl_var_def_blk_start            = 0\nnl_version_brace                = ignore\nnl_while_brace                  = remove\nnl_while_leave_one_liners       = false\noutput_tab_size                 = 8\npos_arith                       = trail\npos_assign                      = trail\npos_bool                        = trail\npos_class_colon                 = ignore\npos_class_comma                 = ignore\npos_comma                       = trail\npos_compare                     = trail\npos_conditional                 = ignore\npos_constr_colon                = ignore\npos_constr_comma                = ignore\npos_enum_comma                  = ignore\npp_define_at_level              = false\npp_if_indent_code               = false\npp_ignore_define_body           = false\npp_indent                       = remove\npp_indent_at_level              = false\npp_indent_brace                 = 1\npp_indent_case                  = true\npp_indent_count                 = 1\npp_indent_extern                = true\npp_indent_func_def              = true\npp_indent_if                    = 0\npp_indent_region                = 0\npp_region_indent_code           = false\npp_space                        = remove\npp_space_count                  = 0\nsp_addr                         = remove\nsp_after_angle                  = ignore\nsp_after_assign                 = ignore\nsp_after_byref                  = ignore\nsp_after_byref_func             = ignore\nsp_after_cast                   = remove\nsp_after_class_colon            = ignore\nsp_after_comma                  = force\nsp_after_constr_colon           = ignore\nsp_after_dc                     = ignore\nsp_after_for_colon              = ignore\nsp_after_invariant_paren        = ignore\nsp_after_mdatype_commas         = ignore\nsp_after_new                    = ignore\nsp_after_newop_paren            = ignore\nsp_after_oc_at_sel              = ignore\nsp_after_oc_at_sel_parens       = ignore\nsp_after_oc_block_caret         = ignore\nsp_after_oc_colon               = ignore\nsp_after_oc_dict_colon          = ignore\nsp_after_oc_msg_receiver        = ignore\nsp_after_oc_property            = ignore\nsp_after_oc_return_type         = ignore\nsp_after_oc_scope               = ignore\nsp_after_oc_type                = ignore\nsp_after_operator               = ignore\nsp_after_operator_sym           = ignore\nsp_after_operator_sym_empty     = ignore\nsp_after_ptr_star               = remove\nsp_after_ptr_star_func          = remove\nsp_after_ptr_star_qualifier     = remove\nsp_after_semi                   = remove\nsp_after_semi_for               = force\nsp_after_semi_for_empty         = remove\nsp_after_send_oc_colon          = ignore\nsp_after_sparen                 = force\nsp_after_tag                    = ignore\nsp_after_throw                  = ignore\nsp_after_tparen_close           = remove\nsp_after_type                   = force\nsp_after_type_brace_init_lst_open = ignore\nsp_angle_colon                  = ignore\nsp_angle_paren                  = ignore\nsp_angle_paren_empty            = ignore\nsp_angle_shift                  = add\nsp_angle_word                   = ignore\nsp_annotation_paren             = ignore\nsp_arith                        = force\nsp_arith_additive               = ignore\nsp_assign                       = force\nsp_assign_default               = ignore\nsp_attribute_paren              = remove\nsp_balance_nested_parens        = false\nsp_before_angle                 = ignore\nsp_before_assign                = ignore\nsp_before_byref                 = ignore\nsp_before_byref_func            = ignore\nsp_before_case_colon            = remove\nsp_before_class_colon           = ignore\nsp_before_comma                 = remove\nsp_before_constr_colon          = ignore\nsp_before_dc                    = ignore\nsp_before_ellipsis              = ignore\nsp_before_for_colon             = ignore\nsp_before_mdatype_commas        = ignore\nsp_before_nl_cont               = force\nsp_before_oc_block_caret        = ignore\nsp_before_oc_colon              = ignore\nsp_before_oc_dict_colon         = ignore\nsp_before_pp_stringify          = ignore\nsp_before_ptr_star              = force\nsp_before_ptr_star_func         = force\nsp_before_semi                  = remove\nsp_before_semi_for              = remove\nsp_before_semi_for_empty        = remove\nsp_before_send_oc_colon         = ignore\nsp_before_sparen                = force\nsp_before_square                = remove\nsp_before_squares               = remove\nsp_before_template_paren        = ignore\nsp_before_tr_cmt                = force\nsp_before_type_brace_init_lst_close = ignore\nsp_before_unnamed_byref         = ignore\nsp_before_unnamed_ptr_star      = force\nsp_between_mdatype_commas       = ignore\nsp_between_new_paren            = ignore\nsp_between_ptr_star             = remove\nsp_bool                         = force\nsp_brace_catch                  = ignore\nsp_brace_else                   = force\nsp_brace_finally                = ignore\nsp_brace_typedef                = force\nsp_case_label                   = force\nsp_catch_brace                  = ignore\nsp_catch_paren                  = ignore\nsp_cmt_cpp_doxygen              = true\nsp_cmt_cpp_qttr                 = true\nsp_cmt_cpp_start                = force\nsp_compare                      = force\nsp_cond_colon                   = force\nsp_cond_colon_after             = ignore\nsp_cond_colon_before            = ignore\nsp_cond_question                = force\nsp_cond_question_after          = ignore\nsp_cond_question_before         = ignore\nsp_cond_ternary_short           = remove\nsp_cparen_oparen                = remove\nsp_cpp_cast_paren               = ignore\nsp_cpp_lambda_assign            = ignore\nsp_d_array_colon                = ignore\nsp_defined_paren                = remove\nsp_deref                        = remove\nsp_else_brace                   = force\nsp_endif_cmt                    = force\nsp_enum_after_assign            = force\nsp_enum_assign                  = ignore\nsp_enum_before_assign           = ignore\nsp_enum_colon                   = ignore\nsp_enum_paren                   = ignore\nsp_extern_paren                 = ignore\nsp_finally_brace                = ignore\nsp_fparen_brace                 = force\nsp_fparen_dbrace                = ignore\nsp_func_call_paren              = remove\nsp_func_call_paren_empty        = ignore\nsp_func_call_user_paren         = ignore\nsp_func_class_paren             = ignore\nsp_func_class_paren_empty       = ignore\nsp_func_def_paren               = remove\nsp_func_def_paren_empty         = remove\nsp_func_proto_paren             = remove\nsp_func_proto_paren_empty       = remove\nsp_getset_brace                 = ignore\nsp_incdec                       = remove\nsp_inside_angle                 = ignore\nsp_inside_braces                = force\nsp_inside_braces_empty          = remove\nsp_inside_braces_enum           = force\nsp_inside_braces_struct         = force\nsp_inside_fparen                = remove\nsp_inside_fparens               = remove\nsp_inside_newop_paren           = ignore\nsp_inside_newop_paren_close     = ignore\nsp_inside_newop_paren_open      = ignore\nsp_inside_oc_at_sel_parens      = ignore\nsp_inside_paren                 = remove\nsp_inside_paren_cast            = remove\nsp_inside_sparen                = remove\nsp_inside_sparen_close          = ignore\nsp_inside_sparen_open           = ignore\nsp_inside_square                = remove\nsp_inside_tparen                = remove\nsp_inside_type_brace_init_lst   = ignore\nsp_inv                          = remove\nsp_invariant_paren              = ignore\nsp_macro                        = force\nsp_macro_func                   = force\nsp_member                       = remove\nsp_not                          = remove\nsp_num_before_tr_cmt            = 1\nsp_paren_brace                  = force\nsp_paren_comma                  = force\nsp_paren_paren                  = remove\nsp_permit_cpp11_shift           = false\nsp_pp_concat                    = add\nsp_pp_stringify                 = remove\nsp_ptr_star_paren               = remove\nsp_range                        = ignore\nsp_return_paren                 = force\nsp_scope_paren                  = ignore\nsp_sign                         = remove\nsp_sizeof_paren                 = remove\nsp_skip_vbrace_tokens           = false\nsp_sparen_brace                 = force\nsp_special_semi                 = remove\nsp_square_fparen                = remove\nsp_super_paren                  = remove\nsp_template_angle               = ignore\nsp_this_paren                   = remove\nsp_throw_paren                  = ignore\nsp_try_brace                    = ignore\nsp_type_brace_init_lst          = ignore\nsp_type_func                    = force\nsp_version_paren                = ignore\nsp_word_brace_ns                = add\nstring_escape_char              = 92\nstring_escape_char2             = 0\nstring_replace_tab_chars        = true\ntok_split_gte                   = false\nuse_indent_continue_only_once   = false\nuse_indent_func_call_param      = true\nuse_options_overriding_for_qt_macros = true\nutf8_bom                        = remove\nutf8_byte                       = true\nutf8_force                      = true\n"
  },
  {
    "path": "3rdparty/Makefile",
    "content": "#\n# Copyright © 2017-2022 The Crust Firmware Authors.\n# SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n#\n\nhostprogs-y += kconfig/\n"
  },
  {
    "path": "3rdparty/kconfig/Makefile",
    "content": "#\n# Copyright © 2017-2022 The Crust Firmware Authors.\n# SPDX-License-Identifier: GPL-2.0-only\n#\n# Based in part on scripts/kconfig/Makefile from Linux v4.19.\n#\n\nccflags-y\t+= -D_GNU_SOURCE \\\n\t\t   -std=gnu11 \\\n\t\t   -Wno-implicit-fallthrough \\\n\t\t   -Wno-pedantic \\\n\t\t   -Wno-sign-compare \\\n\t\t   -Wno-unused-parameter \\\n\t\t   -Wno-vla\ncppflags-y\t+= -I$(src)\n\nBUILDCFLAGS_nconf := $(shell \\\n\tpkg-config --cflags menuw panelw ncursesw 2>/dev/null \\\n\t|| pkg-config --cflags menu panel ncurses 2>/dev/null \\\n\t|| echo \"-D_GNU_SOURCE -I/usr/include/ncurses\")\nBUILDLDLIBS_nconf := $(shell \\\n\tpkg-config --libs menuw panelw ncursesw 2>/dev/null \\\n\t|| pkg-config --libs menu panel ncurses 2>/dev/null \\\n\t|| echo \"-lmenu -lpanel -lncurses\")\n\nbuildprogs-y\t+= conf nconf\ncommon-objs\t:= confdata.o expr.o lexer.lex.o parser.tab.o \\\n\t\t   preprocess.o symbol.o util.o\nconf-objs\t:= $(common-objs) conf.o\nnconf-objs\t:= $(common-objs) nconf.o nconf.gui.o\n\nsilent := $(if $(filter-out 0,$(V)),,-s)\n\n# These targets map 1:1 to the command line options of 'conf'.\nsimple-targets := \\\n\talldefconfig allnoconfig allyesconfig helpnewconfig listnewconfig \\\n\toldconfig olddefconfig randconfig syncconfig\n\n$(simple-targets): $(obj)/conf\n\t$(Q) $< $(silent) --$@ $(SRC)/Kconfig\n\nconfig: $(obj)/conf\n\t$(Q) $< $(silent) --oldaskconfig $(SRC)/Kconfig\n\ndefconfig: $(obj)/conf\n\t$(Q) $< $(silent) --defconfig=$(SRC)/configs/$@ $(SRC)/Kconfig\n\n%_defconfig: $(obj)/conf\n\t$(Q) $< $(silent) --defconfig=$(SRC)/configs/$@ $(SRC)/Kconfig\n\nnconfig: $(obj)/nconf\n\t$(Q) $< $(silent) $(SRC)/Kconfig\n\nsavedefconfig: $(obj)/conf\n\t$(Q) $< $(silent) --$@=defconfig $(SRC)/Kconfig\n\n$(obj)/lexer.lex.c: | $(obj)/.\n$(obj)/lexer.lex.o: $(obj)/parser.tab.c\n$(obj)/parser.tab.c: | $(obj)/.\n\n.PHONY: $(simple-targets) config defconfig %_defconfig nconfig savedefconfig\n"
  },
  {
    "path": "3rdparty/kconfig/conf.c",
    "content": "// SPDX-License-Identifier: GPL-2.0\n/*\n * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>\n */\n\n#include <ctype.h>\n#include <limits.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <time.h>\n#include <unistd.h>\n#include <getopt.h>\n#include <sys/stat.h>\n#include <sys/time.h>\n#include <errno.h>\n\n#include \"lkc.h\"\n\nstatic void conf(struct menu *menu);\nstatic void check_conf(struct menu *menu);\n\nenum input_mode {\n\toldaskconfig,\n\tsyncconfig,\n\toldconfig,\n\tallnoconfig,\n\tallyesconfig,\n\tallmodconfig,\n\talldefconfig,\n\trandconfig,\n\tdefconfig,\n\tsavedefconfig,\n\tlistnewconfig,\n\thelpnewconfig,\n\tolddefconfig,\n\tyes2modconfig,\n\tmod2yesconfig,\n};\nstatic enum input_mode input_mode = oldaskconfig;\n\nstatic int indent = 1;\nstatic int tty_stdio;\nstatic int sync_kconfig;\nstatic int conf_cnt;\nstatic char line[PATH_MAX];\nstatic struct menu *rootEntry;\n\nstatic void print_help(struct menu *menu)\n{\n\tstruct gstr help = str_new();\n\n\tmenu_get_ext_help(menu, &help);\n\n\tprintf(\"\\n%s\\n\", str_get(&help));\n\tstr_free(&help);\n}\n\nstatic void strip(char *str)\n{\n\tchar *p = str;\n\tint l;\n\n\twhile ((isspace(*p)))\n\t\tp++;\n\tl = strlen(p);\n\tif (p != str)\n\t\tmemmove(str, p, l + 1);\n\tif (!l)\n\t\treturn;\n\tp = str + l - 1;\n\twhile ((isspace(*p)))\n\t\t*p-- = 0;\n}\n\n/* Helper function to facilitate fgets() by Jean Sacren. */\nstatic void xfgets(char *str, int size, FILE *in)\n{\n\tif (!fgets(str, size, in))\n\t\tfprintf(stderr, \"\\nError in reading or end of file.\\n\");\n\n\tif (!tty_stdio)\n\t\tprintf(\"%s\", str);\n}\n\nstatic int conf_askvalue(struct symbol *sym, const char *def)\n{\n\tenum symbol_type type = sym_get_type(sym);\n\n\tif (!sym_has_value(sym))\n\t\tprintf(\"(NEW) \");\n\n\tline[0] = '\\n';\n\tline[1] = 0;\n\n\tif (!sym_is_changeable(sym)) {\n\t\tprintf(\"%s\\n\", def);\n\t\tline[0] = '\\n';\n\t\tline[1] = 0;\n\t\treturn 0;\n\t}\n\n\tswitch (input_mode) {\n\tcase oldconfig:\n\tcase syncconfig:\n\t\tif (sym_has_value(sym)) {\n\t\t\tprintf(\"%s\\n\", def);\n\t\t\treturn 0;\n\t\t}\n\t\t/* fall through */\n\tcase oldaskconfig:\n\t\tfflush(stdout);\n\t\txfgets(line, sizeof(line), stdin);\n\t\treturn 1;\n\tdefault:\n\t\tbreak;\n\t}\n\n\tswitch (type) {\n\tcase S_INT:\n\tcase S_HEX:\n\tcase S_STRING:\n\t\tprintf(\"%s\\n\", def);\n\t\treturn 1;\n\tdefault:\n\t\t;\n\t}\n\tprintf(\"%s\", line);\n\treturn 1;\n}\n\nstatic int conf_string(struct menu *menu)\n{\n\tstruct symbol *sym = menu->sym;\n\tconst char *def;\n\n\twhile (1) {\n\t\tprintf(\"%*s%s \", indent - 1, \"\", menu->prompt->text);\n\t\tprintf(\"(%s) \", sym->name);\n\t\tdef = sym_get_string_value(sym);\n\t\tif (sym_get_string_value(sym))\n\t\t\tprintf(\"[%s] \", def);\n\t\tif (!conf_askvalue(sym, def))\n\t\t\treturn 0;\n\t\tswitch (line[0]) {\n\t\tcase '\\n':\n\t\t\tbreak;\n\t\tcase '?':\n\t\t\t/* print help */\n\t\t\tif (line[1] == '\\n') {\n\t\t\t\tprint_help(menu);\n\t\t\t\tdef = NULL;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t/* fall through */\n\t\tdefault:\n\t\t\tline[strlen(line)-1] = 0;\n\t\t\tdef = line;\n\t\t}\n\t\tif (def && sym_set_string_value(sym, def))\n\t\t\treturn 0;\n\t}\n}\n\nstatic int conf_sym(struct menu *menu)\n{\n\tstruct symbol *sym = menu->sym;\n\ttristate oldval, newval;\n\n\twhile (1) {\n\t\tprintf(\"%*s%s \", indent - 1, \"\", menu->prompt->text);\n\t\tif (sym->name)\n\t\t\tprintf(\"(%s) \", sym->name);\n\t\tputchar('[');\n\t\toldval = sym_get_tristate_value(sym);\n\t\tswitch (oldval) {\n\t\tcase no:\n\t\t\tputchar('N');\n\t\t\tbreak;\n\t\tcase mod:\n\t\t\tputchar('M');\n\t\t\tbreak;\n\t\tcase yes:\n\t\t\tputchar('Y');\n\t\t\tbreak;\n\t\t}\n\t\tif (oldval != no && sym_tristate_within_range(sym, no))\n\t\t\tprintf(\"/n\");\n\t\tif (oldval != mod && sym_tristate_within_range(sym, mod))\n\t\t\tprintf(\"/m\");\n\t\tif (oldval != yes && sym_tristate_within_range(sym, yes))\n\t\t\tprintf(\"/y\");\n\t\tprintf(\"/?] \");\n\t\tif (!conf_askvalue(sym, sym_get_string_value(sym)))\n\t\t\treturn 0;\n\t\tstrip(line);\n\n\t\tswitch (line[0]) {\n\t\tcase 'n':\n\t\tcase 'N':\n\t\t\tnewval = no;\n\t\t\tif (!line[1] || !strcmp(&line[1], \"o\"))\n\t\t\t\tbreak;\n\t\t\tcontinue;\n\t\tcase 'm':\n\t\tcase 'M':\n\t\t\tnewval = mod;\n\t\t\tif (!line[1])\n\t\t\t\tbreak;\n\t\t\tcontinue;\n\t\tcase 'y':\n\t\tcase 'Y':\n\t\t\tnewval = yes;\n\t\t\tif (!line[1] || !strcmp(&line[1], \"es\"))\n\t\t\t\tbreak;\n\t\t\tcontinue;\n\t\tcase 0:\n\t\t\tnewval = oldval;\n\t\t\tbreak;\n\t\tcase '?':\n\t\t\tgoto help;\n\t\tdefault:\n\t\t\tcontinue;\n\t\t}\n\t\tif (sym_set_tristate_value(sym, newval))\n\t\t\treturn 0;\nhelp:\n\t\tprint_help(menu);\n\t}\n}\n\nstatic int conf_choice(struct menu *menu)\n{\n\tstruct symbol *sym, *def_sym;\n\tstruct menu *child;\n\tbool is_new;\n\n\tsym = menu->sym;\n\tis_new = !sym_has_value(sym);\n\tif (sym_is_changeable(sym)) {\n\t\tconf_sym(menu);\n\t\tsym_calc_value(sym);\n\t\tswitch (sym_get_tristate_value(sym)) {\n\t\tcase no:\n\t\t\treturn 1;\n\t\tcase mod:\n\t\t\treturn 0;\n\t\tcase yes:\n\t\t\tbreak;\n\t\t}\n\t} else {\n\t\tswitch (sym_get_tristate_value(sym)) {\n\t\tcase no:\n\t\t\treturn 1;\n\t\tcase mod:\n\t\t\tprintf(\"%*s%s\\n\", indent - 1, \"\", menu_get_prompt(menu));\n\t\t\treturn 0;\n\t\tcase yes:\n\t\t\tbreak;\n\t\t}\n\t}\n\n\twhile (1) {\n\t\tint cnt, def;\n\n\t\tprintf(\"%*s%s\\n\", indent - 1, \"\", menu_get_prompt(menu));\n\t\tdef_sym = sym_get_choice_value(sym);\n\t\tcnt = def = 0;\n\t\tline[0] = 0;\n\t\tfor (child = menu->list; child; child = child->next) {\n\t\t\tif (!menu_is_visible(child))\n\t\t\t\tcontinue;\n\t\t\tif (!child->sym) {\n\t\t\t\tprintf(\"%*c %s\\n\", indent, '*', menu_get_prompt(child));\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tcnt++;\n\t\t\tif (child->sym == def_sym) {\n\t\t\t\tdef = cnt;\n\t\t\t\tprintf(\"%*c\", indent, '>');\n\t\t\t} else\n\t\t\t\tprintf(\"%*c\", indent, ' ');\n\t\t\tprintf(\" %d. %s\", cnt, menu_get_prompt(child));\n\t\t\tif (child->sym->name)\n\t\t\t\tprintf(\" (%s)\", child->sym->name);\n\t\t\tif (!sym_has_value(child->sym))\n\t\t\t\tprintf(\" (NEW)\");\n\t\t\tprintf(\"\\n\");\n\t\t}\n\t\tprintf(\"%*schoice\", indent - 1, \"\");\n\t\tif (cnt == 1) {\n\t\t\tprintf(\"[1]: 1\\n\");\n\t\t\tgoto conf_childs;\n\t\t}\n\t\tprintf(\"[1-%d?]: \", cnt);\n\t\tswitch (input_mode) {\n\t\tcase oldconfig:\n\t\tcase syncconfig:\n\t\t\tif (!is_new) {\n\t\t\t\tcnt = def;\n\t\t\t\tprintf(\"%d\\n\", cnt);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t/* fall through */\n\t\tcase oldaskconfig:\n\t\t\tfflush(stdout);\n\t\t\txfgets(line, sizeof(line), stdin);\n\t\t\tstrip(line);\n\t\t\tif (line[0] == '?') {\n\t\t\t\tprint_help(menu);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (!line[0])\n\t\t\t\tcnt = def;\n\t\t\telse if (isdigit(line[0]))\n\t\t\t\tcnt = atoi(line);\n\t\t\telse\n\t\t\t\tcontinue;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\n\tconf_childs:\n\t\tfor (child = menu->list; child; child = child->next) {\n\t\t\tif (!child->sym || !menu_is_visible(child))\n\t\t\t\tcontinue;\n\t\t\tif (!--cnt)\n\t\t\t\tbreak;\n\t\t}\n\t\tif (!child)\n\t\t\tcontinue;\n\t\tif (line[0] && line[strlen(line) - 1] == '?') {\n\t\t\tprint_help(child);\n\t\t\tcontinue;\n\t\t}\n\t\tsym_set_choice_value(sym, child->sym);\n\t\tfor (child = child->list; child; child = child->next) {\n\t\t\tindent += 2;\n\t\t\tconf(child);\n\t\t\tindent -= 2;\n\t\t}\n\t\treturn 1;\n\t}\n}\n\nstatic void conf(struct menu *menu)\n{\n\tstruct symbol *sym;\n\tstruct property *prop;\n\tstruct menu *child;\n\n\tif (!menu_is_visible(menu))\n\t\treturn;\n\n\tsym = menu->sym;\n\tprop = menu->prompt;\n\tif (prop) {\n\t\tconst char *prompt;\n\n\t\tswitch (prop->type) {\n\t\tcase P_MENU:\n\t\t\t/*\n\t\t\t * Except in oldaskconfig mode, we show only menus that\n\t\t\t * contain new symbols.\n\t\t\t */\n\t\t\tif (input_mode != oldaskconfig && rootEntry != menu) {\n\t\t\t\tcheck_conf(menu);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t/* fall through */\n\t\tcase P_COMMENT:\n\t\t\tprompt = menu_get_prompt(menu);\n\t\t\tif (prompt)\n\t\t\t\tprintf(\"%*c\\n%*c %s\\n%*c\\n\",\n\t\t\t\t\tindent, '*',\n\t\t\t\t\tindent, '*', prompt,\n\t\t\t\t\tindent, '*');\n\t\tdefault:\n\t\t\t;\n\t\t}\n\t}\n\n\tif (!sym)\n\t\tgoto conf_childs;\n\n\tif (sym_is_choice(sym)) {\n\t\tconf_choice(menu);\n\t\tif (sym->curr.tri != mod)\n\t\t\treturn;\n\t\tgoto conf_childs;\n\t}\n\n\tswitch (sym->type) {\n\tcase S_INT:\n\tcase S_HEX:\n\tcase S_STRING:\n\t\tconf_string(menu);\n\t\tbreak;\n\tdefault:\n\t\tconf_sym(menu);\n\t\tbreak;\n\t}\n\nconf_childs:\n\tif (sym)\n\t\tindent += 2;\n\tfor (child = menu->list; child; child = child->next)\n\t\tconf(child);\n\tif (sym)\n\t\tindent -= 2;\n}\n\nstatic void check_conf(struct menu *menu)\n{\n\tstruct symbol *sym;\n\tstruct menu *child;\n\n\tif (!menu_is_visible(menu))\n\t\treturn;\n\n\tsym = menu->sym;\n\tif (sym && !sym_has_value(sym)) {\n\t\tif (sym_is_changeable(sym) ||\n\t\t    (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)) {\n\t\t\tif (input_mode == listnewconfig) {\n\t\t\t\tif (sym->name) {\n\t\t\t\t\tconst char *str;\n\n\t\t\t\t\tif (sym->type == S_STRING) {\n\t\t\t\t\t\tstr = sym_get_string_value(sym);\n\t\t\t\t\t\tstr = sym_escape_string_value(str);\n\t\t\t\t\t\tprintf(\"%s%s=%s\\n\", CONFIG_, sym->name, str);\n\t\t\t\t\t\tfree((void *)str);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tstr = sym_get_string_value(sym);\n\t\t\t\t\t\tprintf(\"%s%s=%s\\n\", CONFIG_, sym->name, str);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if (input_mode == helpnewconfig) {\n\t\t\t\tprintf(\"-----\\n\");\n\t\t\t\tprint_help(menu);\n\t\t\t\tprintf(\"-----\\n\");\n\n\t\t\t} else {\n\t\t\t\tif (!conf_cnt++)\n\t\t\t\t\tprintf(\"*\\n* Restart config...\\n*\\n\");\n\t\t\t\trootEntry = menu_get_parent_menu(menu);\n\t\t\t\tconf(rootEntry);\n\t\t\t}\n\t\t}\n\t}\n\n\tfor (child = menu->list; child; child = child->next)\n\t\tcheck_conf(child);\n}\n\nstatic struct option long_opts[] = {\n\t{\"oldaskconfig\",    no_argument,       NULL, oldaskconfig},\n\t{\"oldconfig\",       no_argument,       NULL, oldconfig},\n\t{\"syncconfig\",      no_argument,       NULL, syncconfig},\n\t{\"defconfig\",       required_argument, NULL, defconfig},\n\t{\"savedefconfig\",   required_argument, NULL, savedefconfig},\n\t{\"allnoconfig\",     no_argument,       NULL, allnoconfig},\n\t{\"allyesconfig\",    no_argument,       NULL, allyesconfig},\n\t{\"allmodconfig\",    no_argument,       NULL, allmodconfig},\n\t{\"alldefconfig\",    no_argument,       NULL, alldefconfig},\n\t{\"randconfig\",      no_argument,       NULL, randconfig},\n\t{\"listnewconfig\",   no_argument,       NULL, listnewconfig},\n\t{\"helpnewconfig\",   no_argument,       NULL, helpnewconfig},\n\t{\"olddefconfig\",    no_argument,       NULL, olddefconfig},\n\t{\"yes2modconfig\",   no_argument,       NULL, yes2modconfig},\n\t{\"mod2yesconfig\",   no_argument,       NULL, mod2yesconfig},\n\t{NULL, 0, NULL, 0}\n};\n\nstatic void conf_usage(const char *progname)\n{\n\n\tprintf(\"Usage: %s [-s] [option] <kconfig-file>\\n\", progname);\n\tprintf(\"[option] is _one_ of the following:\\n\");\n\tprintf(\"  --listnewconfig         List new options\\n\");\n\tprintf(\"  --helpnewconfig         List new options and help text\\n\");\n\tprintf(\"  --oldaskconfig          Start a new configuration using a line-oriented program\\n\");\n\tprintf(\"  --oldconfig             Update a configuration using a provided .config as base\\n\");\n\tprintf(\"  --syncconfig            Similar to oldconfig but generates configuration in\\n\"\n\t       \"                          include/{generated/,config/}\\n\");\n\tprintf(\"  --olddefconfig          Same as oldconfig but sets new symbols to their default value\\n\");\n\tprintf(\"  --defconfig <file>      New config with default defined in <file>\\n\");\n\tprintf(\"  --savedefconfig <file>  Save the minimal current configuration to <file>\\n\");\n\tprintf(\"  --allnoconfig           New config where all options are answered with no\\n\");\n\tprintf(\"  --allyesconfig          New config where all options are answered with yes\\n\");\n\tprintf(\"  --allmodconfig          New config where all options are answered with mod\\n\");\n\tprintf(\"  --alldefconfig          New config with all symbols set to default\\n\");\n\tprintf(\"  --randconfig            New config with random answer to all options\\n\");\n\tprintf(\"  --yes2modconfig         Change answers from yes to mod if possible\\n\");\n\tprintf(\"  --mod2yesconfig         Change answers from mod to yes if possible\\n\");\n}\n\nint main(int ac, char **av)\n{\n\tconst char *progname = av[0];\n\tint opt;\n\tconst char *name, *defconfig_file = NULL /* gcc uninit */;\n\tint no_conf_write = 0;\n\n\ttty_stdio = isatty(0) && isatty(1);\n\n\twhile ((opt = getopt_long(ac, av, \"s\", long_opts, NULL)) != -1) {\n\t\tif (opt == 's') {\n\t\t\tconf_set_message_callback(NULL);\n\t\t\tcontinue;\n\t\t}\n\t\tinput_mode = (enum input_mode)opt;\n\t\tswitch (opt) {\n\t\tcase syncconfig:\n\t\t\t/*\n\t\t\t * syncconfig is invoked during the build stage.\n\t\t\t * Suppress distracting \"configuration written to ...\"\n\t\t\t */\n\t\t\tconf_set_message_callback(NULL);\n\t\t\tsync_kconfig = 1;\n\t\t\tbreak;\n\t\tcase defconfig:\n\t\tcase savedefconfig:\n\t\t\tdefconfig_file = optarg;\n\t\t\tbreak;\n\t\tcase randconfig:\n\t\t{\n\t\t\tstruct timeval now;\n\t\t\tunsigned int seed;\n\t\t\tchar *seed_env;\n\n\t\t\t/*\n\t\t\t * Use microseconds derived seed,\n\t\t\t * compensate for systems where it may be zero\n\t\t\t */\n\t\t\tgettimeofday(&now, NULL);\n\t\t\tseed = (unsigned int)((now.tv_sec + 1) * (now.tv_usec + 1));\n\n\t\t\tseed_env = getenv(\"KCONFIG_SEED\");\n\t\t\tif( seed_env && *seed_env ) {\n\t\t\t\tchar *endp;\n\t\t\t\tint tmp = (int)strtol(seed_env, &endp, 0);\n\t\t\t\tif (*endp == '\\0') {\n\t\t\t\t\tseed = tmp;\n\t\t\t\t}\n\t\t\t}\n\t\t\tfprintf( stderr, \"KCONFIG_SEED=0x%X\\n\", seed );\n\t\t\tsrand(seed);\n\t\t\tbreak;\n\t\t}\n\t\tcase oldaskconfig:\n\t\tcase oldconfig:\n\t\tcase allnoconfig:\n\t\tcase allyesconfig:\n\t\tcase allmodconfig:\n\t\tcase alldefconfig:\n\t\tcase listnewconfig:\n\t\tcase helpnewconfig:\n\t\tcase olddefconfig:\n\t\tcase yes2modconfig:\n\t\tcase mod2yesconfig:\n\t\t\tbreak;\n\t\tcase '?':\n\t\t\tconf_usage(progname);\n\t\t\texit(1);\n\t\t\tbreak;\n\t\t}\n\t}\n\tif (ac == optind) {\n\t\tfprintf(stderr, \"%s: Kconfig file missing\\n\", av[0]);\n\t\tconf_usage(progname);\n\t\texit(1);\n\t}\n\tname = av[optind];\n\tconf_parse(name);\n\t//zconfdump(stdout);\n\n\tswitch (input_mode) {\n\tcase defconfig:\n\t\tif (conf_read(defconfig_file)) {\n\t\t\tfprintf(stderr,\n\t\t\t\t\"***\\n\"\n\t\t\t\t  \"*** Can't find default configuration \\\"%s\\\"!\\n\"\n\t\t\t\t  \"***\\n\",\n\t\t\t\tdefconfig_file);\n\t\t\texit(1);\n\t\t}\n\t\tbreak;\n\tcase savedefconfig:\n\tcase syncconfig:\n\tcase oldaskconfig:\n\tcase oldconfig:\n\tcase listnewconfig:\n\tcase helpnewconfig:\n\tcase olddefconfig:\n\tcase yes2modconfig:\n\tcase mod2yesconfig:\n\t\tconf_read(NULL);\n\t\tbreak;\n\tcase allnoconfig:\n\tcase allyesconfig:\n\tcase allmodconfig:\n\tcase alldefconfig:\n\tcase randconfig:\n\t\tname = getenv(\"KCONFIG_ALLCONFIG\");\n\t\tif (!name)\n\t\t\tbreak;\n\t\tif ((strcmp(name, \"\") != 0) && (strcmp(name, \"1\") != 0)) {\n\t\t\tif (conf_read_simple(name, S_DEF_USER)) {\n\t\t\t\tfprintf(stderr,\n\t\t\t\t\t\"*** Can't read seed configuration \\\"%s\\\"!\\n\",\n\t\t\t\t\tname);\n\t\t\t\texit(1);\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tswitch (input_mode) {\n\t\tcase allnoconfig:\tname = \"allno.config\"; break;\n\t\tcase allyesconfig:\tname = \"allyes.config\"; break;\n\t\tcase allmodconfig:\tname = \"allmod.config\"; break;\n\t\tcase alldefconfig:\tname = \"alldef.config\"; break;\n\t\tcase randconfig:\tname = \"allrandom.config\"; break;\n\t\tdefault: break;\n\t\t}\n\t\tif (conf_read_simple(name, S_DEF_USER) &&\n\t\t    conf_read_simple(\"all.config\", S_DEF_USER)) {\n\t\t\tfprintf(stderr,\n\t\t\t\t\"*** KCONFIG_ALLCONFIG set, but no \\\"%s\\\" or \\\"all.config\\\" file found\\n\",\n\t\t\t\tname);\n\t\t\texit(1);\n\t\t}\n\t\tbreak;\n\tdefault:\n\t\tbreak;\n\t}\n\n\tif (sync_kconfig) {\n\t\tname = getenv(\"KCONFIG_NOSILENTUPDATE\");\n\t\tif (name && *name) {\n\t\t\tif (conf_get_changed()) {\n\t\t\t\tfprintf(stderr,\n\t\t\t\t\t\"\\n*** The configuration requires explicit update.\\n\\n\");\n\t\t\t\treturn 1;\n\t\t\t}\n\t\t\tno_conf_write = 1;\n\t\t}\n\t}\n\n\tswitch (input_mode) {\n\tcase allnoconfig:\n\t\tconf_set_all_new_symbols(def_no);\n\t\tbreak;\n\tcase allyesconfig:\n\t\tconf_set_all_new_symbols(def_yes);\n\t\tbreak;\n\tcase allmodconfig:\n\t\tconf_set_all_new_symbols(def_mod);\n\t\tbreak;\n\tcase alldefconfig:\n\t\tconf_set_all_new_symbols(def_default);\n\t\tbreak;\n\tcase randconfig:\n\t\t/* Really nothing to do in this loop */\n\t\twhile (conf_set_all_new_symbols(def_random)) ;\n\t\tbreak;\n\tcase defconfig:\n\t\tconf_set_all_new_symbols(def_default);\n\t\tbreak;\n\tcase savedefconfig:\n\t\tbreak;\n\tcase yes2modconfig:\n\t\tconf_rewrite_mod_or_yes(def_y2m);\n\t\tbreak;\n\tcase mod2yesconfig:\n\t\tconf_rewrite_mod_or_yes(def_m2y);\n\t\tbreak;\n\tcase oldaskconfig:\n\t\trootEntry = &rootmenu;\n\t\tconf(&rootmenu);\n\t\tinput_mode = oldconfig;\n\t\t/* fall through */\n\tcase oldconfig:\n\tcase listnewconfig:\n\tcase helpnewconfig:\n\tcase syncconfig:\n\t\t/* Update until a loop caused no more changes */\n\t\tdo {\n\t\t\tconf_cnt = 0;\n\t\t\tcheck_conf(&rootmenu);\n\t\t} while (conf_cnt);\n\t\tbreak;\n\tcase olddefconfig:\n\tdefault:\n\t\tbreak;\n\t}\n\n\tif (input_mode == savedefconfig) {\n\t\tif (conf_write_defconfig(defconfig_file)) {\n\t\t\tfprintf(stderr, \"n*** Error while saving defconfig to: %s\\n\\n\",\n\t\t\t\tdefconfig_file);\n\t\t\treturn 1;\n\t\t}\n\t} else if (input_mode != listnewconfig && input_mode != helpnewconfig) {\n\t\tif (!no_conf_write && conf_write(NULL)) {\n\t\t\tfprintf(stderr, \"\\n*** Error during writing of the configuration.\\n\\n\");\n\t\t\texit(1);\n\t\t}\n\n\t\t/*\n\t\t * Create auto.conf if it does not exist.\n\t\t * This prevents GNU Make 4.1 or older from emitting\n\t\t * \"include/config/auto.conf: No such file or directory\"\n\t\t * in the top-level Makefile\n\t\t *\n\t\t * syncconfig always creates or updates auto.conf because it is\n\t\t * used during the build.\n\t\t */\n\t\tif (conf_write_autoconf(sync_kconfig) && sync_kconfig) {\n\t\t\tfprintf(stderr,\n\t\t\t\t\"\\n*** Error during sync of the configuration.\\n\\n\");\n\t\t\treturn 1;\n\t\t}\n\t}\n\treturn 0;\n}\n"
  },
  {
    "path": "3rdparty/kconfig/confdata.c",
    "content": "// SPDX-License-Identifier: GPL-2.0\n/*\n * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>\n */\n\n#include <sys/mman.h>\n#include <sys/stat.h>\n#include <ctype.h>\n#include <errno.h>\n#include <fcntl.h>\n#include <limits.h>\n#include <stdarg.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <time.h>\n#include <unistd.h>\n\n#include \"lkc.h\"\n\n/* return true if 'path' exists, false otherwise */\nstatic bool is_present(const char *path)\n{\n\tstruct stat st;\n\n\treturn !stat(path, &st);\n}\n\n/* return true if 'path' exists and it is a directory, false otherwise */\nstatic bool is_dir(const char *path)\n{\n\tstruct stat st;\n\n\tif (stat(path, &st))\n\t\treturn 0;\n\n\treturn S_ISDIR(st.st_mode);\n}\n\n/* return true if the given two files are the same, false otherwise */\nstatic bool is_same(const char *file1, const char *file2)\n{\n\tint fd1, fd2;\n\tstruct stat st1, st2;\n\tvoid *map1, *map2;\n\tbool ret = false;\n\n\tfd1 = open(file1, O_RDONLY);\n\tif (fd1 < 0)\n\t\treturn ret;\n\n\tfd2 = open(file2, O_RDONLY);\n\tif (fd2 < 0)\n\t\tgoto close1;\n\n\tret = fstat(fd1, &st1);\n\tif (ret)\n\t\tgoto close2;\n\tret = fstat(fd2, &st2);\n\tif (ret)\n\t\tgoto close2;\n\n\tif (st1.st_size != st2.st_size)\n\t\tgoto close2;\n\n\tmap1 = mmap(NULL, st1.st_size, PROT_READ, MAP_PRIVATE, fd1, 0);\n\tif (map1 == MAP_FAILED)\n\t\tgoto close2;\n\n\tmap2 = mmap(NULL, st2.st_size, PROT_READ, MAP_PRIVATE, fd2, 0);\n\tif (map2 == MAP_FAILED)\n\t\tgoto close2;\n\n\tif (bcmp(map1, map2, st1.st_size))\n\t\tgoto close2;\n\n\tret = true;\nclose2:\n\tclose(fd2);\nclose1:\n\tclose(fd1);\n\n\treturn ret;\n}\n\n/*\n * Create the parent directory of the given path.\n *\n * For example, if 'include/config/auto.conf' is given, create 'include/config'.\n */\nstatic int make_parent_dir(const char *path)\n{\n\tchar tmp[PATH_MAX + 1];\n\tchar *p;\n\n\tstrncpy(tmp, path, sizeof(tmp));\n\ttmp[sizeof(tmp) - 1] = 0;\n\n\t/* Remove the base name. Just return if nothing is left */\n\tp = strrchr(tmp, '/');\n\tif (!p)\n\t\treturn 0;\n\t*(p + 1) = 0;\n\n\t/* Just in case it is an absolute path */\n\tp = tmp;\n\twhile (*p == '/')\n\t\tp++;\n\n\twhile ((p = strchr(p, '/'))) {\n\t\t*p = 0;\n\n\t\t/* skip if the directory exists */\n\t\tif (!is_dir(tmp) && mkdir(tmp, 0755))\n\t\t\treturn -1;\n\n\t\t*p = '/';\n\t\twhile (*p == '/')\n\t\t\tp++;\n\t}\n\n\treturn 0;\n}\n\nstatic char depfile_path[PATH_MAX];\nstatic size_t depfile_prefix_len;\n\n/* touch depfile for symbol 'name' */\nstatic int conf_touch_dep(const char *name)\n{\n\tint fd, ret;\n\tconst char *s;\n\tchar *d, c;\n\n\t/* check overflow: prefix + name + \".h\" + '\\0' must fit in buffer. */\n\tif (depfile_prefix_len + strlen(name) + 3 > sizeof(depfile_path))\n\t\treturn -1;\n\n\td = depfile_path + depfile_prefix_len;\n\ts = name;\n\n\twhile ((c = *s++))\n\t\t*d++ = (c == '_') ? '/' : tolower(c);\n\tstrcpy(d, \".h\");\n\n\t/* Assume directory path already exists. */\n\tfd = open(depfile_path, O_WRONLY | O_CREAT | O_TRUNC, 0644);\n\tif (fd == -1) {\n\t\tif (errno != ENOENT)\n\t\t\treturn -1;\n\n\t\tret = make_parent_dir(depfile_path);\n\t\tif (ret)\n\t\t\treturn ret;\n\n\t\t/* Try it again. */\n\t\tfd = open(depfile_path, O_WRONLY | O_CREAT | O_TRUNC, 0644);\n\t\tif (fd == -1)\n\t\t\treturn -1;\n\t}\n\tclose(fd);\n\n\treturn 0;\n}\n\nstruct conf_printer {\n\tvoid (*print_symbol)(FILE *, struct symbol *, const char *, void *);\n\tvoid (*print_comment)(FILE *, const char *, void *);\n};\n\nstatic void conf_warning(const char *fmt, ...)\n\t__attribute__ ((format (printf, 1, 2)));\n\nstatic void conf_message(const char *fmt, ...)\n\t__attribute__ ((format (printf, 1, 2)));\n\nstatic const char *conf_filename;\nstatic int conf_lineno, conf_warnings;\n\nstatic void conf_warning(const char *fmt, ...)\n{\n\tva_list ap;\n\tva_start(ap, fmt);\n\tfprintf(stderr, \"%s:%d:warning: \", conf_filename, conf_lineno);\n\tvfprintf(stderr, fmt, ap);\n\tfprintf(stderr, \"\\n\");\n\tva_end(ap);\n\tconf_warnings++;\n}\n\nstatic void conf_default_message_callback(const char *s)\n{\n\tprintf(\"#\\n# \");\n\tprintf(\"%s\", s);\n\tprintf(\"\\n#\\n\");\n}\n\nstatic void (*conf_message_callback)(const char *s) =\n\tconf_default_message_callback;\nvoid conf_set_message_callback(void (*fn)(const char *s))\n{\n\tconf_message_callback = fn;\n}\n\nstatic void conf_message(const char *fmt, ...)\n{\n\tva_list ap;\n\tchar buf[4096];\n\n\tif (!conf_message_callback)\n\t\treturn;\n\n\tva_start(ap, fmt);\n\n\tvsnprintf(buf, sizeof(buf), fmt, ap);\n\tconf_message_callback(buf);\n\tva_end(ap);\n}\n\nconst char *conf_get_configname(void)\n{\n\tchar *name = getenv(\"KCONFIG_CONFIG\");\n\n\treturn name ? name : \".config\";\n}\n\nstatic const char *conf_get_autoconfig_name(void)\n{\n\tchar *name = getenv(\"KCONFIG_AUTOCONFIG\");\n\n\treturn name ? name : \"include/config/auto.conf\";\n}\n\nstatic int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)\n{\n\tchar *p2;\n\n\tswitch (sym->type) {\n\tcase S_TRISTATE:\n\t\tif (p[0] == 'm') {\n\t\t\tsym->def[def].tri = mod;\n\t\t\tsym->flags |= def_flags;\n\t\t\tbreak;\n\t\t}\n\t\t/* fall through */\n\tcase S_BOOLEAN:\n\t\tif (p[0] == 'y') {\n\t\t\tsym->def[def].tri = yes;\n\t\t\tsym->flags |= def_flags;\n\t\t\tbreak;\n\t\t}\n\t\tif (p[0] == 'n') {\n\t\t\tsym->def[def].tri = no;\n\t\t\tsym->flags |= def_flags;\n\t\t\tbreak;\n\t\t}\n\t\tif (def != S_DEF_AUTO)\n\t\t\tconf_warning(\"symbol value '%s' invalid for %s\",\n\t\t\t\t     p, sym->name);\n\t\treturn 1;\n\tcase S_STRING:\n\t\tif (*p++ != '\"')\n\t\t\tbreak;\n\t\tfor (p2 = p; (p2 = strpbrk(p2, \"\\\"\\\\\")); p2++) {\n\t\t\tif (*p2 == '\"') {\n\t\t\t\t*p2 = 0;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tmemmove(p2, p2 + 1, strlen(p2));\n\t\t}\n\t\tif (!p2) {\n\t\t\tif (def != S_DEF_AUTO)\n\t\t\t\tconf_warning(\"invalid string found\");\n\t\t\treturn 1;\n\t\t}\n\t\t/* fall through */\n\tcase S_INT:\n\tcase S_HEX:\n\t\tif (sym_string_valid(sym, p)) {\n\t\t\tsym->def[def].val = xstrdup(p);\n\t\t\tsym->flags |= def_flags;\n\t\t} else {\n\t\t\tif (def != S_DEF_AUTO)\n\t\t\t\tconf_warning(\"symbol value '%s' invalid for %s\",\n\t\t\t\t\t     p, sym->name);\n\t\t\treturn 1;\n\t\t}\n\t\tbreak;\n\tdefault:\n\t\t;\n\t}\n\treturn 0;\n}\n\n#define LINE_GROWTH 16\nstatic int add_byte(int c, char **lineptr, size_t slen, size_t *n)\n{\n\tchar *nline;\n\tsize_t new_size = slen + 1;\n\tif (new_size > *n) {\n\t\tnew_size += LINE_GROWTH - 1;\n\t\tnew_size *= 2;\n\t\tnline = xrealloc(*lineptr, new_size);\n\t\tif (!nline)\n\t\t\treturn -1;\n\n\t\t*lineptr = nline;\n\t\t*n = new_size;\n\t}\n\n\t(*lineptr)[slen] = c;\n\n\treturn 0;\n}\n\nstatic ssize_t compat_getline(char **lineptr, size_t *n, FILE *stream)\n{\n\tchar *line = *lineptr;\n\tsize_t slen = 0;\n\n\tfor (;;) {\n\t\tint c = getc(stream);\n\n\t\tswitch (c) {\n\t\tcase '\\n':\n\t\t\tif (add_byte(c, &line, slen, n) < 0)\n\t\t\t\tgoto e_out;\n\t\t\tslen++;\n\t\t\t/* fall through */\n\t\tcase EOF:\n\t\t\tif (add_byte('\\0', &line, slen, n) < 0)\n\t\t\t\tgoto e_out;\n\t\t\t*lineptr = line;\n\t\t\tif (slen == 0)\n\t\t\t\treturn -1;\n\t\t\treturn slen;\n\t\tdefault:\n\t\t\tif (add_byte(c, &line, slen, n) < 0)\n\t\t\t\tgoto e_out;\n\t\t\tslen++;\n\t\t}\n\t}\n\ne_out:\n\tline[slen-1] = '\\0';\n\t*lineptr = line;\n\treturn -1;\n}\n\nint conf_read_simple(const char *name, int def)\n{\n\tFILE *in = NULL;\n\tchar   *line = NULL;\n\tsize_t  line_asize = 0;\n\tchar *p, *p2;\n\tstruct symbol *sym;\n\tint i, def_flags;\n\n\tif (name) {\n\t\tin = zconf_fopen(name);\n\t} else {\n\t\tstruct property *prop;\n\n\t\tname = conf_get_configname();\n\t\tin = zconf_fopen(name);\n\t\tif (in)\n\t\t\tgoto load;\n\t\tsym_add_change_count(1);\n\t\tif (!sym_defconfig_list)\n\t\t\treturn 1;\n\n\t\tfor_all_defaults(sym_defconfig_list, prop) {\n\t\t\tif (expr_calc_value(prop->visible.expr) == no ||\n\t\t\t    prop->expr->type != E_SYMBOL)\n\t\t\t\tcontinue;\n\t\t\tsym_calc_value(prop->expr->left.sym);\n\t\t\tname = sym_get_string_value(prop->expr->left.sym);\n\t\t\tin = zconf_fopen(name);\n\t\t\tif (in) {\n\t\t\t\tconf_message(\"using defaults found in %s\",\n\t\t\t\t\t name);\n\t\t\t\tgoto load;\n\t\t\t}\n\t\t}\n\t}\n\tif (!in)\n\t\treturn 1;\n\nload:\n\tconf_filename = name;\n\tconf_lineno = 0;\n\tconf_warnings = 0;\n\n\tdef_flags = SYMBOL_DEF << def;\n\tfor_all_symbols(i, sym) {\n\t\tsym->flags |= SYMBOL_CHANGED;\n\t\tsym->flags &= ~(def_flags|SYMBOL_VALID);\n\t\tif (sym_is_choice(sym))\n\t\t\tsym->flags |= def_flags;\n\t\tswitch (sym->type) {\n\t\tcase S_INT:\n\t\tcase S_HEX:\n\t\tcase S_STRING:\n\t\t\tif (sym->def[def].val)\n\t\t\t\tfree(sym->def[def].val);\n\t\t\t/* fall through */\n\t\tdefault:\n\t\t\tsym->def[def].val = NULL;\n\t\t\tsym->def[def].tri = no;\n\t\t}\n\t}\n\n\twhile (compat_getline(&line, &line_asize, in) != -1) {\n\t\tconf_lineno++;\n\t\tsym = NULL;\n\t\tif (line[0] == '#') {\n\t\t\tif (memcmp(line + 2, CONFIG_, strlen(CONFIG_)))\n\t\t\t\tcontinue;\n\t\t\tp = strchr(line + 2 + strlen(CONFIG_), ' ');\n\t\t\tif (!p)\n\t\t\t\tcontinue;\n\t\t\t*p++ = 0;\n\t\t\tif (strncmp(p, \"is not set\", 10))\n\t\t\t\tcontinue;\n\t\t\tif (def == S_DEF_USER) {\n\t\t\t\tsym = sym_find(line + 2 + strlen(CONFIG_));\n\t\t\t\tif (!sym) {\n\t\t\t\t\tsym_add_change_count(1);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tsym = sym_lookup(line + 2 + strlen(CONFIG_), 0);\n\t\t\t\tif (sym->type == S_UNKNOWN)\n\t\t\t\t\tsym->type = S_BOOLEAN;\n\t\t\t}\n\t\t\tif (sym->flags & def_flags) {\n\t\t\t\tconf_warning(\"override: reassigning to symbol %s\", sym->name);\n\t\t\t}\n\t\t\tswitch (sym->type) {\n\t\t\tcase S_BOOLEAN:\n\t\t\tcase S_TRISTATE:\n\t\t\t\tsym->def[def].tri = no;\n\t\t\t\tsym->flags |= def_flags;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\t;\n\t\t\t}\n\t\t} else if (memcmp(line, CONFIG_, strlen(CONFIG_)) == 0) {\n\t\t\tp = strchr(line + strlen(CONFIG_), '=');\n\t\t\tif (!p)\n\t\t\t\tcontinue;\n\t\t\t*p++ = 0;\n\t\t\tp2 = strchr(p, '\\n');\n\t\t\tif (p2) {\n\t\t\t\t*p2-- = 0;\n\t\t\t\tif (*p2 == '\\r')\n\t\t\t\t\t*p2 = 0;\n\t\t\t}\n\n\t\t\tsym = sym_find(line + strlen(CONFIG_));\n\t\t\tif (!sym) {\n\t\t\t\tif (def == S_DEF_AUTO)\n\t\t\t\t\t/*\n\t\t\t\t\t * Reading from include/config/auto.conf\n\t\t\t\t\t * If CONFIG_FOO previously existed in\n\t\t\t\t\t * auto.conf but it is missing now,\n\t\t\t\t\t * include/config/foo.h must be touched.\n\t\t\t\t\t */\n\t\t\t\t\tconf_touch_dep(line + strlen(CONFIG_));\n\t\t\t\telse\n\t\t\t\t\tsym_add_change_count(1);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (sym->flags & def_flags) {\n\t\t\t\tconf_warning(\"override: reassigning to symbol %s\", sym->name);\n\t\t\t}\n\t\t\tif (conf_set_sym_val(sym, def, def_flags, p))\n\t\t\t\tcontinue;\n\t\t} else {\n\t\t\tif (line[0] != '\\r' && line[0] != '\\n')\n\t\t\t\tconf_warning(\"unexpected data: %.*s\",\n\t\t\t\t\t     (int)strcspn(line, \"\\r\\n\"), line);\n\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (sym && sym_is_choice_value(sym)) {\n\t\t\tstruct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));\n\t\t\tswitch (sym->def[def].tri) {\n\t\t\tcase no:\n\t\t\t\tbreak;\n\t\t\tcase mod:\n\t\t\t\tif (cs->def[def].tri == yes) {\n\t\t\t\t\tconf_warning(\"%s creates inconsistent choice state\", sym->name);\n\t\t\t\t\tcs->flags &= ~def_flags;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase yes:\n\t\t\t\tif (cs->def[def].tri != no)\n\t\t\t\t\tconf_warning(\"override: %s changes choice state\", sym->name);\n\t\t\t\tcs->def[def].val = sym;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcs->def[def].tri = EXPR_OR(cs->def[def].tri, sym->def[def].tri);\n\t\t}\n\t}\n\tfree(line);\n\tfclose(in);\n\treturn 0;\n}\n\nint conf_read(const char *name)\n{\n\tstruct symbol *sym;\n\tint conf_unsaved = 0;\n\tint i;\n\n\tsym_set_change_count(0);\n\n\tif (conf_read_simple(name, S_DEF_USER)) {\n\t\tsym_calc_value(modules_sym);\n\t\treturn 1;\n\t}\n\n\tsym_calc_value(modules_sym);\n\n\tfor_all_symbols(i, sym) {\n\t\tsym_calc_value(sym);\n\t\tif (sym_is_choice(sym) || (sym->flags & SYMBOL_NO_WRITE))\n\t\t\tcontinue;\n\t\tif (sym_has_value(sym) && (sym->flags & SYMBOL_WRITE)) {\n\t\t\t/* check that calculated value agrees with saved value */\n\t\t\tswitch (sym->type) {\n\t\t\tcase S_BOOLEAN:\n\t\t\tcase S_TRISTATE:\n\t\t\t\tif (sym->def[S_DEF_USER].tri == sym_get_tristate_value(sym))\n\t\t\t\t\tcontinue;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tif (!strcmp(sym->curr.val, sym->def[S_DEF_USER].val))\n\t\t\t\t\tcontinue;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t} else if (!sym_has_value(sym) && !(sym->flags & SYMBOL_WRITE))\n\t\t\t/* no previous value and not saved */\n\t\t\tcontinue;\n\t\tconf_unsaved++;\n\t\t/* maybe print value in verbose mode... */\n\t}\n\n\tfor_all_symbols(i, sym) {\n\t\tif (sym_has_value(sym) && !sym_is_choice_value(sym)) {\n\t\t\t/* Reset values of generates values, so they'll appear\n\t\t\t * as new, if they should become visible, but that\n\t\t\t * doesn't quite work if the Kconfig and the saved\n\t\t\t * configuration disagree.\n\t\t\t */\n\t\t\tif (sym->visible == no && !conf_unsaved)\n\t\t\t\tsym->flags &= ~SYMBOL_DEF_USER;\n\t\t\tswitch (sym->type) {\n\t\t\tcase S_STRING:\n\t\t\tcase S_INT:\n\t\t\tcase S_HEX:\n\t\t\t\t/* Reset a string value if it's out of range */\n\t\t\t\tif (sym_string_within_range(sym, sym->def[S_DEF_USER].val))\n\t\t\t\t\tbreak;\n\t\t\t\tsym->flags &= ~(SYMBOL_VALID|SYMBOL_DEF_USER);\n\t\t\t\tconf_unsaved++;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tsym_add_change_count(conf_warnings || conf_unsaved);\n\n\treturn 0;\n}\n\n/*\n * Kconfig configuration printer\n *\n * This printer is used when generating the resulting configuration after\n * kconfig invocation and `defconfig' files. Unset symbol might be omitted by\n * passing a non-NULL argument to the printer.\n *\n */\nstatic void\nkconfig_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg)\n{\n\n\tswitch (sym->type) {\n\tcase S_BOOLEAN:\n\tcase S_TRISTATE:\n\t\tif (*value == 'n') {\n\t\t\tbool skip_unset = (arg != NULL);\n\n\t\t\tif (!skip_unset)\n\t\t\t\tfprintf(fp, \"# %s%s is not set\\n\",\n\t\t\t\t    CONFIG_, sym->name);\n\t\t\treturn;\n\t\t}\n\t\tbreak;\n\tdefault:\n\t\tbreak;\n\t}\n\n\tfprintf(fp, \"%s%s=%s\\n\", CONFIG_, sym->name, value);\n}\n\nstatic void\nkconfig_print_comment(FILE *fp, const char *value, void *arg)\n{\n\tconst char *p = value;\n\tsize_t l;\n\n\tfor (;;) {\n\t\tl = strcspn(p, \"\\n\");\n\t\tfprintf(fp, \"#\");\n\t\tif (l) {\n\t\t\tfprintf(fp, \" \");\n\t\t\txfwrite(p, l, 1, fp);\n\t\t\tp += l;\n\t\t}\n\t\tfprintf(fp, \"\\n\");\n\t\tif (*p++ == '\\0')\n\t\t\tbreak;\n\t}\n}\n\nstatic struct conf_printer kconfig_printer_cb =\n{\n\t.print_symbol = kconfig_print_symbol,\n\t.print_comment = kconfig_print_comment,\n};\n\n/*\n * Header printer\n *\n * This printer is used when generating the `include/generated/autoconf.h' file.\n */\nstatic void\nheader_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg)\n{\n\n\tswitch (sym->type) {\n\tcase S_BOOLEAN:\n\tcase S_TRISTATE: {\n\t\tconst char *suffix = \"\";\n\n\t\tswitch (*value) {\n\t\tcase 'n':\n\t\t\tbreak;\n\t\tcase 'm':\n\t\t\tsuffix = \"_MODULE\";\n\t\t\t/* fall through */\n\t\tdefault:\n\t\t\tfprintf(fp, \"#define %s%s%s 1\\n\",\n\t\t\t    CONFIG_, sym->name, suffix);\n\t\t}\n\t\tbreak;\n\t}\n\tcase S_HEX: {\n\t\tconst char *prefix = \"\";\n\n\t\tif (value[0] != '0' || (value[1] != 'x' && value[1] != 'X'))\n\t\t\tprefix = \"0x\";\n\t\tfprintf(fp, \"#define %s%s %s%s\\n\",\n\t\t    CONFIG_, sym->name, prefix, value);\n\t\tbreak;\n\t}\n\tcase S_STRING:\n\tcase S_INT:\n\t\tfprintf(fp, \"#define %s%s %s\\n\",\n\t\t    CONFIG_, sym->name, value);\n\t\tbreak;\n\tdefault:\n\t\tbreak;\n\t}\n\n}\n\nstatic void\nheader_print_comment(FILE *fp, const char *value, void *arg)\n{\n\tconst char *p = value;\n\tsize_t l;\n\n\tfprintf(fp, \"/*\\n\");\n\tfor (;;) {\n\t\tl = strcspn(p, \"\\n\");\n\t\tfprintf(fp, \" *\");\n\t\tif (l) {\n\t\t\tfprintf(fp, \" \");\n\t\t\txfwrite(p, l, 1, fp);\n\t\t\tp += l;\n\t\t}\n\t\tfprintf(fp, \"\\n\");\n\t\tif (*p++ == '\\0')\n\t\t\tbreak;\n\t}\n\tfprintf(fp, \" */\\n\");\n}\n\nstatic struct conf_printer header_printer_cb =\n{\n\t.print_symbol = header_print_symbol,\n\t.print_comment = header_print_comment,\n};\n\nstatic void conf_write_symbol(FILE *fp, struct symbol *sym,\n\t\t\t      struct conf_printer *printer, void *printer_arg)\n{\n\tconst char *str;\n\n\tswitch (sym->type) {\n\tcase S_UNKNOWN:\n\t\tbreak;\n\tcase S_STRING:\n\t\tstr = sym_get_string_value(sym);\n\t\tstr = sym_escape_string_value(str);\n\t\tprinter->print_symbol(fp, sym, str, printer_arg);\n\t\tfree((void *)str);\n\t\tbreak;\n\tdefault:\n\t\tstr = sym_get_string_value(sym);\n\t\tprinter->print_symbol(fp, sym, str, printer_arg);\n\t}\n}\n\nstatic void\nconf_write_heading(FILE *fp, struct conf_printer *printer, void *printer_arg)\n{\n\tchar buf[256];\n\n\tsnprintf(buf, sizeof(buf),\n\t    \"\\n\"\n\t    \"Automatically generated file; DO NOT EDIT.\\n\"\n\t    \"%s\\n\",\n\t    rootmenu.prompt->text);\n\n\tprinter->print_comment(fp, buf, printer_arg);\n}\n\n/*\n * Write out a minimal config.\n * All values that has default values are skipped as this is redundant.\n */\nint conf_write_defconfig(const char *filename)\n{\n\tstruct symbol *sym;\n\tstruct menu *menu;\n\tFILE *out;\n\n\tout = fopen(filename, \"w\");\n\tif (!out)\n\t\treturn 1;\n\n\tsym_clear_all_valid();\n\n\t/* Traverse all menus to find all relevant symbols */\n\tmenu = rootmenu.list;\n\n\twhile (menu != NULL)\n\t{\n\t\tsym = menu->sym;\n\t\tif (sym == NULL) {\n\t\t\tif (!menu_is_visible(menu))\n\t\t\t\tgoto next_menu;\n\t\t} else if (!sym_is_choice(sym)) {\n\t\t\tsym_calc_value(sym);\n\t\t\tif (!(sym->flags & SYMBOL_WRITE))\n\t\t\t\tgoto next_menu;\n\t\t\tsym->flags &= ~SYMBOL_WRITE;\n\t\t\t/* If we cannot change the symbol - skip */\n\t\t\tif (!sym_is_changeable(sym))\n\t\t\t\tgoto next_menu;\n\t\t\t/* If symbol equals to default value - skip */\n\t\t\tif (strcmp(sym_get_string_value(sym), sym_get_string_default(sym)) == 0)\n\t\t\t\tgoto next_menu;\n\n\t\t\t/*\n\t\t\t * If symbol is a choice value and equals to the\n\t\t\t * default for a choice - skip.\n\t\t\t * But only if value is bool and equal to \"y\" and\n\t\t\t * choice is not \"optional\".\n\t\t\t * (If choice is \"optional\" then all values can be \"n\")\n\t\t\t */\n\t\t\tif (sym_is_choice_value(sym)) {\n\t\t\t\tstruct symbol *cs;\n\t\t\t\tstruct symbol *ds;\n\n\t\t\t\tcs = prop_get_symbol(sym_get_choice_prop(sym));\n\t\t\t\tds = sym_choice_default(cs);\n\t\t\t\tif (!sym_is_optional(cs) && sym == ds) {\n\t\t\t\t\tif ((sym->type == S_BOOLEAN) &&\n\t\t\t\t\t    sym_get_tristate_value(sym) == yes)\n\t\t\t\t\t\tgoto next_menu;\n\t\t\t\t}\n\t\t\t}\n\t\t\tconf_write_symbol(out, sym, &kconfig_printer_cb, NULL);\n\t\t}\nnext_menu:\n\t\tif (menu->list != NULL) {\n\t\t\tmenu = menu->list;\n\t\t}\n\t\telse if (menu->next != NULL) {\n\t\t\tmenu = menu->next;\n\t\t} else {\n\t\t\twhile ((menu = menu->parent)) {\n\t\t\t\tif (menu->next != NULL) {\n\t\t\t\t\tmenu = menu->next;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tfclose(out);\n\treturn 0;\n}\n\nint conf_write(const char *name)\n{\n\tFILE *out;\n\tstruct symbol *sym;\n\tstruct menu *menu;\n\tconst char *str;\n\tchar tmpname[PATH_MAX + 1], oldname[PATH_MAX + 1];\n\tchar *env;\n\tint i;\n\tbool need_newline = false;\n\n\tif (!name)\n\t\tname = conf_get_configname();\n\n\tif (!*name) {\n\t\tfprintf(stderr, \"config name is empty\\n\");\n\t\treturn -1;\n\t}\n\n\tif (is_dir(name)) {\n\t\tfprintf(stderr, \"%s: Is a directory\\n\", name);\n\t\treturn -1;\n\t}\n\n\tif (make_parent_dir(name))\n\t\treturn -1;\n\n\tenv = getenv(\"KCONFIG_OVERWRITECONFIG\");\n\tif (env && *env) {\n\t\t*tmpname = 0;\n\t\tout = fopen(name, \"w\");\n\t} else {\n\t\tsnprintf(tmpname, sizeof(tmpname), \"%s.%d.tmp\",\n\t\t\t name, (int)getpid());\n\t\tout = fopen(tmpname, \"w\");\n\t}\n\tif (!out)\n\t\treturn 1;\n\n\tconf_write_heading(out, &kconfig_printer_cb, NULL);\n\n\tif (!conf_get_changed())\n\t\tsym_clear_all_valid();\n\n\tmenu = rootmenu.list;\n\twhile (menu) {\n\t\tsym = menu->sym;\n\t\tif (!sym) {\n\t\t\tif (!menu_is_visible(menu))\n\t\t\t\tgoto next;\n\t\t\tstr = menu_get_prompt(menu);\n\t\t\tfprintf(out, \"\\n\"\n\t\t\t\t     \"#\\n\"\n\t\t\t\t     \"# %s\\n\"\n\t\t\t\t     \"#\\n\", str);\n\t\t\tneed_newline = false;\n\t\t} else if (!(sym->flags & SYMBOL_CHOICE) &&\n\t\t\t   !(sym->flags & SYMBOL_WRITTEN)) {\n\t\t\tsym_calc_value(sym);\n\t\t\tif (!(sym->flags & SYMBOL_WRITE))\n\t\t\t\tgoto next;\n\t\t\tif (need_newline) {\n\t\t\t\tfprintf(out, \"\\n\");\n\t\t\t\tneed_newline = false;\n\t\t\t}\n\t\t\tsym->flags |= SYMBOL_WRITTEN;\n\t\t\tconf_write_symbol(out, sym, &kconfig_printer_cb, NULL);\n\t\t}\n\nnext:\n\t\tif (menu->list) {\n\t\t\tmenu = menu->list;\n\t\t\tcontinue;\n\t\t}\n\t\tif (menu->next)\n\t\t\tmenu = menu->next;\n\t\telse while ((menu = menu->parent)) {\n\t\t\tif (!menu->sym && menu_is_visible(menu) &&\n\t\t\t    menu != &rootmenu) {\n\t\t\t\tstr = menu_get_prompt(menu);\n\t\t\t\tfprintf(out, \"# end of %s\\n\", str);\n\t\t\t\tneed_newline = true;\n\t\t\t}\n\t\t\tif (menu->next) {\n\t\t\t\tmenu = menu->next;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\tfclose(out);\n\n\tfor_all_symbols(i, sym)\n\t\tsym->flags &= ~SYMBOL_WRITTEN;\n\n\tif (*tmpname) {\n\t\tif (is_same(name, tmpname)) {\n\t\t\tconf_message(\"No change to %s\", name);\n\t\t\tunlink(tmpname);\n\t\t\tsym_set_change_count(0);\n\t\t\treturn 0;\n\t\t}\n\n\t\tsnprintf(oldname, sizeof(oldname), \"%s.old\", name);\n\t\trename(name, oldname);\n\t\tif (rename(tmpname, name))\n\t\t\treturn 1;\n\t}\n\n\tconf_message(\"configuration written to %s\", name);\n\n\tsym_set_change_count(0);\n\n\treturn 0;\n}\n\n/* write a dependency file as used by kbuild to track dependencies */\nstatic int conf_write_dep(const char *name)\n{\n\tstruct file *file;\n\tFILE *out;\n\n\tout = fopen(\"..config.tmp\", \"w\");\n\tif (!out)\n\t\treturn 1;\n\tfprintf(out, \"deps_config := \\\\\\n\");\n\tfor (file = file_list; file; file = file->next) {\n\t\tif (file->next)\n\t\t\tfprintf(out, \"\\t%s \\\\\\n\", file->name);\n\t\telse\n\t\t\tfprintf(out, \"\\t%s\\n\", file->name);\n\t}\n\tfprintf(out, \"\\n%s: \\\\\\n\"\n\t\t     \"\\t$(deps_config)\\n\\n\", conf_get_autoconfig_name());\n\n\tenv_write_dep(out, conf_get_autoconfig_name());\n\n\tfprintf(out, \"\\n$(deps_config): ;\\n\");\n\tfclose(out);\n\n\tif (make_parent_dir(name))\n\t\treturn 1;\n\trename(\"..config.tmp\", name);\n\treturn 0;\n}\n\nstatic int conf_touch_deps(void)\n{\n\tconst char *name;\n\tstruct symbol *sym;\n\tint res, i;\n\tchar *s;\n\n\tstrcpy(depfile_path, conf_get_autoconfig_name());\n\tif ((s = strrchr(depfile_path, '/')))\n\t\t*s = '\\0';\n\tdepfile_prefix_len = strlen(depfile_path);\n\n\tname = conf_get_autoconfig_name();\n\tconf_read_simple(name, S_DEF_AUTO);\n\tsym_calc_value(modules_sym);\n\n\tfor_all_symbols(i, sym) {\n\t\tsym_calc_value(sym);\n\t\tif ((sym->flags & SYMBOL_NO_WRITE) || !sym->name)\n\t\t\tcontinue;\n\t\tif (sym->flags & SYMBOL_WRITE) {\n\t\t\tif (sym->flags & SYMBOL_DEF_AUTO) {\n\t\t\t\t/*\n\t\t\t\t * symbol has old and new value,\n\t\t\t\t * so compare them...\n\t\t\t\t */\n\t\t\t\tswitch (sym->type) {\n\t\t\t\tcase S_BOOLEAN:\n\t\t\t\tcase S_TRISTATE:\n\t\t\t\t\tif (sym_get_tristate_value(sym) ==\n\t\t\t\t\t    sym->def[S_DEF_AUTO].tri)\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\tbreak;\n\t\t\t\tcase S_STRING:\n\t\t\t\tcase S_HEX:\n\t\t\t\tcase S_INT:\n\t\t\t\t\tif (!strcmp(sym_get_string_value(sym),\n\t\t\t\t\t\t    sym->def[S_DEF_AUTO].val))\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t/*\n\t\t\t\t * If there is no old value, only 'no' (unset)\n\t\t\t\t * is allowed as new value.\n\t\t\t\t */\n\t\t\t\tswitch (sym->type) {\n\t\t\t\tcase S_BOOLEAN:\n\t\t\t\tcase S_TRISTATE:\n\t\t\t\t\tif (sym_get_tristate_value(sym) == no)\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (!(sym->flags & SYMBOL_DEF_AUTO))\n\t\t\t/* There is neither an old nor a new value. */\n\t\t\tcontinue;\n\t\t/* else\n\t\t *\tThere is an old value, but no new value ('no' (unset)\n\t\t *\tisn't saved in auto.conf, so the old value is always\n\t\t *\tdifferent from 'no').\n\t\t */\n\n\t\tres = conf_touch_dep(sym->name);\n\t\tif (res)\n\t\t\treturn res;\n\t}\n\n\treturn 0;\n}\n\nint conf_write_autoconf(int overwrite)\n{\n\tstruct symbol *sym;\n\tconst char *name;\n\tconst char *autoconf_name = conf_get_autoconfig_name();\n\tchar path[PATH_MAX];\n\tFILE *out, *out_h;\n\tint i;\n\n\tif (!overwrite && is_present(autoconf_name))\n\t\treturn 0;\n\n\tsnprintf(path, sizeof(path), \"%s.cmd\", autoconf_name);\n\tconf_write_dep(path);\n\n\tif (conf_touch_deps())\n\t\treturn 1;\n\n\tout = fopen(\".tmpconfig\", \"w\");\n\tif (!out)\n\t\treturn 1;\n\n\tout_h = fopen(\".tmpconfig.h\", \"w\");\n\tif (!out_h) {\n\t\tfclose(out);\n\t\treturn 1;\n\t}\n\n\tconf_write_heading(out, &kconfig_printer_cb, NULL);\n\tconf_write_heading(out_h, &header_printer_cb, NULL);\n\n\tfor_all_symbols(i, sym) {\n\t\tsym_calc_value(sym);\n\t\tif (!(sym->flags & SYMBOL_WRITE) || !sym->name)\n\t\t\tcontinue;\n\n\t\t/* write symbols to auto.conf and autoconf.h */\n\t\tconf_write_symbol(out, sym, &kconfig_printer_cb, (void *)1);\n\t\tconf_write_symbol(out_h, sym, &header_printer_cb, NULL);\n\t}\n\tfclose(out);\n\tfclose(out_h);\n\n\tname = getenv(\"KCONFIG_AUTOHEADER\");\n\tif (!name)\n\t\tname = \"include/generated/autoconf.h\";\n\tif (make_parent_dir(name))\n\t\treturn 1;\n\tif (rename(\".tmpconfig.h\", name))\n\t\treturn 1;\n\n\tif (make_parent_dir(autoconf_name))\n\t\treturn 1;\n\t/*\n\t * This must be the last step, kbuild has a dependency on auto.conf\n\t * and this marks the successful completion of the previous steps.\n\t */\n\tif (rename(\".tmpconfig\", autoconf_name))\n\t\treturn 1;\n\n\treturn 0;\n}\n\nstatic int sym_change_count;\nstatic void (*conf_changed_callback)(void);\n\nvoid sym_set_change_count(int count)\n{\n\tint _sym_change_count = sym_change_count;\n\tsym_change_count = count;\n\tif (conf_changed_callback &&\n\t    (bool)_sym_change_count != (bool)count)\n\t\tconf_changed_callback();\n}\n\nvoid sym_add_change_count(int count)\n{\n\tsym_set_change_count(count + sym_change_count);\n}\n\nbool conf_get_changed(void)\n{\n\treturn sym_change_count;\n}\n\nvoid conf_set_changed_callback(void (*fn)(void))\n{\n\tconf_changed_callback = fn;\n}\n\nstatic bool randomize_choice_values(struct symbol *csym)\n{\n\tstruct property *prop;\n\tstruct symbol *sym;\n\tstruct expr *e;\n\tint cnt, def;\n\n\t/*\n\t * If choice is mod then we may have more items selected\n\t * and if no then no-one.\n\t * In both cases stop.\n\t */\n\tif (csym->curr.tri != yes)\n\t\treturn false;\n\n\tprop = sym_get_choice_prop(csym);\n\n\t/* count entries in choice block */\n\tcnt = 0;\n\texpr_list_for_each_sym(prop->expr, e, sym)\n\t\tcnt++;\n\n\t/*\n\t * find a random value and set it to yes,\n\t * set the rest to no so we have only one set\n\t */\n\tdef = (rand() % cnt);\n\n\tcnt = 0;\n\texpr_list_for_each_sym(prop->expr, e, sym) {\n\t\tif (def == cnt++) {\n\t\t\tsym->def[S_DEF_USER].tri = yes;\n\t\t\tcsym->def[S_DEF_USER].val = sym;\n\t\t}\n\t\telse {\n\t\t\tsym->def[S_DEF_USER].tri = no;\n\t\t}\n\t\tsym->flags |= SYMBOL_DEF_USER;\n\t\t/* clear VALID to get value calculated */\n\t\tsym->flags &= ~SYMBOL_VALID;\n\t}\n\tcsym->flags |= SYMBOL_DEF_USER;\n\t/* clear VALID to get value calculated */\n\tcsym->flags &= ~(SYMBOL_VALID);\n\n\treturn true;\n}\n\nvoid set_all_choice_values(struct symbol *csym)\n{\n\tstruct property *prop;\n\tstruct symbol *sym;\n\tstruct expr *e;\n\n\tprop = sym_get_choice_prop(csym);\n\n\t/*\n\t * Set all non-assinged choice values to no\n\t */\n\texpr_list_for_each_sym(prop->expr, e, sym) {\n\t\tif (!sym_has_value(sym))\n\t\t\tsym->def[S_DEF_USER].tri = no;\n\t}\n\tcsym->flags |= SYMBOL_DEF_USER;\n\t/* clear VALID to get value calculated */\n\tcsym->flags &= ~(SYMBOL_VALID | SYMBOL_NEED_SET_CHOICE_VALUES);\n}\n\nbool conf_set_all_new_symbols(enum conf_def_mode mode)\n{\n\tstruct symbol *sym, *csym;\n\tint i, cnt, pby, pty, ptm;\t/* pby: probability of bool     = y\n\t\t\t\t\t * pty: probability of tristate = y\n\t\t\t\t\t * ptm: probability of tristate = m\n\t\t\t\t\t */\n\n\tpby = 50; pty = ptm = 33; /* can't go as the default in switch-case\n\t\t\t\t   * below, otherwise gcc whines about\n\t\t\t\t   * -Wmaybe-uninitialized */\n\tif (mode == def_random) {\n\t\tint n, p[3];\n\t\tchar *env = getenv(\"KCONFIG_PROBABILITY\");\n\t\tn = 0;\n\t\twhile( env && *env ) {\n\t\t\tchar *endp;\n\t\t\tint tmp = strtol( env, &endp, 10 );\n\t\t\tif( tmp >= 0 && tmp <= 100 ) {\n\t\t\t\tp[n++] = tmp;\n\t\t\t} else {\n\t\t\t\terrno = ERANGE;\n\t\t\t\tperror( \"KCONFIG_PROBABILITY\" );\n\t\t\t\texit( 1 );\n\t\t\t}\n\t\t\tenv = (*endp == ':') ? endp+1 : endp;\n\t\t\tif( n >=3 ) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tswitch( n ) {\n\t\tcase 1:\n\t\t\tpby = p[0]; ptm = pby/2; pty = pby-ptm;\n\t\t\tbreak;\n\t\tcase 2:\n\t\t\tpty = p[0]; ptm = p[1]; pby = pty + ptm;\n\t\t\tbreak;\n\t\tcase 3:\n\t\t\tpby = p[0]; pty = p[1]; ptm = p[2];\n\t\t\tbreak;\n\t\t}\n\n\t\tif( pty+ptm > 100 ) {\n\t\t\terrno = ERANGE;\n\t\t\tperror( \"KCONFIG_PROBABILITY\" );\n\t\t\texit( 1 );\n\t\t}\n\t}\n\tbool has_changed = false;\n\n\tfor_all_symbols(i, sym) {\n\t\tif (sym_has_value(sym) || (sym->flags & SYMBOL_VALID))\n\t\t\tcontinue;\n\t\tswitch (sym_get_type(sym)) {\n\t\tcase S_BOOLEAN:\n\t\tcase S_TRISTATE:\n\t\t\thas_changed = true;\n\t\t\tswitch (mode) {\n\t\t\tcase def_yes:\n\t\t\t\tsym->def[S_DEF_USER].tri = yes;\n\t\t\t\tbreak;\n\t\t\tcase def_mod:\n\t\t\t\tsym->def[S_DEF_USER].tri = mod;\n\t\t\t\tbreak;\n\t\t\tcase def_no:\n\t\t\t\tif (sym->flags & SYMBOL_ALLNOCONFIG_Y)\n\t\t\t\t\tsym->def[S_DEF_USER].tri = yes;\n\t\t\t\telse\n\t\t\t\t\tsym->def[S_DEF_USER].tri = no;\n\t\t\t\tbreak;\n\t\t\tcase def_random:\n\t\t\t\tsym->def[S_DEF_USER].tri = no;\n\t\t\t\tcnt = rand() % 100;\n\t\t\t\tif (sym->type == S_TRISTATE) {\n\t\t\t\t\tif (cnt < pty)\n\t\t\t\t\t\tsym->def[S_DEF_USER].tri = yes;\n\t\t\t\t\telse if (cnt < (pty+ptm))\n\t\t\t\t\t\tsym->def[S_DEF_USER].tri = mod;\n\t\t\t\t} else if (cnt < pby)\n\t\t\t\t\tsym->def[S_DEF_USER].tri = yes;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (!(sym_is_choice(sym) && mode == def_random))\n\t\t\t\tsym->flags |= SYMBOL_DEF_USER;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\n\t}\n\n\tsym_clear_all_valid();\n\n\t/*\n\t * We have different type of choice blocks.\n\t * If curr.tri equals to mod then we can select several\n\t * choice symbols in one block.\n\t * In this case we do nothing.\n\t * If curr.tri equals yes then only one symbol can be\n\t * selected in a choice block and we set it to yes,\n\t * and the rest to no.\n\t */\n\tif (mode != def_random) {\n\t\tfor_all_symbols(i, csym) {\n\t\t\tif ((sym_is_choice(csym) && !sym_has_value(csym)) ||\n\t\t\t    sym_is_choice_value(csym))\n\t\t\t\tcsym->flags |= SYMBOL_NEED_SET_CHOICE_VALUES;\n\t\t}\n\t}\n\n\tfor_all_symbols(i, csym) {\n\t\tif (sym_has_value(csym) || !sym_is_choice(csym))\n\t\t\tcontinue;\n\n\t\tsym_calc_value(csym);\n\t\tif (mode == def_random)\n\t\t\thas_changed |= randomize_choice_values(csym);\n\t\telse {\n\t\t\tset_all_choice_values(csym);\n\t\t\thas_changed = true;\n\t\t}\n\t}\n\n\treturn has_changed;\n}\n\nvoid conf_rewrite_mod_or_yes(enum conf_def_mode mode)\n{\n\tstruct symbol *sym;\n\tint i;\n\ttristate old_val = (mode == def_y2m) ? yes : mod;\n\ttristate new_val = (mode == def_y2m) ? mod : yes;\n\n\tfor_all_symbols(i, sym) {\n\t\tif (sym_get_type(sym) == S_TRISTATE &&\n\t\t    sym->def[S_DEF_USER].tri == old_val)\n\t\t\tsym->def[S_DEF_USER].tri = new_val;\n\t}\n\tsym_clear_all_valid();\n}\n"
  },
  {
    "path": "3rdparty/kconfig/expr.c",
    "content": "// SPDX-License-Identifier: GPL-2.0\n/*\n * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>\n */\n\n#include <ctype.h>\n#include <errno.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include \"lkc.h\"\n\n#define DEBUG_EXPR\t0\n\nstatic struct expr *expr_eliminate_yn(struct expr *e);\n\nstruct expr *expr_alloc_symbol(struct symbol *sym)\n{\n\tstruct expr *e = xcalloc(1, sizeof(*e));\n\te->type = E_SYMBOL;\n\te->left.sym = sym;\n\treturn e;\n}\n\nstruct expr *expr_alloc_one(enum expr_type type, struct expr *ce)\n{\n\tstruct expr *e = xcalloc(1, sizeof(*e));\n\te->type = type;\n\te->left.expr = ce;\n\treturn e;\n}\n\nstruct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e2)\n{\n\tstruct expr *e = xcalloc(1, sizeof(*e));\n\te->type = type;\n\te->left.expr = e1;\n\te->right.expr = e2;\n\treturn e;\n}\n\nstruct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2)\n{\n\tstruct expr *e = xcalloc(1, sizeof(*e));\n\te->type = type;\n\te->left.sym = s1;\n\te->right.sym = s2;\n\treturn e;\n}\n\nstruct expr *expr_alloc_and(struct expr *e1, struct expr *e2)\n{\n\tif (!e1)\n\t\treturn e2;\n\treturn e2 ? expr_alloc_two(E_AND, e1, e2) : e1;\n}\n\nstruct expr *expr_alloc_or(struct expr *e1, struct expr *e2)\n{\n\tif (!e1)\n\t\treturn e2;\n\treturn e2 ? expr_alloc_two(E_OR, e1, e2) : e1;\n}\n\nstruct expr *expr_copy(const struct expr *org)\n{\n\tstruct expr *e;\n\n\tif (!org)\n\t\treturn NULL;\n\n\te = xmalloc(sizeof(*org));\n\tmemcpy(e, org, sizeof(*org));\n\tswitch (org->type) {\n\tcase E_SYMBOL:\n\t\te->left = org->left;\n\t\tbreak;\n\tcase E_NOT:\n\t\te->left.expr = expr_copy(org->left.expr);\n\t\tbreak;\n\tcase E_EQUAL:\n\tcase E_GEQ:\n\tcase E_GTH:\n\tcase E_LEQ:\n\tcase E_LTH:\n\tcase E_UNEQUAL:\n\t\te->left.sym = org->left.sym;\n\t\te->right.sym = org->right.sym;\n\t\tbreak;\n\tcase E_AND:\n\tcase E_OR:\n\tcase E_LIST:\n\t\te->left.expr = expr_copy(org->left.expr);\n\t\te->right.expr = expr_copy(org->right.expr);\n\t\tbreak;\n\tdefault:\n\t\tfprintf(stderr, \"can't copy type %d\\n\", e->type);\n\t\tfree(e);\n\t\te = NULL;\n\t\tbreak;\n\t}\n\n\treturn e;\n}\n\nvoid expr_free(struct expr *e)\n{\n\tif (!e)\n\t\treturn;\n\n\tswitch (e->type) {\n\tcase E_SYMBOL:\n\t\tbreak;\n\tcase E_NOT:\n\t\texpr_free(e->left.expr);\n\t\tbreak;\n\tcase E_EQUAL:\n\tcase E_GEQ:\n\tcase E_GTH:\n\tcase E_LEQ:\n\tcase E_LTH:\n\tcase E_UNEQUAL:\n\t\tbreak;\n\tcase E_OR:\n\tcase E_AND:\n\t\texpr_free(e->left.expr);\n\t\texpr_free(e->right.expr);\n\t\tbreak;\n\tdefault:\n\t\tfprintf(stderr, \"how to free type %d?\\n\", e->type);\n\t\tbreak;\n\t}\n\tfree(e);\n}\n\nstatic int trans_count;\n\n#define e1 (*ep1)\n#define e2 (*ep2)\n\n/*\n * expr_eliminate_eq() helper.\n *\n * Walks the two expression trees given in 'ep1' and 'ep2'. Any node that does\n * not have type 'type' (E_OR/E_AND) is considered a leaf, and is compared\n * against all other leaves. Two equal leaves are both replaced with either 'y'\n * or 'n' as appropriate for 'type', to be eliminated later.\n */\nstatic void __expr_eliminate_eq(enum expr_type type, struct expr **ep1, struct expr **ep2)\n{\n\t/* Recurse down to leaves */\n\n\tif (e1->type == type) {\n\t\t__expr_eliminate_eq(type, &e1->left.expr, &e2);\n\t\t__expr_eliminate_eq(type, &e1->right.expr, &e2);\n\t\treturn;\n\t}\n\tif (e2->type == type) {\n\t\t__expr_eliminate_eq(type, &e1, &e2->left.expr);\n\t\t__expr_eliminate_eq(type, &e1, &e2->right.expr);\n\t\treturn;\n\t}\n\n\t/* e1 and e2 are leaves. Compare them. */\n\n\tif (e1->type == E_SYMBOL && e2->type == E_SYMBOL &&\n\t    e1->left.sym == e2->left.sym &&\n\t    (e1->left.sym == &symbol_yes || e1->left.sym == &symbol_no))\n\t\treturn;\n\tif (!expr_eq(e1, e2))\n\t\treturn;\n\n\t/* e1 and e2 are equal leaves. Prepare them for elimination. */\n\n\ttrans_count++;\n\texpr_free(e1); expr_free(e2);\n\tswitch (type) {\n\tcase E_OR:\n\t\te1 = expr_alloc_symbol(&symbol_no);\n\t\te2 = expr_alloc_symbol(&symbol_no);\n\t\tbreak;\n\tcase E_AND:\n\t\te1 = expr_alloc_symbol(&symbol_yes);\n\t\te2 = expr_alloc_symbol(&symbol_yes);\n\t\tbreak;\n\tdefault:\n\t\t;\n\t}\n}\n\n/*\n * Rewrites the expressions 'ep1' and 'ep2' to remove operands common to both.\n * Example reductions:\n *\n *\tep1: A && B           ->  ep1: y\n *\tep2: A && B && C      ->  ep2: C\n *\n *\tep1: A || B           ->  ep1: n\n *\tep2: A || B || C      ->  ep2: C\n *\n *\tep1: A && (B && FOO)  ->  ep1: FOO\n *\tep2: (BAR && B) && A  ->  ep2: BAR\n *\n *\tep1: A && (B || C)    ->  ep1: y\n *\tep2: (C || B) && A    ->  ep2: y\n *\n * Comparisons are done between all operands at the same \"level\" of && or ||.\n * For example, in the expression 'e1 && (e2 || e3) && (e4 || e5)', the\n * following operands will be compared:\n *\n *\t- 'e1', 'e2 || e3', and 'e4 || e5', against each other\n *\t- e2 against e3\n *\t- e4 against e5\n *\n * Parentheses are irrelevant within a single level. 'e1 && (e2 && e3)' and\n * '(e1 && e2) && e3' are both a single level.\n *\n * See __expr_eliminate_eq() as well.\n */\nvoid expr_eliminate_eq(struct expr **ep1, struct expr **ep2)\n{\n\tif (!e1 || !e2)\n\t\treturn;\n\tswitch (e1->type) {\n\tcase E_OR:\n\tcase E_AND:\n\t\t__expr_eliminate_eq(e1->type, ep1, ep2);\n\tdefault:\n\t\t;\n\t}\n\tif (e1->type != e2->type) switch (e2->type) {\n\tcase E_OR:\n\tcase E_AND:\n\t\t__expr_eliminate_eq(e2->type, ep1, ep2);\n\tdefault:\n\t\t;\n\t}\n\te1 = expr_eliminate_yn(e1);\n\te2 = expr_eliminate_yn(e2);\n}\n\n#undef e1\n#undef e2\n\n/*\n * Returns true if 'e1' and 'e2' are equal, after minor simplification. Two\n * &&/|| expressions are considered equal if every operand in one expression\n * equals some operand in the other (operands do not need to appear in the same\n * order), recursively.\n */\nint expr_eq(struct expr *e1, struct expr *e2)\n{\n\tint res, old_count;\n\n\t/*\n\t * A NULL expr is taken to be yes, but there's also a different way to\n\t * represent yes. expr_is_yes() checks for either representation.\n\t */\n\tif (!e1 || !e2)\n\t\treturn expr_is_yes(e1) && expr_is_yes(e2);\n\n\tif (e1->type != e2->type)\n\t\treturn 0;\n\tswitch (e1->type) {\n\tcase E_EQUAL:\n\tcase E_GEQ:\n\tcase E_GTH:\n\tcase E_LEQ:\n\tcase E_LTH:\n\tcase E_UNEQUAL:\n\t\treturn e1->left.sym == e2->left.sym && e1->right.sym == e2->right.sym;\n\tcase E_SYMBOL:\n\t\treturn e1->left.sym == e2->left.sym;\n\tcase E_NOT:\n\t\treturn expr_eq(e1->left.expr, e2->left.expr);\n\tcase E_AND:\n\tcase E_OR:\n\t\te1 = expr_copy(e1);\n\t\te2 = expr_copy(e2);\n\t\told_count = trans_count;\n\t\texpr_eliminate_eq(&e1, &e2);\n\t\tres = (e1->type == E_SYMBOL && e2->type == E_SYMBOL &&\n\t\t       e1->left.sym == e2->left.sym);\n\t\texpr_free(e1);\n\t\texpr_free(e2);\n\t\ttrans_count = old_count;\n\t\treturn res;\n\tcase E_LIST:\n\tcase E_RANGE:\n\tcase E_NONE:\n\t\t/* panic */;\n\t}\n\n\tif (DEBUG_EXPR) {\n\t\texpr_fprint(e1, stdout);\n\t\tprintf(\" = \");\n\t\texpr_fprint(e2, stdout);\n\t\tprintf(\" ?\\n\");\n\t}\n\n\treturn 0;\n}\n\n/*\n * Recursively performs the following simplifications in-place (as well as the\n * corresponding simplifications with swapped operands):\n *\n *\texpr && n  ->  n\n *\texpr && y  ->  expr\n *\texpr || n  ->  expr\n *\texpr || y  ->  y\n *\n * Returns the optimized expression.\n */\nstatic struct expr *expr_eliminate_yn(struct expr *e)\n{\n\tstruct expr *tmp;\n\n\tif (e) switch (e->type) {\n\tcase E_AND:\n\t\te->left.expr = expr_eliminate_yn(e->left.expr);\n\t\te->right.expr = expr_eliminate_yn(e->right.expr);\n\t\tif (e->left.expr->type == E_SYMBOL) {\n\t\t\tif (e->left.expr->left.sym == &symbol_no) {\n\t\t\t\texpr_free(e->left.expr);\n\t\t\t\texpr_free(e->right.expr);\n\t\t\t\te->type = E_SYMBOL;\n\t\t\t\te->left.sym = &symbol_no;\n\t\t\t\te->right.expr = NULL;\n\t\t\t\treturn e;\n\t\t\t} else if (e->left.expr->left.sym == &symbol_yes) {\n\t\t\t\tfree(e->left.expr);\n\t\t\t\ttmp = e->right.expr;\n\t\t\t\t*e = *(e->right.expr);\n\t\t\t\tfree(tmp);\n\t\t\t\treturn e;\n\t\t\t}\n\t\t}\n\t\tif (e->right.expr->type == E_SYMBOL) {\n\t\t\tif (e->right.expr->left.sym == &symbol_no) {\n\t\t\t\texpr_free(e->left.expr);\n\t\t\t\texpr_free(e->right.expr);\n\t\t\t\te->type = E_SYMBOL;\n\t\t\t\te->left.sym = &symbol_no;\n\t\t\t\te->right.expr = NULL;\n\t\t\t\treturn e;\n\t\t\t} else if (e->right.expr->left.sym == &symbol_yes) {\n\t\t\t\tfree(e->right.expr);\n\t\t\t\ttmp = e->left.expr;\n\t\t\t\t*e = *(e->left.expr);\n\t\t\t\tfree(tmp);\n\t\t\t\treturn e;\n\t\t\t}\n\t\t}\n\t\tbreak;\n\tcase E_OR:\n\t\te->left.expr = expr_eliminate_yn(e->left.expr);\n\t\te->right.expr = expr_eliminate_yn(e->right.expr);\n\t\tif (e->left.expr->type == E_SYMBOL) {\n\t\t\tif (e->left.expr->left.sym == &symbol_no) {\n\t\t\t\tfree(e->left.expr);\n\t\t\t\ttmp = e->right.expr;\n\t\t\t\t*e = *(e->right.expr);\n\t\t\t\tfree(tmp);\n\t\t\t\treturn e;\n\t\t\t} else if (e->left.expr->left.sym == &symbol_yes) {\n\t\t\t\texpr_free(e->left.expr);\n\t\t\t\texpr_free(e->right.expr);\n\t\t\t\te->type = E_SYMBOL;\n\t\t\t\te->left.sym = &symbol_yes;\n\t\t\t\te->right.expr = NULL;\n\t\t\t\treturn e;\n\t\t\t}\n\t\t}\n\t\tif (e->right.expr->type == E_SYMBOL) {\n\t\t\tif (e->right.expr->left.sym == &symbol_no) {\n\t\t\t\tfree(e->right.expr);\n\t\t\t\ttmp = e->left.expr;\n\t\t\t\t*e = *(e->left.expr);\n\t\t\t\tfree(tmp);\n\t\t\t\treturn e;\n\t\t\t} else if (e->right.expr->left.sym == &symbol_yes) {\n\t\t\t\texpr_free(e->left.expr);\n\t\t\t\texpr_free(e->right.expr);\n\t\t\t\te->type = E_SYMBOL;\n\t\t\t\te->left.sym = &symbol_yes;\n\t\t\t\te->right.expr = NULL;\n\t\t\t\treturn e;\n\t\t\t}\n\t\t}\n\t\tbreak;\n\tdefault:\n\t\t;\n\t}\n\treturn e;\n}\n\n/*\n * bool FOO!=n => FOO\n */\nstruct expr *expr_trans_bool(struct expr *e)\n{\n\tif (!e)\n\t\treturn NULL;\n\tswitch (e->type) {\n\tcase E_AND:\n\tcase E_OR:\n\tcase E_NOT:\n\t\te->left.expr = expr_trans_bool(e->left.expr);\n\t\te->right.expr = expr_trans_bool(e->right.expr);\n\t\tbreak;\n\tcase E_UNEQUAL:\n\t\t// FOO!=n -> FOO\n\t\tif (e->left.sym->type == S_TRISTATE) {\n\t\t\tif (e->right.sym == &symbol_no) {\n\t\t\t\te->type = E_SYMBOL;\n\t\t\t\te->right.sym = NULL;\n\t\t\t}\n\t\t}\n\t\tbreak;\n\tdefault:\n\t\t;\n\t}\n\treturn e;\n}\n\n/*\n * e1 || e2 -> ?\n */\nstatic struct expr *expr_join_or(struct expr *e1, struct expr *e2)\n{\n\tstruct expr *tmp;\n\tstruct symbol *sym1, *sym2;\n\n\tif (expr_eq(e1, e2))\n\t\treturn expr_copy(e1);\n\tif (e1->type != E_EQUAL && e1->type != E_UNEQUAL && e1->type != E_SYMBOL && e1->type != E_NOT)\n\t\treturn NULL;\n\tif (e2->type != E_EQUAL && e2->type != E_UNEQUAL && e2->type != E_SYMBOL && e2->type != E_NOT)\n\t\treturn NULL;\n\tif (e1->type == E_NOT) {\n\t\ttmp = e1->left.expr;\n\t\tif (tmp->type != E_EQUAL && tmp->type != E_UNEQUAL && tmp->type != E_SYMBOL)\n\t\t\treturn NULL;\n\t\tsym1 = tmp->left.sym;\n\t} else\n\t\tsym1 = e1->left.sym;\n\tif (e2->type == E_NOT) {\n\t\tif (e2->left.expr->type != E_SYMBOL)\n\t\t\treturn NULL;\n\t\tsym2 = e2->left.expr->left.sym;\n\t} else\n\t\tsym2 = e2->left.sym;\n\tif (sym1 != sym2)\n\t\treturn NULL;\n\tif (sym1->type != S_BOOLEAN && sym1->type != S_TRISTATE)\n\t\treturn NULL;\n\tif (sym1->type == S_TRISTATE) {\n\t\tif (e1->type == E_EQUAL && e2->type == E_EQUAL &&\n\t\t    ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_mod) ||\n\t\t     (e1->right.sym == &symbol_mod && e2->right.sym == &symbol_yes))) {\n\t\t\t// (a='y') || (a='m') -> (a!='n')\n\t\t\treturn expr_alloc_comp(E_UNEQUAL, sym1, &symbol_no);\n\t\t}\n\t\tif (e1->type == E_EQUAL && e2->type == E_EQUAL &&\n\t\t    ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_no) ||\n\t\t     (e1->right.sym == &symbol_no && e2->right.sym == &symbol_yes))) {\n\t\t\t// (a='y') || (a='n') -> (a!='m')\n\t\t\treturn expr_alloc_comp(E_UNEQUAL, sym1, &symbol_mod);\n\t\t}\n\t\tif (e1->type == E_EQUAL && e2->type == E_EQUAL &&\n\t\t    ((e1->right.sym == &symbol_mod && e2->right.sym == &symbol_no) ||\n\t\t     (e1->right.sym == &symbol_no && e2->right.sym == &symbol_mod))) {\n\t\t\t// (a='m') || (a='n') -> (a!='y')\n\t\t\treturn expr_alloc_comp(E_UNEQUAL, sym1, &symbol_yes);\n\t\t}\n\t}\n\tif (sym1->type == S_BOOLEAN && sym1 == sym2) {\n\t\tif ((e1->type == E_NOT && e1->left.expr->type == E_SYMBOL && e2->type == E_SYMBOL) ||\n\t\t    (e2->type == E_NOT && e2->left.expr->type == E_SYMBOL && e1->type == E_SYMBOL))\n\t\t\treturn expr_alloc_symbol(&symbol_yes);\n\t}\n\n\tif (DEBUG_EXPR) {\n\t\tprintf(\"optimize (\");\n\t\texpr_fprint(e1, stdout);\n\t\tprintf(\") || (\");\n\t\texpr_fprint(e2, stdout);\n\t\tprintf(\")?\\n\");\n\t}\n\treturn NULL;\n}\n\nstatic struct expr *expr_join_and(struct expr *e1, struct expr *e2)\n{\n\tstruct expr *tmp;\n\tstruct symbol *sym1, *sym2;\n\n\tif (expr_eq(e1, e2))\n\t\treturn expr_copy(e1);\n\tif (e1->type != E_EQUAL && e1->type != E_UNEQUAL && e1->type != E_SYMBOL && e1->type != E_NOT)\n\t\treturn NULL;\n\tif (e2->type != E_EQUAL && e2->type != E_UNEQUAL && e2->type != E_SYMBOL && e2->type != E_NOT)\n\t\treturn NULL;\n\tif (e1->type == E_NOT) {\n\t\ttmp = e1->left.expr;\n\t\tif (tmp->type != E_EQUAL && tmp->type != E_UNEQUAL && tmp->type != E_SYMBOL)\n\t\t\treturn NULL;\n\t\tsym1 = tmp->left.sym;\n\t} else\n\t\tsym1 = e1->left.sym;\n\tif (e2->type == E_NOT) {\n\t\tif (e2->left.expr->type != E_SYMBOL)\n\t\t\treturn NULL;\n\t\tsym2 = e2->left.expr->left.sym;\n\t} else\n\t\tsym2 = e2->left.sym;\n\tif (sym1 != sym2)\n\t\treturn NULL;\n\tif (sym1->type != S_BOOLEAN && sym1->type != S_TRISTATE)\n\t\treturn NULL;\n\n\tif ((e1->type == E_SYMBOL && e2->type == E_EQUAL && e2->right.sym == &symbol_yes) ||\n\t    (e2->type == E_SYMBOL && e1->type == E_EQUAL && e1->right.sym == &symbol_yes))\n\t\t// (a) && (a='y') -> (a='y')\n\t\treturn expr_alloc_comp(E_EQUAL, sym1, &symbol_yes);\n\n\tif ((e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_no) ||\n\t    (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_no))\n\t\t// (a) && (a!='n') -> (a)\n\t\treturn expr_alloc_symbol(sym1);\n\n\tif ((e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_mod) ||\n\t    (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_mod))\n\t\t// (a) && (a!='m') -> (a='y')\n\t\treturn expr_alloc_comp(E_EQUAL, sym1, &symbol_yes);\n\n\tif (sym1->type == S_TRISTATE) {\n\t\tif (e1->type == E_EQUAL && e2->type == E_UNEQUAL) {\n\t\t\t// (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b'\n\t\t\tsym2 = e1->right.sym;\n\t\t\tif ((e2->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST))\n\t\t\t\treturn sym2 != e2->right.sym ? expr_alloc_comp(E_EQUAL, sym1, sym2)\n\t\t\t\t\t\t\t     : expr_alloc_symbol(&symbol_no);\n\t\t}\n\t\tif (e1->type == E_UNEQUAL && e2->type == E_EQUAL) {\n\t\t\t// (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b'\n\t\t\tsym2 = e2->right.sym;\n\t\t\tif ((e1->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST))\n\t\t\t\treturn sym2 != e1->right.sym ? expr_alloc_comp(E_EQUAL, sym1, sym2)\n\t\t\t\t\t\t\t     : expr_alloc_symbol(&symbol_no);\n\t\t}\n\t\tif (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL &&\n\t\t\t   ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_no) ||\n\t\t\t    (e1->right.sym == &symbol_no && e2->right.sym == &symbol_yes)))\n\t\t\t// (a!='y') && (a!='n') -> (a='m')\n\t\t\treturn expr_alloc_comp(E_EQUAL, sym1, &symbol_mod);\n\n\t\tif (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL &&\n\t\t\t   ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_mod) ||\n\t\t\t    (e1->right.sym == &symbol_mod && e2->right.sym == &symbol_yes)))\n\t\t\t// (a!='y') && (a!='m') -> (a='n')\n\t\t\treturn expr_alloc_comp(E_EQUAL, sym1, &symbol_no);\n\n\t\tif (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL &&\n\t\t\t   ((e1->right.sym == &symbol_mod && e2->right.sym == &symbol_no) ||\n\t\t\t    (e1->right.sym == &symbol_no && e2->right.sym == &symbol_mod)))\n\t\t\t// (a!='m') && (a!='n') -> (a='m')\n\t\t\treturn expr_alloc_comp(E_EQUAL, sym1, &symbol_yes);\n\n\t\tif ((e1->type == E_SYMBOL && e2->type == E_EQUAL && e2->right.sym == &symbol_mod) ||\n\t\t    (e2->type == E_SYMBOL && e1->type == E_EQUAL && e1->right.sym == &symbol_mod) ||\n\t\t    (e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_yes) ||\n\t\t    (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_yes))\n\t\t\treturn NULL;\n\t}\n\n\tif (DEBUG_EXPR) {\n\t\tprintf(\"optimize (\");\n\t\texpr_fprint(e1, stdout);\n\t\tprintf(\") && (\");\n\t\texpr_fprint(e2, stdout);\n\t\tprintf(\")?\\n\");\n\t}\n\treturn NULL;\n}\n\n/*\n * expr_eliminate_dups() helper.\n *\n * Walks the two expression trees given in 'ep1' and 'ep2'. Any node that does\n * not have type 'type' (E_OR/E_AND) is considered a leaf, and is compared\n * against all other leaves to look for simplifications.\n */\nstatic void expr_eliminate_dups1(enum expr_type type, struct expr **ep1, struct expr **ep2)\n{\n#define e1 (*ep1)\n#define e2 (*ep2)\n\tstruct expr *tmp;\n\n\t/* Recurse down to leaves */\n\n\tif (e1->type == type) {\n\t\texpr_eliminate_dups1(type, &e1->left.expr, &e2);\n\t\texpr_eliminate_dups1(type, &e1->right.expr, &e2);\n\t\treturn;\n\t}\n\tif (e2->type == type) {\n\t\texpr_eliminate_dups1(type, &e1, &e2->left.expr);\n\t\texpr_eliminate_dups1(type, &e1, &e2->right.expr);\n\t\treturn;\n\t}\n\n\t/* e1 and e2 are leaves. Compare and process them. */\n\n\tif (e1 == e2)\n\t\treturn;\n\n\tswitch (e1->type) {\n\tcase E_OR: case E_AND:\n\t\texpr_eliminate_dups1(e1->type, &e1, &e1);\n\tdefault:\n\t\t;\n\t}\n\n\tswitch (type) {\n\tcase E_OR:\n\t\ttmp = expr_join_or(e1, e2);\n\t\tif (tmp) {\n\t\t\texpr_free(e1); expr_free(e2);\n\t\t\te1 = expr_alloc_symbol(&symbol_no);\n\t\t\te2 = tmp;\n\t\t\ttrans_count++;\n\t\t}\n\t\tbreak;\n\tcase E_AND:\n\t\ttmp = expr_join_and(e1, e2);\n\t\tif (tmp) {\n\t\t\texpr_free(e1); expr_free(e2);\n\t\t\te1 = expr_alloc_symbol(&symbol_yes);\n\t\t\te2 = tmp;\n\t\t\ttrans_count++;\n\t\t}\n\t\tbreak;\n\tdefault:\n\t\t;\n\t}\n#undef e1\n#undef e2\n}\n\n/*\n * Rewrites 'e' in-place to remove (\"join\") duplicate and other redundant\n * operands.\n *\n * Example simplifications:\n *\n *\tA || B || A    ->  A || B\n *\tA && B && A=y  ->  A=y && B\n *\n * Returns the deduplicated expression.\n */\nstruct expr *expr_eliminate_dups(struct expr *e)\n{\n\tint oldcount;\n\tif (!e)\n\t\treturn e;\n\n\toldcount = trans_count;\n\twhile (1) {\n\t\ttrans_count = 0;\n\t\tswitch (e->type) {\n\t\tcase E_OR: case E_AND:\n\t\t\texpr_eliminate_dups1(e->type, &e, &e);\n\t\tdefault:\n\t\t\t;\n\t\t}\n\t\tif (!trans_count)\n\t\t\t/* No simplifications done in this pass. We're done */\n\t\t\tbreak;\n\t\te = expr_eliminate_yn(e);\n\t}\n\ttrans_count = oldcount;\n\treturn e;\n}\n\n/*\n * Performs various simplifications involving logical operators and\n * comparisons.\n *\n * Allocates and returns a new expression.\n */\nstruct expr *expr_transform(struct expr *e)\n{\n\tstruct expr *tmp;\n\n\tif (!e)\n\t\treturn NULL;\n\tswitch (e->type) {\n\tcase E_EQUAL:\n\tcase E_GEQ:\n\tcase E_GTH:\n\tcase E_LEQ:\n\tcase E_LTH:\n\tcase E_UNEQUAL:\n\tcase E_SYMBOL:\n\tcase E_LIST:\n\t\tbreak;\n\tdefault:\n\t\te->left.expr = expr_transform(e->left.expr);\n\t\te->right.expr = expr_transform(e->right.expr);\n\t}\n\n\tswitch (e->type) {\n\tcase E_EQUAL:\n\t\tif (e->left.sym->type != S_BOOLEAN)\n\t\t\tbreak;\n\t\tif (e->right.sym == &symbol_no) {\n\t\t\te->type = E_NOT;\n\t\t\te->left.expr = expr_alloc_symbol(e->left.sym);\n\t\t\te->right.sym = NULL;\n\t\t\tbreak;\n\t\t}\n\t\tif (e->right.sym == &symbol_mod) {\n\t\t\tprintf(\"boolean symbol %s tested for 'm'? test forced to 'n'\\n\", e->left.sym->name);\n\t\t\te->type = E_SYMBOL;\n\t\t\te->left.sym = &symbol_no;\n\t\t\te->right.sym = NULL;\n\t\t\tbreak;\n\t\t}\n\t\tif (e->right.sym == &symbol_yes) {\n\t\t\te->type = E_SYMBOL;\n\t\t\te->right.sym = NULL;\n\t\t\tbreak;\n\t\t}\n\t\tbreak;\n\tcase E_UNEQUAL:\n\t\tif (e->left.sym->type != S_BOOLEAN)\n\t\t\tbreak;\n\t\tif (e->right.sym == &symbol_no) {\n\t\t\te->type = E_SYMBOL;\n\t\t\te->right.sym = NULL;\n\t\t\tbreak;\n\t\t}\n\t\tif (e->right.sym == &symbol_mod) {\n\t\t\tprintf(\"boolean symbol %s tested for 'm'? test forced to 'y'\\n\", e->left.sym->name);\n\t\t\te->type = E_SYMBOL;\n\t\t\te->left.sym = &symbol_yes;\n\t\t\te->right.sym = NULL;\n\t\t\tbreak;\n\t\t}\n\t\tif (e->right.sym == &symbol_yes) {\n\t\t\te->type = E_NOT;\n\t\t\te->left.expr = expr_alloc_symbol(e->left.sym);\n\t\t\te->right.sym = NULL;\n\t\t\tbreak;\n\t\t}\n\t\tbreak;\n\tcase E_NOT:\n\t\tswitch (e->left.expr->type) {\n\t\tcase E_NOT:\n\t\t\t// !!a -> a\n\t\t\ttmp = e->left.expr->left.expr;\n\t\t\tfree(e->left.expr);\n\t\t\tfree(e);\n\t\t\te = tmp;\n\t\t\te = expr_transform(e);\n\t\t\tbreak;\n\t\tcase E_EQUAL:\n\t\tcase E_UNEQUAL:\n\t\t\t// !a='x' -> a!='x'\n\t\t\ttmp = e->left.expr;\n\t\t\tfree(e);\n\t\t\te = tmp;\n\t\t\te->type = e->type == E_EQUAL ? E_UNEQUAL : E_EQUAL;\n\t\t\tbreak;\n\t\tcase E_LEQ:\n\t\tcase E_GEQ:\n\t\t\t// !a<='x' -> a>'x'\n\t\t\ttmp = e->left.expr;\n\t\t\tfree(e);\n\t\t\te = tmp;\n\t\t\te->type = e->type == E_LEQ ? E_GTH : E_LTH;\n\t\t\tbreak;\n\t\tcase E_LTH:\n\t\tcase E_GTH:\n\t\t\t// !a<'x' -> a>='x'\n\t\t\ttmp = e->left.expr;\n\t\t\tfree(e);\n\t\t\te = tmp;\n\t\t\te->type = e->type == E_LTH ? E_GEQ : E_LEQ;\n\t\t\tbreak;\n\t\tcase E_OR:\n\t\t\t// !(a || b) -> !a && !b\n\t\t\ttmp = e->left.expr;\n\t\t\te->type = E_AND;\n\t\t\te->right.expr = expr_alloc_one(E_NOT, tmp->right.expr);\n\t\t\ttmp->type = E_NOT;\n\t\t\ttmp->right.expr = NULL;\n\t\t\te = expr_transform(e);\n\t\t\tbreak;\n\t\tcase E_AND:\n\t\t\t// !(a && b) -> !a || !b\n\t\t\ttmp = e->left.expr;\n\t\t\te->type = E_OR;\n\t\t\te->right.expr = expr_alloc_one(E_NOT, tmp->right.expr);\n\t\t\ttmp->type = E_NOT;\n\t\t\ttmp->right.expr = NULL;\n\t\t\te = expr_transform(e);\n\t\t\tbreak;\n\t\tcase E_SYMBOL:\n\t\t\tif (e->left.expr->left.sym == &symbol_yes) {\n\t\t\t\t// !'y' -> 'n'\n\t\t\t\ttmp = e->left.expr;\n\t\t\t\tfree(e);\n\t\t\t\te = tmp;\n\t\t\t\te->type = E_SYMBOL;\n\t\t\t\te->left.sym = &symbol_no;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (e->left.expr->left.sym == &symbol_mod) {\n\t\t\t\t// !'m' -> 'm'\n\t\t\t\ttmp = e->left.expr;\n\t\t\t\tfree(e);\n\t\t\t\te = tmp;\n\t\t\t\te->type = E_SYMBOL;\n\t\t\t\te->left.sym = &symbol_mod;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (e->left.expr->left.sym == &symbol_no) {\n\t\t\t\t// !'n' -> 'y'\n\t\t\t\ttmp = e->left.expr;\n\t\t\t\tfree(e);\n\t\t\t\te = tmp;\n\t\t\t\te->type = E_SYMBOL;\n\t\t\t\te->left.sym = &symbol_yes;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tbreak;\n\t\tdefault:\n\t\t\t;\n\t\t}\n\t\tbreak;\n\tdefault:\n\t\t;\n\t}\n\treturn e;\n}\n\nint expr_contains_symbol(struct expr *dep, struct symbol *sym)\n{\n\tif (!dep)\n\t\treturn 0;\n\n\tswitch (dep->type) {\n\tcase E_AND:\n\tcase E_OR:\n\t\treturn expr_contains_symbol(dep->left.expr, sym) ||\n\t\t       expr_contains_symbol(dep->right.expr, sym);\n\tcase E_SYMBOL:\n\t\treturn dep->left.sym == sym;\n\tcase E_EQUAL:\n\tcase E_GEQ:\n\tcase E_GTH:\n\tcase E_LEQ:\n\tcase E_LTH:\n\tcase E_UNEQUAL:\n\t\treturn dep->left.sym == sym ||\n\t\t       dep->right.sym == sym;\n\tcase E_NOT:\n\t\treturn expr_contains_symbol(dep->left.expr, sym);\n\tdefault:\n\t\t;\n\t}\n\treturn 0;\n}\n\nbool expr_depends_symbol(struct expr *dep, struct symbol *sym)\n{\n\tif (!dep)\n\t\treturn false;\n\n\tswitch (dep->type) {\n\tcase E_AND:\n\t\treturn expr_depends_symbol(dep->left.expr, sym) ||\n\t\t       expr_depends_symbol(dep->right.expr, sym);\n\tcase E_SYMBOL:\n\t\treturn dep->left.sym == sym;\n\tcase E_EQUAL:\n\t\tif (dep->left.sym == sym) {\n\t\t\tif (dep->right.sym == &symbol_yes || dep->right.sym == &symbol_mod)\n\t\t\t\treturn true;\n\t\t}\n\t\tbreak;\n\tcase E_UNEQUAL:\n\t\tif (dep->left.sym == sym) {\n\t\t\tif (dep->right.sym == &symbol_no)\n\t\t\t\treturn true;\n\t\t}\n\t\tbreak;\n\tdefault:\n\t\t;\n\t}\n \treturn false;\n}\n\n/*\n * Inserts explicit comparisons of type 'type' to symbol 'sym' into the\n * expression 'e'.\n *\n * Examples transformations for type == E_UNEQUAL, sym == &symbol_no:\n *\n *\tA              ->  A!=n\n *\t!A             ->  A=n\n *\tA && B         ->  !(A=n || B=n)\n *\tA || B         ->  !(A=n && B=n)\n *\tA && (B || C)  ->  !(A=n || (B=n && C=n))\n *\n * Allocates and returns a new expression.\n */\nstruct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym)\n{\n\tstruct expr *e1, *e2;\n\n\tif (!e) {\n\t\te = expr_alloc_symbol(sym);\n\t\tif (type == E_UNEQUAL)\n\t\t\te = expr_alloc_one(E_NOT, e);\n\t\treturn e;\n\t}\n\tswitch (e->type) {\n\tcase E_AND:\n\t\te1 = expr_trans_compare(e->left.expr, E_EQUAL, sym);\n\t\te2 = expr_trans_compare(e->right.expr, E_EQUAL, sym);\n\t\tif (sym == &symbol_yes)\n\t\t\te = expr_alloc_two(E_AND, e1, e2);\n\t\tif (sym == &symbol_no)\n\t\t\te = expr_alloc_two(E_OR, e1, e2);\n\t\tif (type == E_UNEQUAL)\n\t\t\te = expr_alloc_one(E_NOT, e);\n\t\treturn e;\n\tcase E_OR:\n\t\te1 = expr_trans_compare(e->left.expr, E_EQUAL, sym);\n\t\te2 = expr_trans_compare(e->right.expr, E_EQUAL, sym);\n\t\tif (sym == &symbol_yes)\n\t\t\te = expr_alloc_two(E_OR, e1, e2);\n\t\tif (sym == &symbol_no)\n\t\t\te = expr_alloc_two(E_AND, e1, e2);\n\t\tif (type == E_UNEQUAL)\n\t\t\te = expr_alloc_one(E_NOT, e);\n\t\treturn e;\n\tcase E_NOT:\n\t\treturn expr_trans_compare(e->left.expr, type == E_EQUAL ? E_UNEQUAL : E_EQUAL, sym);\n\tcase E_UNEQUAL:\n\tcase E_LTH:\n\tcase E_LEQ:\n\tcase E_GTH:\n\tcase E_GEQ:\n\tcase E_EQUAL:\n\t\tif (type == E_EQUAL) {\n\t\t\tif (sym == &symbol_yes)\n\t\t\t\treturn expr_copy(e);\n\t\t\tif (sym == &symbol_mod)\n\t\t\t\treturn expr_alloc_symbol(&symbol_no);\n\t\t\tif (sym == &symbol_no)\n\t\t\t\treturn expr_alloc_one(E_NOT, expr_copy(e));\n\t\t} else {\n\t\t\tif (sym == &symbol_yes)\n\t\t\t\treturn expr_alloc_one(E_NOT, expr_copy(e));\n\t\t\tif (sym == &symbol_mod)\n\t\t\t\treturn expr_alloc_symbol(&symbol_yes);\n\t\t\tif (sym == &symbol_no)\n\t\t\t\treturn expr_copy(e);\n\t\t}\n\t\tbreak;\n\tcase E_SYMBOL:\n\t\treturn expr_alloc_comp(type, e->left.sym, sym);\n\tcase E_LIST:\n\tcase E_RANGE:\n\tcase E_NONE:\n\t\t/* panic */;\n\t}\n\treturn NULL;\n}\n\nenum string_value_kind {\n\tk_string,\n\tk_signed,\n\tk_unsigned,\n};\n\nunion string_value {\n\tunsigned long long u;\n\tsigned long long s;\n};\n\nstatic enum string_value_kind expr_parse_string(const char *str,\n\t\t\t\t\t\tenum symbol_type type,\n\t\t\t\t\t\tunion string_value *val)\n{\n\tchar *tail;\n\tenum string_value_kind kind;\n\n\terrno = 0;\n\tswitch (type) {\n\tcase S_BOOLEAN:\n\tcase S_TRISTATE:\n\t\tval->s = !strcmp(str, \"n\") ? 0 :\n\t\t\t !strcmp(str, \"m\") ? 1 :\n\t\t\t !strcmp(str, \"y\") ? 2 : -1;\n\t\treturn k_signed;\n\tcase S_INT:\n\t\tval->s = strtoll(str, &tail, 10);\n\t\tkind = k_signed;\n\t\tbreak;\n\tcase S_HEX:\n\t\tval->u = strtoull(str, &tail, 16);\n\t\tkind = k_unsigned;\n\t\tbreak;\n\tdefault:\n\t\tval->s = strtoll(str, &tail, 0);\n\t\tkind = k_signed;\n\t\tbreak;\n\t}\n\treturn !errno && !*tail && tail > str && isxdigit(tail[-1])\n\t       ? kind : k_string;\n}\n\ntristate expr_calc_value(struct expr *e)\n{\n\ttristate val1, val2;\n\tconst char *str1, *str2;\n\tenum string_value_kind k1 = k_string, k2 = k_string;\n\tunion string_value lval = {}, rval = {};\n\tint res;\n\n\tif (!e)\n\t\treturn yes;\n\n\tswitch (e->type) {\n\tcase E_SYMBOL:\n\t\tsym_calc_value(e->left.sym);\n\t\treturn e->left.sym->curr.tri;\n\tcase E_AND:\n\t\tval1 = expr_calc_value(e->left.expr);\n\t\tval2 = expr_calc_value(e->right.expr);\n\t\treturn EXPR_AND(val1, val2);\n\tcase E_OR:\n\t\tval1 = expr_calc_value(e->left.expr);\n\t\tval2 = expr_calc_value(e->right.expr);\n\t\treturn EXPR_OR(val1, val2);\n\tcase E_NOT:\n\t\tval1 = expr_calc_value(e->left.expr);\n\t\treturn EXPR_NOT(val1);\n\tcase E_EQUAL:\n\tcase E_GEQ:\n\tcase E_GTH:\n\tcase E_LEQ:\n\tcase E_LTH:\n\tcase E_UNEQUAL:\n\t\tbreak;\n\tdefault:\n\t\tprintf(\"expr_calc_value: %d?\\n\", e->type);\n\t\treturn no;\n\t}\n\n\tsym_calc_value(e->left.sym);\n\tsym_calc_value(e->right.sym);\n\tstr1 = sym_get_string_value(e->left.sym);\n\tstr2 = sym_get_string_value(e->right.sym);\n\n\tif (e->left.sym->type != S_STRING || e->right.sym->type != S_STRING) {\n\t\tk1 = expr_parse_string(str1, e->left.sym->type, &lval);\n\t\tk2 = expr_parse_string(str2, e->right.sym->type, &rval);\n\t}\n\n\tif (k1 == k_string || k2 == k_string)\n\t\tres = strcmp(str1, str2);\n\telse if (k1 == k_unsigned || k2 == k_unsigned)\n\t\tres = (lval.u > rval.u) - (lval.u < rval.u);\n\telse /* if (k1 == k_signed && k2 == k_signed) */\n\t\tres = (lval.s > rval.s) - (lval.s < rval.s);\n\n\tswitch(e->type) {\n\tcase E_EQUAL:\n\t\treturn res ? no : yes;\n\tcase E_GEQ:\n\t\treturn res >= 0 ? yes : no;\n\tcase E_GTH:\n\t\treturn res > 0 ? yes : no;\n\tcase E_LEQ:\n\t\treturn res <= 0 ? yes : no;\n\tcase E_LTH:\n\t\treturn res < 0 ? yes : no;\n\tcase E_UNEQUAL:\n\t\treturn res ? yes : no;\n\tdefault:\n\t\tprintf(\"expr_calc_value: relation %d?\\n\", e->type);\n\t\treturn no;\n\t}\n}\n\nstatic int expr_compare_type(enum expr_type t1, enum expr_type t2)\n{\n\tif (t1 == t2)\n\t\treturn 0;\n\tswitch (t1) {\n\tcase E_LEQ:\n\tcase E_LTH:\n\tcase E_GEQ:\n\tcase E_GTH:\n\t\tif (t2 == E_EQUAL || t2 == E_UNEQUAL)\n\t\t\treturn 1;\n\tcase E_EQUAL:\n\tcase E_UNEQUAL:\n\t\tif (t2 == E_NOT)\n\t\t\treturn 1;\n\tcase E_NOT:\n\t\tif (t2 == E_AND)\n\t\t\treturn 1;\n\tcase E_AND:\n\t\tif (t2 == E_OR)\n\t\t\treturn 1;\n\tcase E_OR:\n\t\tif (t2 == E_LIST)\n\t\t\treturn 1;\n\tcase E_LIST:\n\t\tif (t2 == 0)\n\t\t\treturn 1;\n\tdefault:\n\t\treturn -1;\n\t}\n\tprintf(\"[%dgt%d?]\", t1, t2);\n\treturn 0;\n}\n\nvoid expr_print(struct expr *e,\n\t\tvoid (*fn)(void *, struct symbol *, const char *),\n\t\tvoid *data, int prevtoken)\n{\n\tif (!e) {\n\t\tfn(data, NULL, \"y\");\n\t\treturn;\n\t}\n\n\tif (expr_compare_type(prevtoken, e->type) > 0)\n\t\tfn(data, NULL, \"(\");\n\tswitch (e->type) {\n\tcase E_SYMBOL:\n\t\tif (e->left.sym->name)\n\t\t\tfn(data, e->left.sym, e->left.sym->name);\n\t\telse\n\t\t\tfn(data, NULL, \"<choice>\");\n\t\tbreak;\n\tcase E_NOT:\n\t\tfn(data, NULL, \"!\");\n\t\texpr_print(e->left.expr, fn, data, E_NOT);\n\t\tbreak;\n\tcase E_EQUAL:\n\t\tif (e->left.sym->name)\n\t\t\tfn(data, e->left.sym, e->left.sym->name);\n\t\telse\n\t\t\tfn(data, NULL, \"<choice>\");\n\t\tfn(data, NULL, \"=\");\n\t\tfn(data, e->right.sym, e->right.sym->name);\n\t\tbreak;\n\tcase E_LEQ:\n\tcase E_LTH:\n\t\tif (e->left.sym->name)\n\t\t\tfn(data, e->left.sym, e->left.sym->name);\n\t\telse\n\t\t\tfn(data, NULL, \"<choice>\");\n\t\tfn(data, NULL, e->type == E_LEQ ? \"<=\" : \"<\");\n\t\tfn(data, e->right.sym, e->right.sym->name);\n\t\tbreak;\n\tcase E_GEQ:\n\tcase E_GTH:\n\t\tif (e->left.sym->name)\n\t\t\tfn(data, e->left.sym, e->left.sym->name);\n\t\telse\n\t\t\tfn(data, NULL, \"<choice>\");\n\t\tfn(data, NULL, e->type == E_GEQ ? \">=\" : \">\");\n\t\tfn(data, e->right.sym, e->right.sym->name);\n\t\tbreak;\n\tcase E_UNEQUAL:\n\t\tif (e->left.sym->name)\n\t\t\tfn(data, e->left.sym, e->left.sym->name);\n\t\telse\n\t\t\tfn(data, NULL, \"<choice>\");\n\t\tfn(data, NULL, \"!=\");\n\t\tfn(data, e->right.sym, e->right.sym->name);\n\t\tbreak;\n\tcase E_OR:\n\t\texpr_print(e->left.expr, fn, data, E_OR);\n\t\tfn(data, NULL, \" || \");\n\t\texpr_print(e->right.expr, fn, data, E_OR);\n\t\tbreak;\n\tcase E_AND:\n\t\texpr_print(e->left.expr, fn, data, E_AND);\n\t\tfn(data, NULL, \" && \");\n\t\texpr_print(e->right.expr, fn, data, E_AND);\n\t\tbreak;\n\tcase E_LIST:\n\t\tfn(data, e->right.sym, e->right.sym->name);\n\t\tif (e->left.expr) {\n\t\t\tfn(data, NULL, \" ^ \");\n\t\t\texpr_print(e->left.expr, fn, data, E_LIST);\n\t\t}\n\t\tbreak;\n\tcase E_RANGE:\n\t\tfn(data, NULL, \"[\");\n\t\tfn(data, e->left.sym, e->left.sym->name);\n\t\tfn(data, NULL, \" \");\n\t\tfn(data, e->right.sym, e->right.sym->name);\n\t\tfn(data, NULL, \"]\");\n\t\tbreak;\n\tdefault:\n\t  {\n\t\tchar buf[32];\n\t\tsprintf(buf, \"<unknown type %d>\", e->type);\n\t\tfn(data, NULL, buf);\n\t\tbreak;\n\t  }\n\t}\n\tif (expr_compare_type(prevtoken, e->type) > 0)\n\t\tfn(data, NULL, \")\");\n}\n\nstatic void expr_print_file_helper(void *data, struct symbol *sym, const char *str)\n{\n\txfwrite(str, strlen(str), 1, data);\n}\n\nvoid expr_fprint(struct expr *e, FILE *out)\n{\n\texpr_print(e, expr_print_file_helper, out, E_NONE);\n}\n\nstatic void expr_print_gstr_helper(void *data, struct symbol *sym, const char *str)\n{\n\tstruct gstr *gs = (struct gstr*)data;\n\tconst char *sym_str = NULL;\n\n\tif (sym)\n\t\tsym_str = sym_get_string_value(sym);\n\n\tif (gs->max_width) {\n\t\tunsigned extra_length = strlen(str);\n\t\tconst char *last_cr = strrchr(gs->s, '\\n');\n\t\tunsigned last_line_length;\n\n\t\tif (sym_str)\n\t\t\textra_length += 4 + strlen(sym_str);\n\n\t\tif (!last_cr)\n\t\t\tlast_cr = gs->s;\n\n\t\tlast_line_length = strlen(gs->s) - (last_cr - gs->s);\n\n\t\tif ((last_line_length + extra_length) > gs->max_width)\n\t\t\tstr_append(gs, \"\\\\\\n\");\n\t}\n\n\tstr_append(gs, str);\n\tif (sym && sym->type != S_UNKNOWN)\n\t\tstr_printf(gs, \" [=%s]\", sym_str);\n}\n\nvoid expr_gstr_print(struct expr *e, struct gstr *gs)\n{\n\texpr_print(e, expr_print_gstr_helper, gs, E_NONE);\n}\n\n/*\n * Transform the top level \"||\" tokens into newlines and prepend each\n * line with a minus. This makes expressions much easier to read.\n * Suitable for reverse dependency expressions.\n */\nstatic void expr_print_revdep(struct expr *e,\n\t\t\t      void (*fn)(void *, struct symbol *, const char *),\n\t\t\t      void *data, tristate pr_type, const char **title)\n{\n\tif (e->type == E_OR) {\n\t\texpr_print_revdep(e->left.expr, fn, data, pr_type, title);\n\t\texpr_print_revdep(e->right.expr, fn, data, pr_type, title);\n\t} else if (expr_calc_value(e) == pr_type) {\n\t\tif (*title) {\n\t\t\tfn(data, NULL, *title);\n\t\t\t*title = NULL;\n\t\t}\n\n\t\tfn(data, NULL, \"  - \");\n\t\texpr_print(e, fn, data, E_NONE);\n\t\tfn(data, NULL, \"\\n\");\n\t}\n}\n\nvoid expr_gstr_print_revdep(struct expr *e, struct gstr *gs,\n\t\t\t    tristate pr_type, const char *title)\n{\n\texpr_print_revdep(e, expr_print_gstr_helper, gs, pr_type, &title);\n}\n"
  },
  {
    "path": "3rdparty/kconfig/expr.h",
    "content": "/* SPDX-License-Identifier: GPL-2.0 */\n/*\n * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>\n */\n\n#ifndef EXPR_H\n#define EXPR_H\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#include <assert.h>\n#include <stdio.h>\n#include \"list.h\"\n#ifndef __cplusplus\n#include <stdbool.h>\n#endif\n\nstruct file {\n\tstruct file *next;\n\tstruct file *parent;\n\tconst char *name;\n\tint lineno;\n};\n\ntypedef enum tristate {\n\tno, mod, yes\n} tristate;\n\nenum expr_type {\n\tE_NONE, E_OR, E_AND, E_NOT,\n\tE_EQUAL, E_UNEQUAL, E_LTH, E_LEQ, E_GTH, E_GEQ,\n\tE_LIST, E_SYMBOL, E_RANGE\n};\n\nunion expr_data {\n\tstruct expr *expr;\n\tstruct symbol *sym;\n};\n\nstruct expr {\n\tenum expr_type type;\n\tunion expr_data left, right;\n};\n\n#define EXPR_OR(dep1, dep2)\t(((dep1)>(dep2))?(dep1):(dep2))\n#define EXPR_AND(dep1, dep2)\t(((dep1)<(dep2))?(dep1):(dep2))\n#define EXPR_NOT(dep)\t\t(2-(dep))\n\n#define expr_list_for_each_sym(l, e, s) \\\n\tfor (e = (l); e && (s = e->right.sym); e = e->left.expr)\n\nstruct expr_value {\n\tstruct expr *expr;\n\ttristate tri;\n};\n\nstruct symbol_value {\n\tvoid *val;\n\ttristate tri;\n};\n\nenum symbol_type {\n\tS_UNKNOWN, S_BOOLEAN, S_TRISTATE, S_INT, S_HEX, S_STRING\n};\n\n/* enum values are used as index to symbol.def[] */\nenum {\n\tS_DEF_USER,\t\t/* main user value */\n\tS_DEF_AUTO,\t\t/* values read from auto.conf */\n\tS_DEF_DEF3,\t\t/* Reserved for UI usage */\n\tS_DEF_DEF4,\t\t/* Reserved for UI usage */\n\tS_DEF_COUNT\n};\n\n/*\n * Represents a configuration symbol.\n *\n * Choices are represented as a special kind of symbol and have the\n * SYMBOL_CHOICE bit set in 'flags'.\n */\nstruct symbol {\n\t/* The next symbol in the same bucket in the symbol hash table */\n\tstruct symbol *next;\n\n\t/* The name of the symbol, e.g. \"FOO\" for 'config FOO' */\n\tchar *name;\n\n\t/* S_BOOLEAN, S_TRISTATE, ... */\n\tenum symbol_type type;\n\n\t/*\n\t * The calculated value of the symbol. The SYMBOL_VALID bit is set in\n\t * 'flags' when this is up to date. Note that this value might differ\n\t * from the user value set in e.g. a .config file, due to visibility.\n\t */\n\tstruct symbol_value curr;\n\n\t/*\n\t * Values for the symbol provided from outside. def[S_DEF_USER] holds\n\t * the .config value.\n\t */\n\tstruct symbol_value def[S_DEF_COUNT];\n\n\t/*\n\t * An upper bound on the tristate value the user can set for the symbol\n\t * if it is a boolean or tristate. Calculated from prompt dependencies,\n\t * which also inherit dependencies from enclosing menus, choices, and\n\t * ifs. If 'n', the user value will be ignored.\n\t *\n\t * Symbols lacking prompts always have visibility 'n'.\n\t */\n\ttristate visible;\n\n\t/* SYMBOL_* flags */\n\tint flags;\n\n\t/* List of properties. See prop_type. */\n\tstruct property *prop;\n\n\t/* Dependencies from enclosing menus, choices, and ifs */\n\tstruct expr_value dir_dep;\n\n\t/* Reverse dependencies through being selected by other symbols */\n\tstruct expr_value rev_dep;\n\n\t/*\n\t * \"Weak\" reverse dependencies through being implied by other symbols\n\t */\n\tstruct expr_value implied;\n};\n\n#define for_all_symbols(i, sym) for (i = 0; i < SYMBOL_HASHSIZE; i++) for (sym = symbol_hash[i]; sym; sym = sym->next)\n\n#define SYMBOL_CONST      0x0001  /* symbol is const */\n#define SYMBOL_CHECK      0x0008  /* used during dependency checking */\n#define SYMBOL_CHOICE     0x0010  /* start of a choice block (null name) */\n#define SYMBOL_CHOICEVAL  0x0020  /* used as a value in a choice block */\n#define SYMBOL_VALID      0x0080  /* set when symbol.curr is calculated */\n#define SYMBOL_OPTIONAL   0x0100  /* choice is optional - values can be 'n' */\n#define SYMBOL_WRITE      0x0200  /* write symbol to file (KCONFIG_CONFIG) */\n#define SYMBOL_CHANGED    0x0400  /* ? */\n#define SYMBOL_WRITTEN    0x0800  /* track info to avoid double-write to .config */\n#define SYMBOL_NO_WRITE   0x1000  /* Symbol for internal use only; it will not be written */\n#define SYMBOL_CHECKED    0x2000  /* used during dependency checking */\n#define SYMBOL_WARNED     0x8000  /* warning has been issued */\n\n/* Set when symbol.def[] is used */\n#define SYMBOL_DEF        0x10000  /* First bit of SYMBOL_DEF */\n#define SYMBOL_DEF_USER   0x10000  /* symbol.def[S_DEF_USER] is valid */\n#define SYMBOL_DEF_AUTO   0x20000  /* symbol.def[S_DEF_AUTO] is valid */\n#define SYMBOL_DEF3       0x40000  /* symbol.def[S_DEF_3] is valid */\n#define SYMBOL_DEF4       0x80000  /* symbol.def[S_DEF_4] is valid */\n\n/* choice values need to be set before calculating this symbol value */\n#define SYMBOL_NEED_SET_CHOICE_VALUES  0x100000\n\n/* Set symbol to y if allnoconfig; used for symbols that hide others */\n#define SYMBOL_ALLNOCONFIG_Y 0x200000\n\n#define SYMBOL_MAXLENGTH\t256\n#define SYMBOL_HASHSIZE\t\t9973\n\n/* A property represent the config options that can be associated\n * with a config \"symbol\".\n * Sample:\n * config FOO\n *         default y\n *         prompt \"foo prompt\"\n *         select BAR\n * config BAZ\n *         int \"BAZ Value\"\n *         range 1..255\n *\n * Please, also check parser.y:print_symbol() when modifying the\n * list of property types!\n */\nenum prop_type {\n\tP_UNKNOWN,\n\tP_PROMPT,   /* prompt \"foo prompt\" or \"BAZ Value\" */\n\tP_COMMENT,  /* text associated with a comment */\n\tP_MENU,     /* prompt associated with a menu or menuconfig symbol */\n\tP_DEFAULT,  /* default y */\n\tP_CHOICE,   /* choice value */\n\tP_SELECT,   /* select BAR */\n\tP_IMPLY,    /* imply BAR */\n\tP_RANGE,    /* range 7..100 (for a symbol) */\n\tP_SYMBOL,   /* where a symbol is defined */\n};\n\nstruct property {\n\tstruct property *next;     /* next property - null if last */\n\tenum prop_type type;       /* type of property */\n\tconst char *text;          /* the prompt value - P_PROMPT, P_MENU, P_COMMENT */\n\tstruct expr_value visible;\n\tstruct expr *expr;         /* the optional conditional part of the property */\n\tstruct menu *menu;         /* the menu the property are associated with\n\t                            * valid for: P_SELECT, P_RANGE, P_CHOICE,\n\t                            * P_PROMPT, P_DEFAULT, P_MENU, P_COMMENT */\n\tstruct file *file;         /* what file was this property defined */\n\tint lineno;                /* what lineno was this property defined */\n};\n\n#define for_all_properties(sym, st, tok) \\\n\tfor (st = sym->prop; st; st = st->next) \\\n\t\tif (st->type == (tok))\n#define for_all_defaults(sym, st) for_all_properties(sym, st, P_DEFAULT)\n#define for_all_choices(sym, st) for_all_properties(sym, st, P_CHOICE)\n#define for_all_prompts(sym, st) \\\n\tfor (st = sym->prop; st; st = st->next) \\\n\t\tif (st->text)\n\n/*\n * Represents a node in the menu tree, as seen in e.g. menuconfig (though used\n * for all front ends). Each symbol, menu, etc. defined in the Kconfig files\n * gets a node. A symbol defined in multiple locations gets one node at each\n * location.\n */\nstruct menu {\n\t/* The next menu node at the same level */\n\tstruct menu *next;\n\n\t/* The parent menu node, corresponding to e.g. a menu or choice */\n\tstruct menu *parent;\n\n\t/* The first child menu node, for e.g. menus and choices */\n\tstruct menu *list;\n\n\t/*\n\t * The symbol associated with the menu node. Choices are implemented as\n\t * a special kind of symbol. NULL for menus, comments, and ifs.\n\t */\n\tstruct symbol *sym;\n\n\t/*\n\t * The prompt associated with the node. This holds the prompt for a\n\t * symbol as well as the text for a menu or comment, along with the\n\t * type (P_PROMPT, P_MENU, etc.)\n\t */\n\tstruct property *prompt;\n\n\t/*\n\t * 'visible if' dependencies. If more than one is given, they will be\n\t * ANDed together.\n\t */\n\tstruct expr *visibility;\n\n\t/*\n\t * Ordinary dependencies from e.g. 'depends on' and 'if', ANDed\n\t * together\n\t */\n\tstruct expr *dep;\n\n\t/* MENU_* flags */\n\tunsigned int flags;\n\n\t/* Any help text associated with the node */\n\tchar *help;\n\n\t/* The location where the menu node appears in the Kconfig files */\n\tstruct file *file;\n\tint lineno;\n\n\t/* For use by front ends that need to store auxiliary data */\n\tvoid *data;\n};\n\n/*\n * Set on a menu node when the corresponding symbol changes state in some way.\n * Can be checked by front ends.\n */\n#define MENU_CHANGED\t\t0x0001\n\n#define MENU_ROOT\t\t0x0002\n\nstruct jump_key {\n\tstruct list_head entries;\n\tsize_t offset;\n\tstruct menu *target;\n\tint index;\n};\n\n#define JUMP_NB\t\t\t9\n\nextern struct file *file_list;\nextern struct file *current_file;\nstruct file *lookup_file(const char *name);\n\nextern struct symbol symbol_yes, symbol_no, symbol_mod;\nextern struct symbol *modules_sym;\nextern struct symbol *sym_defconfig_list;\nextern int cdebug;\nstruct expr *expr_alloc_symbol(struct symbol *sym);\nstruct expr *expr_alloc_one(enum expr_type type, struct expr *ce);\nstruct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e2);\nstruct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2);\nstruct expr *expr_alloc_and(struct expr *e1, struct expr *e2);\nstruct expr *expr_alloc_or(struct expr *e1, struct expr *e2);\nstruct expr *expr_copy(const struct expr *org);\nvoid expr_free(struct expr *e);\nvoid expr_eliminate_eq(struct expr **ep1, struct expr **ep2);\nint expr_eq(struct expr *e1, struct expr *e2);\ntristate expr_calc_value(struct expr *e);\nstruct expr *expr_trans_bool(struct expr *e);\nstruct expr *expr_eliminate_dups(struct expr *e);\nstruct expr *expr_transform(struct expr *e);\nint expr_contains_symbol(struct expr *dep, struct symbol *sym);\nbool expr_depends_symbol(struct expr *dep, struct symbol *sym);\nstruct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym);\n\nvoid expr_fprint(struct expr *e, FILE *out);\nstruct gstr; /* forward */\nvoid expr_gstr_print(struct expr *e, struct gstr *gs);\nvoid expr_gstr_print_revdep(struct expr *e, struct gstr *gs,\n\t\t\t    tristate pr_type, const char *title);\n\nstatic inline int expr_is_yes(struct expr *e)\n{\n\treturn !e || (e->type == E_SYMBOL && e->left.sym == &symbol_yes);\n}\n\nstatic inline int expr_is_no(struct expr *e)\n{\n\treturn e && (e->type == E_SYMBOL && e->left.sym == &symbol_no);\n}\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* EXPR_H */\n"
  },
  {
    "path": "3rdparty/kconfig/lexer.l",
    "content": "/* SPDX-License-Identifier: GPL-2.0 */\n/*\n * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>\n */\n%option nostdinit noyywrap never-interactive full ecs\n%option 8bit nodefault yylineno\n%x ASSIGN_VAL HELP STRING\n%{\n\n#include <assert.h>\n#include <limits.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <unistd.h>\n\n#include \"lkc.h\"\n#include \"parser.tab.h\"\n\n#define YY_DECL\t\tstatic int yylex1(void)\n\n#define START_STRSIZE\t16\n\nstatic struct {\n\tstruct file *file;\n\tint lineno;\n} current_pos;\n\nstatic int prev_prev_token = T_EOL;\nstatic int prev_token = T_EOL;\nstatic char *text;\nstatic int text_size, text_asize;\n\nstruct buffer {\n\tstruct buffer *parent;\n\tYY_BUFFER_STATE state;\n};\n\nstatic struct buffer *current_buf;\n\nstatic int last_ts, first_ts;\n\nstatic char *expand_token(const char *in, size_t n);\nstatic void append_expanded_string(const char *in);\nstatic void zconf_endhelp(void);\nstatic void zconf_endfile(void);\n\nstatic void new_string(void)\n{\n\ttext = xmalloc(START_STRSIZE);\n\ttext_asize = START_STRSIZE;\n\ttext_size = 0;\n\t*text = 0;\n}\n\nstatic void append_string(const char *str, int size)\n{\n\tint new_size = text_size + size + 1;\n\tif (new_size > text_asize) {\n\t\tnew_size += START_STRSIZE - 1;\n\t\tnew_size &= -START_STRSIZE;\n\t\ttext = xrealloc(text, new_size);\n\t\ttext_asize = new_size;\n\t}\n\tmemcpy(text + text_size, str, size);\n\ttext_size += size;\n\ttext[text_size] = 0;\n}\n\nstatic void alloc_string(const char *str, int size)\n{\n\ttext = xmalloc(size + 1);\n\tmemcpy(text, str, size);\n\ttext[size] = 0;\n}\n\nstatic void warn_ignored_character(char chr)\n{\n\tfprintf(stderr,\n\t        \"%s:%d:warning: ignoring unsupported character '%c'\\n\",\n\t        current_file->name, yylineno, chr);\n}\n%}\n\nn\t[A-Za-z0-9_-]\n\n%%\n\tint str = 0;\n\tint ts, i;\n\n#.*\t\t\t/* ignore comment */\n[ \\t]*\t\t\t/* whitespaces */\n\\\\\\n\t\t\t/* escaped new line */\n\\n\t\t\treturn T_EOL;\n\"allnoconfig_y\"\t\treturn T_ALLNOCONFIG_Y;\n\"bool\"\t\t\treturn T_BOOL;\n\"choice\"\t\treturn T_CHOICE;\n\"comment\"\t\treturn T_COMMENT;\n\"config\"\t\treturn T_CONFIG;\n\"def_bool\"\t\treturn T_DEF_BOOL;\n\"def_tristate\"\t\treturn T_DEF_TRISTATE;\n\"default\"\t\treturn T_DEFAULT;\n\"defconfig_list\"\treturn T_DEFCONFIG_LIST;\n\"depends\"\t\treturn T_DEPENDS;\n\"endchoice\"\t\treturn T_ENDCHOICE;\n\"endif\"\t\t\treturn T_ENDIF;\n\"endmenu\"\t\treturn T_ENDMENU;\n\"help\"\t\t\treturn T_HELP;\n\"hex\"\t\t\treturn T_HEX;\n\"if\"\t\t\treturn T_IF;\n\"imply\"\t\t\treturn T_IMPLY;\n\"int\"\t\t\treturn T_INT;\n\"mainmenu\"\t\treturn T_MAINMENU;\n\"menu\"\t\t\treturn T_MENU;\n\"menuconfig\"\t\treturn T_MENUCONFIG;\n\"modules\"\t\treturn T_MODULES;\n\"on\"\t\t\treturn T_ON;\n\"option\"\t\treturn T_OPTION;\n\"optional\"\t\treturn T_OPTIONAL;\n\"prompt\"\t\treturn T_PROMPT;\n\"range\"\t\t\treturn T_RANGE;\n\"select\"\t\treturn T_SELECT;\n\"source\"\t\treturn T_SOURCE;\n\"string\"\t\treturn T_STRING;\n\"tristate\"\t\treturn T_TRISTATE;\n\"visible\"\t\treturn T_VISIBLE;\n\"||\"\t\t\treturn T_OR;\n\"&&\"\t\t\treturn T_AND;\n\"=\"\t\t\treturn T_EQUAL;\n\"!=\"\t\t\treturn T_UNEQUAL;\n\"<\"\t\t\treturn T_LESS;\n\"<=\"\t\t\treturn T_LESS_EQUAL;\n\">\"\t\t\treturn T_GREATER;\n\">=\"\t\t\treturn T_GREATER_EQUAL;\n\"!\"\t\t\treturn T_NOT;\n\"(\"\t\t\treturn T_OPEN_PAREN;\n\")\"\t\t\treturn T_CLOSE_PAREN;\n\":=\"\t\t\treturn T_COLON_EQUAL;\n\"+=\"\t\t\treturn T_PLUS_EQUAL;\n\\\"|\\'\t\t\t{\n\t\t\t\tstr = yytext[0];\n\t\t\t\tnew_string();\n\t\t\t\tBEGIN(STRING);\n\t\t\t}\n{n}+\t\t\t{\n\t\t\t\talloc_string(yytext, yyleng);\n\t\t\t\tyylval.string = text;\n\t\t\t\treturn T_WORD;\n\t\t\t}\n({n}|$)+\t\t{\n\t\t\t\t/* this token includes at least one '$' */\n\t\t\t\tyylval.string = expand_token(yytext, yyleng);\n\t\t\t\tif (strlen(yylval.string))\n\t\t\t\t\treturn T_WORD;\n\t\t\t\tfree(yylval.string);\n\t\t\t}\n.\t\t\twarn_ignored_character(*yytext);\n\n<ASSIGN_VAL>{\n\t[^[:blank:]\\n]+.*\t{\n\t\talloc_string(yytext, yyleng);\n\t\tyylval.string = text;\n\t\treturn T_ASSIGN_VAL;\n\t}\n\t\\n\t{ BEGIN(INITIAL); return T_EOL; }\n\t.\n}\n\n<STRING>{\n\t\"$\".*\tappend_expanded_string(yytext);\n\t[^$'\"\\\\\\n]+\t{\n\t\tappend_string(yytext, yyleng);\n\t}\n\t\\\\.?\t{\n\t\tappend_string(yytext + 1, yyleng - 1);\n\t}\n\t\\'|\\\"\t{\n\t\tif (str == yytext[0]) {\n\t\t\tBEGIN(INITIAL);\n\t\t\tyylval.string = text;\n\t\t\treturn T_WORD_QUOTE;\n\t\t} else\n\t\t\tappend_string(yytext, 1);\n\t}\n\t\\n\t{\n\t\tfprintf(stderr,\n\t\t\t\"%s:%d:warning: multi-line strings not supported\\n\",\n\t\t\tzconf_curname(), zconf_lineno());\n\t\tunput('\\n');\n\t\tBEGIN(INITIAL);\n\t\tyylval.string = text;\n\t\treturn T_WORD_QUOTE;\n\t}\n\t<<EOF>>\t{\n\t\tBEGIN(INITIAL);\n\t\tyylval.string = text;\n\t\treturn T_WORD_QUOTE;\n\t}\n}\n\n<HELP>{\n\t[ \\t]+\t{\n\t\tts = 0;\n\t\tfor (i = 0; i < yyleng; i++) {\n\t\t\tif (yytext[i] == '\\t')\n\t\t\t\tts = (ts & ~7) + 8;\n\t\t\telse\n\t\t\t\tts++;\n\t\t}\n\t\tlast_ts = ts;\n\t\tif (first_ts) {\n\t\t\tif (ts < first_ts) {\n\t\t\t\tzconf_endhelp();\n\t\t\t\treturn T_HELPTEXT;\n\t\t\t}\n\t\t\tts -= first_ts;\n\t\t\twhile (ts > 8) {\n\t\t\t\tappend_string(\"        \", 8);\n\t\t\t\tts -= 8;\n\t\t\t}\n\t\t\tappend_string(\"        \", ts);\n\t\t}\n\t}\n\t[ \\t]*\\n/[^ \\t\\n] {\n\t\tzconf_endhelp();\n\t\treturn T_HELPTEXT;\n\t}\n\t[ \\t]*\\n\t{\n\t\tappend_string(\"\\n\", 1);\n\t}\n\t[^ \\t\\n].* {\n\t\twhile (yyleng) {\n\t\t\tif ((yytext[yyleng-1] != ' ') && (yytext[yyleng-1] != '\\t'))\n\t\t\t\tbreak;\n\t\t\tyyleng--;\n\t\t}\n\t\tappend_string(yytext, yyleng);\n\t\tif (!first_ts)\n\t\t\tfirst_ts = last_ts;\n\t}\n\t<<EOF>>\t{\n\t\tzconf_endhelp();\n\t\treturn T_HELPTEXT;\n\t}\n}\n\n<<EOF>>\t{\n\tBEGIN(INITIAL);\n\n\tif (prev_token != T_EOL && prev_token != T_HELPTEXT)\n\t\tfprintf(stderr, \"%s:%d:warning: no new line at end of file\\n\",\n\t\t\tcurrent_file->name, yylineno);\n\n\tif (current_file) {\n\t\tzconf_endfile();\n\t\treturn T_EOL;\n\t}\n\tfclose(yyin);\n\tyyterminate();\n}\n\n%%\n\n/* second stage lexer */\nint yylex(void)\n{\n\tint token;\n\nrepeat:\n\ttoken = yylex1();\n\n\tif (prev_token == T_EOL || prev_token == T_HELPTEXT) {\n\t\tif (token == T_EOL) {\n\t\t\t/* Do not pass unneeded T_EOL to the parser. */\n\t\t\tgoto repeat;\n\t\t} else {\n\t\t\t/*\n\t\t\t * For the parser, update file/lineno at the first token\n\t\t\t * of each statement. Generally, \\n is a statement\n\t\t\t * terminator in Kconfig, but it is not always true\n\t\t\t * because \\n could be escaped by a backslash.\n\t\t\t */\n\t\t\tcurrent_pos.file = current_file;\n\t\t\tcurrent_pos.lineno = yylineno;\n\t\t}\n\t}\n\n\tif (prev_prev_token == T_EOL && prev_token == T_WORD &&\n\t    (token == T_EQUAL || token == T_COLON_EQUAL || token == T_PLUS_EQUAL))\n\t\tBEGIN(ASSIGN_VAL);\n\n\tprev_prev_token = prev_token;\n\tprev_token = token;\n\n\treturn token;\n}\n\nstatic char *expand_token(const char *in, size_t n)\n{\n\tchar *out;\n\tint c;\n\tchar c2;\n\tconst char *rest, *end;\n\n\tnew_string();\n\tappend_string(in, n);\n\n\t/* get the whole line because we do not know the end of token. */\n\twhile ((c = input()) != EOF) {\n\t\tif (c == '\\n') {\n\t\t\tunput(c);\n\t\t\tbreak;\n\t\t}\n\t\tc2 = c;\n\t\tappend_string(&c2, 1);\n\t}\n\n\trest = text;\n\tout = expand_one_token(&rest);\n\n\t/* push back unused characters to the input stream */\n\tend = rest + strlen(rest);\n\twhile (end > rest)\n\t\tunput(*--end);\n\n\tfree(text);\n\n\treturn out;\n}\n\nstatic void append_expanded_string(const char *str)\n{\n\tconst char *end;\n\tchar *res;\n\n\tstr++;\n\n\tres = expand_dollar(&str);\n\n\t/* push back unused characters to the input stream */\n\tend = str + strlen(str);\n\twhile (end > str)\n\t\tunput(*--end);\n\n\tappend_string(res, strlen(res));\n\n\tfree(res);\n}\n\nvoid zconf_starthelp(void)\n{\n\tnew_string();\n\tlast_ts = first_ts = 0;\n\tBEGIN(HELP);\n}\n\nstatic void zconf_endhelp(void)\n{\n\tyylval.string = text;\n\tBEGIN(INITIAL);\n}\n\n\n/*\n * Try to open specified file with following names:\n * ./name\n * $(srctree)/name\n * The latter is used when srctree is separate from objtree\n * when compiling the kernel.\n * Return NULL if file is not found.\n */\nFILE *zconf_fopen(const char *name)\n{\n\tchar *env, fullname[PATH_MAX+1];\n\tFILE *f;\n\n\tf = fopen(name, \"r\");\n\tif (!f && name != NULL && name[0] != '/') {\n\t\tenv = getenv(SRCTREE);\n\t\tif (env) {\n\t\t\tsnprintf(fullname, sizeof(fullname),\n\t\t\t\t \"%s/%s\", env, name);\n\t\t\tf = fopen(fullname, \"r\");\n\t\t}\n\t}\n\treturn f;\n}\n\nvoid zconf_initscan(const char *name)\n{\n\tyyin = zconf_fopen(name);\n\tif (!yyin) {\n\t\tfprintf(stderr, \"can't find file %s\\n\", name);\n\t\texit(1);\n\t}\n\n\tcurrent_buf = xmalloc(sizeof(*current_buf));\n\tmemset(current_buf, 0, sizeof(*current_buf));\n\n\tcurrent_file = file_lookup(name);\n\tyylineno = 1;\n}\n\nvoid zconf_nextfile(const char *name)\n{\n\tchar path[PATH_MAX], *slash;\n\tif (strlen(current_file->name) >= PATH_MAX) {\n\t\tfprintf(stderr, \"can't source %s: path too long\\n\", name);\n\t\texit(1);\n\t}\n\tstrcpy(path, current_file->name);\n\tslash = strrchr(path, '/');\n\tif (!slash || strlen(name) >= PATH_MAX - (slash - path) - 1) {\n\t\tfprintf(stderr, \"can't source %s: path too long\\n\", name);\n\t\texit(1);\n\t}\n\tstrcpy(slash + 1, name);\n\tstruct file *iter;\n\tstruct file *file = file_lookup(path);\n\tstruct buffer *buf = xmalloc(sizeof(*buf));\n\tmemset(buf, 0, sizeof(*buf));\n\n\tcurrent_buf->state = YY_CURRENT_BUFFER;\n\tyyin = zconf_fopen(file->name);\n\tif (!yyin) {\n\t\tfprintf(stderr, \"%s:%d: can't open file \\\"%s\\\"\\n\",\n\t\t\tzconf_curname(), zconf_lineno(), file->name);\n\t\texit(1);\n\t}\n\tyy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));\n\tbuf->parent = current_buf;\n\tcurrent_buf = buf;\n\n\tcurrent_file->lineno = yylineno;\n\tfile->parent = current_file;\n\n\tfor (iter = current_file; iter; iter = iter->parent) {\n\t\tif (!strcmp(iter->name, file->name)) {\n\t\t\tfprintf(stderr,\n\t\t\t\t\"Recursive inclusion detected.\\n\"\n\t\t\t\t\"Inclusion path:\\n\"\n\t\t\t\t\"  current file : %s\\n\", file->name);\n\t\t\titer = file;\n\t\t\tdo {\n\t\t\t\titer = iter->parent;\n\t\t\t\tfprintf(stderr, \"  included from: %s:%d\\n\",\n\t\t\t\t\titer->name, iter->lineno - 1);\n\t\t\t} while (strcmp(iter->name, file->name));\n\t\t\texit(1);\n\t\t}\n\t}\n\n\tyylineno = 1;\n\tcurrent_file = file;\n}\n\nstatic void zconf_endfile(void)\n{\n\tstruct buffer *parent;\n\n\tcurrent_file = current_file->parent;\n\tif (current_file)\n\t\tyylineno = current_file->lineno;\n\n\tparent = current_buf->parent;\n\tif (parent) {\n\t\tfclose(yyin);\n\t\tyy_delete_buffer(YY_CURRENT_BUFFER);\n\t\tyy_switch_to_buffer(parent->state);\n\t}\n\tfree(current_buf);\n\tcurrent_buf = parent;\n}\n\nint zconf_lineno(void)\n{\n\treturn current_pos.lineno;\n}\n\nconst char *zconf_curname(void)\n{\n\treturn current_pos.file ? current_pos.file->name : \"<none>\";\n}\n"
  },
  {
    "path": "3rdparty/kconfig/list.h",
    "content": "/* SPDX-License-Identifier: GPL-2.0 */\n#ifndef LIST_H\n#define LIST_H\n\n/*\n * Copied from include/linux/...\n */\n\n#undef offsetof\n#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)\n\n/**\n * container_of - cast a member of a structure out to the containing structure\n * @ptr:        the pointer to the member.\n * @type:       the type of the container struct this is embedded in.\n * @member:     the name of the member within the struct.\n *\n */\n#define container_of(ptr, type, member) ({                      \\\n\tconst typeof( ((type *)0)->member ) *__mptr = (ptr);    \\\n\t(type *)( (char *)__mptr - offsetof(type,member) );})\n\n\nstruct list_head {\n\tstruct list_head *next, *prev;\n};\n\n\n#define LIST_HEAD_INIT(name) { &(name), &(name) }\n\n#define LIST_HEAD(name) \\\n\tstruct list_head name = LIST_HEAD_INIT(name)\n\n/**\n * list_entry - get the struct for this entry\n * @ptr:\tthe &struct list_head pointer.\n * @type:\tthe type of the struct this is embedded in.\n * @member:\tthe name of the list_head within the struct.\n */\n#define list_entry(ptr, type, member) \\\n\tcontainer_of(ptr, type, member)\n\n/**\n * list_for_each_entry\t-\titerate over list of given type\n * @pos:\tthe type * to use as a loop cursor.\n * @head:\tthe head for your list.\n * @member:\tthe name of the list_head within the struct.\n */\n#define list_for_each_entry(pos, head, member)\t\t\t\t\\\n\tfor (pos = list_entry((head)->next, typeof(*pos), member);\t\\\n\t     &pos->member != (head); \t\\\n\t     pos = list_entry(pos->member.next, typeof(*pos), member))\n\n/**\n * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry\n * @pos:\tthe type * to use as a loop cursor.\n * @n:\t\tanother type * to use as temporary storage\n * @head:\tthe head for your list.\n * @member:\tthe name of the list_head within the struct.\n */\n#define list_for_each_entry_safe(pos, n, head, member)\t\t\t\\\n\tfor (pos = list_entry((head)->next, typeof(*pos), member),\t\\\n\t\tn = list_entry(pos->member.next, typeof(*pos), member);\t\\\n\t     &pos->member != (head);\t\t\t\t\t\\\n\t     pos = n, n = list_entry(n->member.next, typeof(*n), member))\n\n/**\n * list_empty - tests whether a list is empty\n * @head: the list to test.\n */\nstatic inline int list_empty(const struct list_head *head)\n{\n\treturn head->next == head;\n}\n\n/*\n * Insert a new entry between two known consecutive entries.\n *\n * This is only for internal list manipulation where we know\n * the prev/next entries already!\n */\nstatic inline void __list_add(struct list_head *_new,\n\t\t\t      struct list_head *prev,\n\t\t\t      struct list_head *next)\n{\n\tnext->prev = _new;\n\t_new->next = next;\n\t_new->prev = prev;\n\tprev->next = _new;\n}\n\n/**\n * list_add_tail - add a new entry\n * @new: new entry to be added\n * @head: list head to add it before\n *\n * Insert a new entry before the specified head.\n * This is useful for implementing queues.\n */\nstatic inline void list_add_tail(struct list_head *_new, struct list_head *head)\n{\n\t__list_add(_new, head->prev, head);\n}\n\n/*\n * Delete a list entry by making the prev/next entries\n * point to each other.\n *\n * This is only for internal list manipulation where we know\n * the prev/next entries already!\n */\nstatic inline void __list_del(struct list_head *prev, struct list_head *next)\n{\n\tnext->prev = prev;\n\tprev->next = next;\n}\n\n#define LIST_POISON1  ((void *) 0x00100100)\n#define LIST_POISON2  ((void *) 0x00200200)\n/**\n * list_del - deletes entry from list.\n * @entry: the element to delete from the list.\n * Note: list_empty() on entry does not return true after this, the entry is\n * in an undefined state.\n */\nstatic inline void list_del(struct list_head *entry)\n{\n\t__list_del(entry->prev, entry->next);\n\tentry->next = (struct list_head*)LIST_POISON1;\n\tentry->prev = (struct list_head*)LIST_POISON2;\n}\n#endif\n"
  },
  {
    "path": "3rdparty/kconfig/lkc.h",
    "content": "/* SPDX-License-Identifier: GPL-2.0 */\n/*\n * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>\n */\n\n#ifndef LKC_H\n#define LKC_H\n\n#include \"expr.h\"\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#include \"lkc_proto.h\"\n\n#define SRCTREE \"srctree\"\n\n#ifndef PACKAGE\n#define PACKAGE \"linux\"\n#endif\n\n#ifndef CONFIG_\n#define CONFIG_ \"CONFIG_\"\n#endif\nstatic inline const char *CONFIG_prefix(void)\n{\n\treturn getenv( \"CONFIG_\" ) ?: CONFIG_;\n}\n#undef CONFIG_\n#define CONFIG_ CONFIG_prefix()\n\nenum conf_def_mode {\n\tdef_default,\n\tdef_yes,\n\tdef_mod,\n\tdef_y2m,\n\tdef_m2y,\n\tdef_no,\n\tdef_random\n};\n\nextern int yylineno;\nvoid zconfdump(FILE *out);\nvoid zconf_starthelp(void);\nFILE *zconf_fopen(const char *name);\nvoid zconf_initscan(const char *name);\nvoid zconf_nextfile(const char *name);\nint zconf_lineno(void);\nconst char *zconf_curname(void);\n\n/* confdata.c */\nconst char *conf_get_configname(void);\nvoid sym_set_change_count(int count);\nvoid sym_add_change_count(int count);\nbool conf_set_all_new_symbols(enum conf_def_mode mode);\nvoid conf_rewrite_mod_or_yes(enum conf_def_mode mode);\nvoid set_all_choice_values(struct symbol *csym);\n\n/* confdata.c and expr.c */\nstatic inline void xfwrite(const void *str, size_t len, size_t count, FILE *out)\n{\n\tassert(len != 0);\n\n\tif (fwrite(str, len, count, out) != count)\n\t\tfprintf(stderr, \"Error in writing or end of file.\\n\");\n}\n\n/* util.c */\nstruct file *file_lookup(const char *name);\nvoid *xmalloc(size_t size);\nvoid *xcalloc(size_t nmemb, size_t size);\nvoid *xrealloc(void *p, size_t size);\nchar *xstrdup(const char *s);\nchar *xstrndup(const char *s, size_t n);\n\n/* lexer.l */\nint yylex(void);\n\nstruct gstr {\n\tsize_t len;\n\tchar  *s;\n\t/*\n\t* when max_width is not zero long lines in string s (if any) get\n\t* wrapped not to exceed the max_width value\n\t*/\n\tint max_width;\n};\nstruct gstr str_new(void);\nvoid str_free(struct gstr *gs);\nvoid str_append(struct gstr *gs, const char *s);\nvoid str_printf(struct gstr *gs, const char *fmt, ...);\nconst char *str_get(struct gstr *gs);\n\n/* menu.c */\nvoid _menu_init(void);\nvoid menu_warn(struct menu *menu, const char *fmt, ...);\nstruct menu *menu_add_menu(void);\nvoid menu_end_menu(void);\nvoid menu_add_entry(struct symbol *sym);\nvoid menu_add_dep(struct expr *dep);\nvoid menu_add_visibility(struct expr *dep);\nstruct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep);\nvoid menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep);\nvoid menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep);\nvoid menu_add_option_modules(void);\nvoid menu_add_option_defconfig_list(void);\nvoid menu_add_option_allnoconfig_y(void);\nvoid menu_finalize(struct menu *parent);\nvoid menu_set_type(int type);\n\nextern struct menu rootmenu;\n\nbool menu_is_empty(struct menu *menu);\nbool menu_is_visible(struct menu *menu);\nbool menu_has_prompt(struct menu *menu);\nconst char *menu_get_prompt(struct menu *menu);\nstruct menu *menu_get_root_menu(struct menu *menu);\nstruct menu *menu_get_parent_menu(struct menu *menu);\nbool menu_has_help(struct menu *menu);\nconst char *menu_get_help(struct menu *menu);\nstruct gstr get_relations_str(struct symbol **sym_arr, struct list_head *head);\nvoid menu_get_ext_help(struct menu *menu, struct gstr *help);\n\n/* symbol.c */\nvoid sym_clear_all_valid(void);\nstruct symbol *sym_choice_default(struct symbol *sym);\nstruct property *sym_get_range_prop(struct symbol *sym);\nconst char *sym_get_string_default(struct symbol *sym);\nstruct symbol *sym_check_deps(struct symbol *sym);\nstruct symbol *prop_get_symbol(struct property *prop);\n\nstatic inline tristate sym_get_tristate_value(struct symbol *sym)\n{\n\treturn sym->curr.tri;\n}\n\n\nstatic inline struct symbol *sym_get_choice_value(struct symbol *sym)\n{\n\treturn (struct symbol *)sym->curr.val;\n}\n\nstatic inline bool sym_set_choice_value(struct symbol *ch, struct symbol *chval)\n{\n\treturn sym_set_tristate_value(chval, yes);\n}\n\nstatic inline bool sym_is_choice(struct symbol *sym)\n{\n\treturn sym->flags & SYMBOL_CHOICE ? true : false;\n}\n\nstatic inline bool sym_is_choice_value(struct symbol *sym)\n{\n\treturn sym->flags & SYMBOL_CHOICEVAL ? true : false;\n}\n\nstatic inline bool sym_is_optional(struct symbol *sym)\n{\n\treturn sym->flags & SYMBOL_OPTIONAL ? true : false;\n}\n\nstatic inline bool sym_has_value(struct symbol *sym)\n{\n\treturn sym->flags & SYMBOL_DEF_USER ? true : false;\n}\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* LKC_H */\n"
  },
  {
    "path": "3rdparty/kconfig/lkc_proto.h",
    "content": "/* SPDX-License-Identifier: GPL-2.0 */\n#include <stdarg.h>\n\n/* confdata.c */\nvoid conf_parse(const char *name);\nint conf_read(const char *name);\nint conf_read_simple(const char *name, int);\nint conf_write_defconfig(const char *name);\nint conf_write(const char *name);\nint conf_write_autoconf(int overwrite);\nbool conf_get_changed(void);\nvoid conf_set_changed_callback(void (*fn)(void));\nvoid conf_set_message_callback(void (*fn)(const char *s));\n\n/* symbol.c */\nextern struct symbol * symbol_hash[SYMBOL_HASHSIZE];\n\nstruct symbol * sym_lookup(const char *name, int flags);\nstruct symbol * sym_find(const char *name);\nconst char * sym_escape_string_value(const char *in);\nstruct symbol ** sym_re_search(const char *pattern);\nconst char * sym_type_name(enum symbol_type type);\nvoid sym_calc_value(struct symbol *sym);\nenum symbol_type sym_get_type(struct symbol *sym);\nbool sym_tristate_within_range(struct symbol *sym,tristate tri);\nbool sym_set_tristate_value(struct symbol *sym,tristate tri);\ntristate sym_toggle_tristate_value(struct symbol *sym);\nbool sym_string_valid(struct symbol *sym, const char *newval);\nbool sym_string_within_range(struct symbol *sym, const char *str);\nbool sym_set_string_value(struct symbol *sym, const char *newval);\nbool sym_is_changeable(struct symbol *sym);\nstruct property * sym_get_choice_prop(struct symbol *sym);\nconst char * sym_get_string_value(struct symbol *sym);\n\nconst char * prop_get_type_name(enum prop_type type);\n\n/* preprocess.c */\nenum variable_flavor {\n\tVAR_SIMPLE,\n\tVAR_RECURSIVE,\n\tVAR_APPEND,\n};\nvoid env_write_dep(FILE *f, const char *auto_conf_name);\nvoid variable_add(const char *name, const char *value,\n\t\t  enum variable_flavor flavor);\nvoid variable_all_del(void);\nchar *expand_dollar(const char **str);\nchar *expand_one_token(const char **str);\n\n/* expr.c */\nvoid expr_print(struct expr *e, void (*fn)(void *, struct symbol *, const char *), void *data, int prevtoken);\n"
  },
  {
    "path": "3rdparty/kconfig/menu.c",
    "content": "// SPDX-License-Identifier: GPL-2.0\n/*\n * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>\n */\n\n#include <ctype.h>\n#include <stdarg.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include \"lkc.h\"\n\nstatic const char nohelp_text[] = \"There is no help available for this option.\";\n\nstruct menu rootmenu;\nstatic struct menu **last_entry_ptr;\n\nstruct file *file_list;\nstruct file *current_file;\n\nvoid menu_warn(struct menu *menu, const char *fmt, ...)\n{\n\tva_list ap;\n\tva_start(ap, fmt);\n\tfprintf(stderr, \"%s:%d:warning: \", menu->file->name, menu->lineno);\n\tvfprintf(stderr, fmt, ap);\n\tfprintf(stderr, \"\\n\");\n\tva_end(ap);\n}\n\nstatic void prop_warn(struct property *prop, const char *fmt, ...)\n{\n\tva_list ap;\n\tva_start(ap, fmt);\n\tfprintf(stderr, \"%s:%d:warning: \", prop->file->name, prop->lineno);\n\tvfprintf(stderr, fmt, ap);\n\tfprintf(stderr, \"\\n\");\n\tva_end(ap);\n}\n\nvoid _menu_init(void)\n{\n\tcurrent_entry = current_menu = &rootmenu;\n\tlast_entry_ptr = &rootmenu.list;\n}\n\nvoid menu_add_entry(struct symbol *sym)\n{\n\tstruct menu *menu;\n\n\tmenu = xmalloc(sizeof(*menu));\n\tmemset(menu, 0, sizeof(*menu));\n\tmenu->sym = sym;\n\tmenu->parent = current_menu;\n\tmenu->file = current_file;\n\tmenu->lineno = zconf_lineno();\n\n\t*last_entry_ptr = menu;\n\tlast_entry_ptr = &menu->next;\n\tcurrent_entry = menu;\n\tif (sym)\n\t\tmenu_add_symbol(P_SYMBOL, sym, NULL);\n}\n\nstruct menu *menu_add_menu(void)\n{\n\tlast_entry_ptr = &current_entry->list;\n\tcurrent_menu = current_entry;\n\treturn current_menu;\n}\n\nvoid menu_end_menu(void)\n{\n\tlast_entry_ptr = &current_menu->next;\n\tcurrent_menu = current_menu->parent;\n}\n\n/*\n * Rewrites 'm' to 'm' && MODULES, so that it evaluates to 'n' when running\n * without modules\n */\nstatic struct expr *rewrite_m(struct expr *e)\n{\n\tif (!e)\n\t\treturn e;\n\n\tswitch (e->type) {\n\tcase E_NOT:\n\t\te->left.expr = rewrite_m(e->left.expr);\n\t\tbreak;\n\tcase E_OR:\n\tcase E_AND:\n\t\te->left.expr = rewrite_m(e->left.expr);\n\t\te->right.expr = rewrite_m(e->right.expr);\n\t\tbreak;\n\tcase E_SYMBOL:\n\t\t/* change 'm' into 'm' && MODULES */\n\t\tif (e->left.sym == &symbol_mod)\n\t\t\treturn expr_alloc_and(e, expr_alloc_symbol(modules_sym));\n\t\tbreak;\n\tdefault:\n\t\tbreak;\n\t}\n\treturn e;\n}\n\nvoid menu_add_dep(struct expr *dep)\n{\n\tcurrent_entry->dep = expr_alloc_and(current_entry->dep, dep);\n}\n\nvoid menu_set_type(int type)\n{\n\tstruct symbol *sym = current_entry->sym;\n\n\tif (sym->type == type)\n\t\treturn;\n\tif (sym->type == S_UNKNOWN) {\n\t\tsym->type = type;\n\t\treturn;\n\t}\n\tmenu_warn(current_entry,\n\t\t\"ignoring type redefinition of '%s' from '%s' to '%s'\",\n\t\tsym->name ? sym->name : \"<choice>\",\n\t\tsym_type_name(sym->type), sym_type_name(type));\n}\n\nstatic struct property *menu_add_prop(enum prop_type type, struct expr *expr,\n\t\t\t\t      struct expr *dep)\n{\n\tstruct property *prop;\n\n\tprop = xmalloc(sizeof(*prop));\n\tmemset(prop, 0, sizeof(*prop));\n\tprop->type = type;\n\tprop->file = current_file;\n\tprop->lineno = zconf_lineno();\n\tprop->menu = current_entry;\n\tprop->expr = expr;\n\tprop->visible.expr = dep;\n\n\t/* append property to the prop list of symbol */\n\tif (current_entry->sym) {\n\t\tstruct property **propp;\n\n\t\tfor (propp = &current_entry->sym->prop;\n\t\t     *propp;\n\t\t     propp = &(*propp)->next)\n\t\t\t;\n\t\t*propp = prop;\n\t}\n\n\treturn prop;\n}\n\nstruct property *menu_add_prompt(enum prop_type type, char *prompt,\n\t\t\t\t struct expr *dep)\n{\n\tstruct property *prop = menu_add_prop(type, NULL, dep);\n\n\tif (isspace(*prompt)) {\n\t\tprop_warn(prop, \"leading whitespace ignored\");\n\t\twhile (isspace(*prompt))\n\t\t\tprompt++;\n\t}\n\tif (current_entry->prompt)\n\t\tprop_warn(prop, \"prompt redefined\");\n\n\t/* Apply all upper menus' visibilities to actual prompts. */\n\tif (type == P_PROMPT) {\n\t\tstruct menu *menu = current_entry;\n\n\t\twhile ((menu = menu->parent) != NULL) {\n\t\t\tstruct expr *dup_expr;\n\n\t\t\tif (!menu->visibility)\n\t\t\t\tcontinue;\n\t\t\t/*\n\t\t\t * Do not add a reference to the menu's visibility\n\t\t\t * expression but use a copy of it. Otherwise the\n\t\t\t * expression reduction functions will modify\n\t\t\t * expressions that have multiple references which\n\t\t\t * can cause unwanted side effects.\n\t\t\t */\n\t\t\tdup_expr = expr_copy(menu->visibility);\n\n\t\t\tprop->visible.expr = expr_alloc_and(prop->visible.expr,\n\t\t\t\t\t\t\t    dup_expr);\n\t\t}\n\t}\n\n\tcurrent_entry->prompt = prop;\n\tprop->text = prompt;\n\n\treturn prop;\n}\n\nvoid menu_add_visibility(struct expr *expr)\n{\n\tcurrent_entry->visibility = expr_alloc_and(current_entry->visibility,\n\t    expr);\n}\n\nvoid menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep)\n{\n\tmenu_add_prop(type, expr, dep);\n}\n\nvoid menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep)\n{\n\tmenu_add_prop(type, expr_alloc_symbol(sym), dep);\n}\n\nvoid menu_add_option_modules(void)\n{\n\tif (modules_sym)\n\t\tzconf_error(\"symbol '%s' redefines option 'modules' already defined by symbol '%s'\",\n\t\t\t    current_entry->sym->name, modules_sym->name);\n\tmodules_sym = current_entry->sym;\n}\n\nvoid menu_add_option_defconfig_list(void)\n{\n\tif (!sym_defconfig_list)\n\t\tsym_defconfig_list = current_entry->sym;\n\telse if (sym_defconfig_list != current_entry->sym)\n\t\tzconf_error(\"trying to redefine defconfig symbol\");\n\tsym_defconfig_list->flags |= SYMBOL_NO_WRITE;\n}\n\nvoid menu_add_option_allnoconfig_y(void)\n{\n\tcurrent_entry->sym->flags |= SYMBOL_ALLNOCONFIG_Y;\n}\n\nstatic int menu_validate_number(struct symbol *sym, struct symbol *sym2)\n{\n\treturn sym2->type == S_INT || sym2->type == S_HEX ||\n\t       (sym2->type == S_UNKNOWN && sym_string_valid(sym, sym2->name));\n}\n\nstatic void sym_check_prop(struct symbol *sym)\n{\n\tstruct property *prop;\n\tstruct symbol *sym2;\n\tchar *use;\n\n\tfor (prop = sym->prop; prop; prop = prop->next) {\n\t\tswitch (prop->type) {\n\t\tcase P_DEFAULT:\n\t\t\tif ((sym->type == S_STRING || sym->type == S_INT || sym->type == S_HEX) &&\n\t\t\t    prop->expr->type != E_SYMBOL)\n\t\t\t\tprop_warn(prop,\n\t\t\t\t    \"default for config symbol '%s'\"\n\t\t\t\t    \" must be a single symbol\", sym->name);\n\t\t\tif (prop->expr->type != E_SYMBOL)\n\t\t\t\tbreak;\n\t\t\tsym2 = prop_get_symbol(prop);\n\t\t\tif (sym->type == S_HEX || sym->type == S_INT) {\n\t\t\t\tif (!menu_validate_number(sym, sym2))\n\t\t\t\t\tprop_warn(prop,\n\t\t\t\t\t    \"'%s': number is invalid\",\n\t\t\t\t\t    sym->name);\n\t\t\t}\n\t\t\tif (sym_is_choice(sym)) {\n\t\t\t\tstruct property *choice_prop =\n\t\t\t\t\tsym_get_choice_prop(sym2);\n\n\t\t\t\tif (!choice_prop ||\n\t\t\t\t    prop_get_symbol(choice_prop) != sym)\n\t\t\t\t\tprop_warn(prop,\n\t\t\t\t\t\t  \"choice default symbol '%s' is not contained in the choice\",\n\t\t\t\t\t\t  sym2->name);\n\t\t\t}\n\t\t\tbreak;\n\t\tcase P_SELECT:\n\t\tcase P_IMPLY:\n\t\t\tuse = prop->type == P_SELECT ? \"select\" : \"imply\";\n\t\t\tsym2 = prop_get_symbol(prop);\n\t\t\tif (sym->type != S_BOOLEAN && sym->type != S_TRISTATE)\n\t\t\t\tprop_warn(prop,\n\t\t\t\t    \"config symbol '%s' uses %s, but is \"\n\t\t\t\t    \"not bool or tristate\", sym->name, use);\n\t\t\telse if (sym2->type != S_UNKNOWN &&\n\t\t\t\t sym2->type != S_BOOLEAN &&\n\t\t\t\t sym2->type != S_TRISTATE)\n\t\t\t\tprop_warn(prop,\n\t\t\t\t    \"'%s' has wrong type. '%s' only \"\n\t\t\t\t    \"accept arguments of bool and \"\n\t\t\t\t    \"tristate type\", sym2->name, use);\n\t\t\tbreak;\n\t\tcase P_RANGE:\n\t\t\tif (sym->type != S_INT && sym->type != S_HEX)\n\t\t\t\tprop_warn(prop, \"range is only allowed \"\n\t\t\t\t\t\t\"for int or hex symbols\");\n\t\t\tif (!menu_validate_number(sym, prop->expr->left.sym) ||\n\t\t\t    !menu_validate_number(sym, prop->expr->right.sym))\n\t\t\t\tprop_warn(prop, \"range is invalid\");\n\t\t\tbreak;\n\t\tdefault:\n\t\t\t;\n\t\t}\n\t}\n}\n\nvoid menu_finalize(struct menu *parent)\n{\n\tstruct menu *menu, *last_menu;\n\tstruct symbol *sym;\n\tstruct property *prop;\n\tstruct expr *parentdep, *basedep, *dep, *dep2, **ep;\n\n\tsym = parent->sym;\n\tif (parent->list) {\n\t\t/*\n\t\t * This menu node has children. We (recursively) process them\n\t\t * and propagate parent dependencies before moving on.\n\t\t */\n\n\t\tif (sym && sym_is_choice(sym)) {\n\t\t\tif (sym->type == S_UNKNOWN) {\n\t\t\t\t/* find the first choice value to find out choice type */\n\t\t\t\tcurrent_entry = parent;\n\t\t\t\tfor (menu = parent->list; menu; menu = menu->next) {\n\t\t\t\t\tif (menu->sym && menu->sym->type != S_UNKNOWN) {\n\t\t\t\t\t\tmenu_set_type(menu->sym->type);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t/* set the type of the remaining choice values */\n\t\t\tfor (menu = parent->list; menu; menu = menu->next) {\n\t\t\t\tcurrent_entry = menu;\n\t\t\t\tif (menu->sym && menu->sym->type == S_UNKNOWN)\n\t\t\t\t\tmenu_set_type(sym->type);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t * Use the choice itself as the parent dependency of\n\t\t\t * the contained items. This turns the mode of the\n\t\t\t * choice into an upper bound on the visibility of the\n\t\t\t * choice value symbols.\n\t\t\t */\n\t\t\tparentdep = expr_alloc_symbol(sym);\n\t\t} else {\n\t\t\t/* Menu node for 'menu', 'if' */\n\t\t\tparentdep = parent->dep;\n\t\t}\n\n\t\t/* For each child menu node... */\n\t\tfor (menu = parent->list; menu; menu = menu->next) {\n\t\t\t/*\n\t\t\t * Propagate parent dependencies to the child menu\n\t\t\t * node, also rewriting and simplifying expressions\n\t\t\t */\n\t\t\tbasedep = rewrite_m(menu->dep);\n\t\t\tbasedep = expr_transform(basedep);\n\t\t\tbasedep = expr_alloc_and(expr_copy(parentdep), basedep);\n\t\t\tbasedep = expr_eliminate_dups(basedep);\n\t\t\tmenu->dep = basedep;\n\n\t\t\tif (menu->sym)\n\t\t\t\t/*\n\t\t\t\t * Note: For symbols, all prompts are included\n\t\t\t\t * too in the symbol's own property list\n\t\t\t\t */\n\t\t\t\tprop = menu->sym->prop;\n\t\t\telse\n\t\t\t\t/*\n\t\t\t\t * For non-symbol menu nodes, we just need to\n\t\t\t\t * handle the prompt\n\t\t\t\t */\n\t\t\t\tprop = menu->prompt;\n\n\t\t\t/* For each property... */\n\t\t\tfor (; prop; prop = prop->next) {\n\t\t\t\tif (prop->menu != menu)\n\t\t\t\t\t/*\n\t\t\t\t\t * Two possibilities:\n\t\t\t\t\t *\n\t\t\t\t\t * 1. The property lacks dependencies\n\t\t\t\t\t *    and so isn't location-specific,\n\t\t\t\t\t *    e.g. an 'option'\n\t\t\t\t\t *\n\t\t\t\t\t * 2. The property belongs to a symbol\n\t\t\t\t\t *    defined in multiple locations and\n\t\t\t\t\t *    is from some other location. It\n\t\t\t\t\t *    will be handled there in that\n\t\t\t\t\t *    case.\n\t\t\t\t\t *\n\t\t\t\t\t * Skip the property.\n\t\t\t\t\t */\n\t\t\t\t\tcontinue;\n\n\t\t\t\t/*\n\t\t\t\t * Propagate parent dependencies to the\n\t\t\t\t * property's condition, rewriting and\n\t\t\t\t * simplifying expressions at the same time\n\t\t\t\t */\n\t\t\t\tdep = rewrite_m(prop->visible.expr);\n\t\t\t\tdep = expr_transform(dep);\n\t\t\t\tdep = expr_alloc_and(expr_copy(basedep), dep);\n\t\t\t\tdep = expr_eliminate_dups(dep);\n\t\t\t\tif (menu->sym && menu->sym->type != S_TRISTATE)\n\t\t\t\t\tdep = expr_trans_bool(dep);\n\t\t\t\tprop->visible.expr = dep;\n\n\t\t\t\t/*\n\t\t\t\t * Handle selects and implies, which modify the\n\t\t\t\t * dependencies of the selected/implied symbol\n\t\t\t\t */\n\t\t\t\tif (prop->type == P_SELECT) {\n\t\t\t\t\tstruct symbol *es = prop_get_symbol(prop);\n\t\t\t\t\tes->rev_dep.expr = expr_alloc_or(es->rev_dep.expr,\n\t\t\t\t\t\t\texpr_alloc_and(expr_alloc_symbol(menu->sym), expr_copy(dep)));\n\t\t\t\t} else if (prop->type == P_IMPLY) {\n\t\t\t\t\tstruct symbol *es = prop_get_symbol(prop);\n\t\t\t\t\tes->implied.expr = expr_alloc_or(es->implied.expr,\n\t\t\t\t\t\t\texpr_alloc_and(expr_alloc_symbol(menu->sym), expr_copy(dep)));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (sym && sym_is_choice(sym))\n\t\t\texpr_free(parentdep);\n\n\t\t/*\n\t\t * Recursively process children in the same fashion before\n\t\t * moving on\n\t\t */\n\t\tfor (menu = parent->list; menu; menu = menu->next)\n\t\t\tmenu_finalize(menu);\n\t} else if (sym) {\n\t\t/*\n\t\t * Automatic submenu creation. If sym is a symbol and A, B, C,\n\t\t * ... are consecutive items (symbols, menus, ifs, etc.) that\n\t\t * all depend on sym, then the following menu structure is\n\t\t * created:\n\t\t *\n\t\t *\tsym\n\t\t *\t +-A\n\t\t *\t +-B\n\t\t *\t +-C\n\t\t *\t ...\n\t\t *\n\t\t * This also works recursively, giving the following structure\n\t\t * if A is a symbol and B depends on A:\n\t\t *\n\t\t *\tsym\n\t\t *\t +-A\n\t\t *\t | +-B\n\t\t *\t +-C\n\t\t *\t ...\n\t\t */\n\n\t\tbasedep = parent->prompt ? parent->prompt->visible.expr : NULL;\n\t\tbasedep = expr_trans_compare(basedep, E_UNEQUAL, &symbol_no);\n\t\tbasedep = expr_eliminate_dups(expr_transform(basedep));\n\n\t\t/* Examine consecutive elements after sym */\n\t\tlast_menu = NULL;\n\t\tfor (menu = parent->next; menu; menu = menu->next) {\n\t\t\tdep = menu->prompt ? menu->prompt->visible.expr : menu->dep;\n\t\t\tif (!expr_contains_symbol(dep, sym))\n\t\t\t\t/* No dependency, quit */\n\t\t\t\tbreak;\n\t\t\tif (expr_depends_symbol(dep, sym))\n\t\t\t\t/* Absolute dependency, put in submenu */\n\t\t\t\tgoto next;\n\n\t\t\t/*\n\t\t\t * Also consider it a dependency on sym if our\n\t\t\t * dependencies contain sym and are a \"superset\" of\n\t\t\t * sym's dependencies, e.g. '(sym || Q) && R' when sym\n\t\t\t * depends on R.\n\t\t\t *\n\t\t\t * Note that 'R' might be from an enclosing menu or if,\n\t\t\t * making this a more common case than it might seem.\n\t\t\t */\n\t\t\tdep = expr_trans_compare(dep, E_UNEQUAL, &symbol_no);\n\t\t\tdep = expr_eliminate_dups(expr_transform(dep));\n\t\t\tdep2 = expr_copy(basedep);\n\t\t\texpr_eliminate_eq(&dep, &dep2);\n\t\t\texpr_free(dep);\n\t\t\tif (!expr_is_yes(dep2)) {\n\t\t\t\t/* Not superset, quit */\n\t\t\t\texpr_free(dep2);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t/* Superset, put in submenu */\n\t\t\texpr_free(dep2);\n\t\tnext:\n\t\t\tmenu_finalize(menu);\n\t\t\tmenu->parent = parent;\n\t\t\tlast_menu = menu;\n\t\t}\n\t\texpr_free(basedep);\n\t\tif (last_menu) {\n\t\t\tparent->list = parent->next;\n\t\t\tparent->next = last_menu->next;\n\t\t\tlast_menu->next = NULL;\n\t\t}\n\n\t\tsym->dir_dep.expr = expr_alloc_or(sym->dir_dep.expr, parent->dep);\n\t}\n\tfor (menu = parent->list; menu; menu = menu->next) {\n\t\tif (sym && sym_is_choice(sym) &&\n\t\t    menu->sym && !sym_is_choice_value(menu->sym)) {\n\t\t\tcurrent_entry = menu;\n\t\t\tmenu->sym->flags |= SYMBOL_CHOICEVAL;\n\t\t\tif (!menu->prompt)\n\t\t\t\tmenu_warn(menu, \"choice value must have a prompt\");\n\t\t\tfor (prop = menu->sym->prop; prop; prop = prop->next) {\n\t\t\t\tif (prop->type == P_DEFAULT)\n\t\t\t\t\tprop_warn(prop, \"defaults for choice \"\n\t\t\t\t\t\t  \"values not supported\");\n\t\t\t\tif (prop->menu == menu)\n\t\t\t\t\tcontinue;\n\t\t\t\tif (prop->type == P_PROMPT &&\n\t\t\t\t    prop->menu->parent->sym != sym)\n\t\t\t\t\tprop_warn(prop, \"choice value used outside its choice group\");\n\t\t\t}\n\t\t\t/* Non-tristate choice values of tristate choices must\n\t\t\t * depend on the choice being set to Y. The choice\n\t\t\t * values' dependencies were propagated to their\n\t\t\t * properties above, so the change here must be re-\n\t\t\t * propagated.\n\t\t\t */\n\t\t\tif (sym->type == S_TRISTATE && menu->sym->type != S_TRISTATE) {\n\t\t\t\tbasedep = expr_alloc_comp(E_EQUAL, sym, &symbol_yes);\n\t\t\t\tmenu->dep = expr_alloc_and(basedep, menu->dep);\n\t\t\t\tfor (prop = menu->sym->prop; prop; prop = prop->next) {\n\t\t\t\t\tif (prop->menu != menu)\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\tprop->visible.expr = expr_alloc_and(expr_copy(basedep),\n\t\t\t\t\t\t\t\t\t    prop->visible.expr);\n\t\t\t\t}\n\t\t\t}\n\t\t\tmenu_add_symbol(P_CHOICE, sym, NULL);\n\t\t\tprop = sym_get_choice_prop(sym);\n\t\t\tfor (ep = &prop->expr; *ep; ep = &(*ep)->left.expr)\n\t\t\t\t;\n\t\t\t*ep = expr_alloc_one(E_LIST, NULL);\n\t\t\t(*ep)->right.sym = menu->sym;\n\t\t}\n\n\t\t/*\n\t\t * This code serves two purposes:\n\t\t *\n\t\t * (1) Flattening 'if' blocks, which do not specify a submenu\n\t\t *     and only add dependencies.\n\t\t *\n\t\t *     (Automatic submenu creation might still create a submenu\n\t\t *     from an 'if' before this code runs.)\n\t\t *\n\t\t * (2) \"Undoing\" any automatic submenus created earlier below\n\t\t *     promptless symbols.\n\t\t *\n\t\t * Before:\n\t\t *\n\t\t *\tA\n\t\t *\tif ... (or promptless symbol)\n\t\t *\t +-B\n\t\t *\t +-C\n\t\t *\tD\n\t\t *\n\t\t * After:\n\t\t *\n\t\t *\tA\n\t\t *\tif ... (or promptless symbol)\n\t\t *\tB\n\t\t *\tC\n\t\t *\tD\n\t\t */\n\t\tif (menu->list && (!menu->prompt || !menu->prompt->text)) {\n\t\t\tfor (last_menu = menu->list; ; last_menu = last_menu->next) {\n\t\t\t\tlast_menu->parent = parent;\n\t\t\t\tif (!last_menu->next)\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tlast_menu->next = menu->next;\n\t\t\tmenu->next = menu->list;\n\t\t\tmenu->list = NULL;\n\t\t}\n\t}\n\n\tif (sym && !(sym->flags & SYMBOL_WARNED)) {\n\t\tif (sym->type == S_UNKNOWN)\n\t\t\tmenu_warn(parent, \"config symbol defined without type\");\n\n\t\tif (sym_is_choice(sym) && !parent->prompt)\n\t\t\tmenu_warn(parent, \"choice must have a prompt\");\n\n\t\t/* Check properties connected to this symbol */\n\t\tsym_check_prop(sym);\n\t\tsym->flags |= SYMBOL_WARNED;\n\t}\n\n\t/*\n\t * For non-optional choices, add a reverse dependency (corresponding to\n\t * a select) of '<visibility> && m'. This prevents the user from\n\t * setting the choice mode to 'n' when the choice is visible.\n\t *\n\t * This would also work for non-choice symbols, but only non-optional\n\t * choices clear SYMBOL_OPTIONAL as of writing. Choices are implemented\n\t * as a type of symbol.\n\t */\n\tif (sym && !sym_is_optional(sym) && parent->prompt) {\n\t\tsym->rev_dep.expr = expr_alloc_or(sym->rev_dep.expr,\n\t\t\t\texpr_alloc_and(parent->prompt->visible.expr,\n\t\t\t\t\texpr_alloc_symbol(&symbol_mod)));\n\t}\n}\n\nbool menu_has_prompt(struct menu *menu)\n{\n\tif (!menu->prompt)\n\t\treturn false;\n\treturn true;\n}\n\n/*\n * Determine if a menu is empty.\n * A menu is considered empty if it contains no or only\n * invisible entries.\n */\nbool menu_is_empty(struct menu *menu)\n{\n\tstruct menu *child;\n\n\tfor (child = menu->list; child; child = child->next) {\n\t\tif (menu_is_visible(child))\n\t\t\treturn(false);\n\t}\n\treturn(true);\n}\n\nbool menu_is_visible(struct menu *menu)\n{\n\tstruct menu *child;\n\tstruct symbol *sym;\n\ttristate visible;\n\n\tif (!menu->prompt)\n\t\treturn false;\n\n\tif (menu->visibility) {\n\t\tif (expr_calc_value(menu->visibility) == no)\n\t\t\treturn false;\n\t}\n\n\tsym = menu->sym;\n\tif (sym) {\n\t\tsym_calc_value(sym);\n\t\tvisible = menu->prompt->visible.tri;\n\t} else\n\t\tvisible = menu->prompt->visible.tri = expr_calc_value(menu->prompt->visible.expr);\n\n\tif (visible != no)\n\t\treturn true;\n\n\tif (!sym || sym_get_tristate_value(menu->sym) == no)\n\t\treturn false;\n\n\tfor (child = menu->list; child; child = child->next) {\n\t\tif (menu_is_visible(child)) {\n\t\t\tif (sym)\n\t\t\t\tsym->flags |= SYMBOL_DEF_USER;\n\t\t\treturn true;\n\t\t}\n\t}\n\n\treturn false;\n}\n\nconst char *menu_get_prompt(struct menu *menu)\n{\n\tif (menu->prompt)\n\t\treturn menu->prompt->text;\n\telse if (menu->sym)\n\t\treturn menu->sym->name;\n\treturn NULL;\n}\n\nstruct menu *menu_get_root_menu(struct menu *menu)\n{\n\treturn &rootmenu;\n}\n\nstruct menu *menu_get_parent_menu(struct menu *menu)\n{\n\tenum prop_type type;\n\n\tfor (; menu != &rootmenu; menu = menu->parent) {\n\t\ttype = menu->prompt ? menu->prompt->type : 0;\n\t\tif (type == P_MENU)\n\t\t\tbreak;\n\t}\n\treturn menu;\n}\n\nbool menu_has_help(struct menu *menu)\n{\n\treturn menu->help != NULL;\n}\n\nconst char *menu_get_help(struct menu *menu)\n{\n\tif (menu->help)\n\t\treturn menu->help;\n\telse\n\t\treturn \"\";\n}\n\nstatic void get_def_str(struct gstr *r, struct menu *menu)\n{\n\tstr_printf(r, \"Defined at %s:%d\\n\",\n\t\t   menu->file->name, menu->lineno);\n}\n\nstatic void get_dep_str(struct gstr *r, struct expr *expr, const char *prefix)\n{\n\tif (!expr_is_yes(expr)) {\n\t\tstr_append(r, prefix);\n\t\texpr_gstr_print(expr, r);\n\t\tstr_append(r, \"\\n\");\n\t}\n}\n\nstatic void get_prompt_str(struct gstr *r, struct property *prop,\n\t\t\t   struct list_head *head)\n{\n\tint i, j;\n\tstruct menu *submenu[8], *menu, *location = NULL;\n\tstruct jump_key *jump = NULL;\n\n\tstr_printf(r, \"  Prompt: %s\\n\", prop->text);\n\n\tget_dep_str(r, prop->menu->dep, \"  Depends on: \");\n\t/*\n\t * Most prompts in Linux have visibility that exactly matches their\n\t * dependencies. For these, we print only the dependencies to improve\n\t * readability. However, prompts with inline \"if\" expressions and\n\t * prompts with a parent that has a \"visible if\" expression have\n\t * differing dependencies and visibility. In these rare cases, we\n\t * print both.\n\t */\n\tif (!expr_eq(prop->menu->dep, prop->visible.expr))\n\t\tget_dep_str(r, prop->visible.expr, \"  Visible if: \");\n\n\tmenu = prop->menu->parent;\n\tfor (i = 0; menu != &rootmenu && i < 8; menu = menu->parent) {\n\t\tbool accessible = menu_is_visible(menu);\n\n\t\tsubmenu[i++] = menu;\n\t\tif (location == NULL && accessible)\n\t\t\tlocation = menu;\n\t}\n\tif (head && location) {\n\t\tjump = xmalloc(sizeof(struct jump_key));\n\n\t\tif (menu_is_visible(prop->menu)) {\n\t\t\t/*\n\t\t\t * There is not enough room to put the hint at the\n\t\t\t * beginning of the \"Prompt\" line. Put the hint on the\n\t\t\t * last \"Location\" line even when it would belong on\n\t\t\t * the former.\n\t\t\t */\n\t\t\tjump->target = prop->menu;\n\t\t} else\n\t\t\tjump->target = location;\n\n\t\tif (list_empty(head))\n\t\t\tjump->index = 0;\n\t\telse\n\t\t\tjump->index = list_entry(head->prev, struct jump_key,\n\t\t\t\t\t\t entries)->index + 1;\n\n\t\tlist_add_tail(&jump->entries, head);\n\t}\n\n\tif (i > 0) {\n\t\tstr_printf(r, \"  Location:\\n\");\n\t\tfor (j = 4; --i >= 0; j += 2) {\n\t\t\tmenu = submenu[i];\n\t\t\tif (jump && menu == location)\n\t\t\t\tjump->offset = strlen(r->s);\n\t\t\tstr_printf(r, \"%*c-> %s\", j, ' ',\n\t\t\t\t   menu_get_prompt(menu));\n\t\t\tif (menu->sym) {\n\t\t\t\tstr_printf(r, \" (%s [=%s])\", menu->sym->name ?\n\t\t\t\t\tmenu->sym->name : \"<choice>\",\n\t\t\t\t\tsym_get_string_value(menu->sym));\n\t\t\t}\n\t\t\tstr_append(r, \"\\n\");\n\t\t}\n\t}\n}\n\nstatic void get_symbol_props_str(struct gstr *r, struct symbol *sym,\n\t\t\t\t enum prop_type tok, const char *prefix)\n{\n\tbool hit = false;\n\tstruct property *prop;\n\n\tfor_all_properties(sym, prop, tok) {\n\t\tif (!hit) {\n\t\t\tstr_append(r, prefix);\n\t\t\thit = true;\n\t\t} else\n\t\t\tstr_printf(r, \" && \");\n\t\texpr_gstr_print(prop->expr, r);\n\t}\n\tif (hit)\n\t\tstr_append(r, \"\\n\");\n}\n\n/*\n * head is optional and may be NULL\n */\nstatic void get_symbol_str(struct gstr *r, struct symbol *sym,\n\t\t    struct list_head *head)\n{\n\tstruct property *prop;\n\n\tif (sym && sym->name) {\n\t\tstr_printf(r, \"Symbol: %s [=%s]\\n\", sym->name,\n\t\t\t   sym_get_string_value(sym));\n\t\tstr_printf(r, \"Type  : %s\\n\", sym_type_name(sym->type));\n\t\tif (sym->type == S_INT || sym->type == S_HEX) {\n\t\t\tprop = sym_get_range_prop(sym);\n\t\t\tif (prop) {\n\t\t\t\tstr_printf(r, \"Range : \");\n\t\t\t\texpr_gstr_print(prop->expr, r);\n\t\t\t\tstr_append(r, \"\\n\");\n\t\t\t}\n\t\t}\n\t}\n\n\t/* Print the definitions with prompts before the ones without */\n\tfor_all_properties(sym, prop, P_SYMBOL) {\n\t\tif (prop->menu->prompt) {\n\t\t\tget_def_str(r, prop->menu);\n\t\t\tget_prompt_str(r, prop->menu->prompt, head);\n\t\t}\n\t}\n\n\tfor_all_properties(sym, prop, P_SYMBOL) {\n\t\tif (!prop->menu->prompt) {\n\t\t\tget_def_str(r, prop->menu);\n\t\t\tget_dep_str(r, prop->menu->dep, \"  Depends on: \");\n\t\t}\n\t}\n\n\tget_symbol_props_str(r, sym, P_SELECT, \"Selects: \");\n\tif (sym->rev_dep.expr) {\n\t\texpr_gstr_print_revdep(sym->rev_dep.expr, r, yes, \"Selected by [y]:\\n\");\n\t\texpr_gstr_print_revdep(sym->rev_dep.expr, r, mod, \"Selected by [m]:\\n\");\n\t\texpr_gstr_print_revdep(sym->rev_dep.expr, r, no, \"Selected by [n]:\\n\");\n\t}\n\n\tget_symbol_props_str(r, sym, P_IMPLY, \"Implies: \");\n\tif (sym->implied.expr) {\n\t\texpr_gstr_print_revdep(sym->implied.expr, r, yes, \"Implied by [y]:\\n\");\n\t\texpr_gstr_print_revdep(sym->implied.expr, r, mod, \"Implied by [m]:\\n\");\n\t\texpr_gstr_print_revdep(sym->implied.expr, r, no, \"Implied by [n]:\\n\");\n\t}\n\n\tstr_append(r, \"\\n\\n\");\n}\n\nstruct gstr get_relations_str(struct symbol **sym_arr, struct list_head *head)\n{\n\tstruct symbol *sym;\n\tstruct gstr res = str_new();\n\tint i;\n\n\tfor (i = 0; sym_arr && (sym = sym_arr[i]); i++)\n\t\tget_symbol_str(&res, sym, head);\n\tif (!i)\n\t\tstr_append(&res, \"No matches found.\\n\");\n\treturn res;\n}\n\n\nvoid menu_get_ext_help(struct menu *menu, struct gstr *help)\n{\n\tstruct symbol *sym = menu->sym;\n\tconst char *help_text = nohelp_text;\n\n\tif (menu_has_help(menu)) {\n\t\tif (sym->name)\n\t\t\tstr_printf(help, \"%s%s:\\n\\n\", CONFIG_, sym->name);\n\t\thelp_text = menu_get_help(menu);\n\t}\n\tstr_printf(help, \"%s\\n\", help_text);\n\tif (sym)\n\t\tget_symbol_str(help, sym, NULL);\n}\n"
  },
  {
    "path": "3rdparty/kconfig/nconf-cfg.sh",
    "content": "#!/bin/sh\n# SPDX-License-Identifier: GPL-2.0\n\nPKG=\"ncursesw menuw panelw\"\nPKG2=\"ncurses menu panel\"\n\nif [ -n \"$(command -v pkg-config)\" ]; then\n\tif pkg-config --exists $PKG; then\n\t\techo cflags=\\\"$(pkg-config --cflags $PKG)\\\"\n\t\techo libs=\\\"$(pkg-config --libs $PKG)\\\"\n\t\texit 0\n\tfi\n\n\tif pkg-config --exists $PKG2; then\n\t\techo cflags=\\\"$(pkg-config --cflags $PKG2)\\\"\n\t\techo libs=\\\"$(pkg-config --libs $PKG2)\\\"\n\t\texit 0\n\tfi\nfi\n\n# Check the default paths in case pkg-config is not installed.\n# (Even if it is installed, some distributions such as openSUSE cannot\n# find ncurses by pkg-config.)\nif [ -f /usr/include/ncursesw/ncurses.h ]; then\n\techo cflags=\\\"-D_GNU_SOURCE -I/usr/include/ncursesw\\\"\n\techo libs=\\\"-lncursesw -lmenuw -lpanelw\\\"\n\texit 0\nfi\n\nif [ -f /usr/include/ncurses/ncurses.h ]; then\n\techo cflags=\\\"-D_GNU_SOURCE -I/usr/include/ncurses\\\"\n\techo libs=\\\"-lncurses -lmenu -lpanel\\\"\n\texit 0\nfi\n\nif [ -f /usr/include/ncurses.h ]; then\n\techo cflags=\\\"-D_GNU_SOURCE\\\"\n\techo libs=\\\"-lncurses -lmenu -lpanel\\\"\n\texit 0\nfi\n\necho >&2 \"*\"\necho >&2 \"* Unable to find the ncurses package.\"\necho >&2 \"* Install ncurses (ncurses-devel or libncurses-dev\"\necho >&2 \"* depending on your distribution).\"\necho >&2 \"*\"\necho >&2 \"* You may also need to install pkg-config to find the\"\necho >&2 \"* ncurses installed in a non-default location.\"\necho >&2 \"*\"\nexit 1\n"
  },
  {
    "path": "3rdparty/kconfig/nconf.c",
    "content": "// SPDX-License-Identifier: GPL-2.0\n/*\n * Copyright (C) 2008 Nir Tzachar <nir.tzachar@gmail.com>\n *\n * Derived from menuconfig.\n */\n#ifndef _GNU_SOURCE\n#define _GNU_SOURCE\n#endif\n#include <string.h>\n#include <strings.h>\n#include <stdlib.h>\n\n#include \"lkc.h\"\n#include \"nconf.h\"\n#include <ctype.h>\n\nstatic const char nconf_global_help[] =\n\"Help windows\\n\"\n\"------------\\n\"\n\"o  Global help:  Unless in a data entry window, pressing <F1> will give \\n\"\n\"   you the global help window, which you are just reading.\\n\"\n\"\\n\"\n\"o  A short version of the global help is available by pressing <F3>.\\n\"\n\"\\n\"\n\"o  Local help:  To get help related to the current menu entry, use any\\n\"\n\"   of <?> <h>, or if in a data entry window then press <F1>.\\n\"\n\"\\n\"\n\"\\n\"\n\"Menu entries\\n\"\n\"------------\\n\"\n\"This interface lets you select features and parameters for the kernel\\n\"\n\"build.  Kernel features can either be built-in, modularized, or removed.\\n\"\n\"Parameters must be entered as text or decimal or hexadecimal numbers.\\n\"\n\"\\n\"\n\"Menu entries beginning with following braces represent features that\\n\"\n\"  [ ]  can be built in or removed\\n\"\n\"  < >  can be built in, modularized or removed\\n\"\n\"  { }  can be built in or modularized, are selected by another feature\\n\"\n\"  - -  are selected by another feature\\n\"\n\"  XXX  cannot be selected.  Symbol Info <F2> tells you why.\\n\"\n\"*, M or whitespace inside braces means to build in, build as a module\\n\"\n\"or to exclude the feature respectively.\\n\"\n\"\\n\"\n\"To change any of these features, highlight it with the movement keys\\n\"\n\"listed below and press <y> to build it in, <m> to make it a module or\\n\"\n\"<n> to remove it.  You may press the <Space> key to cycle through the\\n\"\n\"available options.\\n\"\n\"\\n\"\n\"A trailing \\\"--->\\\" designates a submenu, a trailing \\\"----\\\" an\\n\"\n\"empty submenu.\\n\"\n\"\\n\"\n\"Menu navigation keys\\n\"\n\"----------------------------------------------------------------------\\n\"\n\"Linewise up                 <Up>\\n\"\n\"Linewise down               <Down>\\n\"\n\"Pagewise up                 <Page Up>\\n\"\n\"Pagewise down               <Page Down>\\n\"\n\"First entry                 <Home>\\n\"\n\"Last entry                  <End>\\n\"\n\"Enter a submenu             <Right>  <Enter>\\n\"\n\"Go back to parent menu      <Left>   <Esc>  <F5>\\n\"\n\"Close a help window         <Enter>  <Esc>  <F5>\\n\"\n\"Close entry window, apply   <Enter>\\n\"\n\"Close entry window, forget  <Esc>  <F5>\\n\"\n\"Start incremental, case-insensitive search for STRING in menu entries,\\n\"\n\"    no regex support, STRING is displayed in upper left corner\\n\"\n\"                            </>STRING\\n\"\n\"    Remove last character   <Backspace>\\n\"\n\"    Jump to next hit        <Down>\\n\"\n\"    Jump to previous hit    <Up>\\n\"\n\"Exit menu search mode       </>  <Esc>\\n\"\n\"Search for configuration variables with or without leading CONFIG_\\n\"\n\"                            <F8>RegExpr<Enter>\\n\"\n\"Verbose search help         <F8><F1>\\n\"\n\"----------------------------------------------------------------------\\n\"\n\"\\n\"\n\"Unless in a data entry window, key <1> may be used instead of <F1>,\\n\"\n\"<2> instead of <F2>, etc.\\n\"\n\"\\n\"\n\"\\n\"\n\"Radiolist (Choice list)\\n\"\n\"-----------------------\\n\"\n\"Use the movement keys listed above to select the option you wish to set\\n\"\n\"and press <Space>.\\n\"\n\"\\n\"\n\"\\n\"\n\"Data entry\\n\"\n\"----------\\n\"\n\"Enter the requested information and press <Enter>.  Hexadecimal values\\n\"\n\"may be entered without the \\\"0x\\\" prefix.\\n\"\n\"\\n\"\n\"\\n\"\n\"Text Box (Help Window)\\n\"\n\"----------------------\\n\"\n\"Use movement keys as listed in table above.\\n\"\n\"\\n\"\n\"Press any of <Enter> <Esc> <q> <F5> <F9> to exit.\\n\"\n\"\\n\"\n\"\\n\"\n\"Alternate configuration files\\n\"\n\"-----------------------------\\n\"\n\"nconfig supports switching between different configurations.\\n\"\n\"Press <F6> to save your current configuration.  Press <F7> and enter\\n\"\n\"a file name to load a previously saved configuration.\\n\"\n\"\\n\"\n\"\\n\"\n\"Terminal configuration\\n\"\n\"----------------------\\n\"\n\"If you use nconfig in a xterm window, make sure your TERM environment\\n\"\n\"variable specifies a terminal configuration which supports at least\\n\"\n\"16 colors.  Otherwise nconfig will look rather bad.\\n\"\n\"\\n\"\n\"If the \\\"stty size\\\" command reports the current terminalsize correctly,\\n\"\n\"nconfig will adapt to sizes larger than the traditional 80x25 \\\"standard\\\"\\n\"\n\"and display longer menus properly.\\n\"\n\"\\n\"\n\"\\n\"\n\"Single menu mode\\n\"\n\"----------------\\n\"\n\"If you prefer to have all of the menu entries listed in a single menu,\\n\"\n\"rather than the default multimenu hierarchy, run nconfig with\\n\"\n\"NCONFIG_MODE environment variable set to single_menu.  Example:\\n\"\n\"\\n\"\n\"make NCONFIG_MODE=single_menu nconfig\\n\"\n\"\\n\"\n\"<Enter> will then unfold the appropriate category, or fold it if it\\n\"\n\"is already unfolded.  Folded menu entries will be designated by a\\n\"\n\"leading \\\"++>\\\" and unfolded entries by a leading \\\"-->\\\".\\n\"\n\"\\n\"\n\"Note that this mode can eventually be a little more CPU expensive than\\n\"\n\"the default mode, especially with a larger number of unfolded submenus.\\n\"\n\"\\n\",\nmenu_no_f_instructions[] =\n\"Legend:  [*] built-in  [ ] excluded  <M> module  < > module capable.\\n\"\n\"Submenus are designated by a trailing \\\"--->\\\", empty ones by \\\"----\\\".\\n\"\n\"\\n\"\n\"Use the following keys to navigate the menus:\\n\"\n\"Move up or down with <Up> and <Down>.\\n\"\n\"Enter a submenu with <Enter> or <Right>.\\n\"\n\"Exit a submenu to its parent menu with <Esc> or <Left>.\\n\"\n\"Pressing <y> includes, <n> excludes, <m> modularizes features.\\n\"\n\"Pressing <Space> cycles through the available options.\\n\"\n\"To search for menu entries press </>.\\n\"\n\"<Esc> always leaves the current window.\\n\"\n\"\\n\"\n\"You do not have function keys support.\\n\"\n\"Press <1> instead of <F1>, <2> instead of <F2>, etc.\\n\"\n\"For verbose global help use key <1>.\\n\"\n\"For help related to the current menu entry press <?> or <h>.\\n\",\nmenu_instructions[] =\n\"Legend:  [*] built-in  [ ] excluded  <M> module  < > module capable.\\n\"\n\"Submenus are designated by a trailing \\\"--->\\\", empty ones by \\\"----\\\".\\n\"\n\"\\n\"\n\"Use the following keys to navigate the menus:\\n\"\n\"Move up or down with <Up> or <Down>.\\n\"\n\"Enter a submenu with <Enter> or <Right>.\\n\"\n\"Exit a submenu to its parent menu with <Esc> or <Left>.\\n\"\n\"Pressing <y> includes, <n> excludes, <m> modularizes features.\\n\"\n\"Pressing <Space> cycles through the available options.\\n\"\n\"To search for menu entries press </>.\\n\"\n\"<Esc> always leaves the current window.\\n\"\n\"\\n\"\n\"Pressing <1> may be used instead of <F1>, <2> instead of <F2>, etc.\\n\"\n\"For verbose global help press <F1>.\\n\"\n\"For help related to the current menu entry press <?> or <h>.\\n\",\nradiolist_instructions[] =\n\"Press <Up>, <Down>, <Home> or <End> to navigate a radiolist, select\\n\"\n\"with <Space>.\\n\"\n\"For help related to the current entry press <?> or <h>.\\n\"\n\"For global help press <F1>.\\n\",\ninputbox_instructions_int[] =\n\"Please enter a decimal value.\\n\"\n\"Fractions will not be accepted.\\n\"\n\"Press <Enter> to apply, <Esc> to cancel.\",\ninputbox_instructions_hex[] =\n\"Please enter a hexadecimal value.\\n\"\n\"Press <Enter> to apply, <Esc> to cancel.\",\ninputbox_instructions_string[] =\n\"Please enter a string value.\\n\"\n\"Press <Enter> to apply, <Esc> to cancel.\",\nsetmod_text[] =\n\"This feature depends on another feature which has been configured as a\\n\"\n\"module.  As a result, the current feature will be built as a module too.\",\nload_config_text[] =\n\"Enter the name of the configuration file you wish to load.\\n\"\n\"Accept the name shown to restore the configuration you last\\n\"\n\"retrieved.  Leave empty to abort.\",\nload_config_help[] =\n\"For various reasons, one may wish to keep several different\\n\"\n\"configurations available on a single machine.\\n\"\n\"\\n\"\n\"If you have saved a previous configuration in a file other than the\\n\"\n\"default one, entering its name here will allow you to load and modify\\n\"\n\"that configuration.\\n\"\n\"\\n\"\n\"Leave empty to abort.\\n\",\nsave_config_text[] =\n\"Enter a filename to which this configuration should be saved\\n\"\n\"as an alternate.  Leave empty to abort.\",\nsave_config_help[] =\n\"For various reasons, one may wish to keep several different\\n\"\n\"configurations available on a single machine.\\n\"\n\"\\n\"\n\"Entering a file name here will allow you to later retrieve, modify\\n\"\n\"and use the current configuration as an alternate to whatever\\n\"\n\"configuration options you have selected at that time.\\n\"\n\"\\n\"\n\"Leave empty to abort.\\n\",\nsearch_help[] =\n\"Search for symbols (configuration variable names CONFIG_*) and display\\n\"\n\"their relations.  Regular expressions are supported.\\n\"\n\"Example:  Search for \\\"^FOO\\\".\\n\"\n\"Result:\\n\"\n\"-----------------------------------------------------------------\\n\"\n\"Symbol: FOO [ = m]\\n\"\n\"Prompt: Foo bus is used to drive the bar HW\\n\"\n\"Defined at drivers/pci/Kconfig:47\\n\"\n\"Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\\n\"\n\"Location:\\n\"\n\"  -> Bus options (PCI, PCMCIA, EISA, ISA)\\n\"\n\"    -> PCI support (PCI [ = y])\\n\"\n\"      -> PCI access mode (<choice> [ = y])\\n\"\n\"Selects: LIBCRC32\\n\"\n\"Selected by: BAR\\n\"\n\"-----------------------------------------------------------------\\n\"\n\"o  The line 'Prompt:' shows the text displayed for this symbol in\\n\"\n\"   the menu hierarchy.\\n\"\n\"o  The 'Defined at' line tells at what file / line number the symbol is\\n\"\n\"   defined.\\n\"\n\"o  The 'Depends on:' line lists symbols that need to be defined for\\n\"\n\"   this symbol to be visible and selectable in the menu.\\n\"\n\"o  The 'Location:' lines tell, where in the menu structure this symbol\\n\"\n\"   is located.  A location followed by a [ = y] indicates that this is\\n\"\n\"   a selectable menu item, and the current value is displayed inside\\n\"\n\"   brackets.\\n\"\n\"o  The 'Selects:' line tells, what symbol will be automatically selected\\n\"\n\"   if this symbol is selected (y or m).\\n\"\n\"o  The 'Selected by' line tells what symbol has selected this symbol.\\n\"\n\"\\n\"\n\"Only relevant lines are shown.\\n\"\n\"\\n\\n\"\n\"Search examples:\\n\"\n\"USB  => find all symbols containing USB\\n\"\n\"^USB => find all symbols starting with USB\\n\"\n\"USB$ => find all symbols ending with USB\\n\"\n\"\\n\";\n\nstruct mitem {\n\tchar str[256];\n\tchar tag;\n\tvoid *usrptr;\n\tint is_visible;\n};\n\n#define MAX_MENU_ITEMS 4096\nstatic int show_all_items;\nstatic int indent;\nstatic struct menu *current_menu;\nstatic int child_count;\nstatic int single_menu_mode;\n/* the window in which all information appears */\nstatic WINDOW *main_window;\n/* the largest size of the menu window */\nstatic int mwin_max_lines;\nstatic int mwin_max_cols;\n/* the window in which we show option buttons */\nstatic MENU *curses_menu;\nstatic ITEM *curses_menu_items[MAX_MENU_ITEMS];\nstatic struct mitem k_menu_items[MAX_MENU_ITEMS];\nstatic int items_num;\nstatic int global_exit;\n/* the currently selected button */\nstatic const char *current_instructions = menu_instructions;\n\nstatic char *dialog_input_result;\nstatic int dialog_input_result_len;\n\nstatic void conf(struct menu *menu);\nstatic void conf_choice(struct menu *menu);\nstatic void conf_string(struct menu *menu);\nstatic void conf_load(void);\nstatic void conf_save(void);\nstatic void show_help(struct menu *menu);\nstatic int do_exit(void);\nstatic void setup_windows(void);\nstatic void search_conf(void);\n\ntypedef void (*function_key_handler_t)(int *key, struct menu *menu);\nstatic void handle_f1(int *key, struct menu *current_item);\nstatic void handle_f2(int *key, struct menu *current_item);\nstatic void handle_f3(int *key, struct menu *current_item);\nstatic void handle_f4(int *key, struct menu *current_item);\nstatic void handle_f5(int *key, struct menu *current_item);\nstatic void handle_f6(int *key, struct menu *current_item);\nstatic void handle_f7(int *key, struct menu *current_item);\nstatic void handle_f8(int *key, struct menu *current_item);\nstatic void handle_f9(int *key, struct menu *current_item);\n\nstruct function_keys {\n\tconst char *key_str;\n\tconst char *func;\n\tfunction_key key;\n\tfunction_key_handler_t handler;\n};\n\nstatic const int function_keys_num = 9;\nstatic struct function_keys function_keys[] = {\n\t{\n\t\t.key_str = \"F1\",\n\t\t.func = \"Help\",\n\t\t.key = F_HELP,\n\t\t.handler = handle_f1,\n\t},\n\t{\n\t\t.key_str = \"F2\",\n\t\t.func = \"SymInfo\",\n\t\t.key = F_SYMBOL,\n\t\t.handler = handle_f2,\n\t},\n\t{\n\t\t.key_str = \"F3\",\n\t\t.func = \"Help 2\",\n\t\t.key = F_INSTS,\n\t\t.handler = handle_f3,\n\t},\n\t{\n\t\t.key_str = \"F4\",\n\t\t.func = \"ShowAll\",\n\t\t.key = F_CONF,\n\t\t.handler = handle_f4,\n\t},\n\t{\n\t\t.key_str = \"F5\",\n\t\t.func = \"Back\",\n\t\t.key = F_BACK,\n\t\t.handler = handle_f5,\n\t},\n\t{\n\t\t.key_str = \"F6\",\n\t\t.func = \"Save\",\n\t\t.key = F_SAVE,\n\t\t.handler = handle_f6,\n\t},\n\t{\n\t\t.key_str = \"F7\",\n\t\t.func = \"Load\",\n\t\t.key = F_LOAD,\n\t\t.handler = handle_f7,\n\t},\n\t{\n\t\t.key_str = \"F8\",\n\t\t.func = \"SymSearch\",\n\t\t.key = F_SEARCH,\n\t\t.handler = handle_f8,\n\t},\n\t{\n\t\t.key_str = \"F9\",\n\t\t.func = \"Exit\",\n\t\t.key = F_EXIT,\n\t\t.handler = handle_f9,\n\t},\n};\n\nstatic void print_function_line(void)\n{\n\tint i;\n\tint offset = 1;\n\tconst int skip = 1;\n\tint lines = getmaxy(stdscr);\n\n\tfor (i = 0; i < function_keys_num; i++) {\n\t\t(void) wattrset(main_window, attributes[FUNCTION_HIGHLIGHT]);\n\t\tmvwprintw(main_window, lines-3, offset,\n\t\t\t\t\"%s\",\n\t\t\t\tfunction_keys[i].key_str);\n\t\t(void) wattrset(main_window, attributes[FUNCTION_TEXT]);\n\t\toffset += strlen(function_keys[i].key_str);\n\t\tmvwprintw(main_window, lines-3,\n\t\t\t\toffset, \"%s\",\n\t\t\t\tfunction_keys[i].func);\n\t\toffset += strlen(function_keys[i].func) + skip;\n\t}\n\t(void) wattrset(main_window, attributes[NORMAL]);\n}\n\n/* help */\nstatic void handle_f1(int *key, struct menu *current_item)\n{\n\tshow_scroll_win(main_window,\n\t\t\t\"Global help\", nconf_global_help);\n\treturn;\n}\n\n/* symbole help */\nstatic void handle_f2(int *key, struct menu *current_item)\n{\n\tshow_help(current_item);\n\treturn;\n}\n\n/* instructions */\nstatic void handle_f3(int *key, struct menu *current_item)\n{\n\tshow_scroll_win(main_window,\n\t\t\t\"Short help\",\n\t\t\tcurrent_instructions);\n\treturn;\n}\n\n/* config */\nstatic void handle_f4(int *key, struct menu *current_item)\n{\n\tint res = btn_dialog(main_window,\n\t\t\t\"Show all symbols?\",\n\t\t\t2,\n\t\t\t\"   <Show All>   \",\n\t\t\t\"<Don't show all>\");\n\tif (res == 0)\n\t\tshow_all_items = 1;\n\telse if (res == 1)\n\t\tshow_all_items = 0;\n\n\treturn;\n}\n\n/* back */\nstatic void handle_f5(int *key, struct menu *current_item)\n{\n\t*key = KEY_LEFT;\n\treturn;\n}\n\n/* save */\nstatic void handle_f6(int *key, struct menu *current_item)\n{\n\tconf_save();\n\treturn;\n}\n\n/* load */\nstatic void handle_f7(int *key, struct menu *current_item)\n{\n\tconf_load();\n\treturn;\n}\n\n/* search */\nstatic void handle_f8(int *key, struct menu *current_item)\n{\n\tsearch_conf();\n\treturn;\n}\n\n/* exit */\nstatic void handle_f9(int *key, struct menu *current_item)\n{\n\tdo_exit();\n\treturn;\n}\n\n/* return != 0 to indicate the key was handles */\nstatic int process_special_keys(int *key, struct menu *menu)\n{\n\tint i;\n\n\tif (*key == KEY_RESIZE) {\n\t\tsetup_windows();\n\t\treturn 1;\n\t}\n\n\tfor (i = 0; i < function_keys_num; i++) {\n\t\tif (*key == KEY_F(function_keys[i].key) ||\n\t\t    *key == '0' + function_keys[i].key){\n\t\t\tfunction_keys[i].handler(key, menu);\n\t\t\treturn 1;\n\t\t}\n\t}\n\n\treturn 0;\n}\n\nstatic void clean_items(void)\n{\n\tint i;\n\tfor (i = 0; curses_menu_items[i]; i++)\n\t\tfree_item(curses_menu_items[i]);\n\tbzero(curses_menu_items, sizeof(curses_menu_items));\n\tbzero(k_menu_items, sizeof(k_menu_items));\n\titems_num = 0;\n}\n\ntypedef enum {MATCH_TINKER_PATTERN_UP, MATCH_TINKER_PATTERN_DOWN,\n\tFIND_NEXT_MATCH_DOWN, FIND_NEXT_MATCH_UP} match_f;\n\n/* return the index of the matched item, or -1 if no such item exists */\nstatic int get_mext_match(const char *match_str, match_f flag)\n{\n\tint match_start = item_index(current_item(curses_menu));\n\tint index;\n\n\tif (flag == FIND_NEXT_MATCH_DOWN)\n\t\t++match_start;\n\telse if (flag == FIND_NEXT_MATCH_UP)\n\t\t--match_start;\n\n\tindex = match_start;\n\tindex = (index + items_num) % items_num;\n\twhile (true) {\n\t\tchar *str = k_menu_items[index].str;\n\t\tif (strcasestr(str, match_str) != NULL)\n\t\t\treturn index;\n\t\tif (flag == FIND_NEXT_MATCH_UP ||\n\t\t    flag == MATCH_TINKER_PATTERN_UP)\n\t\t\t--index;\n\t\telse\n\t\t\t++index;\n\t\tindex = (index + items_num) % items_num;\n\t\tif (index == match_start)\n\t\t\treturn -1;\n\t}\n}\n\n/* Make a new item. */\nstatic void item_make(struct menu *menu, char tag, const char *fmt, ...)\n{\n\tva_list ap;\n\n\tif (items_num > MAX_MENU_ITEMS-1)\n\t\treturn;\n\n\tbzero(&k_menu_items[items_num], sizeof(k_menu_items[0]));\n\tk_menu_items[items_num].tag = tag;\n\tk_menu_items[items_num].usrptr = menu;\n\tif (menu != NULL)\n\t\tk_menu_items[items_num].is_visible =\n\t\t\tmenu_is_visible(menu);\n\telse\n\t\tk_menu_items[items_num].is_visible = 1;\n\n\tva_start(ap, fmt);\n\tvsnprintf(k_menu_items[items_num].str,\n\t\t  sizeof(k_menu_items[items_num].str),\n\t\t  fmt, ap);\n\tva_end(ap);\n\n\tif (!k_menu_items[items_num].is_visible)\n\t\tmemcpy(k_menu_items[items_num].str, \"XXX\", 3);\n\n\tcurses_menu_items[items_num] = new_item(\n\t\t\tk_menu_items[items_num].str,\n\t\t\tk_menu_items[items_num].str);\n\tset_item_userptr(curses_menu_items[items_num],\n\t\t\t&k_menu_items[items_num]);\n\t/*\n\tif (!k_menu_items[items_num].is_visible)\n\t\titem_opts_off(curses_menu_items[items_num], O_SELECTABLE);\n\t*/\n\n\titems_num++;\n\tcurses_menu_items[items_num] = NULL;\n}\n\n/* very hackish. adds a string to the last item added */\nstatic void item_add_str(const char *fmt, ...)\n{\n\tva_list ap;\n\tint index = items_num-1;\n\tchar new_str[256];\n\tchar tmp_str[256];\n\n\tif (index < 0)\n\t\treturn;\n\n\tva_start(ap, fmt);\n\tvsnprintf(new_str, sizeof(new_str), fmt, ap);\n\tva_end(ap);\n\tsnprintf(tmp_str, sizeof(tmp_str), \"%s%s\",\n\t\t\tk_menu_items[index].str, new_str);\n\tstrncpy(k_menu_items[index].str,\n\t\ttmp_str,\n\t\tsizeof(k_menu_items[index].str));\n\n\tfree_item(curses_menu_items[index]);\n\tcurses_menu_items[index] = new_item(\n\t\t\tk_menu_items[index].str,\n\t\t\tk_menu_items[index].str);\n\tset_item_userptr(curses_menu_items[index],\n\t\t\t&k_menu_items[index]);\n}\n\n/* get the tag of the currently selected item */\nstatic char item_tag(void)\n{\n\tITEM *cur;\n\tstruct mitem *mcur;\n\n\tcur = current_item(curses_menu);\n\tif (cur == NULL)\n\t\treturn 0;\n\tmcur = (struct mitem *) item_userptr(cur);\n\treturn mcur->tag;\n}\n\nstatic int curses_item_index(void)\n{\n\treturn  item_index(current_item(curses_menu));\n}\n\nstatic void *item_data(void)\n{\n\tITEM *cur;\n\tstruct mitem *mcur;\n\n\tcur = current_item(curses_menu);\n\tif (!cur)\n\t\treturn NULL;\n\tmcur = (struct mitem *) item_userptr(cur);\n\treturn mcur->usrptr;\n\n}\n\nstatic int item_is_tag(char tag)\n{\n\treturn item_tag() == tag;\n}\n\nstatic char filename[PATH_MAX+1];\nstatic char menu_backtitle[PATH_MAX+128];\nstatic const char *set_config_filename(const char *config_filename)\n{\n\tint size;\n\n\tsize = snprintf(menu_backtitle, sizeof(menu_backtitle),\n\t\t\t\"%s - %s\", config_filename, rootmenu.prompt->text);\n\tif (size >= sizeof(menu_backtitle))\n\t\tmenu_backtitle[sizeof(menu_backtitle)-1] = '\\0';\n\n\tsize = snprintf(filename, sizeof(filename), \"%s\", config_filename);\n\tif (size >= sizeof(filename))\n\t\tfilename[sizeof(filename)-1] = '\\0';\n\treturn menu_backtitle;\n}\n\n/* return = 0 means we are successful.\n * -1 means go on doing what you were doing\n */\nstatic int do_exit(void)\n{\n\tint res;\n\tif (!conf_get_changed()) {\n\t\tglobal_exit = 1;\n\t\treturn 0;\n\t}\n\tres = btn_dialog(main_window,\n\t\t\t\"Do you wish to save your new configuration?\\n\"\n\t\t\t\t\"<ESC> to cancel and resume nconfig.\",\n\t\t\t2,\n\t\t\t\"   <save>   \",\n\t\t\t\"<don't save>\");\n\tif (res == KEY_EXIT) {\n\t\tglobal_exit = 0;\n\t\treturn -1;\n\t}\n\n\t/* if we got here, the user really wants to exit */\n\tswitch (res) {\n\tcase 0:\n\t\tres = conf_write(filename);\n\t\tif (res)\n\t\t\tbtn_dialog(\n\t\t\t\tmain_window,\n\t\t\t\t\"Error during writing of configuration.\\n\"\n\t\t\t\t  \"Your configuration changes were NOT saved.\",\n\t\t\t\t  1,\n\t\t\t\t  \"<OK>\");\n\t\tconf_write_autoconf(0);\n\t\tbreak;\n\tdefault:\n\t\tbtn_dialog(\n\t\t\tmain_window,\n\t\t\t\"Your configuration changes were NOT saved.\",\n\t\t\t1,\n\t\t\t\"<OK>\");\n\t\tbreak;\n\t}\n\tglobal_exit = 1;\n\treturn 0;\n}\n\n\nstatic void search_conf(void)\n{\n\tstruct symbol **sym_arr;\n\tstruct gstr res;\n\tstruct gstr title;\n\tchar *dialog_input;\n\tint dres;\n\n\ttitle = str_new();\n\tstr_printf( &title, \"Enter (sub)string or regexp to search for \"\n\t\t\t      \"(with or without \\\"%s\\\")\", CONFIG_);\n\nagain:\n\tdres = dialog_inputbox(main_window,\n\t\t\t\"Search Configuration Parameter\",\n\t\t\tstr_get(&title),\n\t\t\t\"\", &dialog_input_result, &dialog_input_result_len);\n\tswitch (dres) {\n\tcase 0:\n\t\tbreak;\n\tcase 1:\n\t\tshow_scroll_win(main_window,\n\t\t\t\t\"Search Configuration\", search_help);\n\t\tgoto again;\n\tdefault:\n\t\tstr_free(&title);\n\t\treturn;\n\t}\n\n\t/* strip the prefix if necessary */\n\tdialog_input = dialog_input_result;\n\tif (strncasecmp(dialog_input_result, CONFIG_, strlen(CONFIG_)) == 0)\n\t\tdialog_input += strlen(CONFIG_);\n\n\tsym_arr = sym_re_search(dialog_input);\n\tres = get_relations_str(sym_arr, NULL);\n\tfree(sym_arr);\n\tshow_scroll_win(main_window,\n\t\t\t\"Search Results\", str_get(&res));\n\tstr_free(&res);\n\tstr_free(&title);\n}\n\n\nstatic void build_conf(struct menu *menu)\n{\n\tstruct symbol *sym;\n\tstruct property *prop;\n\tstruct menu *child;\n\tint type, tmp, doint = 2;\n\ttristate val;\n\tchar ch;\n\n\tif (!menu || (!show_all_items && !menu_is_visible(menu)))\n\t\treturn;\n\n\tsym = menu->sym;\n\tprop = menu->prompt;\n\tif (!sym) {\n\t\tif (prop && menu != current_menu) {\n\t\t\tconst char *prompt = menu_get_prompt(menu);\n\t\t\tenum prop_type ptype;\n\t\t\tptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;\n\t\t\tswitch (ptype) {\n\t\t\tcase P_MENU:\n\t\t\t\tchild_count++;\n\t\t\t\tif (single_menu_mode) {\n\t\t\t\t\titem_make(menu, 'm',\n\t\t\t\t\t\t\"%s%*c%s\",\n\t\t\t\t\t\tmenu->data ? \"-->\" : \"++>\",\n\t\t\t\t\t\tindent + 1, ' ', prompt);\n\t\t\t\t} else\n\t\t\t\t\titem_make(menu, 'm',\n\t\t\t\t\t\t  \"   %*c%s  %s\",\n\t\t\t\t\t\t  indent + 1, ' ', prompt,\n\t\t\t\t\t\t  menu_is_empty(menu) ? \"----\" : \"--->\");\n\n\t\t\t\tif (single_menu_mode && menu->data)\n\t\t\t\t\tgoto conf_childs;\n\t\t\t\treturn;\n\t\t\tcase P_COMMENT:\n\t\t\t\tif (prompt) {\n\t\t\t\t\tchild_count++;\n\t\t\t\t\titem_make(menu, ':',\n\t\t\t\t\t\t\"   %*c*** %s ***\",\n\t\t\t\t\t\tindent + 1, ' ',\n\t\t\t\t\t\tprompt);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tif (prompt) {\n\t\t\t\t\tchild_count++;\n\t\t\t\t\titem_make(menu, ':', \"---%*c%s\",\n\t\t\t\t\t\tindent + 1, ' ',\n\t\t\t\t\t\tprompt);\n\t\t\t\t}\n\t\t\t}\n\t\t} else\n\t\t\tdoint = 0;\n\t\tgoto conf_childs;\n\t}\n\n\ttype = sym_get_type(sym);\n\tif (sym_is_choice(sym)) {\n\t\tstruct symbol *def_sym = sym_get_choice_value(sym);\n\t\tstruct menu *def_menu = NULL;\n\n\t\tchild_count++;\n\t\tfor (child = menu->list; child; child = child->next) {\n\t\t\tif (menu_is_visible(child) && child->sym == def_sym)\n\t\t\t\tdef_menu = child;\n\t\t}\n\n\t\tval = sym_get_tristate_value(sym);\n\t\tif (sym_is_changeable(sym)) {\n\t\t\tswitch (type) {\n\t\t\tcase S_BOOLEAN:\n\t\t\t\titem_make(menu, 't', \"[%c]\",\n\t\t\t\t\t\tval == no ? ' ' : '*');\n\t\t\t\tbreak;\n\t\t\tcase S_TRISTATE:\n\t\t\t\tswitch (val) {\n\t\t\t\tcase yes:\n\t\t\t\t\tch = '*';\n\t\t\t\t\tbreak;\n\t\t\t\tcase mod:\n\t\t\t\t\tch = 'M';\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tch = ' ';\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\titem_make(menu, 't', \"<%c>\", ch);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t} else {\n\t\t\titem_make(menu, def_menu ? 't' : ':', \"   \");\n\t\t}\n\n\t\titem_add_str(\"%*c%s\", indent + 1,\n\t\t\t\t' ', menu_get_prompt(menu));\n\t\tif (val == yes) {\n\t\t\tif (def_menu) {\n\t\t\t\titem_add_str(\" (%s)\",\n\t\t\t\t\tmenu_get_prompt(def_menu));\n\t\t\t\titem_add_str(\"  --->\");\n\t\t\t\tif (def_menu->list) {\n\t\t\t\t\tindent += 2;\n\t\t\t\t\tbuild_conf(def_menu);\n\t\t\t\t\tindent -= 2;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t} else {\n\t\tif (menu == current_menu) {\n\t\t\titem_make(menu, ':',\n\t\t\t\t\"---%*c%s\", indent + 1,\n\t\t\t\t' ', menu_get_prompt(menu));\n\t\t\tgoto conf_childs;\n\t\t}\n\t\tchild_count++;\n\t\tval = sym_get_tristate_value(sym);\n\t\tif (sym_is_choice_value(sym) && val == yes) {\n\t\t\titem_make(menu, ':', \"   \");\n\t\t} else {\n\t\t\tswitch (type) {\n\t\t\tcase S_BOOLEAN:\n\t\t\t\tif (sym_is_changeable(sym))\n\t\t\t\t\titem_make(menu, 't', \"[%c]\",\n\t\t\t\t\t\tval == no ? ' ' : '*');\n\t\t\t\telse\n\t\t\t\t\titem_make(menu, 't', \"-%c-\",\n\t\t\t\t\t\tval == no ? ' ' : '*');\n\t\t\t\tbreak;\n\t\t\tcase S_TRISTATE:\n\t\t\t\tswitch (val) {\n\t\t\t\tcase yes:\n\t\t\t\t\tch = '*';\n\t\t\t\t\tbreak;\n\t\t\t\tcase mod:\n\t\t\t\t\tch = 'M';\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tch = ' ';\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif (sym_is_changeable(sym)) {\n\t\t\t\t\tif (sym->rev_dep.tri == mod)\n\t\t\t\t\t\titem_make(menu,\n\t\t\t\t\t\t\t't', \"{%c}\", ch);\n\t\t\t\t\telse\n\t\t\t\t\t\titem_make(menu,\n\t\t\t\t\t\t\t't', \"<%c>\", ch);\n\t\t\t\t} else\n\t\t\t\t\titem_make(menu, 't', \"-%c-\", ch);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\ttmp = 2 + strlen(sym_get_string_value(sym));\n\t\t\t\titem_make(menu, 's', \"    (%s)\",\n\t\t\t\t\t\tsym_get_string_value(sym));\n\t\t\t\ttmp = indent - tmp + 4;\n\t\t\t\tif (tmp < 0)\n\t\t\t\t\ttmp = 0;\n\t\t\t\titem_add_str(\"%*c%s%s\", tmp, ' ',\n\t\t\t\t\t\tmenu_get_prompt(menu),\n\t\t\t\t\t\t(sym_has_value(sym) ||\n\t\t\t\t\t\t !sym_is_changeable(sym)) ? \"\" :\n\t\t\t\t\t\t\" (NEW)\");\n\t\t\t\tgoto conf_childs;\n\t\t\t}\n\t\t}\n\t\titem_add_str(\"%*c%s%s\", indent + 1, ' ',\n\t\t\t\tmenu_get_prompt(menu),\n\t\t\t\t(sym_has_value(sym) || !sym_is_changeable(sym)) ?\n\t\t\t\t\"\" : \" (NEW)\");\n\t\tif (menu->prompt && menu->prompt->type == P_MENU) {\n\t\t\titem_add_str(\"  %s\", menu_is_empty(menu) ? \"----\" : \"--->\");\n\t\t\treturn;\n\t\t}\n\t}\n\nconf_childs:\n\tindent += doint;\n\tfor (child = menu->list; child; child = child->next)\n\t\tbuild_conf(child);\n\tindent -= doint;\n}\n\nstatic void reset_menu(void)\n{\n\tunpost_menu(curses_menu);\n\tclean_items();\n}\n\n/* adjust the menu to show this item.\n * prefer not to scroll the menu if possible*/\nstatic void center_item(int selected_index, int *last_top_row)\n{\n\tint toprow;\n\n\tset_top_row(curses_menu, *last_top_row);\n\ttoprow = top_row(curses_menu);\n\tif (selected_index < toprow ||\n\t    selected_index >= toprow+mwin_max_lines) {\n\t\ttoprow = max(selected_index-mwin_max_lines/2, 0);\n\t\tif (toprow >= item_count(curses_menu)-mwin_max_lines)\n\t\t\ttoprow = item_count(curses_menu)-mwin_max_lines;\n\t\tset_top_row(curses_menu, toprow);\n\t}\n\tset_current_item(curses_menu,\n\t\t\tcurses_menu_items[selected_index]);\n\t*last_top_row = toprow;\n\tpost_menu(curses_menu);\n\trefresh_all_windows(main_window);\n}\n\n/* this function assumes reset_menu has been called before */\nstatic void show_menu(const char *prompt, const char *instructions,\n\t\tint selected_index, int *last_top_row)\n{\n\tint maxx, maxy;\n\tWINDOW *menu_window;\n\n\tcurrent_instructions = instructions;\n\n\tclear();\n\t(void) wattrset(main_window, attributes[NORMAL]);\n\tprint_in_middle(stdscr, 1, 0, getmaxx(stdscr),\n\t\t\tmenu_backtitle,\n\t\t\tattributes[MAIN_HEADING]);\n\n\t(void) wattrset(main_window, attributes[MAIN_MENU_BOX]);\n\tbox(main_window, 0, 0);\n\t(void) wattrset(main_window, attributes[MAIN_MENU_HEADING]);\n\tmvwprintw(main_window, 0, 3, \" %s \", prompt);\n\t(void) wattrset(main_window, attributes[NORMAL]);\n\n\tset_menu_items(curses_menu, curses_menu_items);\n\n\t/* position the menu at the middle of the screen */\n\tscale_menu(curses_menu, &maxy, &maxx);\n\tmaxx = min(maxx, mwin_max_cols-2);\n\tmaxy = mwin_max_lines;\n\tmenu_window = derwin(main_window,\n\t\t\tmaxy,\n\t\t\tmaxx,\n\t\t\t2,\n\t\t\t(mwin_max_cols-maxx)/2);\n\tkeypad(menu_window, TRUE);\n\tset_menu_win(curses_menu, menu_window);\n\tset_menu_sub(curses_menu, menu_window);\n\n\t/* must reassert this after changing items, otherwise returns to a\n\t * default of 16\n\t */\n\tset_menu_format(curses_menu, maxy, 1);\n\tcenter_item(selected_index, last_top_row);\n\tset_menu_format(curses_menu, maxy, 1);\n\n\tprint_function_line();\n\n\t/* Post the menu */\n\tpost_menu(curses_menu);\n\trefresh_all_windows(main_window);\n}\n\nstatic void adj_match_dir(match_f *match_direction)\n{\n\tif (*match_direction == FIND_NEXT_MATCH_DOWN)\n\t\t*match_direction =\n\t\t\tMATCH_TINKER_PATTERN_DOWN;\n\telse if (*match_direction == FIND_NEXT_MATCH_UP)\n\t\t*match_direction =\n\t\t\tMATCH_TINKER_PATTERN_UP;\n\t/* else, do no change.. */\n}\n\nstruct match_state\n{\n\tint in_search;\n\tmatch_f match_direction;\n\tchar pattern[256];\n};\n\n/* Return 0 means I have handled the key. In such a case, ans should hold the\n * item to center, or -1 otherwise.\n * Else return -1 .\n */\nstatic int do_match(int key, struct match_state *state, int *ans)\n{\n\tchar c = (char) key;\n\tint terminate_search = 0;\n\t*ans = -1;\n\tif (key == '/' || (state->in_search && key == 27)) {\n\t\tmove(0, 0);\n\t\trefresh();\n\t\tclrtoeol();\n\t\tstate->in_search = 1-state->in_search;\n\t\tbzero(state->pattern, sizeof(state->pattern));\n\t\tstate->match_direction = MATCH_TINKER_PATTERN_DOWN;\n\t\treturn 0;\n\t} else if (!state->in_search)\n\t\treturn 1;\n\n\tif (isalnum(c) || isgraph(c) || c == ' ') {\n\t\tstate->pattern[strlen(state->pattern)] = c;\n\t\tstate->pattern[strlen(state->pattern)] = '\\0';\n\t\tadj_match_dir(&state->match_direction);\n\t\t*ans = get_mext_match(state->pattern,\n\t\t\t\tstate->match_direction);\n\t} else if (key == KEY_DOWN) {\n\t\tstate->match_direction = FIND_NEXT_MATCH_DOWN;\n\t\t*ans = get_mext_match(state->pattern,\n\t\t\t\tstate->match_direction);\n\t} else if (key == KEY_UP) {\n\t\tstate->match_direction = FIND_NEXT_MATCH_UP;\n\t\t*ans = get_mext_match(state->pattern,\n\t\t\t\tstate->match_direction);\n\t} else if (key == KEY_BACKSPACE || key == 8 || key == 127) {\n\t\tstate->pattern[strlen(state->pattern)-1] = '\\0';\n\t\tadj_match_dir(&state->match_direction);\n\t} else\n\t\tterminate_search = 1;\n\n\tif (terminate_search) {\n\t\tstate->in_search = 0;\n\t\tbzero(state->pattern, sizeof(state->pattern));\n\t\tmove(0, 0);\n\t\trefresh();\n\t\tclrtoeol();\n\t\treturn -1;\n\t}\n\treturn 0;\n}\n\nstatic void conf(struct menu *menu)\n{\n\tstruct menu *submenu = NULL;\n\tconst char *prompt = menu_get_prompt(menu);\n\tstruct symbol *sym;\n\tint res;\n\tint current_index = 0;\n\tint last_top_row = 0;\n\tstruct match_state match_state = {\n\t\t.in_search = 0,\n\t\t.match_direction = MATCH_TINKER_PATTERN_DOWN,\n\t\t.pattern = \"\",\n\t};\n\n\twhile (!global_exit) {\n\t\treset_menu();\n\t\tcurrent_menu = menu;\n\t\tbuild_conf(menu);\n\t\tif (!child_count)\n\t\t\tbreak;\n\n\t\tshow_menu(prompt ? prompt : \"Main Menu\",\n\t\t\t\tmenu_instructions,\n\t\t\t\tcurrent_index, &last_top_row);\n\t\tkeypad((menu_win(curses_menu)), TRUE);\n\t\twhile (!global_exit) {\n\t\t\tif (match_state.in_search) {\n\t\t\t\tmvprintw(0, 0,\n\t\t\t\t\t\"searching: %s\", match_state.pattern);\n\t\t\t\tclrtoeol();\n\t\t\t}\n\t\t\trefresh_all_windows(main_window);\n\t\t\tres = wgetch(menu_win(curses_menu));\n\t\t\tif (!res)\n\t\t\t\tbreak;\n\t\t\tif (do_match(res, &match_state, &current_index) == 0) {\n\t\t\t\tif (current_index != -1)\n\t\t\t\t\tcenter_item(current_index,\n\t\t\t\t\t\t    &last_top_row);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (process_special_keys(&res,\n\t\t\t\t\t\t(struct menu *) item_data()))\n\t\t\t\tbreak;\n\t\t\tswitch (res) {\n\t\t\tcase KEY_DOWN:\n\t\t\t\tmenu_driver(curses_menu, REQ_DOWN_ITEM);\n\t\t\t\tbreak;\n\t\t\tcase KEY_UP:\n\t\t\t\tmenu_driver(curses_menu, REQ_UP_ITEM);\n\t\t\t\tbreak;\n\t\t\tcase KEY_NPAGE:\n\t\t\t\tmenu_driver(curses_menu, REQ_SCR_DPAGE);\n\t\t\t\tbreak;\n\t\t\tcase KEY_PPAGE:\n\t\t\t\tmenu_driver(curses_menu, REQ_SCR_UPAGE);\n\t\t\t\tbreak;\n\t\t\tcase KEY_HOME:\n\t\t\t\tmenu_driver(curses_menu, REQ_FIRST_ITEM);\n\t\t\t\tbreak;\n\t\t\tcase KEY_END:\n\t\t\t\tmenu_driver(curses_menu, REQ_LAST_ITEM);\n\t\t\t\tbreak;\n\t\t\tcase 'h':\n\t\t\tcase '?':\n\t\t\t\tshow_help((struct menu *) item_data());\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (res == 10 || res == 27 ||\n\t\t\t\tres == 32 || res == 'n' || res == 'y' ||\n\t\t\t\tres == KEY_LEFT || res == KEY_RIGHT ||\n\t\t\t\tres == 'm')\n\t\t\t\tbreak;\n\t\t\trefresh_all_windows(main_window);\n\t\t}\n\n\t\trefresh_all_windows(main_window);\n\t\t/* if ESC or left*/\n\t\tif (res == 27 || (menu != &rootmenu && res == KEY_LEFT))\n\t\t\tbreak;\n\n\t\t/* remember location in the menu */\n\t\tlast_top_row = top_row(curses_menu);\n\t\tcurrent_index = curses_item_index();\n\n\t\tif (!item_tag())\n\t\t\tcontinue;\n\n\t\tsubmenu = (struct menu *) item_data();\n\t\tif (!submenu || !menu_is_visible(submenu))\n\t\t\tcontinue;\n\t\tsym = submenu->sym;\n\n\t\tswitch (res) {\n\t\tcase ' ':\n\t\t\tif (item_is_tag('t'))\n\t\t\t\tsym_toggle_tristate_value(sym);\n\t\t\telse if (item_is_tag('m'))\n\t\t\t\tconf(submenu);\n\t\t\tbreak;\n\t\tcase KEY_RIGHT:\n\t\tcase 10: /* ENTER WAS PRESSED */\n\t\t\tswitch (item_tag()) {\n\t\t\tcase 'm':\n\t\t\t\tif (single_menu_mode)\n\t\t\t\t\tsubmenu->data =\n\t\t\t\t\t\t(void *) (long) !submenu->data;\n\t\t\t\telse\n\t\t\t\t\tconf(submenu);\n\t\t\t\tbreak;\n\t\t\tcase 't':\n\t\t\t\tif (sym_is_choice(sym) &&\n\t\t\t\t    sym_get_tristate_value(sym) == yes)\n\t\t\t\t\tconf_choice(submenu);\n\t\t\t\telse if (submenu->prompt &&\n\t\t\t\t\t submenu->prompt->type == P_MENU)\n\t\t\t\t\tconf(submenu);\n\t\t\t\telse if (res == 10)\n\t\t\t\t\tsym_toggle_tristate_value(sym);\n\t\t\t\tbreak;\n\t\t\tcase 's':\n\t\t\t\tconf_string(submenu);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase 'y':\n\t\t\tif (item_is_tag('t')) {\n\t\t\t\tif (sym_set_tristate_value(sym, yes))\n\t\t\t\t\tbreak;\n\t\t\t\tif (sym_set_tristate_value(sym, mod))\n\t\t\t\t\tbtn_dialog(main_window, setmod_text, 0);\n\t\t\t}\n\t\t\tbreak;\n\t\tcase 'n':\n\t\t\tif (item_is_tag('t'))\n\t\t\t\tsym_set_tristate_value(sym, no);\n\t\t\tbreak;\n\t\tcase 'm':\n\t\t\tif (item_is_tag('t'))\n\t\t\t\tsym_set_tristate_value(sym, mod);\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\nstatic void conf_message_callback(const char *s)\n{\n\tbtn_dialog(main_window, s, 1, \"<OK>\");\n}\n\nstatic void show_help(struct menu *menu)\n{\n\tstruct gstr help;\n\n\tif (!menu)\n\t\treturn;\n\n\thelp = str_new();\n\tmenu_get_ext_help(menu, &help);\n\tshow_scroll_win(main_window, menu_get_prompt(menu), str_get(&help));\n\tstr_free(&help);\n}\n\nstatic void conf_choice(struct menu *menu)\n{\n\tconst char *prompt = menu_get_prompt(menu);\n\tstruct menu *child = NULL;\n\tstruct symbol *active;\n\tint selected_index = 0;\n\tint last_top_row = 0;\n\tint res, i = 0;\n\tstruct match_state match_state = {\n\t\t.in_search = 0,\n\t\t.match_direction = MATCH_TINKER_PATTERN_DOWN,\n\t\t.pattern = \"\",\n\t};\n\n\tactive = sym_get_choice_value(menu->sym);\n\t/* this is mostly duplicated from the conf() function. */\n\twhile (!global_exit) {\n\t\treset_menu();\n\n\t\tfor (i = 0, child = menu->list; child; child = child->next) {\n\t\t\tif (!show_all_items && !menu_is_visible(child))\n\t\t\t\tcontinue;\n\n\t\t\tif (child->sym == sym_get_choice_value(menu->sym))\n\t\t\t\titem_make(child, ':', \"<X> %s\",\n\t\t\t\t\t\tmenu_get_prompt(child));\n\t\t\telse if (child->sym)\n\t\t\t\titem_make(child, ':', \"    %s\",\n\t\t\t\t\t\tmenu_get_prompt(child));\n\t\t\telse\n\t\t\t\titem_make(child, ':', \"*** %s ***\",\n\t\t\t\t\t\tmenu_get_prompt(child));\n\n\t\t\tif (child->sym == active){\n\t\t\t\tlast_top_row = top_row(curses_menu);\n\t\t\t\tselected_index = i;\n\t\t\t}\n\t\t\ti++;\n\t\t}\n\t\tshow_menu(prompt ? prompt : \"Choice Menu\",\n\t\t\t\tradiolist_instructions,\n\t\t\t\tselected_index,\n\t\t\t\t&last_top_row);\n\t\twhile (!global_exit) {\n\t\t\tif (match_state.in_search) {\n\t\t\t\tmvprintw(0, 0, \"searching: %s\",\n\t\t\t\t\t match_state.pattern);\n\t\t\t\tclrtoeol();\n\t\t\t}\n\t\t\trefresh_all_windows(main_window);\n\t\t\tres = wgetch(menu_win(curses_menu));\n\t\t\tif (!res)\n\t\t\t\tbreak;\n\t\t\tif (do_match(res, &match_state, &selected_index) == 0) {\n\t\t\t\tif (selected_index != -1)\n\t\t\t\t\tcenter_item(selected_index,\n\t\t\t\t\t\t    &last_top_row);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (process_special_keys(\n\t\t\t\t\t\t&res,\n\t\t\t\t\t\t(struct menu *) item_data()))\n\t\t\t\tbreak;\n\t\t\tswitch (res) {\n\t\t\tcase KEY_DOWN:\n\t\t\t\tmenu_driver(curses_menu, REQ_DOWN_ITEM);\n\t\t\t\tbreak;\n\t\t\tcase KEY_UP:\n\t\t\t\tmenu_driver(curses_menu, REQ_UP_ITEM);\n\t\t\t\tbreak;\n\t\t\tcase KEY_NPAGE:\n\t\t\t\tmenu_driver(curses_menu, REQ_SCR_DPAGE);\n\t\t\t\tbreak;\n\t\t\tcase KEY_PPAGE:\n\t\t\t\tmenu_driver(curses_menu, REQ_SCR_UPAGE);\n\t\t\t\tbreak;\n\t\t\tcase KEY_HOME:\n\t\t\t\tmenu_driver(curses_menu, REQ_FIRST_ITEM);\n\t\t\t\tbreak;\n\t\t\tcase KEY_END:\n\t\t\t\tmenu_driver(curses_menu, REQ_LAST_ITEM);\n\t\t\t\tbreak;\n\t\t\tcase 'h':\n\t\t\tcase '?':\n\t\t\t\tshow_help((struct menu *) item_data());\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (res == 10 || res == 27 || res == ' ' ||\n\t\t\t\t\tres == KEY_LEFT){\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\trefresh_all_windows(main_window);\n\t\t}\n\t\t/* if ESC or left */\n\t\tif (res == 27 || res == KEY_LEFT)\n\t\t\tbreak;\n\n\t\tchild = item_data();\n\t\tif (!child || !menu_is_visible(child) || !child->sym)\n\t\t\tcontinue;\n\t\tswitch (res) {\n\t\tcase ' ':\n\t\tcase  10:\n\t\tcase KEY_RIGHT:\n\t\t\tsym_set_tristate_value(child->sym, yes);\n\t\t\treturn;\n\t\tcase 'h':\n\t\tcase '?':\n\t\t\tshow_help(child);\n\t\t\tactive = child->sym;\n\t\t\tbreak;\n\t\tcase KEY_EXIT:\n\t\t\treturn;\n\t\t}\n\t}\n}\n\nstatic void conf_string(struct menu *menu)\n{\n\tconst char *prompt = menu_get_prompt(menu);\n\n\twhile (1) {\n\t\tint res;\n\t\tconst char *heading;\n\n\t\tswitch (sym_get_type(menu->sym)) {\n\t\tcase S_INT:\n\t\t\theading = inputbox_instructions_int;\n\t\t\tbreak;\n\t\tcase S_HEX:\n\t\t\theading = inputbox_instructions_hex;\n\t\t\tbreak;\n\t\tcase S_STRING:\n\t\t\theading = inputbox_instructions_string;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\theading = \"Internal nconf error!\";\n\t\t}\n\t\tres = dialog_inputbox(main_window,\n\t\t\t\tprompt ? prompt : \"Main Menu\",\n\t\t\t\theading,\n\t\t\t\tsym_get_string_value(menu->sym),\n\t\t\t\t&dialog_input_result,\n\t\t\t\t&dialog_input_result_len);\n\t\tswitch (res) {\n\t\tcase 0:\n\t\t\tif (sym_set_string_value(menu->sym,\n\t\t\t\t\t\tdialog_input_result))\n\t\t\t\treturn;\n\t\t\tbtn_dialog(main_window,\n\t\t\t\t\"You have made an invalid entry.\", 0);\n\t\t\tbreak;\n\t\tcase 1:\n\t\t\tshow_help(menu);\n\t\t\tbreak;\n\t\tcase KEY_EXIT:\n\t\t\treturn;\n\t\t}\n\t}\n}\n\nstatic void conf_load(void)\n{\n\twhile (1) {\n\t\tint res;\n\t\tres = dialog_inputbox(main_window,\n\t\t\t\tNULL, load_config_text,\n\t\t\t\tfilename,\n\t\t\t\t&dialog_input_result,\n\t\t\t\t&dialog_input_result_len);\n\t\tswitch (res) {\n\t\tcase 0:\n\t\t\tif (!dialog_input_result[0])\n\t\t\t\treturn;\n\t\t\tif (!conf_read(dialog_input_result)) {\n\t\t\t\tset_config_filename(dialog_input_result);\n\t\t\t\tsym_set_change_count(1);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tbtn_dialog(main_window, \"File does not exist!\", 0);\n\t\t\tbreak;\n\t\tcase 1:\n\t\t\tshow_scroll_win(main_window,\n\t\t\t\t\t\"Load Alternate Configuration\",\n\t\t\t\t\tload_config_help);\n\t\t\tbreak;\n\t\tcase KEY_EXIT:\n\t\t\treturn;\n\t\t}\n\t}\n}\n\nstatic void conf_save(void)\n{\n\twhile (1) {\n\t\tint res;\n\t\tres = dialog_inputbox(main_window,\n\t\t\t\tNULL, save_config_text,\n\t\t\t\tfilename,\n\t\t\t\t&dialog_input_result,\n\t\t\t\t&dialog_input_result_len);\n\t\tswitch (res) {\n\t\tcase 0:\n\t\t\tif (!dialog_input_result[0])\n\t\t\t\treturn;\n\t\t\tres = conf_write(dialog_input_result);\n\t\t\tif (!res) {\n\t\t\t\tset_config_filename(dialog_input_result);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tbtn_dialog(main_window, \"Can't create file!\",\n\t\t\t\t1, \"<OK>\");\n\t\t\tbreak;\n\t\tcase 1:\n\t\t\tshow_scroll_win(main_window,\n\t\t\t\t\"Save Alternate Configuration\",\n\t\t\t\tsave_config_help);\n\t\t\tbreak;\n\t\tcase KEY_EXIT:\n\t\t\treturn;\n\t\t}\n\t}\n}\n\nstatic void setup_windows(void)\n{\n\tint lines, columns;\n\n\tgetmaxyx(stdscr, lines, columns);\n\n\tif (main_window != NULL)\n\t\tdelwin(main_window);\n\n\t/* set up the menu and menu window */\n\tmain_window = newwin(lines-2, columns-2, 2, 1);\n\tkeypad(main_window, TRUE);\n\tmwin_max_lines = lines-7;\n\tmwin_max_cols = columns-6;\n\n\t/* panels order is from bottom to top */\n\tnew_panel(main_window);\n}\n\nint main(int ac, char **av)\n{\n\tint lines, columns;\n\tchar *mode;\n\n\tif (ac > 1 && strcmp(av[1], \"-s\") == 0) {\n\t\t/* Silence conf_read() until the real callback is set up */\n\t\tconf_set_message_callback(NULL);\n\t\tav++;\n\t}\n\tconf_parse(av[1]);\n\tconf_read(NULL);\n\n\tmode = getenv(\"NCONFIG_MODE\");\n\tif (mode) {\n\t\tif (!strcasecmp(mode, \"single_menu\"))\n\t\t\tsingle_menu_mode = 1;\n\t}\n\n\t/* Initialize curses */\n\tinitscr();\n\t/* set color theme */\n\tset_colors();\n\n\tcbreak();\n\tnoecho();\n\tkeypad(stdscr, TRUE);\n\tcurs_set(0);\n\n\tgetmaxyx(stdscr, lines, columns);\n\tif (columns < 75 || lines < 20) {\n\t\tendwin();\n\t\tprintf(\"Your terminal should have at \"\n\t\t\t\"least 20 lines and 75 columns\\n\");\n\t\treturn 1;\n\t}\n\n\tnotimeout(stdscr, FALSE);\n#if NCURSES_REENTRANT\n\tset_escdelay(1);\n#else\n\tESCDELAY = 1;\n#endif\n\n\t/* set btns menu */\n\tcurses_menu = new_menu(curses_menu_items);\n\tmenu_opts_off(curses_menu, O_SHOWDESC);\n\tmenu_opts_on(curses_menu, O_SHOWMATCH);\n\tmenu_opts_on(curses_menu, O_ONEVALUE);\n\tmenu_opts_on(curses_menu, O_NONCYCLIC);\n\tmenu_opts_on(curses_menu, O_IGNORECASE);\n\tset_menu_mark(curses_menu, \" \");\n\tset_menu_fore(curses_menu, attributes[MAIN_MENU_FORE]);\n\tset_menu_back(curses_menu, attributes[MAIN_MENU_BACK]);\n\tset_menu_grey(curses_menu, attributes[MAIN_MENU_GREY]);\n\n\tset_config_filename(conf_get_configname());\n\tsetup_windows();\n\n\t/* check for KEY_FUNC(1) */\n\tif (has_key(KEY_F(1)) == FALSE) {\n\t\tshow_scroll_win(main_window,\n\t\t\t\t\"Instructions\",\n\t\t\t\tmenu_no_f_instructions);\n\t}\n\n\tconf_set_message_callback(conf_message_callback);\n\t/* do the work */\n\twhile (!global_exit) {\n\t\tconf(&rootmenu);\n\t\tif (!global_exit && do_exit() == 0)\n\t\t\tbreak;\n\t}\n\t/* ok, we are done */\n\tunpost_menu(curses_menu);\n\tfree_menu(curses_menu);\n\tdelwin(main_window);\n\tclear();\n\trefresh();\n\tendwin();\n\treturn 0;\n}\n"
  },
  {
    "path": "3rdparty/kconfig/nconf.gui.c",
    "content": "// SPDX-License-Identifier: GPL-2.0\n/*\n * Copyright (C) 2008 Nir Tzachar <nir.tzachar@gmail.com>\n *\n * Derived from menuconfig.\n */\n#include \"nconf.h\"\n#include \"lkc.h\"\n\n/* a list of all the different widgets we use */\nattributes_t attributes[ATTR_MAX+1] = {0};\n\n/* available colors:\n   COLOR_BLACK   0\n   COLOR_RED     1\n   COLOR_GREEN   2\n   COLOR_YELLOW  3\n   COLOR_BLUE    4\n   COLOR_MAGENTA 5\n   COLOR_CYAN    6\n   COLOR_WHITE   7\n   */\nstatic void set_normal_colors(void)\n{\n\tinit_pair(NORMAL, -1, -1);\n\tinit_pair(MAIN_HEADING, COLOR_MAGENTA, -1);\n\n\t/* FORE is for the selected item */\n\tinit_pair(MAIN_MENU_FORE, -1, -1);\n\t/* BACK for all the rest */\n\tinit_pair(MAIN_MENU_BACK, -1, -1);\n\tinit_pair(MAIN_MENU_GREY, -1, -1);\n\tinit_pair(MAIN_MENU_HEADING, COLOR_GREEN, -1);\n\tinit_pair(MAIN_MENU_BOX, COLOR_YELLOW, -1);\n\n\tinit_pair(SCROLLWIN_TEXT, -1, -1);\n\tinit_pair(SCROLLWIN_HEADING, COLOR_GREEN, -1);\n\tinit_pair(SCROLLWIN_BOX, COLOR_YELLOW, -1);\n\n\tinit_pair(DIALOG_TEXT, -1, -1);\n\tinit_pair(DIALOG_BOX, COLOR_YELLOW, -1);\n\tinit_pair(DIALOG_MENU_BACK, COLOR_YELLOW, -1);\n\tinit_pair(DIALOG_MENU_FORE, COLOR_RED, -1);\n\n\tinit_pair(INPUT_BOX, COLOR_YELLOW, -1);\n\tinit_pair(INPUT_HEADING, COLOR_GREEN, -1);\n\tinit_pair(INPUT_TEXT, -1, -1);\n\tinit_pair(INPUT_FIELD, -1, -1);\n\n\tinit_pair(FUNCTION_HIGHLIGHT, -1, -1);\n\tinit_pair(FUNCTION_TEXT, COLOR_YELLOW, -1);\n}\n\n/* available attributes:\n   A_NORMAL        Normal display (no highlight)\n   A_STANDOUT      Best highlighting mode of the terminal.\n   A_UNDERLINE     Underlining\n   A_REVERSE       Reverse video\n   A_BLINK         Blinking\n   A_DIM           Half bright\n   A_BOLD          Extra bright or bold\n   A_PROTECT       Protected mode\n   A_INVIS         Invisible or blank mode\n   A_ALTCHARSET    Alternate character set\n   A_CHARTEXT      Bit-mask to extract a character\n   COLOR_PAIR(n)   Color-pair number n\n   */\nstatic void normal_color_theme(void)\n{\n\t/* automatically add color... */\n#define mkattr(name, attr) do { \\\nattributes[name] = attr | COLOR_PAIR(name); } while (0)\n\tmkattr(NORMAL, NORMAL);\n\tmkattr(MAIN_HEADING, A_BOLD | A_UNDERLINE);\n\n\tmkattr(MAIN_MENU_FORE, A_REVERSE);\n\tmkattr(MAIN_MENU_BACK, A_NORMAL);\n\tmkattr(MAIN_MENU_GREY, A_NORMAL);\n\tmkattr(MAIN_MENU_HEADING, A_BOLD);\n\tmkattr(MAIN_MENU_BOX, A_NORMAL);\n\n\tmkattr(SCROLLWIN_TEXT, A_NORMAL);\n\tmkattr(SCROLLWIN_HEADING, A_BOLD);\n\tmkattr(SCROLLWIN_BOX, A_BOLD);\n\n\tmkattr(DIALOG_TEXT, A_BOLD);\n\tmkattr(DIALOG_BOX, A_BOLD);\n\tmkattr(DIALOG_MENU_FORE, A_STANDOUT);\n\tmkattr(DIALOG_MENU_BACK, A_NORMAL);\n\n\tmkattr(INPUT_BOX, A_NORMAL);\n\tmkattr(INPUT_HEADING, A_BOLD);\n\tmkattr(INPUT_TEXT, A_NORMAL);\n\tmkattr(INPUT_FIELD, A_UNDERLINE);\n\n\tmkattr(FUNCTION_HIGHLIGHT, A_BOLD);\n\tmkattr(FUNCTION_TEXT, A_REVERSE);\n}\n\nstatic void no_colors_theme(void)\n{\n\t/* automatically add highlight, no color */\n#define mkattrn(name, attr) { attributes[name] = attr; }\n\n\tmkattrn(NORMAL, NORMAL);\n\tmkattrn(MAIN_HEADING, A_BOLD | A_UNDERLINE);\n\n\tmkattrn(MAIN_MENU_FORE, A_STANDOUT);\n\tmkattrn(MAIN_MENU_BACK, A_NORMAL);\n\tmkattrn(MAIN_MENU_GREY, A_NORMAL);\n\tmkattrn(MAIN_MENU_HEADING, A_BOLD);\n\tmkattrn(MAIN_MENU_BOX, A_NORMAL);\n\n\tmkattrn(SCROLLWIN_TEXT, A_NORMAL);\n\tmkattrn(SCROLLWIN_HEADING, A_BOLD);\n\tmkattrn(SCROLLWIN_BOX, A_BOLD);\n\n\tmkattrn(DIALOG_TEXT, A_NORMAL);\n\tmkattrn(DIALOG_BOX, A_BOLD);\n\tmkattrn(DIALOG_MENU_FORE, A_STANDOUT);\n\tmkattrn(DIALOG_MENU_BACK, A_NORMAL);\n\n\tmkattrn(INPUT_BOX, A_BOLD);\n\tmkattrn(INPUT_HEADING, A_BOLD);\n\tmkattrn(INPUT_TEXT, A_NORMAL);\n\tmkattrn(INPUT_FIELD, A_UNDERLINE);\n\n\tmkattrn(FUNCTION_HIGHLIGHT, A_BOLD);\n\tmkattrn(FUNCTION_TEXT, A_REVERSE);\n}\n\nvoid set_colors(void)\n{\n\tstart_color();\n\tuse_default_colors();\n\tset_normal_colors();\n\tif (has_colors()) {\n\t\tnormal_color_theme();\n\t} else {\n\t\t/* give defaults */\n\t\tno_colors_theme();\n\t}\n}\n\n\n/* this changes the windows attributes !!! */\nvoid print_in_middle(WINDOW *win,\n\t\tint starty,\n\t\tint startx,\n\t\tint width,\n\t\tconst char *string,\n\t\tchtype color)\n{      int length, x, y;\n\tfloat temp;\n\n\n\tif (win == NULL)\n\t\twin = stdscr;\n\tgetyx(win, y, x);\n\tif (startx != 0)\n\t\tx = startx;\n\tif (starty != 0)\n\t\ty = starty;\n\tif (width == 0)\n\t\twidth = 80;\n\n\tlength = strlen(string);\n\ttemp = (width - length) / 2;\n\tx = startx + (int)temp;\n\t(void) wattrset(win, color);\n\tmvwprintw(win, y, x, \"%s\", string);\n\trefresh();\n}\n\nint get_line_no(const char *text)\n{\n\tint i;\n\tint total = 1;\n\n\tif (!text)\n\t\treturn 0;\n\n\tfor (i = 0; text[i] != '\\0'; i++)\n\t\tif (text[i] == '\\n')\n\t\t\ttotal++;\n\treturn total;\n}\n\nconst char *get_line(const char *text, int line_no)\n{\n\tint i;\n\tint lines = 0;\n\n\tif (!text)\n\t\treturn NULL;\n\n\tfor (i = 0; text[i] != '\\0' && lines < line_no; i++)\n\t\tif (text[i] == '\\n')\n\t\t\tlines++;\n\treturn text+i;\n}\n\nint get_line_length(const char *line)\n{\n\tint res = 0;\n\twhile (*line != '\\0' && *line != '\\n') {\n\t\tline++;\n\t\tres++;\n\t}\n\treturn res;\n}\n\n/* print all lines to the window. */\nvoid fill_window(WINDOW *win, const char *text)\n{\n\tint x, y;\n\tint total_lines = get_line_no(text);\n\tint i;\n\n\tgetmaxyx(win, y, x);\n\t/* do not go over end of line */\n\ttotal_lines = min(total_lines, y);\n\tfor (i = 0; i < total_lines; i++) {\n\t\tchar tmp[x+10];\n\t\tconst char *line = get_line(text, i);\n\t\tint len = get_line_length(line);\n\t\tstrncpy(tmp, line, min(len, x));\n\t\ttmp[len] = '\\0';\n\t\tmvwprintw(win, i, 0, \"%s\", tmp);\n\t}\n}\n\n/* get the message, and buttons.\n * each button must be a char*\n * return the selected button\n *\n * this dialog is used for 2 different things:\n * 1) show a text box, no buttons.\n * 2) show a dialog, with horizontal buttons\n */\nint btn_dialog(WINDOW *main_window, const char *msg, int btn_num, ...)\n{\n\tva_list ap;\n\tchar *btn;\n\tint btns_width = 0;\n\tint msg_lines = 0;\n\tint msg_width = 0;\n\tint total_width;\n\tint win_rows = 0;\n\tWINDOW *win;\n\tWINDOW *msg_win;\n\tWINDOW *menu_win;\n\tMENU *menu;\n\tITEM *btns[btn_num+1];\n\tint i, x, y;\n\tint res = -1;\n\n\n\tva_start(ap, btn_num);\n\tfor (i = 0; i < btn_num; i++) {\n\t\tbtn = va_arg(ap, char *);\n\t\tbtns[i] = new_item(btn, \"\");\n\t\tbtns_width += strlen(btn)+1;\n\t}\n\tva_end(ap);\n\tbtns[btn_num] = NULL;\n\n\t/* find the widest line of msg: */\n\tmsg_lines = get_line_no(msg);\n\tfor (i = 0; i < msg_lines; i++) {\n\t\tconst char *line = get_line(msg, i);\n\t\tint len = get_line_length(line);\n\t\tif (msg_width < len)\n\t\t\tmsg_width = len;\n\t}\n\n\ttotal_width = max(msg_width, btns_width);\n\t/* place dialog in middle of screen */\n\ty = (getmaxy(stdscr)-(msg_lines+4))/2;\n\tx = (getmaxx(stdscr)-(total_width+4))/2;\n\n\n\t/* create the windows */\n\tif (btn_num > 0)\n\t\twin_rows = msg_lines+4;\n\telse\n\t\twin_rows = msg_lines+2;\n\n\twin = newwin(win_rows, total_width+4, y, x);\n\tkeypad(win, TRUE);\n\tmenu_win = derwin(win, 1, btns_width, win_rows-2,\n\t\t\t1+(total_width+2-btns_width)/2);\n\tmenu = new_menu(btns);\n\tmsg_win = derwin(win, win_rows-2, msg_width, 1,\n\t\t\t1+(total_width+2-msg_width)/2);\n\n\tset_menu_fore(menu, attributes[DIALOG_MENU_FORE]);\n\tset_menu_back(menu, attributes[DIALOG_MENU_BACK]);\n\n\t(void) wattrset(win, attributes[DIALOG_BOX]);\n\tbox(win, 0, 0);\n\n\t/* print message */\n\t(void) wattrset(msg_win, attributes[DIALOG_TEXT]);\n\tfill_window(msg_win, msg);\n\n\tset_menu_win(menu, win);\n\tset_menu_sub(menu, menu_win);\n\tset_menu_format(menu, 1, btn_num);\n\tmenu_opts_off(menu, O_SHOWDESC);\n\tmenu_opts_off(menu, O_SHOWMATCH);\n\tmenu_opts_on(menu, O_ONEVALUE);\n\tmenu_opts_on(menu, O_NONCYCLIC);\n\tset_menu_mark(menu, \"\");\n\tpost_menu(menu);\n\n\n\ttouchwin(win);\n\trefresh_all_windows(main_window);\n\twhile ((res = wgetch(win))) {\n\t\tswitch (res) {\n\t\tcase KEY_LEFT:\n\t\t\tmenu_driver(menu, REQ_LEFT_ITEM);\n\t\t\tbreak;\n\t\tcase KEY_RIGHT:\n\t\t\tmenu_driver(menu, REQ_RIGHT_ITEM);\n\t\t\tbreak;\n\t\tcase 10: /* ENTER */\n\t\tcase 27: /* ESCAPE */\n\t\tcase ' ':\n\t\tcase KEY_F(F_BACK):\n\t\tcase KEY_F(F_EXIT):\n\t\t\tbreak;\n\t\t}\n\t\ttouchwin(win);\n\t\trefresh_all_windows(main_window);\n\n\t\tif (res == 10 || res == ' ') {\n\t\t\tres = item_index(current_item(menu));\n\t\t\tbreak;\n\t\t} else if (res == 27 || res == KEY_F(F_BACK) ||\n\t\t\t\tres == KEY_F(F_EXIT)) {\n\t\t\tres = KEY_EXIT;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tunpost_menu(menu);\n\tfree_menu(menu);\n\tfor (i = 0; i < btn_num; i++)\n\t\tfree_item(btns[i]);\n\n\tdelwin(win);\n\treturn res;\n}\n\nint dialog_inputbox(WINDOW *main_window,\n\t\tconst char *title, const char *prompt,\n\t\tconst char *init, char **resultp, int *result_len)\n{\n\tint prompt_lines = 0;\n\tint prompt_width = 0;\n\tWINDOW *win;\n\tWINDOW *prompt_win;\n\tWINDOW *form_win;\n\tPANEL *panel;\n\tint i, x, y, lines, columns, win_lines, win_cols;\n\tint res = -1;\n\tint cursor_position = strlen(init);\n\tint cursor_form_win;\n\tchar *result = *resultp;\n\n\tgetmaxyx(stdscr, lines, columns);\n\n\tif (strlen(init)+1 > *result_len) {\n\t\t*result_len = strlen(init)+1;\n\t\t*resultp = result = xrealloc(result, *result_len);\n\t}\n\n\t/* find the widest line of msg: */\n\tprompt_lines = get_line_no(prompt);\n\tfor (i = 0; i < prompt_lines; i++) {\n\t\tconst char *line = get_line(prompt, i);\n\t\tint len = get_line_length(line);\n\t\tprompt_width = max(prompt_width, len);\n\t}\n\n\tif (title)\n\t\tprompt_width = max(prompt_width, strlen(title));\n\n\twin_lines = min(prompt_lines+6, lines-2);\n\twin_cols = min(prompt_width+7, columns-2);\n\tprompt_lines = max(win_lines-6, 0);\n\tprompt_width = max(win_cols-7, 0);\n\n\t/* place dialog in middle of screen */\n\ty = (lines-win_lines)/2;\n\tx = (columns-win_cols)/2;\n\n\tstrncpy(result, init, *result_len);\n\n\t/* create the windows */\n\twin = newwin(win_lines, win_cols, y, x);\n\tprompt_win = derwin(win, prompt_lines+1, prompt_width, 2, 2);\n\tform_win = derwin(win, 1, prompt_width, prompt_lines+3, 2);\n\tkeypad(form_win, TRUE);\n\n\t(void) wattrset(form_win, attributes[INPUT_FIELD]);\n\n\t(void) wattrset(win, attributes[INPUT_BOX]);\n\tbox(win, 0, 0);\n\t(void) wattrset(win, attributes[INPUT_HEADING]);\n\tif (title)\n\t\tmvwprintw(win, 0, 3, \"%s\", title);\n\n\t/* print message */\n\t(void) wattrset(prompt_win, attributes[INPUT_TEXT]);\n\tfill_window(prompt_win, prompt);\n\n\tmvwprintw(form_win, 0, 0, \"%*s\", prompt_width, \" \");\n\tcursor_form_win = min(cursor_position, prompt_width-1);\n\tmvwprintw(form_win, 0, 0, \"%s\",\n\t\t  result + cursor_position-cursor_form_win);\n\n\t/* create panels */\n\tpanel = new_panel(win);\n\n\t/* show the cursor */\n\tcurs_set(1);\n\n\ttouchwin(win);\n\trefresh_all_windows(main_window);\n\twhile ((res = wgetch(form_win))) {\n\t\tint len = strlen(result);\n\t\tswitch (res) {\n\t\tcase 10: /* ENTER */\n\t\tcase 27: /* ESCAPE */\n\t\tcase KEY_F(F_HELP):\n\t\tcase KEY_F(F_EXIT):\n\t\tcase KEY_F(F_BACK):\n\t\t\tbreak;\n\t\tcase 8:   /* ^H */\n\t\tcase 127: /* ^? */\n\t\tcase KEY_BACKSPACE:\n\t\t\tif (cursor_position > 0) {\n\t\t\t\tmemmove(&result[cursor_position-1],\n\t\t\t\t\t\t&result[cursor_position],\n\t\t\t\t\t\tlen-cursor_position+1);\n\t\t\t\tcursor_position--;\n\t\t\t\tcursor_form_win--;\n\t\t\t\tlen--;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase KEY_DC:\n\t\t\tif (cursor_position >= 0 && cursor_position < len) {\n\t\t\t\tmemmove(&result[cursor_position],\n\t\t\t\t\t\t&result[cursor_position+1],\n\t\t\t\t\t\tlen-cursor_position+1);\n\t\t\t\tlen--;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase KEY_UP:\n\t\tcase KEY_RIGHT:\n\t\t\tif (cursor_position < len) {\n\t\t\t\tcursor_position++;\n\t\t\t\tcursor_form_win++;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase KEY_DOWN:\n\t\tcase KEY_LEFT:\n\t\t\tif (cursor_position > 0) {\n\t\t\t\tcursor_position--;\n\t\t\t\tcursor_form_win--;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase KEY_HOME:\n\t\t\tcursor_position = 0;\n\t\t\tcursor_form_win = 0;\n\t\t\tbreak;\n\t\tcase KEY_END:\n\t\t\tcursor_position = len;\n\t\t\tcursor_form_win = min(cursor_position, prompt_width-1);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tif ((isgraph(res) || isspace(res))) {\n\t\t\t\t/* one for new char, one for '\\0' */\n\t\t\t\tif (len+2 > *result_len) {\n\t\t\t\t\t*result_len = len+2;\n\t\t\t\t\t*resultp = result = realloc(result,\n\t\t\t\t\t\t\t\t*result_len);\n\t\t\t\t}\n\t\t\t\t/* insert the char at the proper position */\n\t\t\t\tmemmove(&result[cursor_position+1],\n\t\t\t\t\t\t&result[cursor_position],\n\t\t\t\t\t\tlen-cursor_position+1);\n\t\t\t\tresult[cursor_position] = res;\n\t\t\t\tcursor_position++;\n\t\t\t\tcursor_form_win++;\n\t\t\t\tlen++;\n\t\t\t} else {\n\t\t\t\tmvprintw(0, 0, \"unknown key: %d\\n\", res);\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tif (cursor_form_win < 0)\n\t\t\tcursor_form_win = 0;\n\t\telse if (cursor_form_win > prompt_width-1)\n\t\t\tcursor_form_win = prompt_width-1;\n\n\t\twmove(form_win, 0, 0);\n\t\twclrtoeol(form_win);\n\t\tmvwprintw(form_win, 0, 0, \"%*s\", prompt_width, \" \");\n\t\tmvwprintw(form_win, 0, 0, \"%s\",\n\t\t\tresult + cursor_position-cursor_form_win);\n\t\twmove(form_win, 0, cursor_form_win);\n\t\ttouchwin(win);\n\t\trefresh_all_windows(main_window);\n\n\t\tif (res == 10) {\n\t\t\tres = 0;\n\t\t\tbreak;\n\t\t} else if (res == 27 || res == KEY_F(F_BACK) ||\n\t\t\t\tres == KEY_F(F_EXIT)) {\n\t\t\tres = KEY_EXIT;\n\t\t\tbreak;\n\t\t} else if (res == KEY_F(F_HELP)) {\n\t\t\tres = 1;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t/* hide the cursor */\n\tcurs_set(0);\n\tdel_panel(panel);\n\tdelwin(prompt_win);\n\tdelwin(form_win);\n\tdelwin(win);\n\treturn res;\n}\n\n/* refresh all windows in the correct order */\nvoid refresh_all_windows(WINDOW *main_window)\n{\n\tupdate_panels();\n\ttouchwin(main_window);\n\trefresh();\n}\n\n/* layman's scrollable window... */\nvoid show_scroll_win(WINDOW *main_window,\n\t\tconst char *title,\n\t\tconst char *text)\n{\n\tint res;\n\tint total_lines = get_line_no(text);\n\tint x, y, lines, columns;\n\tint start_x = 0, start_y = 0;\n\tint text_lines = 0, text_cols = 0;\n\tint total_cols = 0;\n\tint win_cols = 0;\n\tint win_lines = 0;\n\tint i = 0;\n\tWINDOW *win;\n\tWINDOW *pad;\n\tPANEL *panel;\n\n\tgetmaxyx(stdscr, lines, columns);\n\n\t/* find the widest line of msg: */\n\ttotal_lines = get_line_no(text);\n\tfor (i = 0; i < total_lines; i++) {\n\t\tconst char *line = get_line(text, i);\n\t\tint len = get_line_length(line);\n\t\ttotal_cols = max(total_cols, len+2);\n\t}\n\n\t/* create the pad */\n\tpad = newpad(total_lines+10, total_cols+10);\n\t(void) wattrset(pad, attributes[SCROLLWIN_TEXT]);\n\tfill_window(pad, text);\n\n\twin_lines = min(total_lines+4, lines-2);\n\twin_cols = min(total_cols+2, columns-2);\n\ttext_lines = max(win_lines-4, 0);\n\ttext_cols = max(win_cols-2, 0);\n\n\t/* place window in middle of screen */\n\ty = (lines-win_lines)/2;\n\tx = (columns-win_cols)/2;\n\n\twin = newwin(win_lines, win_cols, y, x);\n\tkeypad(win, TRUE);\n\t/* show the help in the help window, and show the help panel */\n\t(void) wattrset(win, attributes[SCROLLWIN_BOX]);\n\tbox(win, 0, 0);\n\t(void) wattrset(win, attributes[SCROLLWIN_HEADING]);\n\tmvwprintw(win, 0, 3, \" %s \", title);\n\tpanel = new_panel(win);\n\n\t/* handle scrolling */\n\tdo {\n\n\t\tcopywin(pad, win, start_y, start_x, 2, 2, text_lines,\n\t\t\t\ttext_cols, 0);\n\t\tprint_in_middle(win,\n\t\t\t\ttext_lines+2,\n\t\t\t\t0,\n\t\t\t\ttext_cols,\n\t\t\t\t\"<OK>\",\n\t\t\t\tattributes[DIALOG_MENU_FORE]);\n\t\twrefresh(win);\n\n\t\tres = wgetch(win);\n\t\tswitch (res) {\n\t\tcase KEY_NPAGE:\n\t\tcase ' ':\n\t\tcase 'd':\n\t\t\tstart_y += text_lines-2;\n\t\t\tbreak;\n\t\tcase KEY_PPAGE:\n\t\tcase 'u':\n\t\t\tstart_y -= text_lines+2;\n\t\t\tbreak;\n\t\tcase KEY_HOME:\n\t\t\tstart_y = 0;\n\t\t\tbreak;\n\t\tcase KEY_END:\n\t\t\tstart_y = total_lines-text_lines;\n\t\t\tbreak;\n\t\tcase KEY_DOWN:\n\t\tcase 'j':\n\t\t\tstart_y++;\n\t\t\tbreak;\n\t\tcase KEY_UP:\n\t\tcase 'k':\n\t\t\tstart_y--;\n\t\t\tbreak;\n\t\tcase KEY_LEFT:\n\t\tcase 'h':\n\t\t\tstart_x--;\n\t\t\tbreak;\n\t\tcase KEY_RIGHT:\n\t\tcase 'l':\n\t\t\tstart_x++;\n\t\t\tbreak;\n\t\t}\n\t\tif (res == 10 || res == 27 || res == 'q' ||\n\t\t\tres == KEY_F(F_HELP) || res == KEY_F(F_BACK) ||\n\t\t\tres == KEY_F(F_EXIT))\n\t\t\tbreak;\n\t\tif (start_y < 0)\n\t\t\tstart_y = 0;\n\t\tif (start_y >= total_lines-text_lines)\n\t\t\tstart_y = total_lines-text_lines;\n\t\tif (start_x < 0)\n\t\t\tstart_x = 0;\n\t\tif (start_x >= total_cols-text_cols)\n\t\t\tstart_x = total_cols-text_cols;\n\t} while (res);\n\n\tdel_panel(panel);\n\tdelwin(win);\n\trefresh_all_windows(main_window);\n}\n"
  },
  {
    "path": "3rdparty/kconfig/nconf.h",
    "content": "/* SPDX-License-Identifier: GPL-2.0 */\n/*\n * Copyright (C) 2008 Nir Tzachar <nir.tzachar@gmail.com>\n *\n * Derived from menuconfig.\n */\n\n#include <ctype.h>\n#include <errno.h>\n#include <fcntl.h>\n#include <limits.h>\n#include <stdarg.h>\n#include <stdlib.h>\n#include <string.h>\n#include <unistd.h>\n#include <ncurses.h>\n#include <menu.h>\n#include <panel.h>\n#include <form.h>\n\n#include <stdio.h>\n#include <time.h>\n#include <sys/time.h>\n\n#define max(a, b) ({\\\n\t\ttypeof(a) _a = a;\\\n\t\ttypeof(b) _b = b;\\\n\t\t_a > _b ? _a : _b; })\n\n#define min(a, b) ({\\\n\t\ttypeof(a) _a = a;\\\n\t\ttypeof(b) _b = b;\\\n\t\t_a < _b ? _a : _b; })\n\ntypedef enum {\n\tNORMAL = 1,\n\tMAIN_HEADING,\n\tMAIN_MENU_BOX,\n\tMAIN_MENU_FORE,\n\tMAIN_MENU_BACK,\n\tMAIN_MENU_GREY,\n\tMAIN_MENU_HEADING,\n\tSCROLLWIN_TEXT,\n\tSCROLLWIN_HEADING,\n\tSCROLLWIN_BOX,\n\tDIALOG_TEXT,\n\tDIALOG_MENU_FORE,\n\tDIALOG_MENU_BACK,\n\tDIALOG_BOX,\n\tINPUT_BOX,\n\tINPUT_HEADING,\n\tINPUT_TEXT,\n\tINPUT_FIELD,\n\tFUNCTION_TEXT,\n\tFUNCTION_HIGHLIGHT,\n\tATTR_MAX\n} attributes_t;\nextern attributes_t attributes[];\n\ntypedef enum {\n\tF_HELP = 1,\n\tF_SYMBOL = 2,\n\tF_INSTS = 3,\n\tF_CONF = 4,\n\tF_BACK = 5,\n\tF_SAVE = 6,\n\tF_LOAD = 7,\n\tF_SEARCH = 8,\n\tF_EXIT = 9,\n} function_key;\n\nvoid set_colors(void);\n\n/* this changes the windows attributes !!! */\nvoid print_in_middle(WINDOW *win,\n\t\tint starty,\n\t\tint startx,\n\t\tint width,\n\t\tconst char *string,\n\t\tchtype color);\nint get_line_length(const char *line);\nint get_line_no(const char *text);\nconst char *get_line(const char *text, int line_no);\nvoid fill_window(WINDOW *win, const char *text);\nint btn_dialog(WINDOW *main_window, const char *msg, int btn_num, ...);\nint dialog_inputbox(WINDOW *main_window,\n\t\tconst char *title, const char *prompt,\n\t\tconst char *init, char **resultp, int *result_len);\nvoid refresh_all_windows(WINDOW *main_window);\nvoid show_scroll_win(WINDOW *main_window,\n\t\tconst char *title,\n\t\tconst char *text);\n"
  },
  {
    "path": "3rdparty/kconfig/parser.y",
    "content": "/* SPDX-License-Identifier: GPL-2.0 */\n/*\n * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>\n */\n%{\n\n#include <ctype.h>\n#include <stdarg.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <stdbool.h>\n\n#include \"lkc.h\"\n\n#define printd(mask, fmt...) if (cdebug & (mask)) printf(fmt)\n\n#define PRINTD\t\t0x0001\n#define DEBUG_PARSE\t0x0002\n\nint cdebug = PRINTD;\n\nstatic void yyerror(const char *err);\nstatic void zconfprint(const char *err, ...);\nstatic void zconf_error(const char *err, ...);\nstatic bool zconf_endtoken(const char *tokenname,\n\t\t\t   const char *expected_tokenname);\n\nstruct symbol *symbol_hash[SYMBOL_HASHSIZE];\n\nstatic struct menu *current_menu, *current_entry;\n\n%}\n\n%union\n{\n\tchar *string;\n\tstruct symbol *symbol;\n\tstruct expr *expr;\n\tstruct menu *menu;\n\tenum symbol_type type;\n\tenum variable_flavor flavor;\n}\n\n%token <string> T_HELPTEXT\n%token <string> T_WORD\n%token <string> T_WORD_QUOTE\n%token T_ALLNOCONFIG_Y\n%token T_BOOL\n%token T_CHOICE\n%token T_CLOSE_PAREN\n%token T_COLON_EQUAL\n%token T_COMMENT\n%token T_CONFIG\n%token T_DEFAULT\n%token T_DEFCONFIG_LIST\n%token T_DEF_BOOL\n%token T_DEF_TRISTATE\n%token T_DEPENDS\n%token T_ENDCHOICE\n%token T_ENDIF\n%token T_ENDMENU\n%token T_HELP\n%token T_HEX\n%token T_IF\n%token T_IMPLY\n%token T_INT\n%token T_MAINMENU\n%token T_MENU\n%token T_MENUCONFIG\n%token T_MODULES\n%token T_ON\n%token T_OPEN_PAREN\n%token T_OPTION\n%token T_OPTIONAL\n%token T_PLUS_EQUAL\n%token T_PROMPT\n%token T_RANGE\n%token T_SELECT\n%token T_SOURCE\n%token T_STRING\n%token T_TRISTATE\n%token T_VISIBLE\n%token T_EOL\n%token <string> T_ASSIGN_VAL\n\n%left T_OR\n%left T_AND\n%left T_EQUAL T_UNEQUAL\n%left T_LESS T_LESS_EQUAL T_GREATER T_GREATER_EQUAL\n%nonassoc T_NOT\n\n%type <symbol> nonconst_symbol\n%type <symbol> symbol\n%type <type> type logic_type default\n%type <expr> expr\n%type <expr> if_expr\n%type <string> end\n%type <menu> if_entry menu_entry choice_entry\n%type <string> word_opt assign_val\n%type <flavor> assign_op\n\n%destructor {\n\tfprintf(stderr, \"%s:%d: missing end statement for this entry\\n\",\n\t\t$$->file->name, $$->lineno);\n\tif (current_menu == $$)\n\t\tmenu_end_menu();\n} if_entry menu_entry choice_entry\n\n%%\ninput: mainmenu_stmt stmt_list | stmt_list;\n\n/* mainmenu entry */\n\nmainmenu_stmt: T_MAINMENU T_WORD_QUOTE T_EOL\n{\n\tmenu_add_prompt(P_MENU, $2, NULL);\n};\n\nstmt_list:\n\t  /* empty */\n\t| stmt_list assignment_stmt\n\t| stmt_list choice_stmt\n\t| stmt_list comment_stmt\n\t| stmt_list config_stmt\n\t| stmt_list if_stmt\n\t| stmt_list menu_stmt\n\t| stmt_list menuconfig_stmt\n\t| stmt_list source_stmt\n\t| stmt_list T_WORD error T_EOL\t{ zconf_error(\"unknown statement \\\"%s\\\"\", $2); }\n\t| stmt_list error T_EOL\t\t{ zconf_error(\"invalid statement\"); }\n;\n\nstmt_list_in_choice:\n\t  /* empty */\n\t| stmt_list_in_choice comment_stmt\n\t| stmt_list_in_choice config_stmt\n\t| stmt_list_in_choice if_stmt_in_choice\n\t| stmt_list_in_choice error T_EOL\t{ zconf_error(\"invalid statement\"); }\n;\n\n/* config/menuconfig entry */\n\nconfig_entry_start: T_CONFIG nonconst_symbol T_EOL\n{\n\t$2->flags |= SYMBOL_OPTIONAL;\n\tmenu_add_entry($2);\n\tprintd(DEBUG_PARSE, \"%s:%d:config %s\\n\", zconf_curname(), zconf_lineno(), $2->name);\n};\n\nconfig_stmt: config_entry_start config_option_list\n{\n\tprintd(DEBUG_PARSE, \"%s:%d:endconfig\\n\", zconf_curname(), zconf_lineno());\n};\n\nmenuconfig_entry_start: T_MENUCONFIG nonconst_symbol T_EOL\n{\n\t$2->flags |= SYMBOL_OPTIONAL;\n\tmenu_add_entry($2);\n\tprintd(DEBUG_PARSE, \"%s:%d:menuconfig %s\\n\", zconf_curname(), zconf_lineno(), $2->name);\n};\n\nmenuconfig_stmt: menuconfig_entry_start config_option_list\n{\n\tif (current_entry->prompt)\n\t\tcurrent_entry->prompt->type = P_MENU;\n\telse\n\t\tzconfprint(\"warning: menuconfig statement without prompt\");\n\tprintd(DEBUG_PARSE, \"%s:%d:endconfig\\n\", zconf_curname(), zconf_lineno());\n};\n\nconfig_option_list:\n\t  /* empty */\n\t| config_option_list config_option\n\t| config_option_list depends\n\t| config_option_list help\n;\n\nconfig_option: type prompt_stmt_opt T_EOL\n{\n\tmenu_set_type($1);\n\tprintd(DEBUG_PARSE, \"%s:%d:type(%u)\\n\",\n\t\tzconf_curname(), zconf_lineno(),\n\t\t$1);\n};\n\nconfig_option: T_PROMPT T_WORD_QUOTE if_expr T_EOL\n{\n\tmenu_add_prompt(P_PROMPT, $2, $3);\n\tprintd(DEBUG_PARSE, \"%s:%d:prompt\\n\", zconf_curname(), zconf_lineno());\n};\n\nconfig_option: default expr if_expr T_EOL\n{\n\tmenu_add_expr(P_DEFAULT, $2, $3);\n\tif ($1 != S_UNKNOWN)\n\t\tmenu_set_type($1);\n\tprintd(DEBUG_PARSE, \"%s:%d:default(%u)\\n\",\n\t\tzconf_curname(), zconf_lineno(),\n\t\t$1);\n};\n\nconfig_option: T_SELECT nonconst_symbol if_expr T_EOL\n{\n\tmenu_add_symbol(P_SELECT, $2, $3);\n\tprintd(DEBUG_PARSE, \"%s:%d:select\\n\", zconf_curname(), zconf_lineno());\n};\n\nconfig_option: T_IMPLY nonconst_symbol if_expr T_EOL\n{\n\tmenu_add_symbol(P_IMPLY, $2, $3);\n\tprintd(DEBUG_PARSE, \"%s:%d:imply\\n\", zconf_curname(), zconf_lineno());\n};\n\nconfig_option: T_RANGE symbol symbol if_expr T_EOL\n{\n\tmenu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,$2, $3), $4);\n\tprintd(DEBUG_PARSE, \"%s:%d:range\\n\", zconf_curname(), zconf_lineno());\n};\n\nconfig_option: T_OPTION T_MODULES T_EOL\n{\n\tmenu_add_option_modules();\n};\n\nconfig_option: T_OPTION T_DEFCONFIG_LIST T_EOL\n{\n\tmenu_add_option_defconfig_list();\n};\n\nconfig_option: T_OPTION T_ALLNOCONFIG_Y T_EOL\n{\n\tmenu_add_option_allnoconfig_y();\n};\n\n/* choice entry */\n\nchoice: T_CHOICE word_opt T_EOL\n{\n\tstruct symbol *sym = sym_lookup($2, SYMBOL_CHOICE);\n\tsym->flags |= SYMBOL_NO_WRITE;\n\tmenu_add_entry(sym);\n\tmenu_add_expr(P_CHOICE, NULL, NULL);\n\tfree($2);\n\tprintd(DEBUG_PARSE, \"%s:%d:choice\\n\", zconf_curname(), zconf_lineno());\n};\n\nchoice_entry: choice choice_option_list\n{\n\t$$ = menu_add_menu();\n};\n\nchoice_end: end\n{\n\tif (zconf_endtoken($1, \"choice\")) {\n\t\tmenu_end_menu();\n\t\tprintd(DEBUG_PARSE, \"%s:%d:endchoice\\n\", zconf_curname(), zconf_lineno());\n\t}\n};\n\nchoice_stmt: choice_entry stmt_list_in_choice choice_end\n;\n\nchoice_option_list:\n\t  /* empty */\n\t| choice_option_list choice_option\n\t| choice_option_list depends\n\t| choice_option_list help\n;\n\nchoice_option: T_PROMPT T_WORD_QUOTE if_expr T_EOL\n{\n\tmenu_add_prompt(P_PROMPT, $2, $3);\n\tprintd(DEBUG_PARSE, \"%s:%d:prompt\\n\", zconf_curname(), zconf_lineno());\n};\n\nchoice_option: logic_type prompt_stmt_opt T_EOL\n{\n\tmenu_set_type($1);\n\tprintd(DEBUG_PARSE, \"%s:%d:type(%u)\\n\",\n\t       zconf_curname(), zconf_lineno(), $1);\n};\n\nchoice_option: T_OPTIONAL T_EOL\n{\n\tcurrent_entry->sym->flags |= SYMBOL_OPTIONAL;\n\tprintd(DEBUG_PARSE, \"%s:%d:optional\\n\", zconf_curname(), zconf_lineno());\n};\n\nchoice_option: T_DEFAULT nonconst_symbol if_expr T_EOL\n{\n\tmenu_add_symbol(P_DEFAULT, $2, $3);\n\tprintd(DEBUG_PARSE, \"%s:%d:default\\n\",\n\t       zconf_curname(), zconf_lineno());\n};\n\ntype:\n\t  logic_type\n\t| T_INT\t\t\t{ $$ = S_INT; }\n\t| T_HEX\t\t\t{ $$ = S_HEX; }\n\t| T_STRING\t\t{ $$ = S_STRING; }\n\nlogic_type:\n\t  T_BOOL\t\t{ $$ = S_BOOLEAN; }\n\t| T_TRISTATE\t\t{ $$ = S_TRISTATE; }\n\ndefault:\n\t  T_DEFAULT\t\t{ $$ = S_UNKNOWN; }\n\t| T_DEF_BOOL\t\t{ $$ = S_BOOLEAN; }\n\t| T_DEF_TRISTATE\t{ $$ = S_TRISTATE; }\n\n/* if entry */\n\nif_entry: T_IF expr T_EOL\n{\n\tprintd(DEBUG_PARSE, \"%s:%d:if\\n\", zconf_curname(), zconf_lineno());\n\tmenu_add_entry(NULL);\n\tmenu_add_dep($2);\n\t$$ = menu_add_menu();\n};\n\nif_end: end\n{\n\tif (zconf_endtoken($1, \"if\")) {\n\t\tmenu_end_menu();\n\t\tprintd(DEBUG_PARSE, \"%s:%d:endif\\n\", zconf_curname(), zconf_lineno());\n\t}\n};\n\nif_stmt: if_entry stmt_list if_end\n;\n\nif_stmt_in_choice: if_entry stmt_list_in_choice if_end\n;\n\n/* menu entry */\n\nmenu: T_MENU T_WORD_QUOTE T_EOL\n{\n\tmenu_add_entry(NULL);\n\tmenu_add_prompt(P_MENU, $2, NULL);\n\tprintd(DEBUG_PARSE, \"%s:%d:menu\\n\", zconf_curname(), zconf_lineno());\n};\n\nmenu_entry: menu menu_option_list\n{\n\t$$ = menu_add_menu();\n};\n\nmenu_end: end\n{\n\tif (zconf_endtoken($1, \"menu\")) {\n\t\tmenu_end_menu();\n\t\tprintd(DEBUG_PARSE, \"%s:%d:endmenu\\n\", zconf_curname(), zconf_lineno());\n\t}\n};\n\nmenu_stmt: menu_entry stmt_list menu_end\n;\n\nmenu_option_list:\n\t  /* empty */\n\t| menu_option_list visible\n\t| menu_option_list depends\n;\n\nsource_stmt: T_SOURCE T_WORD_QUOTE T_EOL\n{\n\tprintd(DEBUG_PARSE, \"%s:%d:source %s\\n\", zconf_curname(), zconf_lineno(), $2);\n\tzconf_nextfile($2);\n\tfree($2);\n};\n\n/* comment entry */\n\ncomment: T_COMMENT T_WORD_QUOTE T_EOL\n{\n\tmenu_add_entry(NULL);\n\tmenu_add_prompt(P_COMMENT, $2, NULL);\n\tprintd(DEBUG_PARSE, \"%s:%d:comment\\n\", zconf_curname(), zconf_lineno());\n};\n\ncomment_stmt: comment comment_option_list\n;\n\ncomment_option_list:\n\t  /* empty */\n\t| comment_option_list depends\n;\n\n/* help option */\n\nhelp_start: T_HELP T_EOL\n{\n\tprintd(DEBUG_PARSE, \"%s:%d:help\\n\", zconf_curname(), zconf_lineno());\n\tzconf_starthelp();\n};\n\nhelp: help_start T_HELPTEXT\n{\n\tif (current_entry->help) {\n\t\tfree(current_entry->help);\n\t\tzconfprint(\"warning: '%s' defined with more than one help text -- only the last one will be used\",\n\t\t\t   current_entry->sym->name ?: \"<choice>\");\n\t}\n\n\t/* Is the help text empty or all whitespace? */\n\tif ($2[strspn($2, \" \\f\\n\\r\\t\\v\")] == '\\0')\n\t\tzconfprint(\"warning: '%s' defined with blank help text\",\n\t\t\t   current_entry->sym->name ?: \"<choice>\");\n\n\tcurrent_entry->help = $2;\n};\n\n/* depends option */\n\ndepends: T_DEPENDS T_ON expr T_EOL\n{\n\tmenu_add_dep($3);\n\tprintd(DEBUG_PARSE, \"%s:%d:depends on\\n\", zconf_curname(), zconf_lineno());\n};\n\n/* visibility option */\nvisible: T_VISIBLE if_expr T_EOL\n{\n\tmenu_add_visibility($2);\n};\n\n/* prompt statement */\n\nprompt_stmt_opt:\n\t  /* empty */\n\t| T_WORD_QUOTE if_expr\n{\n\tmenu_add_prompt(P_PROMPT, $1, $2);\n};\n\nend:\t  T_ENDMENU T_EOL\t{ $$ = \"menu\"; }\n\t| T_ENDCHOICE T_EOL\t{ $$ = \"choice\"; }\n\t| T_ENDIF T_EOL\t\t{ $$ = \"if\"; }\n;\n\nif_expr:  /* empty */\t\t\t{ $$ = NULL; }\n\t| T_IF expr\t\t\t{ $$ = $2; }\n;\n\nexpr:\t  symbol\t\t\t\t{ $$ = expr_alloc_symbol($1); }\n\t| symbol T_LESS symbol\t\t\t{ $$ = expr_alloc_comp(E_LTH, $1, $3); }\n\t| symbol T_LESS_EQUAL symbol\t\t{ $$ = expr_alloc_comp(E_LEQ, $1, $3); }\n\t| symbol T_GREATER symbol\t\t{ $$ = expr_alloc_comp(E_GTH, $1, $3); }\n\t| symbol T_GREATER_EQUAL symbol\t\t{ $$ = expr_alloc_comp(E_GEQ, $1, $3); }\n\t| symbol T_EQUAL symbol\t\t\t{ $$ = expr_alloc_comp(E_EQUAL, $1, $3); }\n\t| symbol T_UNEQUAL symbol\t\t{ $$ = expr_alloc_comp(E_UNEQUAL, $1, $3); }\n\t| T_OPEN_PAREN expr T_CLOSE_PAREN\t{ $$ = $2; }\n\t| T_NOT expr\t\t\t\t{ $$ = expr_alloc_one(E_NOT, $2); }\n\t| expr T_OR expr\t\t\t{ $$ = expr_alloc_two(E_OR, $1, $3); }\n\t| expr T_AND expr\t\t\t{ $$ = expr_alloc_two(E_AND, $1, $3); }\n;\n\n/* For symbol definitions, selects, etc., where quotes are not accepted */\nnonconst_symbol: T_WORD { $$ = sym_lookup($1, 0); free($1); };\n\nsymbol:\t  nonconst_symbol\n\t| T_WORD_QUOTE\t{ $$ = sym_lookup($1, SYMBOL_CONST); free($1); }\n;\n\nword_opt: /* empty */\t\t\t{ $$ = NULL; }\n\t| T_WORD\n\n/* assignment statement */\n\nassignment_stmt:  T_WORD assign_op assign_val T_EOL\t{ variable_add($1, $3, $2); free($1); free($3); }\n\nassign_op:\n\t  T_EQUAL\t{ $$ = VAR_RECURSIVE; }\n\t| T_COLON_EQUAL\t{ $$ = VAR_SIMPLE; }\n\t| T_PLUS_EQUAL\t{ $$ = VAR_APPEND; }\n;\n\nassign_val:\n\t/* empty */\t\t{ $$ = xstrdup(\"\"); };\n\t| T_ASSIGN_VAL\n;\n\n%%\n\nvoid conf_parse(const char *name)\n{\n\tstruct symbol *sym;\n\tint i;\n\n\tzconf_initscan(name);\n\n\t_menu_init();\n\n\tif (getenv(\"ZCONF_DEBUG\"))\n\t\tyydebug = 1;\n\tyyparse();\n\n\t/* Variables are expanded in the parse phase. We can free them here. */\n\tvariable_all_del();\n\n\tif (yynerrs)\n\t\texit(1);\n\tif (!modules_sym)\n\t\tmodules_sym = sym_find( \"n\" );\n\n\tif (!menu_has_prompt(&rootmenu)) {\n\t\tcurrent_entry = &rootmenu;\n\t\tmenu_add_prompt(P_MENU, \"Main menu\", NULL);\n\t}\n\n\tmenu_finalize(&rootmenu);\n\tfor_all_symbols(i, sym) {\n\t\tif (sym_check_deps(sym))\n\t\t\tyynerrs++;\n\t}\n\tif (yynerrs)\n\t\texit(1);\n\tsym_set_change_count(1);\n}\n\nstatic bool zconf_endtoken(const char *tokenname,\n\t\t\t   const char *expected_tokenname)\n{\n\tif (strcmp(tokenname, expected_tokenname)) {\n\t\tzconf_error(\"unexpected '%s' within %s block\",\n\t\t\t    tokenname, expected_tokenname);\n\t\tyynerrs++;\n\t\treturn false;\n\t}\n\tif (current_menu->file != current_file) {\n\t\tzconf_error(\"'%s' in different file than '%s'\",\n\t\t\t    tokenname, expected_tokenname);\n\t\tfprintf(stderr, \"%s:%d: location of the '%s'\\n\",\n\t\t\tcurrent_menu->file->name, current_menu->lineno,\n\t\t\texpected_tokenname);\n\t\tyynerrs++;\n\t\treturn false;\n\t}\n\treturn true;\n}\n\nstatic void zconfprint(const char *err, ...)\n{\n\tva_list ap;\n\n\tfprintf(stderr, \"%s:%d: \", zconf_curname(), zconf_lineno());\n\tva_start(ap, err);\n\tvfprintf(stderr, err, ap);\n\tva_end(ap);\n\tfprintf(stderr, \"\\n\");\n}\n\nstatic void zconf_error(const char *err, ...)\n{\n\tva_list ap;\n\n\tyynerrs++;\n\tfprintf(stderr, \"%s:%d: \", zconf_curname(), zconf_lineno());\n\tva_start(ap, err);\n\tvfprintf(stderr, err, ap);\n\tva_end(ap);\n\tfprintf(stderr, \"\\n\");\n}\n\nstatic void yyerror(const char *err)\n{\n\tfprintf(stderr, \"%s:%d: %s\\n\", zconf_curname(), zconf_lineno() + 1, err);\n}\n\nstatic void print_quoted_string(FILE *out, const char *str)\n{\n\tconst char *p;\n\tint len;\n\n\tputc('\"', out);\n\twhile ((p = strchr(str, '\"'))) {\n\t\tlen = p - str;\n\t\tif (len)\n\t\t\tfprintf(out, \"%.*s\", len, str);\n\t\tfputs(\"\\\\\\\"\", out);\n\t\tstr = p + 1;\n\t}\n\tfputs(str, out);\n\tputc('\"', out);\n}\n\nstatic void print_symbol(FILE *out, struct menu *menu)\n{\n\tstruct symbol *sym = menu->sym;\n\tstruct property *prop;\n\n\tif (sym_is_choice(sym))\n\t\tfprintf(out, \"\\nchoice\\n\");\n\telse\n\t\tfprintf(out, \"\\nconfig %s\\n\", sym->name);\n\tswitch (sym->type) {\n\tcase S_BOOLEAN:\n\t\tfputs(\"  bool\\n\", out);\n\t\tbreak;\n\tcase S_TRISTATE:\n\t\tfputs(\"  tristate\\n\", out);\n\t\tbreak;\n\tcase S_STRING:\n\t\tfputs(\"  string\\n\", out);\n\t\tbreak;\n\tcase S_INT:\n\t\tfputs(\"  integer\\n\", out);\n\t\tbreak;\n\tcase S_HEX:\n\t\tfputs(\"  hex\\n\", out);\n\t\tbreak;\n\tdefault:\n\t\tfputs(\"  ???\\n\", out);\n\t\tbreak;\n\t}\n\tfor (prop = sym->prop; prop; prop = prop->next) {\n\t\tif (prop->menu != menu)\n\t\t\tcontinue;\n\t\tswitch (prop->type) {\n\t\tcase P_PROMPT:\n\t\t\tfputs(\"  prompt \", out);\n\t\t\tprint_quoted_string(out, prop->text);\n\t\t\tif (!expr_is_yes(prop->visible.expr)) {\n\t\t\t\tfputs(\" if \", out);\n\t\t\t\texpr_fprint(prop->visible.expr, out);\n\t\t\t}\n\t\t\tfputc('\\n', out);\n\t\t\tbreak;\n\t\tcase P_DEFAULT:\n\t\t\tfputs( \"  default \", out);\n\t\t\texpr_fprint(prop->expr, out);\n\t\t\tif (!expr_is_yes(prop->visible.expr)) {\n\t\t\t\tfputs(\" if \", out);\n\t\t\t\texpr_fprint(prop->visible.expr, out);\n\t\t\t}\n\t\t\tfputc('\\n', out);\n\t\t\tbreak;\n\t\tcase P_CHOICE:\n\t\t\tfputs(\"  #choice value\\n\", out);\n\t\t\tbreak;\n\t\tcase P_SELECT:\n\t\t\tfputs( \"  select \", out);\n\t\t\texpr_fprint(prop->expr, out);\n\t\t\tfputc('\\n', out);\n\t\t\tbreak;\n\t\tcase P_IMPLY:\n\t\t\tfputs( \"  imply \", out);\n\t\t\texpr_fprint(prop->expr, out);\n\t\t\tfputc('\\n', out);\n\t\t\tbreak;\n\t\tcase P_RANGE:\n\t\t\tfputs( \"  range \", out);\n\t\t\texpr_fprint(prop->expr, out);\n\t\t\tfputc('\\n', out);\n\t\t\tbreak;\n\t\tcase P_MENU:\n\t\t\tfputs( \"  menu \", out);\n\t\t\tprint_quoted_string(out, prop->text);\n\t\t\tfputc('\\n', out);\n\t\t\tbreak;\n\t\tcase P_SYMBOL:\n\t\t\tfputs( \"  symbol \", out);\n\t\t\tfprintf(out, \"%s\\n\", prop->menu->sym->name);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tfprintf(out, \"  unknown prop %d!\\n\", prop->type);\n\t\t\tbreak;\n\t\t}\n\t}\n\tif (menu->help) {\n\t\tint len = strlen(menu->help);\n\t\twhile (menu->help[--len] == '\\n')\n\t\t\tmenu->help[len] = 0;\n\t\tfprintf(out, \"  help\\n%s\\n\", menu->help);\n\t}\n}\n\nvoid zconfdump(FILE *out)\n{\n\tstruct property *prop;\n\tstruct symbol *sym;\n\tstruct menu *menu;\n\n\tmenu = rootmenu.list;\n\twhile (menu) {\n\t\tif ((sym = menu->sym))\n\t\t\tprint_symbol(out, menu);\n\t\telse if ((prop = menu->prompt)) {\n\t\t\tswitch (prop->type) {\n\t\t\tcase P_COMMENT:\n\t\t\t\tfputs(\"\\ncomment \", out);\n\t\t\t\tprint_quoted_string(out, prop->text);\n\t\t\t\tfputs(\"\\n\", out);\n\t\t\t\tbreak;\n\t\t\tcase P_MENU:\n\t\t\t\tfputs(\"\\nmenu \", out);\n\t\t\t\tprint_quoted_string(out, prop->text);\n\t\t\t\tfputs(\"\\n\", out);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\t;\n\t\t\t}\n\t\t\tif (!expr_is_yes(prop->visible.expr)) {\n\t\t\t\tfputs(\"  depends \", out);\n\t\t\t\texpr_fprint(prop->visible.expr, out);\n\t\t\t\tfputc('\\n', out);\n\t\t\t}\n\t\t}\n\n\t\tif (menu->list)\n\t\t\tmenu = menu->list;\n\t\telse if (menu->next)\n\t\t\tmenu = menu->next;\n\t\telse while ((menu = menu->parent)) {\n\t\t\tif (menu->prompt && menu->prompt->type == P_MENU)\n\t\t\t\tfputs(\"\\nendmenu\\n\", out);\n\t\t\tif (menu->next) {\n\t\t\t\tmenu = menu->next;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n}\n\n#include \"menu.c\"\n"
  },
  {
    "path": "3rdparty/kconfig/preprocess.c",
    "content": "// SPDX-License-Identifier: GPL-2.0\n//\n// Copyright (C) 2018 Masahiro Yamada <yamada.masahiro@socionext.com>\n\n#include <ctype.h>\n#include <stdarg.h>\n#include <stdbool.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include \"list.h\"\n#include \"lkc.h\"\n\n#define ARRAY_SIZE(arr)\t\t(sizeof(arr) / sizeof((arr)[0]))\n\nstatic char *expand_string_with_args(const char *in, int argc, char *argv[]);\nstatic char *expand_string(const char *in);\n\nstatic void __attribute__((noreturn)) pperror(const char *format, ...)\n{\n\tva_list ap;\n\n\tfprintf(stderr, \"%s:%d: \", current_file->name, yylineno);\n\tva_start(ap, format);\n\tvfprintf(stderr, format, ap);\n\tva_end(ap);\n\tfprintf(stderr, \"\\n\");\n\n\texit(1);\n}\n\n/*\n * Environment variables\n */\nstatic LIST_HEAD(env_list);\n\nstruct env {\n\tchar *name;\n\tchar *value;\n\tstruct list_head node;\n};\n\nstatic void env_add(const char *name, const char *value)\n{\n\tstruct env *e;\n\n\te = xmalloc(sizeof(*e));\n\te->name = xstrdup(name);\n\te->value = xstrdup(value);\n\n\tlist_add_tail(&e->node, &env_list);\n}\n\nstatic void env_del(struct env *e)\n{\n\tlist_del(&e->node);\n\tfree(e->name);\n\tfree(e->value);\n\tfree(e);\n}\n\n/* The returned pointer must be freed when done */\nstatic char *env_expand(const char *name)\n{\n\tstruct env *e;\n\tconst char *value;\n\n\tif (!*name)\n\t\treturn NULL;\n\n\tlist_for_each_entry(e, &env_list, node) {\n\t\tif (!strcmp(name, e->name))\n\t\t\treturn xstrdup(e->value);\n\t}\n\n\tvalue = getenv(name);\n\tif (!value)\n\t\treturn NULL;\n\n\t/*\n\t * We need to remember all referenced environment variables.\n\t * They will be written out to include/config/auto.conf.cmd\n\t */\n\tenv_add(name, value);\n\n\treturn xstrdup(value);\n}\n\nvoid env_write_dep(FILE *f, const char *autoconfig_name)\n{\n\tstruct env *e, *tmp;\n\n\tlist_for_each_entry_safe(e, tmp, &env_list, node) {\n\t\tfprintf(f, \"ifneq \\\"$(%s)\\\" \\\"%s\\\"\\n\", e->name, e->value);\n\t\tfprintf(f, \"%s: FORCE\\n\", autoconfig_name);\n\t\tfprintf(f, \"endif\\n\");\n\t\tenv_del(e);\n\t}\n}\n\n/*\n * Built-in functions\n */\nstruct function {\n\tconst char *name;\n\tunsigned int min_args;\n\tunsigned int max_args;\n\tchar *(*func)(int argc, char *argv[]);\n};\n\nstatic char *do_error_if(int argc, char *argv[])\n{\n\tif (!strcmp(argv[0], \"y\"))\n\t\tpperror(\"%s\", argv[1]);\n\n\treturn NULL;\n}\n\nstatic char *do_filename(int argc, char *argv[])\n{\n\treturn xstrdup(current_file->name);\n}\n\nstatic char *do_info(int argc, char *argv[])\n{\n\tprintf(\"%s\\n\", argv[0]);\n\n\treturn xstrdup(\"\");\n}\n\nstatic char *do_lineno(int argc, char *argv[])\n{\n\tchar buf[16];\n\n\tsprintf(buf, \"%d\", yylineno);\n\n\treturn xstrdup(buf);\n}\n\nstatic char *do_shell(int argc, char *argv[])\n{\n\tFILE *p;\n\tchar buf[256];\n\tchar *cmd;\n\tsize_t nread;\n\tint i;\n\n\tcmd = argv[0];\n\n\tp = popen(cmd, \"r\");\n\tif (!p) {\n\t\tperror(cmd);\n\t\texit(1);\n\t}\n\n\tnread = fread(buf, 1, sizeof(buf), p);\n\tif (nread == sizeof(buf))\n\t\tnread--;\n\n\t/* remove trailing new lines */\n\twhile (nread > 0 && buf[nread - 1] == '\\n')\n\t\tnread--;\n\n\tbuf[nread] = 0;\n\n\t/* replace a new line with a space */\n\tfor (i = 0; i < nread; i++) {\n\t\tif (buf[i] == '\\n')\n\t\t\tbuf[i] = ' ';\n\t}\n\n\tif (pclose(p) == -1) {\n\t\tperror(cmd);\n\t\texit(1);\n\t}\n\n\treturn xstrdup(buf);\n}\n\nstatic char *do_warning_if(int argc, char *argv[])\n{\n\tif (!strcmp(argv[0], \"y\"))\n\t\tfprintf(stderr, \"%s:%d: %s\\n\",\n\t\t\tcurrent_file->name, yylineno, argv[1]);\n\n\treturn xstrdup(\"\");\n}\n\nstatic const struct function function_table[] = {\n\t/* Name\t\tMIN\tMAX\tFunction */\n\t{ \"error-if\",\t2,\t2,\tdo_error_if },\n\t{ \"filename\",\t0,\t0,\tdo_filename },\n\t{ \"info\",\t1,\t1,\tdo_info },\n\t{ \"lineno\",\t0,\t0,\tdo_lineno },\n\t{ \"shell\",\t1,\t1,\tdo_shell },\n\t{ \"warning-if\",\t2,\t2,\tdo_warning_if },\n};\n\n#define FUNCTION_MAX_ARGS\t\t16\n\nstatic char *function_expand(const char *name, int argc, char *argv[])\n{\n\tconst struct function *f;\n\tint i;\n\n\tfor (i = 0; i < ARRAY_SIZE(function_table); i++) {\n\t\tf = &function_table[i];\n\t\tif (strcmp(f->name, name))\n\t\t\tcontinue;\n\n\t\tif (argc < f->min_args)\n\t\t\tpperror(\"too few function arguments passed to '%s'\",\n\t\t\t\tname);\n\n\t\tif (argc > f->max_args)\n\t\t\tpperror(\"too many function arguments passed to '%s'\",\n\t\t\t\tname);\n\n\t\treturn f->func(argc, argv);\n\t}\n\n\treturn NULL;\n}\n\n/*\n * Variables (and user-defined functions)\n */\nstatic LIST_HEAD(variable_list);\n\nstruct variable {\n\tchar *name;\n\tchar *value;\n\tenum variable_flavor flavor;\n\tint exp_count;\n\tstruct list_head node;\n};\n\nstatic struct variable *variable_lookup(const char *name)\n{\n\tstruct variable *v;\n\n\tlist_for_each_entry(v, &variable_list, node) {\n\t\tif (!strcmp(name, v->name))\n\t\t\treturn v;\n\t}\n\n\treturn NULL;\n}\n\nstatic char *variable_expand(const char *name, int argc, char *argv[])\n{\n\tstruct variable *v;\n\tchar *res;\n\n\tv = variable_lookup(name);\n\tif (!v)\n\t\treturn NULL;\n\n\tif (argc == 0 && v->exp_count)\n\t\tpperror(\"Recursive variable '%s' references itself (eventually)\",\n\t\t\tname);\n\n\tif (v->exp_count > 1000)\n\t\tpperror(\"Too deep recursive expansion\");\n\n\tv->exp_count++;\n\n\tif (v->flavor == VAR_RECURSIVE)\n\t\tres = expand_string_with_args(v->value, argc, argv);\n\telse\n\t\tres = xstrdup(v->value);\n\n\tv->exp_count--;\n\n\treturn res;\n}\n\nvoid variable_add(const char *name, const char *value,\n\t\t  enum variable_flavor flavor)\n{\n\tstruct variable *v;\n\tchar *new_value;\n\tbool append = false;\n\n\tv = variable_lookup(name);\n\tif (v) {\n\t\t/* For defined variables, += inherits the existing flavor */\n\t\tif (flavor == VAR_APPEND) {\n\t\t\tflavor = v->flavor;\n\t\t\tappend = true;\n\t\t} else {\n\t\t\tfree(v->value);\n\t\t}\n\t} else {\n\t\t/* For undefined variables, += assumes the recursive flavor */\n\t\tif (flavor == VAR_APPEND)\n\t\t\tflavor = VAR_RECURSIVE;\n\n\t\tv = xmalloc(sizeof(*v));\n\t\tv->name = xstrdup(name);\n\t\tv->exp_count = 0;\n\t\tlist_add_tail(&v->node, &variable_list);\n\t}\n\n\tv->flavor = flavor;\n\n\tif (flavor == VAR_SIMPLE)\n\t\tnew_value = expand_string(value);\n\telse\n\t\tnew_value = xstrdup(value);\n\n\tif (append) {\n\t\tv->value = xrealloc(v->value,\n\t\t\t\t    strlen(v->value) + strlen(new_value) + 2);\n\t\tstrcat(v->value, \" \");\n\t\tstrcat(v->value, new_value);\n\t\tfree(new_value);\n\t} else {\n\t\tv->value = new_value;\n\t}\n}\n\nstatic void variable_del(struct variable *v)\n{\n\tlist_del(&v->node);\n\tfree(v->name);\n\tfree(v->value);\n\tfree(v);\n}\n\nvoid variable_all_del(void)\n{\n\tstruct variable *v, *tmp;\n\n\tlist_for_each_entry_safe(v, tmp, &variable_list, node)\n\t\tvariable_del(v);\n}\n\n/*\n * Evaluate a clause with arguments.  argc/argv are arguments from the upper\n * function call.\n *\n * Returned string must be freed when done\n */\nstatic char *eval_clause(const char *str, size_t len, int argc, char *argv[])\n{\n\tchar *tmp, *name, *res, *endptr, *prev, *p;\n\tint new_argc = 0;\n\tchar *new_argv[FUNCTION_MAX_ARGS];\n\tint nest = 0;\n\tint i;\n\tunsigned long n;\n\n\ttmp = xstrndup(str, len);\n\n\t/*\n\t * If variable name is '1', '2', etc.  It is generally an argument\n\t * from a user-function call (i.e. local-scope variable).  If not\n\t * available, then look-up global-scope variables.\n\t */\n\tn = strtoul(tmp, &endptr, 10);\n\tif (!*endptr && n > 0 && n <= argc) {\n\t\tres = xstrdup(argv[n - 1]);\n\t\tgoto free_tmp;\n\t}\n\n\tprev = p = tmp;\n\n\t/*\n\t * Split into tokens\n\t * The function name and arguments are separated by a comma.\n\t * For example, if the function call is like this:\n\t *   $(foo,$(x),$(y))\n\t *\n\t * The input string for this helper should be:\n\t *   foo,$(x),$(y)\n\t *\n\t * and split into:\n\t *   new_argv[0] = 'foo'\n\t *   new_argv[1] = '$(x)'\n\t *   new_argv[2] = '$(y)'\n\t */\n\twhile (*p) {\n\t\tif (nest == 0 && *p == ',') {\n\t\t\t*p = 0;\n\t\t\tif (new_argc >= FUNCTION_MAX_ARGS)\n\t\t\t\tpperror(\"too many function arguments\");\n\t\t\tnew_argv[new_argc++] = prev;\n\t\t\tprev = p + 1;\n\t\t} else if (*p == '(') {\n\t\t\tnest++;\n\t\t} else if (*p == ')') {\n\t\t\tnest--;\n\t\t}\n\n\t\tp++;\n\t}\n\tnew_argv[new_argc++] = prev;\n\n\t/*\n\t * Shift arguments\n\t * new_argv[0] represents a function name or a variable name.  Put it\n\t * into 'name', then shift the rest of the arguments.  This simplifies\n\t * 'const' handling.\n\t */\n\tname = expand_string_with_args(new_argv[0], argc, argv);\n\tnew_argc--;\n\tfor (i = 0; i < new_argc; i++)\n\t\tnew_argv[i] = expand_string_with_args(new_argv[i + 1],\n\t\t\t\t\t\t      argc, argv);\n\n\t/* Search for variables */\n\tres = variable_expand(name, new_argc, new_argv);\n\tif (res)\n\t\tgoto free;\n\n\t/* Look for built-in functions */\n\tres = function_expand(name, new_argc, new_argv);\n\tif (res)\n\t\tgoto free;\n\n\t/* Last, try environment variable */\n\tif (new_argc == 0) {\n\t\tres = env_expand(name);\n\t\tif (res)\n\t\t\tgoto free;\n\t}\n\n\tres = xstrdup(\"\");\nfree:\n\tfor (i = 0; i < new_argc; i++)\n\t\tfree(new_argv[i]);\n\tfree(name);\nfree_tmp:\n\tfree(tmp);\n\n\treturn res;\n}\n\n/*\n * Expand a string that follows '$'\n *\n * For example, if the input string is\n *     ($(FOO)$($(BAR)))$(BAZ)\n * this helper evaluates\n *     $($(FOO)$($(BAR)))\n * and returns a new string containing the expansion (note that the string is\n * recursively expanded), also advancing 'str' to point to the next character\n * after the corresponding closing parenthesis, in this case, *str will be\n *     $(BAR)\n */\nstatic char *expand_dollar_with_args(const char **str, int argc, char *argv[])\n{\n\tconst char *p = *str;\n\tconst char *q;\n\tint nest = 0;\n\n\t/*\n\t * In Kconfig, variable/function references always start with \"$(\".\n\t * Neither single-letter variables as in $A nor curly braces as in ${CC}\n\t * are supported.  '$' not followed by '(' loses its special meaning.\n\t */\n\tif (*p != '(') {\n\t\t*str = p;\n\t\treturn xstrdup(\"$\");\n\t}\n\n\tp++;\n\tq = p;\n\twhile (*q) {\n\t\tif (*q == '(') {\n\t\t\tnest++;\n\t\t} else if (*q == ')') {\n\t\t\tif (nest-- == 0)\n\t\t\t\tbreak;\n\t\t}\n\t\tq++;\n\t}\n\n\tif (!*q)\n\t\tpperror(\"unterminated reference to '%s': missing ')'\", p);\n\n\t/* Advance 'str' to after the expanded initial portion of the string */\n\t*str = q + 1;\n\n\treturn eval_clause(p, q - p, argc, argv);\n}\n\nchar *expand_dollar(const char **str)\n{\n\treturn expand_dollar_with_args(str, 0, NULL);\n}\n\nstatic char *__expand_string(const char **str, bool (*is_end)(char c),\n\t\t\t     int argc, char *argv[])\n{\n\tconst char *in, *p;\n\tchar *expansion, *out;\n\tsize_t in_len, out_len;\n\n\tout = xmalloc(1);\n\t*out = 0;\n\tout_len = 1;\n\n\tp = in = *str;\n\n\twhile (1) {\n\t\tif (*p == '$') {\n\t\t\tin_len = p - in;\n\t\t\tp++;\n\t\t\texpansion = expand_dollar_with_args(&p, argc, argv);\n\t\t\tout_len += in_len + strlen(expansion);\n\t\t\tout = xrealloc(out, out_len);\n\t\t\tstrncat(out, in, in_len);\n\t\t\tstrcat(out, expansion);\n\t\t\tfree(expansion);\n\t\t\tin = p;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (is_end(*p))\n\t\t\tbreak;\n\n\t\tp++;\n\t}\n\n\tin_len = p - in;\n\tout_len += in_len;\n\tout = xrealloc(out, out_len);\n\tstrncat(out, in, in_len);\n\n\t/* Advance 'str' to the end character */\n\t*str = p;\n\n\treturn out;\n}\n\nstatic bool is_end_of_str(char c)\n{\n\treturn !c;\n}\n\n/*\n * Expand variables and functions in the given string.  Undefined variables\n * expand to an empty string.\n * The returned string must be freed when done.\n */\nstatic char *expand_string_with_args(const char *in, int argc, char *argv[])\n{\n\treturn __expand_string(&in, is_end_of_str, argc, argv);\n}\n\nstatic char *expand_string(const char *in)\n{\n\treturn expand_string_with_args(in, 0, NULL);\n}\n\nstatic bool is_end_of_token(char c)\n{\n\treturn !(isalnum(c) || c == '_' || c == '-');\n}\n\n/*\n * Expand variables in a token.  The parsing stops when a token separater\n * (in most cases, it is a whitespace) is encountered.  'str' is updated to\n * point to the next character.\n *\n * The returned string must be freed when done.\n */\nchar *expand_one_token(const char **str)\n{\n\treturn __expand_string(str, is_end_of_token, 0, NULL);\n}\n"
  },
  {
    "path": "3rdparty/kconfig/symbol.c",
    "content": "// SPDX-License-Identifier: GPL-2.0\n/*\n * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>\n */\n\n#include <ctype.h>\n#include <stdlib.h>\n#include <string.h>\n#include <regex.h>\n#include <sys/utsname.h>\n\n#include \"lkc.h\"\n\nstruct symbol symbol_yes = {\n\t.name = \"y\",\n\t.curr = { \"y\", yes },\n\t.flags = SYMBOL_CONST|SYMBOL_VALID,\n};\n\nstruct symbol symbol_mod = {\n\t.name = \"m\",\n\t.curr = { \"m\", mod },\n\t.flags = SYMBOL_CONST|SYMBOL_VALID,\n};\n\nstruct symbol symbol_no = {\n\t.name = \"n\",\n\t.curr = { \"n\", no },\n\t.flags = SYMBOL_CONST|SYMBOL_VALID,\n};\n\nstatic struct symbol symbol_empty = {\n\t.name = \"\",\n\t.curr = { \"\", no },\n\t.flags = SYMBOL_VALID,\n};\n\nstruct symbol *sym_defconfig_list;\nstruct symbol *modules_sym;\nstatic tristate modules_val;\n\nenum symbol_type sym_get_type(struct symbol *sym)\n{\n\tenum symbol_type type = sym->type;\n\n\tif (type == S_TRISTATE) {\n\t\tif (sym_is_choice_value(sym) && sym->visible == yes)\n\t\t\ttype = S_BOOLEAN;\n\t\telse if (modules_val == no)\n\t\t\ttype = S_BOOLEAN;\n\t}\n\treturn type;\n}\n\nconst char *sym_type_name(enum symbol_type type)\n{\n\tswitch (type) {\n\tcase S_BOOLEAN:\n\t\treturn \"bool\";\n\tcase S_TRISTATE:\n\t\treturn \"tristate\";\n\tcase S_INT:\n\t\treturn \"integer\";\n\tcase S_HEX:\n\t\treturn \"hex\";\n\tcase S_STRING:\n\t\treturn \"string\";\n\tcase S_UNKNOWN:\n\t\treturn \"unknown\";\n\t}\n\treturn \"???\";\n}\n\nstruct property *sym_get_choice_prop(struct symbol *sym)\n{\n\tstruct property *prop;\n\n\tfor_all_choices(sym, prop)\n\t\treturn prop;\n\treturn NULL;\n}\n\nstatic struct property *sym_get_default_prop(struct symbol *sym)\n{\n\tstruct property *prop;\n\n\tfor_all_defaults(sym, prop) {\n\t\tprop->visible.tri = expr_calc_value(prop->visible.expr);\n\t\tif (prop->visible.tri != no)\n\t\t\treturn prop;\n\t}\n\treturn NULL;\n}\n\nstruct property *sym_get_range_prop(struct symbol *sym)\n{\n\tstruct property *prop;\n\n\tfor_all_properties(sym, prop, P_RANGE) {\n\t\tprop->visible.tri = expr_calc_value(prop->visible.expr);\n\t\tif (prop->visible.tri != no)\n\t\t\treturn prop;\n\t}\n\treturn NULL;\n}\n\nstatic long long sym_get_range_val(struct symbol *sym, int base)\n{\n\tsym_calc_value(sym);\n\tswitch (sym->type) {\n\tcase S_INT:\n\t\tbase = 10;\n\t\tbreak;\n\tcase S_HEX:\n\t\tbase = 16;\n\t\tbreak;\n\tdefault:\n\t\tbreak;\n\t}\n\treturn strtoll(sym->curr.val, NULL, base);\n}\n\nstatic void sym_validate_range(struct symbol *sym)\n{\n\tstruct property *prop;\n\tint base;\n\tlong long val, val2;\n\tchar str[64];\n\n\tswitch (sym->type) {\n\tcase S_INT:\n\t\tbase = 10;\n\t\tbreak;\n\tcase S_HEX:\n\t\tbase = 16;\n\t\tbreak;\n\tdefault:\n\t\treturn;\n\t}\n\tprop = sym_get_range_prop(sym);\n\tif (!prop)\n\t\treturn;\n\tval = strtoll(sym->curr.val, NULL, base);\n\tval2 = sym_get_range_val(prop->expr->left.sym, base);\n\tif (val >= val2) {\n\t\tval2 = sym_get_range_val(prop->expr->right.sym, base);\n\t\tif (val <= val2)\n\t\t\treturn;\n\t}\n\tif (sym->type == S_INT)\n\t\tsprintf(str, \"%lld\", val2);\n\telse\n\t\tsprintf(str, \"0x%llx\", val2);\n\tsym->curr.val = xstrdup(str);\n}\n\nstatic void sym_set_changed(struct symbol *sym)\n{\n\tstruct property *prop;\n\n\tsym->flags |= SYMBOL_CHANGED;\n\tfor (prop = sym->prop; prop; prop = prop->next) {\n\t\tif (prop->menu)\n\t\t\tprop->menu->flags |= MENU_CHANGED;\n\t}\n}\n\nstatic void sym_set_all_changed(void)\n{\n\tstruct symbol *sym;\n\tint i;\n\n\tfor_all_symbols(i, sym)\n\t\tsym_set_changed(sym);\n}\n\nstatic void sym_calc_visibility(struct symbol *sym)\n{\n\tstruct property *prop;\n\tstruct symbol *choice_sym = NULL;\n\ttristate tri;\n\n\t/* any prompt visible? */\n\ttri = no;\n\n\tif (sym_is_choice_value(sym))\n\t\tchoice_sym = prop_get_symbol(sym_get_choice_prop(sym));\n\n\tfor_all_prompts(sym, prop) {\n\t\tprop->visible.tri = expr_calc_value(prop->visible.expr);\n\t\t/*\n\t\t * Tristate choice_values with visibility 'mod' are\n\t\t * not visible if the corresponding choice's value is\n\t\t * 'yes'.\n\t\t */\n\t\tif (choice_sym && sym->type == S_TRISTATE &&\n\t\t    prop->visible.tri == mod && choice_sym->curr.tri == yes)\n\t\t\tprop->visible.tri = no;\n\n\t\ttri = EXPR_OR(tri, prop->visible.tri);\n\t}\n\tif (tri == mod && (sym->type != S_TRISTATE || modules_val == no))\n\t\ttri = yes;\n\tif (sym->visible != tri) {\n\t\tsym->visible = tri;\n\t\tsym_set_changed(sym);\n\t}\n\tif (sym_is_choice_value(sym))\n\t\treturn;\n\t/* defaulting to \"yes\" if no explicit \"depends on\" are given */\n\ttri = yes;\n\tif (sym->dir_dep.expr)\n\t\ttri = expr_calc_value(sym->dir_dep.expr);\n\tif (tri == mod && sym_get_type(sym) == S_BOOLEAN)\n\t\ttri = yes;\n\tif (sym->dir_dep.tri != tri) {\n\t\tsym->dir_dep.tri = tri;\n\t\tsym_set_changed(sym);\n\t}\n\ttri = no;\n\tif (sym->rev_dep.expr)\n\t\ttri = expr_calc_value(sym->rev_dep.expr);\n\tif (tri == mod && sym_get_type(sym) == S_BOOLEAN)\n\t\ttri = yes;\n\tif (sym->rev_dep.tri != tri) {\n\t\tsym->rev_dep.tri = tri;\n\t\tsym_set_changed(sym);\n\t}\n\ttri = no;\n\tif (sym->implied.expr)\n\t\ttri = expr_calc_value(sym->implied.expr);\n\tif (tri == mod && sym_get_type(sym) == S_BOOLEAN)\n\t\ttri = yes;\n\tif (sym->implied.tri != tri) {\n\t\tsym->implied.tri = tri;\n\t\tsym_set_changed(sym);\n\t}\n}\n\n/*\n * Find the default symbol for a choice.\n * First try the default values for the choice symbol\n * Next locate the first visible choice value\n * Return NULL if none was found\n */\nstruct symbol *sym_choice_default(struct symbol *sym)\n{\n\tstruct symbol *def_sym;\n\tstruct property *prop;\n\tstruct expr *e;\n\n\t/* any of the defaults visible? */\n\tfor_all_defaults(sym, prop) {\n\t\tprop->visible.tri = expr_calc_value(prop->visible.expr);\n\t\tif (prop->visible.tri == no)\n\t\t\tcontinue;\n\t\tdef_sym = prop_get_symbol(prop);\n\t\tif (def_sym->visible != no)\n\t\t\treturn def_sym;\n\t}\n\n\t/* just get the first visible value */\n\tprop = sym_get_choice_prop(sym);\n\texpr_list_for_each_sym(prop->expr, e, def_sym)\n\t\tif (def_sym->visible != no)\n\t\t\treturn def_sym;\n\n\t/* failed to locate any defaults */\n\treturn NULL;\n}\n\nstatic struct symbol *sym_calc_choice(struct symbol *sym)\n{\n\tstruct symbol *def_sym;\n\tstruct property *prop;\n\tstruct expr *e;\n\tint flags;\n\n\t/* first calculate all choice values' visibilities */\n\tflags = sym->flags;\n\tprop = sym_get_choice_prop(sym);\n\texpr_list_for_each_sym(prop->expr, e, def_sym) {\n\t\tsym_calc_visibility(def_sym);\n\t\tif (def_sym->visible != no)\n\t\t\tflags &= def_sym->flags;\n\t}\n\n\tsym->flags &= flags | ~SYMBOL_DEF_USER;\n\n\t/* is the user choice visible? */\n\tdef_sym = sym->def[S_DEF_USER].val;\n\tif (def_sym && def_sym->visible != no)\n\t\treturn def_sym;\n\n\tdef_sym = sym_choice_default(sym);\n\n\tif (def_sym == NULL)\n\t\t/* no choice? reset tristate value */\n\t\tsym->curr.tri = no;\n\n\treturn def_sym;\n}\n\nstatic void sym_warn_unmet_dep(struct symbol *sym)\n{\n\tstruct gstr gs = str_new();\n\n\tstr_printf(&gs,\n\t\t   \"\\nWARNING: unmet direct dependencies detected for %s\\n\",\n\t\t   sym->name);\n\tstr_printf(&gs,\n\t\t   \"  Depends on [%c]: \",\n\t\t   sym->dir_dep.tri == mod ? 'm' : 'n');\n\texpr_gstr_print(sym->dir_dep.expr, &gs);\n\tstr_printf(&gs, \"\\n\");\n\n\texpr_gstr_print_revdep(sym->rev_dep.expr, &gs, yes,\n\t\t\t       \"  Selected by [y]:\\n\");\n\texpr_gstr_print_revdep(sym->rev_dep.expr, &gs, mod,\n\t\t\t       \"  Selected by [m]:\\n\");\n\n\tfputs(str_get(&gs), stderr);\n}\n\nvoid sym_calc_value(struct symbol *sym)\n{\n\tstruct symbol_value newval, oldval;\n\tstruct property *prop;\n\tstruct expr *e;\n\n\tif (!sym)\n\t\treturn;\n\n\tif (sym->flags & SYMBOL_VALID)\n\t\treturn;\n\n\tif (sym_is_choice_value(sym) &&\n\t    sym->flags & SYMBOL_NEED_SET_CHOICE_VALUES) {\n\t\tsym->flags &= ~SYMBOL_NEED_SET_CHOICE_VALUES;\n\t\tprop = sym_get_choice_prop(sym);\n\t\tsym_calc_value(prop_get_symbol(prop));\n\t}\n\n\tsym->flags |= SYMBOL_VALID;\n\n\toldval = sym->curr;\n\n\tswitch (sym->type) {\n\tcase S_INT:\n\tcase S_HEX:\n\tcase S_STRING:\n\t\tnewval = symbol_empty.curr;\n\t\tbreak;\n\tcase S_BOOLEAN:\n\tcase S_TRISTATE:\n\t\tnewval = symbol_no.curr;\n\t\tbreak;\n\tdefault:\n\t\tsym->curr.val = sym->name;\n\t\tsym->curr.tri = no;\n\t\treturn;\n\t}\n\tsym->flags &= ~SYMBOL_WRITE;\n\n\tsym_calc_visibility(sym);\n\n\tif (sym->visible != no)\n\t\tsym->flags |= SYMBOL_WRITE;\n\n\t/* set default if recursively called */\n\tsym->curr = newval;\n\n\tswitch (sym_get_type(sym)) {\n\tcase S_BOOLEAN:\n\tcase S_TRISTATE:\n\t\tif (sym_is_choice_value(sym) && sym->visible == yes) {\n\t\t\tprop = sym_get_choice_prop(sym);\n\t\t\tnewval.tri = (prop_get_symbol(prop)->curr.val == sym) ? yes : no;\n\t\t} else {\n\t\t\tif (sym->visible != no) {\n\t\t\t\t/* if the symbol is visible use the user value\n\t\t\t\t * if available, otherwise try the default value\n\t\t\t\t */\n\t\t\t\tif (sym_has_value(sym)) {\n\t\t\t\t\tnewval.tri = EXPR_AND(sym->def[S_DEF_USER].tri,\n\t\t\t\t\t\t\t      sym->visible);\n\t\t\t\t\tgoto calc_newval;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (sym->rev_dep.tri != no)\n\t\t\t\tsym->flags |= SYMBOL_WRITE;\n\t\t\tif (!sym_is_choice(sym)) {\n\t\t\t\tprop = sym_get_default_prop(sym);\n\t\t\t\tif (prop) {\n\t\t\t\t\tnewval.tri = EXPR_AND(expr_calc_value(prop->expr),\n\t\t\t\t\t\t\t      prop->visible.tri);\n\t\t\t\t\tif (newval.tri != no)\n\t\t\t\t\t\tsym->flags |= SYMBOL_WRITE;\n\t\t\t\t}\n\t\t\t\tif (sym->implied.tri != no) {\n\t\t\t\t\tsym->flags |= SYMBOL_WRITE;\n\t\t\t\t\tnewval.tri = EXPR_OR(newval.tri, sym->implied.tri);\n\t\t\t\t\tnewval.tri = EXPR_AND(newval.tri,\n\t\t\t\t\t\t\t      sym->dir_dep.tri);\n\t\t\t\t}\n\t\t\t}\n\t\tcalc_newval:\n\t\t\tif (sym->dir_dep.tri < sym->rev_dep.tri)\n\t\t\t\tsym_warn_unmet_dep(sym);\n\t\t\tnewval.tri = EXPR_OR(newval.tri, sym->rev_dep.tri);\n\t\t}\n\t\tif (newval.tri == mod && sym_get_type(sym) == S_BOOLEAN)\n\t\t\tnewval.tri = yes;\n\t\tbreak;\n\tcase S_STRING:\n\tcase S_HEX:\n\tcase S_INT:\n\t\tif (sym->visible != no && sym_has_value(sym)) {\n\t\t\tnewval.val = sym->def[S_DEF_USER].val;\n\t\t\tbreak;\n\t\t}\n\t\tprop = sym_get_default_prop(sym);\n\t\tif (prop) {\n\t\t\tstruct symbol *ds = prop_get_symbol(prop);\n\t\t\tif (ds) {\n\t\t\t\tsym->flags |= SYMBOL_WRITE;\n\t\t\t\tsym_calc_value(ds);\n\t\t\t\tnewval.val = ds->curr.val;\n\t\t\t}\n\t\t}\n\t\tbreak;\n\tdefault:\n\t\t;\n\t}\n\n\tsym->curr = newval;\n\tif (sym_is_choice(sym) && newval.tri == yes)\n\t\tsym->curr.val = sym_calc_choice(sym);\n\tsym_validate_range(sym);\n\n\tif (memcmp(&oldval, &sym->curr, sizeof(oldval))) {\n\t\tsym_set_changed(sym);\n\t\tif (modules_sym == sym) {\n\t\t\tsym_set_all_changed();\n\t\t\tmodules_val = modules_sym->curr.tri;\n\t\t}\n\t}\n\n\tif (sym_is_choice(sym)) {\n\t\tstruct symbol *choice_sym;\n\n\t\tprop = sym_get_choice_prop(sym);\n\t\texpr_list_for_each_sym(prop->expr, e, choice_sym) {\n\t\t\tif ((sym->flags & SYMBOL_WRITE) &&\n\t\t\t    choice_sym->visible != no)\n\t\t\t\tchoice_sym->flags |= SYMBOL_WRITE;\n\t\t\tif (sym->flags & SYMBOL_CHANGED)\n\t\t\t\tsym_set_changed(choice_sym);\n\t\t}\n\t}\n\n\tif (sym->flags & SYMBOL_NO_WRITE)\n\t\tsym->flags &= ~SYMBOL_WRITE;\n\n\tif (sym->flags & SYMBOL_NEED_SET_CHOICE_VALUES)\n\t\tset_all_choice_values(sym);\n}\n\nvoid sym_clear_all_valid(void)\n{\n\tstruct symbol *sym;\n\tint i;\n\n\tfor_all_symbols(i, sym)\n\t\tsym->flags &= ~SYMBOL_VALID;\n\tsym_add_change_count(1);\n\tsym_calc_value(modules_sym);\n}\n\nbool sym_tristate_within_range(struct symbol *sym, tristate val)\n{\n\tint type = sym_get_type(sym);\n\n\tif (sym->visible == no)\n\t\treturn false;\n\n\tif (type != S_BOOLEAN && type != S_TRISTATE)\n\t\treturn false;\n\n\tif (type == S_BOOLEAN && val == mod)\n\t\treturn false;\n\tif (sym->visible <= sym->rev_dep.tri)\n\t\treturn false;\n\tif (sym_is_choice_value(sym) && sym->visible == yes)\n\t\treturn val == yes;\n\treturn val >= sym->rev_dep.tri && val <= sym->visible;\n}\n\nbool sym_set_tristate_value(struct symbol *sym, tristate val)\n{\n\ttristate oldval = sym_get_tristate_value(sym);\n\n\tif (oldval != val && !sym_tristate_within_range(sym, val))\n\t\treturn false;\n\n\tif (!(sym->flags & SYMBOL_DEF_USER)) {\n\t\tsym->flags |= SYMBOL_DEF_USER;\n\t\tsym_set_changed(sym);\n\t}\n\t/*\n\t * setting a choice value also resets the new flag of the choice\n\t * symbol and all other choice values.\n\t */\n\tif (sym_is_choice_value(sym) && val == yes) {\n\t\tstruct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));\n\t\tstruct property *prop;\n\t\tstruct expr *e;\n\n\t\tcs->def[S_DEF_USER].val = sym;\n\t\tcs->flags |= SYMBOL_DEF_USER;\n\t\tprop = sym_get_choice_prop(cs);\n\t\tfor (e = prop->expr; e; e = e->left.expr) {\n\t\t\tif (e->right.sym->visible != no)\n\t\t\t\te->right.sym->flags |= SYMBOL_DEF_USER;\n\t\t}\n\t}\n\n\tsym->def[S_DEF_USER].tri = val;\n\tif (oldval != val)\n\t\tsym_clear_all_valid();\n\n\treturn true;\n}\n\ntristate sym_toggle_tristate_value(struct symbol *sym)\n{\n\ttristate oldval, newval;\n\n\toldval = newval = sym_get_tristate_value(sym);\n\tdo {\n\t\tswitch (newval) {\n\t\tcase no:\n\t\t\tnewval = mod;\n\t\t\tbreak;\n\t\tcase mod:\n\t\t\tnewval = yes;\n\t\t\tbreak;\n\t\tcase yes:\n\t\t\tnewval = no;\n\t\t\tbreak;\n\t\t}\n\t\tif (sym_set_tristate_value(sym, newval))\n\t\t\tbreak;\n\t} while (oldval != newval);\n\treturn newval;\n}\n\nbool sym_string_valid(struct symbol *sym, const char *str)\n{\n\tsigned char ch;\n\n\tswitch (sym->type) {\n\tcase S_STRING:\n\t\treturn true;\n\tcase S_INT:\n\t\tch = *str++;\n\t\tif (ch == '-')\n\t\t\tch = *str++;\n\t\tif (!isdigit(ch))\n\t\t\treturn false;\n\t\tif (ch == '0' && *str != 0)\n\t\t\treturn false;\n\t\twhile ((ch = *str++)) {\n\t\t\tif (!isdigit(ch))\n\t\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\tcase S_HEX:\n\t\tif (str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))\n\t\t\tstr += 2;\n\t\tch = *str++;\n\t\tdo {\n\t\t\tif (!isxdigit(ch))\n\t\t\t\treturn false;\n\t\t} while ((ch = *str++));\n\t\treturn true;\n\tcase S_BOOLEAN:\n\tcase S_TRISTATE:\n\t\tswitch (str[0]) {\n\t\tcase 'y': case 'Y':\n\t\tcase 'm': case 'M':\n\t\tcase 'n': case 'N':\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\tdefault:\n\t\treturn false;\n\t}\n}\n\nbool sym_string_within_range(struct symbol *sym, const char *str)\n{\n\tstruct property *prop;\n\tlong long val;\n\n\tswitch (sym->type) {\n\tcase S_STRING:\n\t\treturn sym_string_valid(sym, str);\n\tcase S_INT:\n\t\tif (!sym_string_valid(sym, str))\n\t\t\treturn false;\n\t\tprop = sym_get_range_prop(sym);\n\t\tif (!prop)\n\t\t\treturn true;\n\t\tval = strtoll(str, NULL, 10);\n\t\treturn val >= sym_get_range_val(prop->expr->left.sym, 10) &&\n\t\t       val <= sym_get_range_val(prop->expr->right.sym, 10);\n\tcase S_HEX:\n\t\tif (!sym_string_valid(sym, str))\n\t\t\treturn false;\n\t\tprop = sym_get_range_prop(sym);\n\t\tif (!prop)\n\t\t\treturn true;\n\t\tval = strtoll(str, NULL, 16);\n\t\treturn val >= sym_get_range_val(prop->expr->left.sym, 16) &&\n\t\t       val <= sym_get_range_val(prop->expr->right.sym, 16);\n\tcase S_BOOLEAN:\n\tcase S_TRISTATE:\n\t\tswitch (str[0]) {\n\t\tcase 'y': case 'Y':\n\t\t\treturn sym_tristate_within_range(sym, yes);\n\t\tcase 'm': case 'M':\n\t\t\treturn sym_tristate_within_range(sym, mod);\n\t\tcase 'n': case 'N':\n\t\t\treturn sym_tristate_within_range(sym, no);\n\t\t}\n\t\treturn false;\n\tdefault:\n\t\treturn false;\n\t}\n}\n\nbool sym_set_string_value(struct symbol *sym, const char *newval)\n{\n\tconst char *oldval;\n\tchar *val;\n\tint size;\n\n\tswitch (sym->type) {\n\tcase S_BOOLEAN:\n\tcase S_TRISTATE:\n\t\tswitch (newval[0]) {\n\t\tcase 'y': case 'Y':\n\t\t\treturn sym_set_tristate_value(sym, yes);\n\t\tcase 'm': case 'M':\n\t\t\treturn sym_set_tristate_value(sym, mod);\n\t\tcase 'n': case 'N':\n\t\t\treturn sym_set_tristate_value(sym, no);\n\t\t}\n\t\treturn false;\n\tdefault:\n\t\t;\n\t}\n\n\tif (!sym_string_within_range(sym, newval))\n\t\treturn false;\n\n\tif (!(sym->flags & SYMBOL_DEF_USER)) {\n\t\tsym->flags |= SYMBOL_DEF_USER;\n\t\tsym_set_changed(sym);\n\t}\n\n\toldval = sym->def[S_DEF_USER].val;\n\tsize = strlen(newval) + 1;\n\tif (sym->type == S_HEX && (newval[0] != '0' || (newval[1] != 'x' && newval[1] != 'X'))) {\n\t\tsize += 2;\n\t\tsym->def[S_DEF_USER].val = val = xmalloc(size);\n\t\t*val++ = '0';\n\t\t*val++ = 'x';\n\t} else if (!oldval || strcmp(oldval, newval))\n\t\tsym->def[S_DEF_USER].val = val = xmalloc(size);\n\telse\n\t\treturn true;\n\n\tstrcpy(val, newval);\n\tfree((void *)oldval);\n\tsym_clear_all_valid();\n\n\treturn true;\n}\n\n/*\n * Find the default value associated to a symbol.\n * For tristate symbol handle the modules=n case\n * in which case \"m\" becomes \"y\".\n * If the symbol does not have any default then fallback\n * to the fixed default values.\n */\nconst char *sym_get_string_default(struct symbol *sym)\n{\n\tstruct property *prop;\n\tstruct symbol *ds;\n\tconst char *str;\n\ttristate val;\n\n\tsym_calc_visibility(sym);\n\tsym_calc_value(modules_sym);\n\tval = symbol_no.curr.tri;\n\tstr = symbol_empty.curr.val;\n\n\t/* If symbol has a default value look it up */\n\tprop = sym_get_default_prop(sym);\n\tif (prop != NULL) {\n\t\tswitch (sym->type) {\n\t\tcase S_BOOLEAN:\n\t\tcase S_TRISTATE:\n\t\t\t/* The visibility may limit the value from yes => mod */\n\t\t\tval = EXPR_AND(expr_calc_value(prop->expr), prop->visible.tri);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\t/*\n\t\t\t * The following fails to handle the situation\n\t\t\t * where a default value is further limited by\n\t\t\t * the valid range.\n\t\t\t */\n\t\t\tds = prop_get_symbol(prop);\n\t\t\tif (ds != NULL) {\n\t\t\t\tsym_calc_value(ds);\n\t\t\t\tstr = (const char *)ds->curr.val;\n\t\t\t}\n\t\t}\n\t}\n\n\t/* Handle select statements */\n\tval = EXPR_OR(val, sym->rev_dep.tri);\n\n\t/* transpose mod to yes if modules are not enabled */\n\tif (val == mod)\n\t\tif (!sym_is_choice_value(sym) && modules_sym->curr.tri == no)\n\t\t\tval = yes;\n\n\t/* transpose mod to yes if type is bool */\n\tif (sym->type == S_BOOLEAN && val == mod)\n\t\tval = yes;\n\n\t/* adjust the default value if this symbol is implied by another */\n\tif (val < sym->implied.tri)\n\t\tval = sym->implied.tri;\n\n\tswitch (sym->type) {\n\tcase S_BOOLEAN:\n\tcase S_TRISTATE:\n\t\tswitch (val) {\n\t\tcase no: return \"n\";\n\t\tcase mod: return \"m\";\n\t\tcase yes: return \"y\";\n\t\t}\n\tcase S_INT:\n\tcase S_HEX:\n\t\treturn str;\n\tcase S_STRING:\n\t\treturn str;\n\tcase S_UNKNOWN:\n\t\tbreak;\n\t}\n\treturn \"\";\n}\n\nconst char *sym_get_string_value(struct symbol *sym)\n{\n\ttristate val;\n\n\tswitch (sym->type) {\n\tcase S_BOOLEAN:\n\tcase S_TRISTATE:\n\t\tval = sym_get_tristate_value(sym);\n\t\tswitch (val) {\n\t\tcase no:\n\t\t\treturn \"n\";\n\t\tcase mod:\n\t\t\tsym_calc_value(modules_sym);\n\t\t\treturn (modules_sym->curr.tri == no) ? \"n\" : \"m\";\n\t\tcase yes:\n\t\t\treturn \"y\";\n\t\t}\n\t\tbreak;\n\tdefault:\n\t\t;\n\t}\n\treturn (const char *)sym->curr.val;\n}\n\nbool sym_is_changeable(struct symbol *sym)\n{\n\treturn sym->visible > sym->rev_dep.tri;\n}\n\nstatic unsigned strhash(const char *s)\n{\n\t/* fnv32 hash */\n\tunsigned hash = 2166136261U;\n\tfor (; *s; s++)\n\t\thash = (hash ^ *s) * 0x01000193;\n\treturn hash;\n}\n\nstruct symbol *sym_lookup(const char *name, int flags)\n{\n\tstruct symbol *symbol;\n\tchar *new_name;\n\tint hash;\n\n\tif (name) {\n\t\tif (name[0] && !name[1]) {\n\t\t\tswitch (name[0]) {\n\t\t\tcase 'y': return &symbol_yes;\n\t\t\tcase 'm': return &symbol_mod;\n\t\t\tcase 'n': return &symbol_no;\n\t\t\t}\n\t\t}\n\t\thash = strhash(name) % SYMBOL_HASHSIZE;\n\n\t\tfor (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {\n\t\t\tif (symbol->name &&\n\t\t\t    !strcmp(symbol->name, name) &&\n\t\t\t    (flags ? symbol->flags & flags\n\t\t\t\t   : !(symbol->flags & (SYMBOL_CONST|SYMBOL_CHOICE))))\n\t\t\t\treturn symbol;\n\t\t}\n\t\tnew_name = xstrdup(name);\n\t} else {\n\t\tnew_name = NULL;\n\t\thash = 0;\n\t}\n\n\tsymbol = xmalloc(sizeof(*symbol));\n\tmemset(symbol, 0, sizeof(*symbol));\n\tsymbol->name = new_name;\n\tsymbol->type = S_UNKNOWN;\n\tsymbol->flags = flags;\n\n\tsymbol->next = symbol_hash[hash];\n\tsymbol_hash[hash] = symbol;\n\n\treturn symbol;\n}\n\nstruct symbol *sym_find(const char *name)\n{\n\tstruct symbol *symbol = NULL;\n\tint hash = 0;\n\n\tif (!name)\n\t\treturn NULL;\n\n\tif (name[0] && !name[1]) {\n\t\tswitch (name[0]) {\n\t\tcase 'y': return &symbol_yes;\n\t\tcase 'm': return &symbol_mod;\n\t\tcase 'n': return &symbol_no;\n\t\t}\n\t}\n\thash = strhash(name) % SYMBOL_HASHSIZE;\n\n\tfor (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {\n\t\tif (symbol->name &&\n\t\t    !strcmp(symbol->name, name) &&\n\t\t    !(symbol->flags & SYMBOL_CONST))\n\t\t\t\tbreak;\n\t}\n\n\treturn symbol;\n}\n\nconst char *sym_escape_string_value(const char *in)\n{\n\tconst char *p;\n\tsize_t reslen;\n\tchar *res;\n\tsize_t l;\n\n\treslen = strlen(in) + strlen(\"\\\"\\\"\") + 1;\n\n\tp = in;\n\tfor (;;) {\n\t\tl = strcspn(p, \"\\\"\\\\\");\n\t\tp += l;\n\n\t\tif (p[0] == '\\0')\n\t\t\tbreak;\n\n\t\treslen++;\n\t\tp++;\n\t}\n\n\tres = xmalloc(reslen);\n\tres[0] = '\\0';\n\n\tstrcat(res, \"\\\"\");\n\n\tp = in;\n\tfor (;;) {\n\t\tl = strcspn(p, \"\\\"\\\\\");\n\t\tstrncat(res, p, l);\n\t\tp += l;\n\n\t\tif (p[0] == '\\0')\n\t\t\tbreak;\n\n\t\tstrcat(res, \"\\\\\");\n\t\tstrncat(res, p++, 1);\n\t}\n\n\tstrcat(res, \"\\\"\");\n\treturn res;\n}\n\nstruct sym_match {\n\tstruct symbol\t*sym;\n\toff_t\t\tso, eo;\n};\n\n/* Compare matched symbols as thus:\n * - first, symbols that match exactly\n * - then, alphabetical sort\n */\nstatic int sym_rel_comp(const void *sym1, const void *sym2)\n{\n\tconst struct sym_match *s1 = sym1;\n\tconst struct sym_match *s2 = sym2;\n\tint exact1, exact2;\n\n\t/* Exact match:\n\t * - if matched length on symbol s1 is the length of that symbol,\n\t *   then this symbol should come first;\n\t * - if matched length on symbol s2 is the length of that symbol,\n\t *   then this symbol should come first.\n\t * Note: since the search can be a regexp, both symbols may match\n\t * exactly; if this is the case, we can't decide which comes first,\n\t * and we fallback to sorting alphabetically.\n\t */\n\texact1 = (s1->eo - s1->so) == strlen(s1->sym->name);\n\texact2 = (s2->eo - s2->so) == strlen(s2->sym->name);\n\tif (exact1 && !exact2)\n\t\treturn -1;\n\tif (!exact1 && exact2)\n\t\treturn 1;\n\n\t/* As a fallback, sort symbols alphabetically */\n\treturn strcmp(s1->sym->name, s2->sym->name);\n}\n\nstruct symbol **sym_re_search(const char *pattern)\n{\n\tstruct symbol *sym, **sym_arr = NULL;\n\tstruct sym_match *sym_match_arr = NULL;\n\tint i, cnt, size;\n\tregex_t re;\n\tregmatch_t match[1];\n\n\tcnt = size = 0;\n\t/* Skip if empty */\n\tif (strlen(pattern) == 0)\n\t\treturn NULL;\n\tif (regcomp(&re, pattern, REG_EXTENDED|REG_ICASE))\n\t\treturn NULL;\n\n\tfor_all_symbols(i, sym) {\n\t\tif (sym->flags & SYMBOL_CONST || !sym->name)\n\t\t\tcontinue;\n\t\tif (regexec(&re, sym->name, 1, match, 0))\n\t\t\tcontinue;\n\t\tif (cnt >= size) {\n\t\t\tvoid *tmp;\n\t\t\tsize += 16;\n\t\t\ttmp = realloc(sym_match_arr, size * sizeof(struct sym_match));\n\t\t\tif (!tmp)\n\t\t\t\tgoto sym_re_search_free;\n\t\t\tsym_match_arr = tmp;\n\t\t}\n\t\tsym_calc_value(sym);\n\t\t/* As regexec returned 0, we know we have a match, so\n\t\t * we can use match[0].rm_[se]o without further checks\n\t\t */\n\t\tsym_match_arr[cnt].so = match[0].rm_so;\n\t\tsym_match_arr[cnt].eo = match[0].rm_eo;\n\t\tsym_match_arr[cnt++].sym = sym;\n\t}\n\tif (sym_match_arr) {\n\t\tqsort(sym_match_arr, cnt, sizeof(struct sym_match), sym_rel_comp);\n\t\tsym_arr = malloc((cnt+1) * sizeof(struct symbol *));\n\t\tif (!sym_arr)\n\t\t\tgoto sym_re_search_free;\n\t\tfor (i = 0; i < cnt; i++)\n\t\t\tsym_arr[i] = sym_match_arr[i].sym;\n\t\tsym_arr[cnt] = NULL;\n\t}\nsym_re_search_free:\n\t/* sym_match_arr can be NULL if no match, but free(NULL) is OK */\n\tfree(sym_match_arr);\n\tregfree(&re);\n\n\treturn sym_arr;\n}\n\n/*\n * When we check for recursive dependencies we use a stack to save\n * current state so we can print out relevant info to user.\n * The entries are located on the call stack so no need to free memory.\n * Note insert() remove() must always match to properly clear the stack.\n */\nstatic struct dep_stack {\n\tstruct dep_stack *prev, *next;\n\tstruct symbol *sym;\n\tstruct property *prop;\n\tstruct expr **expr;\n} *check_top;\n\nstatic void dep_stack_insert(struct dep_stack *stack, struct symbol *sym)\n{\n\tmemset(stack, 0, sizeof(*stack));\n\tif (check_top)\n\t\tcheck_top->next = stack;\n\tstack->prev = check_top;\n\tstack->sym = sym;\n\tcheck_top = stack;\n}\n\nstatic void dep_stack_remove(void)\n{\n\tcheck_top = check_top->prev;\n\tif (check_top)\n\t\tcheck_top->next = NULL;\n}\n\n/*\n * Called when we have detected a recursive dependency.\n * check_top point to the top of the stact so we use\n * the ->prev pointer to locate the bottom of the stack.\n */\nstatic void sym_check_print_recursive(struct symbol *last_sym)\n{\n\tstruct dep_stack *stack;\n\tstruct symbol *sym, *next_sym;\n\tstruct menu *menu = NULL;\n\tstruct property *prop;\n\tstruct dep_stack cv_stack;\n\n\tif (sym_is_choice_value(last_sym)) {\n\t\tdep_stack_insert(&cv_stack, last_sym);\n\t\tlast_sym = prop_get_symbol(sym_get_choice_prop(last_sym));\n\t}\n\n\tfor (stack = check_top; stack != NULL; stack = stack->prev)\n\t\tif (stack->sym == last_sym)\n\t\t\tbreak;\n\tif (!stack) {\n\t\tfprintf(stderr, \"unexpected recursive dependency error\\n\");\n\t\treturn;\n\t}\n\n\tfor (; stack; stack = stack->next) {\n\t\tsym = stack->sym;\n\t\tnext_sym = stack->next ? stack->next->sym : last_sym;\n\t\tprop = stack->prop;\n\t\tif (prop == NULL)\n\t\t\tprop = stack->sym->prop;\n\n\t\t/* for choice values find the menu entry (used below) */\n\t\tif (sym_is_choice(sym) || sym_is_choice_value(sym)) {\n\t\t\tfor (prop = sym->prop; prop; prop = prop->next) {\n\t\t\t\tmenu = prop->menu;\n\t\t\t\tif (prop->menu)\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (stack->sym == last_sym)\n\t\t\tfprintf(stderr, \"%s:%d:error: recursive dependency detected!\\n\",\n\t\t\t\tprop->file->name, prop->lineno);\n\n\t\tif (sym_is_choice(sym)) {\n\t\t\tfprintf(stderr, \"%s:%d:\\tchoice %s contains symbol %s\\n\",\n\t\t\t\tmenu->file->name, menu->lineno,\n\t\t\t\tsym->name ? sym->name : \"<choice>\",\n\t\t\t\tnext_sym->name ? next_sym->name : \"<choice>\");\n\t\t} else if (sym_is_choice_value(sym)) {\n\t\t\tfprintf(stderr, \"%s:%d:\\tsymbol %s is part of choice %s\\n\",\n\t\t\t\tmenu->file->name, menu->lineno,\n\t\t\t\tsym->name ? sym->name : \"<choice>\",\n\t\t\t\tnext_sym->name ? next_sym->name : \"<choice>\");\n\t\t} else if (stack->expr == &sym->dir_dep.expr) {\n\t\t\tfprintf(stderr, \"%s:%d:\\tsymbol %s depends on %s\\n\",\n\t\t\t\tprop->file->name, prop->lineno,\n\t\t\t\tsym->name ? sym->name : \"<choice>\",\n\t\t\t\tnext_sym->name ? next_sym->name : \"<choice>\");\n\t\t} else if (stack->expr == &sym->rev_dep.expr) {\n\t\t\tfprintf(stderr, \"%s:%d:\\tsymbol %s is selected by %s\\n\",\n\t\t\t\tprop->file->name, prop->lineno,\n\t\t\t\tsym->name ? sym->name : \"<choice>\",\n\t\t\t\tnext_sym->name ? next_sym->name : \"<choice>\");\n\t\t} else if (stack->expr == &sym->implied.expr) {\n\t\t\tfprintf(stderr, \"%s:%d:\\tsymbol %s is implied by %s\\n\",\n\t\t\t\tprop->file->name, prop->lineno,\n\t\t\t\tsym->name ? sym->name : \"<choice>\",\n\t\t\t\tnext_sym->name ? next_sym->name : \"<choice>\");\n\t\t} else if (stack->expr) {\n\t\t\tfprintf(stderr, \"%s:%d:\\tsymbol %s %s value contains %s\\n\",\n\t\t\t\tprop->file->name, prop->lineno,\n\t\t\t\tsym->name ? sym->name : \"<choice>\",\n\t\t\t\tprop_get_type_name(prop->type),\n\t\t\t\tnext_sym->name ? next_sym->name : \"<choice>\");\n\t\t} else {\n\t\t\tfprintf(stderr, \"%s:%d:\\tsymbol %s %s is visible depending on %s\\n\",\n\t\t\t\tprop->file->name, prop->lineno,\n\t\t\t\tsym->name ? sym->name : \"<choice>\",\n\t\t\t\tprop_get_type_name(prop->type),\n\t\t\t\tnext_sym->name ? next_sym->name : \"<choice>\");\n\t\t}\n\t}\n\n\tfprintf(stderr,\n\t\t\"For a resolution refer to Documentation/kbuild/kconfig-language.rst\\n\"\n\t\t\"subsection \\\"Kconfig recursive dependency limitations\\\"\\n\"\n\t\t\"\\n\");\n\n\tif (check_top == &cv_stack)\n\t\tdep_stack_remove();\n}\n\nstatic struct symbol *sym_check_expr_deps(struct expr *e)\n{\n\tstruct symbol *sym;\n\n\tif (!e)\n\t\treturn NULL;\n\tswitch (e->type) {\n\tcase E_OR:\n\tcase E_AND:\n\t\tsym = sym_check_expr_deps(e->left.expr);\n\t\tif (sym)\n\t\t\treturn sym;\n\t\treturn sym_check_expr_deps(e->right.expr);\n\tcase E_NOT:\n\t\treturn sym_check_expr_deps(e->left.expr);\n\tcase E_EQUAL:\n\tcase E_GEQ:\n\tcase E_GTH:\n\tcase E_LEQ:\n\tcase E_LTH:\n\tcase E_UNEQUAL:\n\t\tsym = sym_check_deps(e->left.sym);\n\t\tif (sym)\n\t\t\treturn sym;\n\t\treturn sym_check_deps(e->right.sym);\n\tcase E_SYMBOL:\n\t\treturn sym_check_deps(e->left.sym);\n\tdefault:\n\t\tbreak;\n\t}\n\tfprintf(stderr, \"Oops! How to check %d?\\n\", e->type);\n\treturn NULL;\n}\n\n/* return NULL when dependencies are OK */\nstatic struct symbol *sym_check_sym_deps(struct symbol *sym)\n{\n\tstruct symbol *sym2;\n\tstruct property *prop;\n\tstruct dep_stack stack;\n\n\tdep_stack_insert(&stack, sym);\n\n\tstack.expr = &sym->dir_dep.expr;\n\tsym2 = sym_check_expr_deps(sym->dir_dep.expr);\n\tif (sym2)\n\t\tgoto out;\n\n\tstack.expr = &sym->rev_dep.expr;\n\tsym2 = sym_check_expr_deps(sym->rev_dep.expr);\n\tif (sym2)\n\t\tgoto out;\n\n\tstack.expr = &sym->implied.expr;\n\tsym2 = sym_check_expr_deps(sym->implied.expr);\n\tif (sym2)\n\t\tgoto out;\n\n\tstack.expr = NULL;\n\n\tfor (prop = sym->prop; prop; prop = prop->next) {\n\t\tif (prop->type == P_CHOICE || prop->type == P_SELECT ||\n\t\t    prop->type == P_IMPLY)\n\t\t\tcontinue;\n\t\tstack.prop = prop;\n\t\tsym2 = sym_check_expr_deps(prop->visible.expr);\n\t\tif (sym2)\n\t\t\tbreak;\n\t\tif (prop->type != P_DEFAULT || sym_is_choice(sym))\n\t\t\tcontinue;\n\t\tstack.expr = &prop->expr;\n\t\tsym2 = sym_check_expr_deps(prop->expr);\n\t\tif (sym2)\n\t\t\tbreak;\n\t\tstack.expr = NULL;\n\t}\n\nout:\n\tdep_stack_remove();\n\n\treturn sym2;\n}\n\nstatic struct symbol *sym_check_choice_deps(struct symbol *choice)\n{\n\tstruct symbol *sym, *sym2;\n\tstruct property *prop;\n\tstruct expr *e;\n\tstruct dep_stack stack;\n\n\tdep_stack_insert(&stack, choice);\n\n\tprop = sym_get_choice_prop(choice);\n\texpr_list_for_each_sym(prop->expr, e, sym)\n\t\tsym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);\n\n\tchoice->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);\n\tsym2 = sym_check_sym_deps(choice);\n\tchoice->flags &= ~SYMBOL_CHECK;\n\tif (sym2)\n\t\tgoto out;\n\n\texpr_list_for_each_sym(prop->expr, e, sym) {\n\t\tsym2 = sym_check_sym_deps(sym);\n\t\tif (sym2)\n\t\t\tbreak;\n\t}\nout:\n\texpr_list_for_each_sym(prop->expr, e, sym)\n\t\tsym->flags &= ~SYMBOL_CHECK;\n\n\tif (sym2 && sym_is_choice_value(sym2) &&\n\t    prop_get_symbol(sym_get_choice_prop(sym2)) == choice)\n\t\tsym2 = choice;\n\n\tdep_stack_remove();\n\n\treturn sym2;\n}\n\nstruct symbol *sym_check_deps(struct symbol *sym)\n{\n\tstruct symbol *sym2;\n\tstruct property *prop;\n\n\tif (sym->flags & SYMBOL_CHECK) {\n\t\tsym_check_print_recursive(sym);\n\t\treturn sym;\n\t}\n\tif (sym->flags & SYMBOL_CHECKED)\n\t\treturn NULL;\n\n\tif (sym_is_choice_value(sym)) {\n\t\tstruct dep_stack stack;\n\n\t\t/* for choice groups start the check with main choice symbol */\n\t\tdep_stack_insert(&stack, sym);\n\t\tprop = sym_get_choice_prop(sym);\n\t\tsym2 = sym_check_deps(prop_get_symbol(prop));\n\t\tdep_stack_remove();\n\t} else if (sym_is_choice(sym)) {\n\t\tsym2 = sym_check_choice_deps(sym);\n\t} else {\n\t\tsym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);\n\t\tsym2 = sym_check_sym_deps(sym);\n\t\tsym->flags &= ~SYMBOL_CHECK;\n\t}\n\n\treturn sym2;\n}\n\nstruct symbol *prop_get_symbol(struct property *prop)\n{\n\tif (prop->expr && (prop->expr->type == E_SYMBOL ||\n\t\t\t   prop->expr->type == E_LIST))\n\t\treturn prop->expr->left.sym;\n\treturn NULL;\n}\n\nconst char *prop_get_type_name(enum prop_type type)\n{\n\tswitch (type) {\n\tcase P_PROMPT:\n\t\treturn \"prompt\";\n\tcase P_COMMENT:\n\t\treturn \"comment\";\n\tcase P_MENU:\n\t\treturn \"menu\";\n\tcase P_DEFAULT:\n\t\treturn \"default\";\n\tcase P_CHOICE:\n\t\treturn \"choice\";\n\tcase P_SELECT:\n\t\treturn \"select\";\n\tcase P_IMPLY:\n\t\treturn \"imply\";\n\tcase P_RANGE:\n\t\treturn \"range\";\n\tcase P_SYMBOL:\n\t\treturn \"symbol\";\n\tcase P_UNKNOWN:\n\t\tbreak;\n\t}\n\treturn \"unknown\";\n}\n"
  },
  {
    "path": "3rdparty/kconfig/util.c",
    "content": "// SPDX-License-Identifier: GPL-2.0\n/*\n * Copyright (C) 2002-2005 Roman Zippel <zippel@linux-m68k.org>\n * Copyright (C) 2002-2005 Sam Ravnborg <sam@ravnborg.org>\n */\n\n#include <stdarg.h>\n#include <stdlib.h>\n#include <string.h>\n#include \"lkc.h\"\n\n/* file already present in list? If not add it */\nstruct file *file_lookup(const char *name)\n{\n\tstruct file *file;\n\n\tfor (file = file_list; file; file = file->next) {\n\t\tif (!strcmp(name, file->name)) {\n\t\t\treturn file;\n\t\t}\n\t}\n\n\tfile = xmalloc(sizeof(*file));\n\tmemset(file, 0, sizeof(*file));\n\tfile->name = xstrdup(name);\n\tfile->next = file_list;\n\tfile_list = file;\n\treturn file;\n}\n\n/* Allocate initial growable string */\nstruct gstr str_new(void)\n{\n\tstruct gstr gs;\n\tgs.s = xmalloc(sizeof(char) * 64);\n\tgs.len = 64;\n\tgs.max_width = 0;\n\tstrcpy(gs.s, \"\\0\");\n\treturn gs;\n}\n\n/* Free storage for growable string */\nvoid str_free(struct gstr *gs)\n{\n\tif (gs->s)\n\t\tfree(gs->s);\n\tgs->s = NULL;\n\tgs->len = 0;\n}\n\n/* Append to growable string */\nvoid str_append(struct gstr *gs, const char *s)\n{\n\tsize_t l;\n\tif (s) {\n\t\tl = strlen(gs->s) + strlen(s) + 1;\n\t\tif (l > gs->len) {\n\t\t\tgs->s = xrealloc(gs->s, l);\n\t\t\tgs->len = l;\n\t\t}\n\t\tstrcat(gs->s, s);\n\t}\n}\n\n/* Append printf formatted string to growable string */\nvoid str_printf(struct gstr *gs, const char *fmt, ...)\n{\n\tva_list ap;\n\tchar s[10000]; /* big enough... */\n\tva_start(ap, fmt);\n\tvsnprintf(s, sizeof(s), fmt, ap);\n\tstr_append(gs, s);\n\tva_end(ap);\n}\n\n/* Retrieve value of growable string */\nconst char *str_get(struct gstr *gs)\n{\n\treturn gs->s;\n}\n\nvoid *xmalloc(size_t size)\n{\n\tvoid *p = malloc(size);\n\tif (p)\n\t\treturn p;\n\tfprintf(stderr, \"Out of memory.\\n\");\n\texit(1);\n}\n\nvoid *xcalloc(size_t nmemb, size_t size)\n{\n\tvoid *p = calloc(nmemb, size);\n\tif (p)\n\t\treturn p;\n\tfprintf(stderr, \"Out of memory.\\n\");\n\texit(1);\n}\n\nvoid *xrealloc(void *p, size_t size)\n{\n\tp = realloc(p, size);\n\tif (p)\n\t\treturn p;\n\tfprintf(stderr, \"Out of memory.\\n\");\n\texit(1);\n}\n\nchar *xstrdup(const char *s)\n{\n\tchar *p;\n\n\tp = strdup(s);\n\tif (p)\n\t\treturn p;\n\tfprintf(stderr, \"Out of memory.\\n\");\n\texit(1);\n}\n\nchar *xstrndup(const char *s, size_t n)\n{\n\tchar *p;\n\n\tp = strndup(s, n);\n\tif (p)\n\t\treturn p;\n\tfprintf(stderr, \"Out of memory.\\n\");\n\texit(1);\n}\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contribution guidelines\n\nThank you for expressing interest in contributing to the development and/or\nmaintenance of the Crust firmware. This document contains guidelines and\nprocedures for contributing to the project.\n\n## Code of conduct\n\nBy contributing to Crust firmware, you are entering into an agreement to uphold\nthe project's [Code of Conduct][conduct]. Please review that document.\n\n## Issue tracking\n\nBugs and features are tracked through the GitHub [issues page][issues]. When\nfiling issues, please follow the provided issue template.\n\n### Labels\n\nLabels are used to indicate the lifecycle of all Crust firmware issues. Labels\nare prefixed with letters corresponding to the chart below.\n\n| Prefix           | Description\n|------------------|-----------------------------------------------------------\n| Area (A)         | Indicates the area of the project impacted.\n| Difficulty (D)   | Indicates the expected difficulty of an issue.\n| Resolution (R)   | Indicates the resolution of an issue.\n| Status (S)       | Indicates the status of an issue.\n| Type (T)         | Indicates the type of an issue.\n\nAdditionally, the labels \"good first issue\" and \"help wanted\" may be applied to\nan issue or pull request. An issue labeled with \"good first issue\" is an issue\nthat is recommended for new contributors. An issue labeled with \"help wanted\"\nis an issue that project maintainers request community help resolving.\n\n## Submitting a patch\n\nThe Crust firmware project accepts patches through the use of GitHub pull\nrequests. It is recommended that pull requests correspond to an issue on the\nCrust firmware [issues page][issues]. Pull requests submitted _without_ a\ncorresponding issue will require more review to understand the intent behind\nthe code change.\n\n### Commits\n\nAll contributions to this project must be released under the open-source\nlicense used by the project. To help ensure this, all commits you make must be\naccompanied by your real name and a `Signed-off-by` tag asserting authorship\nand permission to contribute, per the [Developer Certificate of Origin][dco].\nThis tag can be added automatically by git using `git commit -s`.\n\nEach change submitted in a pull request that addresses a different scope of the\nproject should be contained within its own commit. For example, a pull request\nadding support for a new hardware component could include the following four\ncommits:\n\n1. The first commit should add the headers and source files for the generic\n   driver class, if one is being added. (e.g. `drivers/<class>/<class>.c` and\n   `include/drivers/<class>.h`).\n2. The second commit should add the driver and its header (e.g.\n   `drivers/<class>/<driver>.c` and `include/drivers/<class>/<driver>.h`).\n3. The third commit may use the device from common code (e.g. in\n   `common/system.c` or `common/scpi_cmds.c`).\n4. The fourth commit would enable the device in Kconfig on the appropriate\n   boards and platforms.\n\nChanges addressing feedback from project maintainers should be squashed into\nexisting commits rather than being included at the end of a pull request as a\nnew commit.\n\n### Continuous integration testing\n\nAll pull requests are built and tested with Travis CI upon submission. To\nensure that your changes will pass the CI build, the following process should\nbe used:\n\n- Verify the source code style by running `make check-format`. (This requires\n  installing [Uncrustify][uncrustify]. See below.)\n- Build the firmware using several `defconfig`s for various platforms.\n\n## Architecture\n\nThis firmware is designed to be flexible yet extremely lightweight. It borrows\nheavily from ideas in both Linux and ATF for its layout and driver model. The\ncode is divided into directories based on major function:\n\n- `configs`: These files contain configuration for each board supported by this\n  firmware. They determine which subdirectory of `platform` is used and which\n  devices are enabled.\n- `common`: Files in this directory contain the main logic of the firmware,\n  which involves power state sequencing and handling SCPI commands.\n- `drivers`: This directory contains a subdirectory for each class of drivers.\n  - `drivers/<class>`: These directories contain all of the drivers of a class,\n    as well as generic dispatch code (in `drivers/<class>/<class>.c`).\n- `include`: This directory contains headers for code in the rest of the\n  firmware, as well as the definitions for a freestanding C implementation.\n- `lib`: This directory contains standalone utility code.\n- `platform`: This directory contains a subdirectory for each supported\n  platform, which refers to a family of SoCs with a similar programming\n  interface.\n  - `platform/<platform>/include`: This directory contains headers with\n    platform-specific macro definitions, such as memory addresses of devices\n    and register layouts that change between platforms.\n- `scripts`: These files are used to assist in building and linking the\n  firmware, but contain no code themselves.\n- `tools`: Each file here is a self-contained program intended to be run on the\n  host machine (in Linux userspace on the ARM cores) to gather information,\n  manipulate hardware, load firmware, or for other reasons.\n\n## Formatting\n\nCrust firmware uses Uncrustify to format all source code files. Running `make\nformat` will format all project files according to a predefined style guide.\n\nThe following are _general_ formatting guidelines:\n- Lines should be no longer than 79 characters plus the trailing newline\n  character.\n- Use tabs for indentation and spaces for alignment for all C source code and\n  header files.\n- Trim all trailing whitespace.\n- Where multiple words must be combined into one, use hyphens in strings,\n  filenames, and documentation; however, use underscores in function, variable\n  names and header guards.\n\n### Writing headers\n\n- Header files act as APIs and are reserved for functions that will be\n  exposed to the rest of the project. Macros, `struct` definitions, and\n  function declarations that are only utilized by a driver or module belong in\n  the corresponding implementation file, rather than the header file.\n- Public macros, function prototypes, and declarations should be documented\n  according to [Doxygen JavaDoc-style comment blocks][doxygen].\n- Functions defined in assembly should also be declared in a header, unless\n  they are not intended to be called directly (e.g. `__udivsi3`).\n- Ideally, the header should be named the same as the driver or source file,\n  except that it should be placed inside the include hierarchy.\n- The header guard should be the same as the path you would need to put in your\n  `#include` directive, but with the following changes:\n  - All letters should be uppercase.\n  - All hyphens, slashes, and periods should be replaced by underscores.\n\n### Assembly\n\nAssembly files are preprocessed, so they should use the file extension `.S`\n(and this is the only extension the build system looks for). They should not\nhave the same path as a C file (excluding the extension), as the build system\ncannot disambiguate the two.\n\nAssembly should be formatted as follows:\n- Local control-flow labels should be numbered, not named.\n- Local data labels should be named descriptively.\n- Global data and functions should use the `data` and `func`/`endfunc` macros\n  from `macros.S`.\n- Indent the instruction by one tab.\n- Indent the first operand with one tab.\n- Separate following operands with a single space.\n- Use `#` to start comments.\n- Align comments at 40 columns with tabs.\n\n[conduct]: docs/code_of_conduct.md\n[dco]: https://developercertificate.org\n[doxygen]: https://www.stack.nl/~dimitri/doxygen/manual/docblocks.html\n[issues]: https://github.com/crust-firmware/crust/issues\n[uncrustify]: https://github.com/uncrustify/uncrustify\n"
  },
  {
    "path": "Doxyfile",
    "content": "# Doxyfile 1.8.16\n\n#---------------------------------------------------------------------------\n# Project related configuration options\n#---------------------------------------------------------------------------\n\nDOXYFILE_ENCODING      = UTF-8\nPROJECT_NAME           = \"crust\"\nPROJECT_BRIEF          = \"SCP firmware for sunxi SoCs\"\nOUTPUT_DIRECTORY       = @OBJ@/docs\nBRIEF_MEMBER_DESC      = YES\nREPEAT_BRIEF           = YES\nALWAYS_DETAILED_SEC    = NO\nFULL_PATH_NAMES        = YES\nJAVADOC_AUTOBRIEF      = YES\nJAVADOC_BANNER         = YES\nTAB_SIZE               = 8\nOPTIMIZE_OUTPUT_FOR_C  = YES\nMARKDOWN_SUPPORT       = YES\nAUTOLINK_SUPPORT       = YES\nINLINE_SIMPLE_STRUCTS  = YES\n\n#---------------------------------------------------------------------------\n# Build related configuration options\n#---------------------------------------------------------------------------\n\nEXTRACT_ALL            = YES\nEXTRACT_PRIVATE        = NO\nEXTRACT_STATIC         = NO\nHIDE_UNDOC_MEMBERS     = NO\nHIDE_UNDOC_CLASSES     = NO\nHIDE_IN_BODY_DOCS      = NO\nINTERNAL_DOCS          = NO\nHIDE_SCOPE_NAMES       = NO\nSHOW_INCLUDE_FILES     = YES\nFORCE_LOCAL_INCLUDES   = NO\nINLINE_INFO            = YES\nSORT_MEMBER_DOCS       = YES\nSORT_BRIEF_DOCS        = YES\nSORT_GROUP_NAMES       = NO\nSTRICT_PROTO_MATCHING  = NO\nGENERATE_TODOLIST      = YES\nGENERATE_TESTLIST      = YES\nGENERATE_BUGLIST       = YES\nGENERATE_DEPRECATEDLIST= YES\nMAX_INITIALIZER_LINES  = 0\nSHOW_USED_FILES        = NO\nSHOW_FILES             = YES\nSHOW_NAMESPACES        = NO\n\n#---------------------------------------------------------------------------\n# Configuration options related to warning and progress messages\n#---------------------------------------------------------------------------\n\nQUIET                  = YES\nWARNINGS               = YES\nWARN_IF_UNDOCUMENTED   = YES\nWARN_IF_DOC_ERROR      = YES\nWARN_NO_PARAMDOC       = YES\nWARN_AS_ERROR          = NO\n\n#---------------------------------------------------------------------------\n# Configuration options related to the input files\n#---------------------------------------------------------------------------\n\nINPUT                  = @SRC@/common \\\n                         @SRC@/drivers \\\n                         @SRC@/include \\\n                         @SRC@/lib \\\n                         @SRC@/platform \\\n                         @DOCS@\nINPUT_ENCODING         = UTF-8\nFILE_PATTERNS          = *.c \\\n                         *.h \\\n                         *.md\nRECURSIVE              = YES\nEXCLUDE                =\nEXCLUDE_SYMLINKS       = YES\nEXCLUDE_PATTERNS       =\nEXCLUDE_SYMBOLS        =\nUSE_MDFILE_AS_MAINPAGE = README.md\n\n#---------------------------------------------------------------------------\n# Configuration options related to source browsing\n#---------------------------------------------------------------------------\n\nSOURCE_BROWSER         = YES\nINLINE_SOURCES         = NO\nSTRIP_CODE_COMMENTS    = YES\nREFERENCED_BY_RELATION = YES\nREFERENCES_RELATION    = YES\nREFERENCES_LINK_SOURCE = NO\nVERBATIM_HEADERS       = YES\n\n#---------------------------------------------------------------------------\n# Configuration options related to the alphabetical class index\n#---------------------------------------------------------------------------\n\nALPHABETICAL_INDEX     = YES\nCOLS_IN_ALPHA_INDEX    = 5\n\n#---------------------------------------------------------------------------\n# Configuration options related to the HTML output\n#---------------------------------------------------------------------------\n\nGENERATE_HTML          = YES\nHTML_OUTPUT            = html\nHTML_FILE_EXTENSION    = .html\nHTML_TIMESTAMP         = NO\nHTML_DYNAMIC_MENUS     = NO\nHTML_DYNAMIC_SECTIONS  = YES\nSEARCHENGINE           = YES\nSERVER_BASED_SEARCH    = NO\n\n#---------------------------------------------------------------------------\n# Configuration options related to the other outputs\n#---------------------------------------------------------------------------\n\nGENERATE_LATEX         = NO\nGENERATE_RTF           = NO\nGENERATE_MAN           = NO\nGENERATE_XML           = NO\nGENERATE_DOCBOOK       = NO\nGENERATE_AUTOGEN_DEF   = NO\nGENERATE_PERLMOD       = NO\n\n#---------------------------------------------------------------------------\n# Configuration options related to the preprocessor\n#---------------------------------------------------------------------------\n\nENABLE_PREPROCESSING   = YES\nMACRO_EXPANSION        = YES\nEXPAND_ONLY_PREDEF     = YES\nSEARCH_INCLUDES        = YES\nINCLUDE_PATH           = @SRC@/include/drivers\nPREDEFINED             = ATTRIBUTE(...)= UNUSED= WEAK=\nSKIP_FUNCTION_MACROS   = YES\n\n#---------------------------------------------------------------------------\n# Configuration options related to the dot tool\n#---------------------------------------------------------------------------\n\nHAVE_DOT               = YES\nDOT_FONTNAME           = sans-serif\nINCLUDE_GRAPH          = YES\nINCLUDED_BY_GRAPH      = YES\nCALL_GRAPH             = YES\nDIRECTORY_GRAPH        = NO\nDOT_IMAGE_FORMAT       = svg\nINTERACTIVE_SVG        = NO\nDOT_GRAPH_MAX_NODES    = 100\nDOT_TRANSPARENT        = YES\nGENERATE_LEGEND        = YES\nDOT_CLEANUP            = YES\n"
  },
  {
    "path": "Kconfig",
    "content": "#\n# Copyright © 2017-2022 The Crust Firmware Authors.\n# SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n#\n\nmainmenu \"Crust Firmware Configuration\"\n\nsource \"arch/Kconfig\"\nsource \"platform/Kconfig\"\nsource \"drivers/Kconfig\"\nsource \"common/Kconfig\"\n"
  },
  {
    "path": "LICENSE.md",
    "content": "# Crust Firmware Licensing\n\nThe Crust firmware itself is dual-licensed as BSD-3-clause or GPL-2.0-only. You\nmay use and redistribute it under either set of license terms.\n\nIt uses some third-party BSD-1-Clause and MIT-licensed headers; those licenses\nare compatible with either main license.\n\nThe Kconfig configuration system is licensed as GPL-2.0-only. However, it is a\nbuild time dependency only, and all GPL-2.0-only files are restricted to the\n`3rdparty/kconfig` directory.\n\n## BSD 1-clause License\n\n    Copyright © 2014 OpenRISC Project Maintainers. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following condition is met:\n\n1. Redistributions of source code must retain the above copyright notice, this\n   list of conditions and the following disclaimer.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\nFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\nDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\nOR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n---\n\n## BSD 3-clause License\n\n    Copyright © 2013-2017, ARM Limited and Contributors. All rights reserved.\n    Copyright © 2017-2022 The Crust Firmware Authors.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n1. Redistributions of source code must retain the above copyright notice, this\n   list of conditions and the following disclaimer.\n\n2. Redistributions in binary form must reproduce the above copyright notice,\n   this list of conditions and the following disclaimer in the documentation\n   and/or other materials provided with the distribution.\n\n3. Neither the name of the copyright holder nor the names of its contributors\n   may be used to endorse or promote products derived from this software\n   without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\nFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\nDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\nOR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n---\n\n## GNU General Public License\n\nVersion 2, June 1991\n\n    Copyright (C) 1989, 1991 Free Software Foundation, Inc.\n    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n\nEveryone is permitted to copy and distribute verbatim copies of this license\ndocument, but changing it is not allowed.\n\n### Preamble\n\nThe licenses for most software are designed to take away your freedom to share\nand change it. By contrast, the GNU General Public License is intended to\nguarantee your freedom to share and change free software--to make sure the\nsoftware is free for all its users. This General Public License applies to most\nof the Free Software Foundation's software and to any other program whose\nauthors commit to using it. (Some other Free Software Foundation software is\ncovered by the GNU Lesser General Public License instead.) You can apply it to\nyour programs, too.\n\nWhen we speak of free software, we are referring to freedom, not price. Our\nGeneral Public Licenses are designed to make sure that you have the freedom to\ndistribute copies of free software (and charge for this service if you wish),\nthat you receive source code or can get it if you want it, that you can change\nthe software or use pieces of it in new free programs; and that you know you\ncan do these things.\n\nTo protect your rights, we need to make restrictions that forbid anyone to deny\nyou these rights or to ask you to surrender the rights. These restrictions\ntranslate to certain responsibilities for you if you distribute copies of the\nsoftware, or if you modify it.\n\nFor example, if you distribute copies of such a program, whether gratis or for\na fee, you must give the recipients all the rights that you have. You must make\nsure that they, too, receive or can get the source code. And you must show them\nthese terms so they know their rights.\n\nWe protect your rights with two steps: (1) copyright the software, and (2)\noffer you this license which gives you legal permission to copy, distribute\nand/or modify the software.\n\nAlso, for each author's protection and ours, we want to make certain that\neveryone understands that there is no warranty for this free software. If the\nsoftware is modified by someone else and passed on, we want its recipients to\nknow that what they have is not the original, so that any problems introduced\nby others will not reflect on the original authors' reputations.\n\nFinally, any free program is threatened constantly by software patents. We wish\nto avoid the danger that redistributors of a free program will individually\nobtain patent licenses, in effect making the program proprietary. To prevent\nthis, we have made it clear that any patent must be licensed for everyone's\nfree use or not licensed at all.\n\nThe precise terms and conditions for copying, distribution and modification\nfollow.\n\n### Terms and Conditions for Copying, Distribution and Modification\n\n0.  This License applies to any program or other work which contains a notice\n    placed by the copyright holder saying it may be distributed under the terms\n    of this General Public License. The \"Program\", below, refers to any such\n    program or work, and a \"work based on the Program\" means either the Program\n    or any derivative work under copyright law: that is to say, a work\n    containing the Program or a portion of it, either verbatim or with\n    modifications and/or translated into another language. (Hereinafter,\n    translation is included without limitation in the term \"modification\".)\n    Each licensee is addressed as \"you\".\n\n    Activities other than copying, distribution and modification are not\n    covered by this License; they are outside its scope. The act of running the\n    Program is not restricted, and the output from the Program is covered only\n    if its contents constitute a work based on the Program (independent of\n    having been made by running the Program). Whether that is true depends on\n    what the Program does.\n\n1.  You may copy and distribute verbatim copies of the Program's source code as\n    you receive it, in any medium, provided that you conspicuously and\n    appropriately publish on each copy an appropriate copyright notice and\n    disclaimer of warranty; keep intact all the notices that refer to this\n    License and to the absence of any warranty; and give any other recipients\n    of the Program a copy of this License along with the Program.\n\n    You may charge a fee for the physical act of transferring a copy, and you\n    may at your option offer warranty protection in exchange for a fee.\n\n2.  You may modify your copy or copies of the Program or any portion of it,\n    thus forming a work based on the Program, and copy and distribute such\n    modifications or work under the terms of Section 1 above, provided that you\n    also meet all of these conditions:\n\n\n    a) You must cause the modified files to carry prominent notices stating\n    that you changed the files and the date of any change.\n\n\n    b) You must cause any work that you distribute or publish, that in whole or\n    in part contains or is derived from the Program or any part thereof, to be\n    licensed as a whole at no charge to all third parties under the terms of\n    this License.\n\n\n    c) If the modified program normally reads commands interactively when run,\n    you must cause it, when started running for such interactive use in the\n    most ordinary way, to print or display an announcement including an\n    appropriate copyright notice and a notice that there is no warranty (or\n    else, saying that you provide a warranty) and that users may redistribute\n    the program under these conditions, and telling the user how to view a copy\n    of this License. (Exception: if the Program itself is interactive but does\n    not normally print such an announcement, your work based on the Program is\n    not required to print an announcement.)\n\n    These requirements apply to the modified work as a whole. If identifiable\n    sections of that work are not derived from the Program, and can be\n    reasonably considered independent and separate works in themselves, then\n    this License, and its terms, do not apply to those sections when you\n    distribute them as separate works. But when you distribute the same\n    sections as part of a whole which is a work based on the Program, the\n    distribution of the whole must be on the terms of this License, whose\n    permissions for other licensees extend to the entire whole, and thus to\n    each and every part regardless of who wrote it.\n\n    Thus, it is not the intent of this section to claim rights or contest your\n    rights to work written entirely by you; rather, the intent is to exercise\n    the right to control the distribution of derivative or collective works\n    based on the Program.\n\n    In addition, mere aggregation of another work not based on the Program with\n    the Program (or with a work based on the Program) on a volume of a storage\n    or distribution medium does not bring the other work under the scope of\n    this License.\n\n3.  You may copy and distribute the Program (or a work based on it, under\n    Section 2) in object code or executable form under the terms of Sections 1\n    and 2 above provided that you also do one of the following:\n\n\n    a) Accompany it with the complete corresponding machine-readable source\n    code, which must be distributed under the terms of Sections 1 and 2 above\n    on a medium customarily used for software interchange; or,\n\n\n    b) Accompany it with a written offer, valid for at least three years, to\n    give any third party, for a charge no more than your cost of physically\n    performing source distribution, a complete machine-readable copy of the\n    corresponding source code, to be distributed under the terms of Sections 1\n    and 2 above on a medium customarily used for software interchange; or,\n\n\n    c) Accompany it with the information you received as to the offer to\n    distribute corresponding source code. (This alternative is allowed only for\n    noncommercial distribution and only if you received the program in object\n    code or executable form with such an offer, in accord with Subsection b\n    above.)\n\n    The source code for a work means the preferred form of the work for making\n    modifications to it. For an executable work, complete source code means all\n    the source code for all modules it contains, plus any associated interface\n    definition files, plus the scripts used to control compilation and\n    installation of the executable. However, as a special exception, the source\n    code distributed need not include anything that is normally distributed (in\n    either source or binary form) with the major components (compiler, kernel,\n    and so on) of the operating system on which the executable runs, unless\n    that component itself accompanies the executable.\n\n    If distribution of executable or object code is made by offering access to\n    copy from a designated place, then offering equivalent access to copy the\n    source code from the same place counts as distribution of the source code,\n    even though third parties are not compelled to copy the source along with\n    the object code.\n\n4.  You may not copy, modify, sublicense, or distribute the Program except as\n    expressly provided under this License. Any attempt otherwise to copy,\n    modify, sublicense or distribute the Program is void, and will\n    automatically terminate your rights under this License. However, parties\n    who have received copies, or rights, from you under this License will not\n    have their licenses terminated so long as such parties remain in full\n    compliance.\n\n5.  You are not required to accept this License, since you have not signed it.\n    However, nothing else grants you permission to modify or distribute the\n    Program or its derivative works. These actions are prohibited by law if you\n    do not accept this License. Therefore, by modifying or distributing the\n    Program (or any work based on the Program), you indicate your acceptance of\n    this License to do so, and all its terms and conditions for copying,\n    distributing or modifying the Program or works based on it.\n\n6.  Each time you redistribute the Program (or any work based on the Program),\n    the recipient automatically receives a license from the original licensor\n    to copy, distribute or modify the Program subject to these terms and\n    conditions. You may not impose any further restrictions on the recipients'\n    exercise of the rights granted herein. You are not responsible for\n    enforcing compliance by third parties to this License.\n\n7.  If, as a consequence of a court judgment or allegation of patent\n    infringement or for any other reason (not limited to patent issues),\n    conditions are imposed on you (whether by court order, agreement or\n    otherwise) that contradict the conditions of this License, they do not\n    excuse you from the conditions of this License. If you cannot distribute so\n    as to satisfy simultaneously your obligations under this License and any\n    other pertinent obligations, then as a consequence you may not distribute\n    the Program at all. For example, if a patent license would not permit\n    royalty-free redistribution of the Program by all those who receive copies\n    directly or indirectly through you, then the only way you could satisfy\n    both it and this License would be to refrain entirely from distribution of\n    the Program.\n\n    If any portion of this section is held invalid or unenforceable under any\n    particular circumstance, the balance of the section is intended to apply\n    and the section as a whole is intended to apply in other circumstances.\n\n    It is not the purpose of this section to induce you to infringe any patents\n    or other property right claims or to contest validity of any such claims;\n    this section has the sole purpose of protecting the integrity of the free\n    software distribution system, which is implemented by public license\n    practices. Many people have made generous contributions to the wide range\n    of software distributed through that system in reliance on consistent\n    application of that system; it is up to the author/donor to decide if he or\n    she is willing to distribute software through any other system and a\n    licensee cannot impose that choice.\n\n    This section is intended to make thoroughly clear what is believed to be a\n    consequence of the rest of this License.\n\n8.  If the distribution and/or use of the Program is restricted in certain\n    countries either by patents or by copyrighted interfaces, the original\n    copyright holder who places the Program under this License may add an\n    explicit geographical distribution limitation excluding those countries, so\n    that distribution is permitted only in or among countries not thus\n    excluded. In such case, this License incorporates the limitation as if\n    written in the body of this License.\n\n9.  The Free Software Foundation may publish revised and/or new versions of the\n    General Public License from time to time. Such new versions will be similar\n    in spirit to the present version, but may differ in detail to address new\n    problems or concerns.\n\n    Each version is given a distinguishing version number. If the Program\n    specifies a version number of this License which applies to it and \"any\n    later version\", you have the option of following the terms and conditions\n    either of that version or of any later version published by the Free\n    Software Foundation. If the Program does not specify a version number of\n    this License, you may choose any version ever published by the Free\n    Software Foundation.\n\n10. If you wish to incorporate parts of the Program into other free programs\n    whose distribution conditions are different, write to the author to ask for\n    permission. For software which is copyrighted by the Free Software\n    Foundation, write to the Free Software Foundation; we sometimes make\n    exceptions for this. Our decision will be guided by the two goals of\n    preserving the free status of all derivatives of our free software and of\n    promoting the sharing and reuse of software generally.\n\n### NO WARRANTY\n\n11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR\n    THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN\n    OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\n    PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\n    OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n    MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO\n    THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM\n    PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR\n    CORRECTION.\n\n12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL\n    ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE\n    THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\n    GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\n    USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\n    DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\n    PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\n    EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\n    SUCH DAMAGES.\n\n### End of Terms and Conditions\n\n### How to Apply These Terms to Your New Programs\n\nIf you develop a new program, and you want it to be of the greatest possible\nuse to the public, the best way to achieve this is to make it free software\nwhich everyone can redistribute and change under these terms.\n\nTo do so, attach the following notices to the program. It is safest to attach\nthem to the start of each source file to most effectively convey the exclusion\nof warranty; and each file should have at least the \"copyright\" line and a\npointer to where the full notice is found.\n\n    <one line to give the program's name and an idea of what it does.>\n    Copyright (C) <year> <name of author>\n\n    This program is free software; you can redistribute it and/or modify it\n    under the terms of the GNU General Public License as published by the Free\n    Software Foundation; either version 2 of the License, or (at your option)\n    any later version.\n\n    This program is distributed in the hope that it will be useful, but WITHOUT\n    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\n    FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for\n    more details.\n\n    You should have received a copy of the GNU General Public License along\n    with this program; if not, write to the Free Software Foundation, Inc.,\n    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n\nAlso add information on how to contact you by electronic and paper mail.\n\nIf the program is interactive, make it output a short notice like this when it\nstarts in an interactive mode:\n\n    Gnomovision version 69, Copyright (C) year name of author\n    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type 'show w'.\n    This is free software, and you are welcome to redistribute it under certain\n    conditions; type 'show c' for details.\n\nThe hypothetical commands 'show w' and 'show c' should show the appropriate\nparts of the General Public License. Of course, the commands you use may be\ncalled something other than 'show w' and 'show c'; they could even be\nmouse-clicks or menu items--whatever suits your program.\n\nYou should also get your employer (if you work as a programmer) or your school,\nif any, to sign a \"copyright disclaimer\" for the program, if necessary. Here is\na sample; alter the names:\n\n    Yoyodyne, Inc., hereby disclaims all copyright interest in the program\n    'Gnomovision' (which makes passes at compilers) written by James Hacker.\n\n    signature of Ty Coon, 1 April 1989\n    Ty Coon, President of Vice\n\nThis General Public License does not permit incorporating your program into\nproprietary programs. If your program is a subroutine library, you may consider\nit more useful to permit linking proprietary applications with the library. If\nthis is what you want to do, use the [GNU Lesser General Public\nLicense](https://www.gnu.org/licenses/lgpl.html) instead of this License.\n\n---\n\n## MIT License\n\n    Copyright © 2005-2014 Rich Felker, et al.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\nof the Software, and to permit persons to whom the Software is furnished to do\nso, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "Makefile",
    "content": "#\n# Copyright © 2017-2022 The Crust Firmware Authors.\n# SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n#\n\nSRC\t\t = .\nOBJ\t\t = build\nTGT\t\t = $(OBJ)/scp\n\nBUILDAR\t\t = ar\nBUILDCC\t\t?= cc\n\nHOST_COMPILE\t?= aarch64-linux-musl-\nHOSTAR\t\t = $(HOST_COMPILE)gcc-ar\nHOSTCC\t\t = $(HOST_COMPILE)gcc\n\nAR\t\t = $(CROSS_COMPILE)gcc-ar\nCC\t\t = $(CROSS_COMPILE)gcc\nLD\t\t = $(shell $(CC) -print-prog-name=ld)\nOBJCOPY\t\t = $(CROSS_COMPILE)objcopy\n\nLEX\t\t = lex\nYACC\t\t = bison\n\nCOMMON_CFLAGS\t = -Os -pipe -std=c11 \\\n\t\t   -fdata-sections \\\n\t\t   -ffunction-sections \\\n\t\t   -fno-builtin \\\n\t\t   -fno-common \\\n\t\t   -fvar-tracking-assignments \\\n\t\t   -g$(if $(CONFIG_DEBUG_INFO),gdb,0) \\\n\t\t   -Wall -Wextra -Wformat=2 -Wpedantic -Wshadow \\\n\t\t   -Werror=implicit-function-declaration \\\n\t\t   -Werror=implicit-int \\\n\t\t   -Werror=pointer-arith \\\n\t\t   -Werror=pointer-sign \\\n\t\t   -Werror=strict-prototypes \\\n\t\t   -Werror=undef \\\n\t\t   -Werror=vla \\\n\t\t   -Wno-missing-field-initializers\nCOMMON_CPPFLAGS\t = -I$(OBJ)/include \\\n\t\t   -I$(SRC)/platform/$(CONFIG_PLATFORM)/include \\\n\t\t   -I$(SRC)/arch/$(CONFIG_ARCH)/include \\\n\t\t   -I$(SRC)/include/common \\\n\t\t   -I$(SRC)/include/lib\n\nHEADERS\t\t = $(OBJ)/include/config.h \\\n\t\t   $(SRC)/lib/compiler.h \\\n\t\t   $(SRC)/lib/kconfig.h\n\nBUILDCFLAGS\t = $(COMMON_CFLAGS)\nBUILDCPPFLAGS\t = $(COMMON_CPPFLAGS) \\\n\t\t   -D_XOPEN_SOURCE=700\nBUILDLDFLAGS\t =\nBUILDLDLIBS\t =\n\nHOSTCFLAGS\t = $(COMMON_CFLAGS) \\\n\t\t   -Werror=implicit-fallthrough=5\nHOSTCPPFLAGS\t = $(COMMON_CPPFLAGS) \\\n\t\t   -D_XOPEN_SOURCE=700\nHOSTLDFLAGS\t =\nHOSTLDLIBS\t =\n\nAFLAGS\t\t = -Wa,--fatal-warnings \\\n\t\t   -Wa,--noexecstack\nCFLAGS\t\t = $(COMMON_CFLAGS) \\\n\t\t   -ffreestanding \\\n\t\t   -flto \\\n\t\t   -fno-asynchronous-unwind-tables \\\n\t\t   -fno-pie \\\n\t\t   -fno-stack-protector \\\n\t\t   -fomit-frame-pointer \\\n\t\t   -funsigned-char \\\n\t\t   -Werror=implicit-fallthrough=5\nCPPFLAGS\t = $(COMMON_CPPFLAGS) \\\n\t\t   -I$(SRC)/include/drivers \\\n\t\t   -I$(SRC)/include/stdlib \\\n\t\t   $(foreach header,$(HEADERS),-include $(notdir $(header))) \\\n\t\t   -nostdinc \\\n\t\t   -Werror=missing-include-dirs\nLDFLAGS\t\t = -nostdlib \\\n\t\t   -no-pie \\\n\t\t   -static \\\n\t\t   -Wl,-O1 \\\n\t\t   -Wl,--build-id=none \\\n\t\t   -Wl,--fatal-warnings \\\n\t\t   -Wl,--gc-sections \\\n\t\t   -Wl,--no-dynamic-linker \\\n\t\t   -Wl,--no-undefined \\\n\t\t   $(call ld-option,--no-warn-rwx-segments)\n\nld-option\t = $(shell $(LD) -v $1 >/dev/null 2>&1 && printf '%s' '-Wl,$1')\n\n###############################################################################\n\n.DEFAULT_GOAL\t:= all\nGOALS\t\t:= $(if $(MAKECMDGOALS),$(MAKECMDGOALS),$(.DEFAULT_GOAL))\nMAKEFLAGS\t+= -Rr\n\nDOCS\t\t = $(wildcard $(SRC)/*.md $(SRC)/docs/*.md)\nOBJ_DEPS\t = $(OBJ)/include/version.h\n\nexport KCONFIG_AUTOCONFIG := $(OBJ)/include/config/auto.conf\nexport KCONFIG_AUTOHEADER := $(OBJ)/include/config.h\n\nifneq ($(filter-out %clean %clobber %config %format,$(GOALS)),)\n  include $(OBJ)/include/config/auto.conf\n  include $(OBJ)/include/config/auto.conf.cmd\nendif\n\ninclude $(SRC)/scripts/Makefile.format\ninclude $(SRC)/scripts/Makefile.kbuild\n\n$(call descend,3rdparty arch common drivers lib tools)\n\n###############################################################################\n\nM := @$(if $(filter-out 0,$(V)),:,exec printf '  %-7s %s\\n')\nQ :=  $(if $(filter-out 0,$(V)),,@)exec\n\nall: scp $(test-all)\n\ncheck: $(test-all:%=%.test)\n\nclean:\n\t$(Q) rm -fr $(TGT)\n\nclobber:\n\t$(Q) rm -fr $(OBJ)\n\ndistclean:\n\t$(Q) rm -fr $(OBJ) ..config* .config*\n\nhtml: $(OBJ)/docs\n\nscp: $(TGT)/scp.bin\n\ntools: $(tools-all)\n\n.config:;\n\n%/.:\n\t$(Q) mkdir -p $*\n\n%.d:;\n\n$(OBJ)/docs: $(OBJ)/Doxyfile $(DOCS) $(obj-all)\n\t$(M) DOXYGEN $@\n\t$(Q) doxygen $<\n\t$(Q) touch $@\n\n$(OBJ)/Doxyfile: $(SRC)/Doxyfile\n\t$(Q) sed 's|@DOCS@|$(DOCS)|g;s|@OBJ@|$(OBJ)|g;s|@SRC@|$(SRC)|g' $< > $@\n\n$(OBJ)/%.test: $(SRC)/scripts/test.sh $(OBJ)/%\n\t$(M) TEST $@\n\t$(Q) $^ $@\n\n$(OBJ)/%: $(OBJ)/%.o\n\t$(M) HOSTLD $@\n\t$(Q) $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^ $(HOSTLDLIBS)\n\n$(test-all): $(OBJ)/lib.a\n$(tools-all): $(OBJ)/lib.a\n\n$(OBJ)/lib.a:\n\t$(M) HOSTAR $@\n\t$(Q) $(HOSTAR) Drcs $@ $^\n\n$(OBJ)/%.o: $(OBJ)/%.c\n\t$(M) HOSTCC $@\n\t$(Q) $(HOSTCC) $(HOSTCPPFLAGS) $(HOSTCFLAGS) -MMD -c -o $@ $<\n\n$(OBJ)/%.o: $(SRC)/%.c\n\t$(M) HOSTCC $@\n\t$(Q) $(HOSTCC) $(HOSTCPPFLAGS) $(HOSTCFLAGS) -MMD -c -o $@ $<\n\n$(OBJ)/%.lex.c: $(SRC)/%.l\n\t$(M) LEX $@\n\t$(Q) $(LEX) -o $@ $<\n\n$(OBJ)/%.tab.c $(OBJ)/%.tab.h: $(SRC)/%.y\n\t$(M) YACC $@\n\t$(Q) $(YACC) -d -t -o $@ $<\n\n$(OBJ)/include/config.h: $(OBJ)/include/config/auto.conf;\n\n$(OBJ)/include/config/auto.conf: $(OBJ)/3rdparty/kconfig/conf .config\n\t$(M) GEN $@\n\t$(Q) $< --syncconfig $(SRC)/Kconfig\n\n$(OBJ)/include/config/auto.conf.cmd: $(OBJ)/include/config/auto.conf;\n\n$(OBJ)/include/version.h: $(SRC)/scripts/version.sh FORCE | $(OBJ)/include/.\n\t$(Q) $< $(realpath $(SRC)) $@\n\n$(TGT)/%.bin: $(TGT)/%.elf\n\t$(M) OBJCOPY $@\n\t$(Q) $(OBJCOPY) -O binary -S --reverse-bytes 4 $< $@\n\n$(TGT)/%.elf $(TGT)/%.map: $(obj-all) $(TGT)/lib.a\n\t$(M) LD $@\n\t$(Q) $(CC) $(CFLAGS) $(LDFLAGS) -Wl,-Map,$(TGT)/$*.map -o $@ -T $^\n\n$(TGT)/lib.a:\n\t$(M) AR $@\n\t$(Q) $(AR) Drcs $@ $^\n\n$(TGT)/%.o: $(SRC)/%.c\n\t$(M) CC $@\n\t$(Q) $(CC) $(CPPFLAGS) $(CFLAGS) $(AFLAGS) -MMD -c -o $@ $<\n\n$(TGT)/%.o: $(SRC)/%.S\n\t$(M) AS $@\n\t$(Q) $(CC) $(CPPFLAGS) $(AFLAGS) -MMD -c -o $@ $<\n\n$(TGT)/%.ld.o: $(SRC)/%.ld.S\n\t$(M) CPP $@\n\t$(Q) $(CC) $(CPPFLAGS) -E -MMD -MT $@ -P -o $@ $<\n\n$(SRC)/Makefile:;\n$(SRC)/%.h:;\n\n.PHONY: FORCE all check clean clobber distclean doc scp tools\n.SECONDARY:\n.SUFFIXES:\n"
  },
  {
    "path": "README.md",
    "content": "# Crust: Libre SCP firmware for Allwinner sunxi SoCs\n\n[![CI status](https://travis-ci.com/crust-firmware/crust.svg?branch=master)][t]\n\n[t]: https://travis-ci.com/crust-firmware/crust\n\n## What is it?\n\nThe crust is the lowest-level component of a delicious fruit pie. Similarly,\nCrust is the lowest-level firmware component that runs on `$FRUIT` (Banana,\nOrange, Lichee) Pi single-board computers and other Allwinner-based devices,\nsuch as the Olimex TERES-I laptop and the Pine64 PinePhone.\n\nCrust improves battery life and thermal performance by implementing a deep\nsleep state. During deep sleep, the CPU cores, the DRAM controller, and most\nonboard peripherals are powered down, reducing power consumption by 80% or more\ncompared to an idle device. On boards without a PMIC, Crust is also responsible\nfor orderly power-off and power-on of the device.\n\nFor this to work, Crust runs outside the main CPU and DRAM, on a dedicated\nalways-on microprocessor called a System Control Processor (SCP). Crust is\ndesigned to run on a specific SCP implementation, Allwinner's [AR100][].\n\nNote that Crust only provides the mechanism for deep sleep. It does not dictate\nany system sleep policy. Specifically, Crust does _not_ decide when to go to\nsleep; the Linux kernel or userspace does that. And with one exception\n(listening for IR remote control key presses), Crust does not decide when to\nwake the system up, either; the hardware, as programmed by Linux, does that.\nCrust is designed to be a mostly-invisible implementation detail of the Linux\npower management interface.\n\nSee [Crust's ABI documentation][abi] for a detailed description of how Crust\ninteracts with Linux and other firmware components at runtime.\n\nInterested users and contributors are encouraged to join `#linux-sunxi` on OFTC\nto discuss the firmware and its integration with other software.\n\n[abi]: docs/abi.md\n[AR100]: https://linux-sunxi.org/AR100\n\n## Supported devices\n\nCrust supports any board with a SoC listed in the table below. There is no\nboard-specific code needed for basic functionality. Boards that are tested and\nknown to work have a `defconfig` file in the repository. For everything else,\nuse the defconfig for a similar board, or run `make config` or `make nconfig`\nto choose the appropriate options (there aren't many).\n\n|  SoC  |   Support level   | SCPI | CPU cores | CPU subsystem | DRAM | PMIC |\n|-------|-------------------|------|-----------|---------------|------|------|\n| A23   | Known to run      | Yes  | Yes       | Yes           | No   | Yes  |\n| A33   | Known to run      | Yes  | Yes       | Yes           | No   | Yes  |\n| A64   | Production/stable | Yes  | Yes       | Yes           | Yes  | Yes  |\n| A83T  | Known to compile  | Yes  | No        | No            | No   | No   |\n| H3    | Working beta      | Yes  | Yes       | Yes           | Yes  | N/A  |\n| H5    | Production/stable | Yes  | Yes       | Yes           | Yes  | N/A  |\n| H6    | Production/stable | Yes  | Yes       | Yes           | Yes  | Yes  |\n\n## Prerequisites\n\nCrust supports mainline Linux only. It completely replaces Allwinner's bespoke,\nproprietary firmware with a libre solution that supports [standard\nprotocols][scpi] and is developed entirely in the open with community input.\nEffort is underway to upstream all changes to third-party projects; however,\nsome patches are currently still needed.\n\n- ARM Trusted Firmware-A: upstream support for Crust was merged in commit\n  [`c335ad480d41`][atf-c335ad480d41], and is present in all releases starting\n  with [v2.3][atf-v2.3]. Optional patches for improved support are available in\n  the `crust` branch of [the crust-firmware fork][crust-atf].\n- Linux: while Linux does not directly communicate with Crust, it requires some\n  small patches to cleanly share the clock controller and PMIC bus controller\n  hardware with Crust. They are available in the `crust-minimal` branch of [the\n  crust-firmware fork][crust-linux]. Those patches, plus additional optional\n  changes for reduced power consumption (helpful even if you are not using\n  Crust), are available in the `crust` branch.\n- U-Boot: upstream support for loading Crust into SRAM was merged in commit\n  [`18261b855223`][u-boot-18261b855223], and is present in all releases\n  starting with [v2021.01-rc1][u-boot-v2021.01-rc1]. It is also possible to\n  load Crust by padding your ATF binary to 48KiB (64KiB for H6) and then\n  concatenating Crust onto the end.\n\nNote: The default PMIC bus configuration for most H6 boards is not compatible\nwith versions of Linux before commit [`531fdbeedeb8`][531fdbeedeb8]. To use\nCrust on those boards with older versions of Linux, you must explicitly select\n`CONFIG_I2C_PINS_PL0_PL1`, or you may use the Crust v0.4 release.\n\n[atf-c335ad480d41]: https://github.com/ARM-Software/ARM-Trusted-Firmware/commits/c335ad480d41\n[atf-v2.3]: https://github.com/ARM-software/arm-trusted-firmware/releases/tag/v2.3\n[crust-atf]: https://github.com/crust-firmware/arm-trusted-firmware\n[crust-linux]: https://github.com/crust-firmware/linux\n[scpi]: http://infocenter.arm.com/help/topic/com.arm.doc.dui0922-/index.html\n[u-boot-18261b855223]: https://github.com/u-boot/u-boot/commit/18261b855223\n[u-boot-v2021.01-rc1]: https://github.com/u-boot/u-boot/releases/tag/v2021.01-rc1\n[531fdbeedeb8]: https://git.kernel.org/torvalds/c/531fdbeedeb8\n\n## Building the firmware\n\nAn easy way to get all the pieces in the right places, with the right patches,\nis to use the `Makefile` in the [crust-firmware meta repository][crust-meta].\nSee the README file there for further instructions. Alternatively, you can\nbuild each firmware component individually. See the [README.sunxi64][sunxi64]\nfile in the U-Boot source tree for more details. Installation of the combined\nU-Boot+ATF+Crust binary works the same as for U-Boot without Crust.\n\nBuilding Crust requires a cross-compiler targeting the `or1k` architecture\n(OpenRISC 1000, *not* RISC-V), which is officially supported in upstream GCC\nstarting with GCC 9.1.0. Prebuilt toolchains are available from [musl.cc][],\n[bootlin][], and possibly your Linux distribution's package archive.\n\nIf your cross toolchain has a different tuple (the toolchain's `libc` is not\nrelevant when compiling freestanding firmware programs), or if it is not in\nyour `PATH`, export `CROSS_COMPILE` or edit the top of the `Makefile` to\nprovide the appropriate prefix or full path.\n\nRun `make` to build the firmware, which will be placed at `build/scp/scp.bin`.\nAdding `V=1` to the command line will perform a verbose build, showing you the\ncommands as they run. Set `SRC`, `OBJ`, or `TGT` as necessary if you want to do\nan out-of-tree build.\n\n[bootlin]: https://toolchains.bootlin.com/\n[crust-meta]: https://github.com/crust-firmware/meta\n[musl.cc]: http://musl.cc/or1k-linux-musl-cross.tgz\n[sunxi64]: https://github.com/u-boot/u-boot/raw/master/board/sunxi/README.sunxi64\n\n## Contributing\n\nThe success of the crust firmware project is made possible by community\nsupport. For more information regarding community contributions, please\nreference the crust firmware [contribution guidelines][cg].\n\n[cg]: CONTRIBUTING.md\n"
  },
  {
    "path": "arch/Kconfig",
    "content": "#\n# Copyright © 2020-2022 The Crust Firmware Authors.\n# SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n#\n\nconfig ARCH\n\tstring\n\tdefault \"or1k\" if ARCH_OR1K\n\nconfig ARCH_OR1K\n\tbool\n\tdefault y\n"
  },
  {
    "path": "arch/Makefile",
    "content": "#\n# Copyright © 2020-2022 The Crust Firmware Authors.\n# SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n#\n\nobj-$(CONFIG_ARCH_OR1K) += or1k/\n"
  },
  {
    "path": "arch/or1k/Makefile",
    "content": "#\n# Copyright © 2020-2022 The Crust Firmware Authors.\n# SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n#\n\nCROSS_COMPILE\t?= or1k-linux-musl-\nCFLAGS\t\t+= -ffixed-r2 \\\n\t\t   -msfimm -mshftimm -msoft-div -msoft-mul\n\n# The first object is used as the linker script.\nobj-y += scp.ld.o\n\nobj-y += counter.o\nobj-y += exception.o\nobj-y += math.o\nobj-y += runtime.o\nobj-y += start.o\n"
  },
  {
    "path": "arch/or1k/counter.c",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <counter.h>\n#include <spr.h>\n\nvoid\ncycle_counter_init(void)\n{\n\tmtspr(SPR_TICK_TTMR_ADDR,\n\t      SPR_TICK_TTMR_MODE_CONTINUE << SPR_TICK_TTMR_MODE_LSB);\n}\n\nuint32_t\ncycle_counter_read(void)\n{\n\treturn mfspr(SPR_TICK_TTCR_ADDR);\n}\n"
  },
  {
    "path": "arch/or1k/exception.c",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <debug.h>\n#include <exception.h>\n#include <spr.h>\n#include <steps.h>\n\nvoid\nreport_exception(uint32_t exception)\n{\n\tuint32_t pc;\n\n\tif (!exception)\n\t\treturn;\n\n\tpc = mfspr(SPR_SYS_EPCR_ADDR(0));\n\trecord_exception(exception, pc);\n\terror(\"Exception %u at %p!\", exception, (void *)pc);\n}\n"
  },
  {
    "path": "arch/or1k/include/asm/exception.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef ASM_EXCEPTION_H\n#define ASM_EXCEPTION_H\n\n#define RESET_EXCEPTION             0x01\n#define BUS_ERROR                   0x02\n#define DATA_PAGE_FAULT             0x03\n#define INSTRUCTION_PAGE_FAULT      0x04\n#define TICK_TIMER_EXCEPTION        0x05\n#define ALIGNMENT_EXCEPTION         0x06\n#define ILLEGAL_INSTRUCTION         0x07\n#define EXTERNAL_INTERRUPT          0x08\n#define DATA_TLB_MISS               0x09\n#define INSTRUCTION_TLB_MISS        0x0a\n#define RANGE_EXCEPTION             0x0b\n#define SYSTEM_CALL                 0x0c\n#define FLOATING_POINT_EXCEPTION    0x0d\n#define TRAP_EXCEPTION              0x0e\n\n#define EXCEPTION_VECTOR_ADDRESS(n) (0x100 * (n))\n\n#endif /* ASM_EXCEPTION_H */\n"
  },
  {
    "path": "arch/or1k/include/asm/spr.h",
    "content": "/*\n * Copyright © 2014 OpenRISC Project Maintainers. All rights reserved.\n * SPDX-License-Identifier: BSD-1-Clause\n */\n\n#ifndef ASM_SPR_H\n#define ASM_SPR_H\n\n#include <util.h>\n\n#define SPR_GROUP_BITS 5\n#define SPR_GROUP_LSB  11\n#define SPR_GROUP_MSB  15\n#define SPR_INDEX_BITS 11\n#define SPR_INDEX_LSB  0\n#define SPR_INDEX_MSB  10\n\n/****************/\n/* System Group */\n/****************/\n#define SPR_SYS_GROUP                    0x00\n\n/* Version Register */\n#define SPR_SYS_VR_INDEX                 U(0x000)\n#define SPR_SYS_VR_ADDR                  U(0x0000)\n\n/* Revision */\n#define SPR_SYS_VR_REV_LSB               0\n#define SPR_SYS_VR_REV_MSB               5\n#define SPR_SYS_VR_REV_BITS              6\n#define SPR_SYS_VR_REV_MASK              U(0x0000003f)\n#define SPR_SYS_VR_REV_GET(x)            (((x) >> 0) & U(0x0000003f))\n#define SPR_SYS_VR_REV_SET(x, y)         (((x) & U(0xffffffc0)) | \\\n\t                                  ((y) << 0))\n\n/* Updated Version Registers Present */\n#define SPR_SYS_VR_UVRP_OFFSET           6\n#define SPR_SYS_VR_UVRP_MASK             0x00000040\n#define SPR_SYS_VR_UVRP_GET(x)           (((x) >> 6) & 0x1)\n#define SPR_SYS_VR_UVRP_SET(x, y)        (((x) & U(0xffffffbf)) | \\\n\t                                  ((!!(y)) << 6))\n\n/* Configuration Template */\n#define SPR_SYS_VR_CFG_LSB               16\n#define SPR_SYS_VR_CFG_MSB               23\n#define SPR_SYS_VR_CFG_BITS              8\n#define SPR_SYS_VR_CFG_MASK              U(0x00ff0000)\n#define SPR_SYS_VR_CFG_GET(x)            (((x) >> 16) & U(0x000000ff))\n#define SPR_SYS_VR_CFG_SET(x, y)         (((x) & U(0xff00ffff)) | \\\n\t                                  ((y) << 16))\n\n/* Version */\n#define SPR_SYS_VR_VER_LSB               24\n#define SPR_SYS_VR_VER_MSB               31\n#define SPR_SYS_VR_VER_BITS              8\n#define SPR_SYS_VR_VER_MASK              U(0xff000000)\n#define SPR_SYS_VR_VER_GET(x)            (((x) >> 24) & U(0x000000ff))\n#define SPR_SYS_VR_VER_SET(x, y)         (((x) & U(0x00ffffff)) | \\\n\t                                  ((y) << 24))\n\n/* Unit Present Register */\n#define SPR_SYS_UPR_INDEX                U(0x001)\n#define SPR_SYS_UPR_ADDR                 U(0x0001)\n\n/* UPR Present */\n#define SPR_SYS_UPR_UP_OFFSET            0\n#define SPR_SYS_UPR_UP_MASK              0x00000001\n#define SPR_SYS_UPR_UP_GET(x)            (((x) >> 0) & 0x1)\n#define SPR_SYS_UPR_UP_SET(x, y)         (((x) & U(0xfffffffe)) | \\\n\t                                  ((!!(y)) << 0))\n\n/* Data Cache Present */\n#define SPR_SYS_UPR_DCP_OFFSET           1\n#define SPR_SYS_UPR_DCP_MASK             0x00000002\n#define SPR_SYS_UPR_DCP_GET(x)           (((x) >> 1) & 0x1)\n#define SPR_SYS_UPR_DCP_SET(x, y)        (((x) & U(0xfffffffd)) | \\\n\t                                  ((!!(y)) << 1))\n\n/* Instruction Cache Present */\n#define SPR_SYS_UPR_ICP_OFFSET           2\n#define SPR_SYS_UPR_ICP_MASK             0x00000004\n#define SPR_SYS_UPR_ICP_GET(x)           (((x) >> 2) & 0x1)\n#define SPR_SYS_UPR_ICP_SET(x, y)        (((x) & U(0xfffffffb)) | \\\n\t                                  ((!!(y)) << 2))\n\n/* Data MMU Present */\n#define SPR_SYS_UPR_DMP_OFFSET           3\n#define SPR_SYS_UPR_DMP_MASK             0x00000008\n#define SPR_SYS_UPR_DMP_GET(x)           (((x) >> 3) & 0x1)\n#define SPR_SYS_UPR_DMP_SET(x, y)        (((x) & U(0xfffffff7)) | \\\n\t                                  ((!!(y)) << 3))\n\n/* Instruction MMU Present */\n#define SPR_SYS_UPR_IMP_OFFSET           4\n#define SPR_SYS_UPR_IMP_MASK             0x00000010\n#define SPR_SYS_UPR_IMP_GET(x)           (((x) >> 4) & 0x1)\n#define SPR_SYS_UPR_IMP_SET(x, y)        (((x) & U(0xffffffef)) | \\\n\t                                  ((!!(y)) << 4))\n\n/* MAC Present */\n#define SPR_SYS_UPR_MP_OFFSET            5\n#define SPR_SYS_UPR_MP_MASK              0x00000020\n#define SPR_SYS_UPR_MP_GET(x)            (((x) >> 5) & 0x1)\n#define SPR_SYS_UPR_MP_SET(x, y)         (((x) & U(0xffffffdf)) | \\\n\t                                  ((!!(y)) << 5))\n\n/* Debug Unit Present */\n#define SPR_SYS_UPR_DUP_OFFSET           6\n#define SPR_SYS_UPR_DUP_MASK             0x00000040\n#define SPR_SYS_UPR_DUP_GET(x)           (((x) >> 6) & 0x1)\n#define SPR_SYS_UPR_DUP_SET(x, y)        (((x) & U(0xffffffbf)) | \\\n\t                                  ((!!(y)) << 6))\n\n/* Performance Counters Unit Present */\n#define SPR_SYS_UPR_PCUP_OFFSET          7\n#define SPR_SYS_UPR_PCUP_MASK            0x00000080\n#define SPR_SYS_UPR_PCUP_GET(x)          (((x) >> 7) & 0x1)\n#define SPR_SYS_UPR_PCUP_SET(x, y)       (((x) & U(0xffffff7f)) | \\\n\t                                  ((!!(y)) << 7))\n\n/* Power Management Present */\n#define SPR_SYS_UPR_PICP_OFFSET          8\n#define SPR_SYS_UPR_PICP_MASK            0x00000100\n#define SPR_SYS_UPR_PICP_GET(x)          (((x) >> 8) & 0x1)\n#define SPR_SYS_UPR_PICP_SET(x, y)       (((x) & U(0xfffffeff)) | \\\n\t                                  ((!!(y)) << 8))\n\n/* Programmable Interrupt Controller Present */\n#define SPR_SYS_UPR_PMP_OFFSET           9\n#define SPR_SYS_UPR_PMP_MASK             0x00000200\n#define SPR_SYS_UPR_PMP_GET(x)           (((x) >> 9) & 0x1)\n#define SPR_SYS_UPR_PMP_SET(x, y)        (((x) & U(0xfffffdff)) | \\\n\t                                  ((!!(y)) << 9))\n\n/* Tick Timer Present */\n#define SPR_SYS_UPR_TTP_OFFSET           10\n#define SPR_SYS_UPR_TTP_MASK             0x00000400\n#define SPR_SYS_UPR_TTP_GET(x)           (((x) >> 10) & 0x1)\n#define SPR_SYS_UPR_TTP_SET(x, y)        (((x) & U(0xfffffbff)) | \\\n\t                                  ((!!(y)) << 10))\n\n/* Custom Units Present */\n#define SPR_SYS_UPR_CUP_LSB              24\n#define SPR_SYS_UPR_CUP_MSB              31\n#define SPR_SYS_UPR_CUP_BITS             8\n#define SPR_SYS_UPR_CUP_MASK             U(0xff000000)\n#define SPR_SYS_UPR_CUP_GET(x)           (((x) >> 24) & U(0x000000ff))\n#define SPR_SYS_UPR_CUP_SET(x, y)        (((x) & U(0x00ffffff)) | \\\n\t                                  ((y) << 24))\n\n/* CPU Configuration Register */\n#define SPR_SYS_CPUCFGR_INDEX            U(0x002)\n#define SPR_SYS_CPUCFGR_ADDR             U(0x0002)\n\n/* Number of Shadow GPR Files */\n#define SPR_SYS_CPUCFGR_NSGF_LSB         0\n#define SPR_SYS_CPUCFGR_NSGF_MSB         3\n#define SPR_SYS_CPUCFGR_NSGF_BITS        4\n#define SPR_SYS_CPUCFGR_NSGF_MASK        U(0x0000000f)\n#define SPR_SYS_CPUCFGR_NSGF_GET(x)      (((x) >> 0) & U(0x0000000f))\n#define SPR_SYS_CPUCFGR_NSGF_SET(x, y)   (((x) & U(0xfffffff0)) | \\\n\t                                  ((y) << 0))\n\n/* Custom GPR File */\n#define SPR_SYS_CPUCFGR_CGF_OFFSET       4\n#define SPR_SYS_CPUCFGR_CGF_MASK         0x00000010\n#define SPR_SYS_CPUCFGR_CGF_GET(x)       (((x) >> 4) & 0x1)\n#define SPR_SYS_CPUCFGR_CGF_SET(x, y)    (((x) & U(0xffffffef)) | \\\n\t                                  ((!!(y)) << 4))\n\n/* ORBIS32 Supported */\n#define SPR_SYS_CPUCFGR_OB32S_OFFSET     5\n#define SPR_SYS_CPUCFGR_OB32S_MASK       0x00000020\n#define SPR_SYS_CPUCFGR_OB32S_GET(x)     (((x) >> 5) & 0x1)\n#define SPR_SYS_CPUCFGR_OB32S_SET(x, y)  (((x) & U(0xffffffdf)) | \\\n\t                                  ((!!(y)) << 5))\n\n/* ORBIS64 Supported */\n#define SPR_SYS_CPUCFGR_OB64S_OFFSET     6\n#define SPR_SYS_CPUCFGR_OB64S_MASK       0x00000040\n#define SPR_SYS_CPUCFGR_OB64S_GET(x)     (((x) >> 6) & 0x1)\n#define SPR_SYS_CPUCFGR_OB64S_SET(x, y)  (((x) & U(0xffffffbf)) | \\\n\t                                  ((!!(y)) << 6))\n\n/* ORFPX32 Supported */\n#define SPR_SYS_CPUCFGR_OF32S_OFFSET     7\n#define SPR_SYS_CPUCFGR_OF32S_MASK       0x00000080\n#define SPR_SYS_CPUCFGR_OF32S_GET(x)     (((x) >> 7) & 0x1)\n#define SPR_SYS_CPUCFGR_OF32S_SET(x, y)  (((x) & U(0xffffff7f)) | \\\n\t                                  ((!!(y)) << 7))\n\n/* ORFPX64 Supported */\n#define SPR_SYS_CPUCFGR_OF64S_OFFSET     8\n#define SPR_SYS_CPUCFGR_OF64S_MASK       0x00000100\n#define SPR_SYS_CPUCFGR_OF64S_GET(x)     (((x) >> 8) & 0x1)\n#define SPR_SYS_CPUCFGR_OF64S_SET(x, y)  (((x) & U(0xfffffeff)) | \\\n\t                                  ((!!(y)) << 8))\n\n/* ORVDX64 Supported */\n#define SPR_SYS_CPUCFGR_OV64S_OFFSET     9\n#define SPR_SYS_CPUCFGR_OV64S_MASK       0x00000200\n#define SPR_SYS_CPUCFGR_OV64S_GET(x)     (((x) >> 9) & 0x1)\n#define SPR_SYS_CPUCFGR_OV64S_SET(x, y)  (((x) & U(0xfffffdff)) | \\\n\t                                  ((!!(y)) << 9))\n\n/* No Delay-Slot */\n#define SPR_SYS_CPUCFGR_ND_OFFSET        10\n#define SPR_SYS_CPUCFGR_ND_MASK          0x00000400\n#define SPR_SYS_CPUCFGR_ND_GET(x)        (((x) >> 10) & 0x1)\n#define SPR_SYS_CPUCFGR_ND_SET(x, y)     (((x) & U(0xfffffbff)) | \\\n\t                                  ((!!(y)) << 10))\n\n/* Architecture Version Register Present */\n#define SPR_SYS_CPUCFGR_AVRP_OFFSET      11\n#define SPR_SYS_CPUCFGR_AVRP_MASK        0x00000800\n#define SPR_SYS_CPUCFGR_AVRP_GET(x)      (((x) >> 11) & 0x1)\n#define SPR_SYS_CPUCFGR_AVRP_SET(x, y)   (((x) & U(0xfffff7ff)) | \\\n\t                                  ((!!(y)) << 11))\n\n/* Exception Vector Base Address Register Present */\n#define SPR_SYS_CPUCFGR_EVBARP_OFFSET    12\n#define SPR_SYS_CPUCFGR_EVBARP_MASK      0x00001000\n#define SPR_SYS_CPUCFGR_EVBARP_GET(x)    (((x) >> 12) & 0x1)\n#define SPR_SYS_CPUCFGR_EVBARP_SET(x, y) (((x) & U(0xffffefff)) | \\\n\t                                  ((!!(y)) << 12))\n\n/* Implementation-Specific Registers (ISR0-7) Present */\n#define SPR_SYS_CPUCFGR_ISRP_OFFSET      13\n#define SPR_SYS_CPUCFGR_ISRP_MASK        0x00002000\n#define SPR_SYS_CPUCFGR_ISRP_GET(x)      (((x) >> 13) & 0x1)\n#define SPR_SYS_CPUCFGR_ISRP_SET(x, y)   (((x) & U(0xffffdfff)) | \\\n\t                                  ((!!(y)) << 13))\n\n/* Arithmetic Exception Control/Status Registers Present */\n#define SPR_SYS_CPUCFGR_AECSRP_OFFSET    14\n#define SPR_SYS_CPUCFGR_AECSRP_MASK      0x00004000\n#define SPR_SYS_CPUCFGR_AECSRP_GET(x)    (((x) >> 14) & 0x1)\n#define SPR_SYS_CPUCFGR_AECSRP_SET(x, y) (((x) & U(0xffffbfff)) | \\\n\t                                  ((!!(y)) << 14))\n\n/* Data MMU Configuration Register */\n#define SPR_SYS_DMMUCFGR_INDEX           U(0x003)\n#define SPR_SYS_DMMUCFGR_ADDR            U(0x0003)\n\n/* Number of TLB Ways */\n#define SPR_SYS_DMMUCFGR_NTW_LSB         0\n#define SPR_SYS_DMMUCFGR_NTW_MSB         1\n#define SPR_SYS_DMMUCFGR_NTW_BITS        2\n#define SPR_SYS_DMMUCFGR_NTW_MASK        U(0x00000003)\n#define SPR_SYS_DMMUCFGR_NTW_GET(x)      (((x) >> 0) & U(0x00000003))\n#define SPR_SYS_DMMUCFGR_NTW_SET(x, y)   (((x) & U(0xfffffffc)) | \\\n\t                                  ((y) << 0))\n\n/* Number of TLB Sets */\n#define SPR_SYS_DMMUCFGR_NTS_LSB         2\n#define SPR_SYS_DMMUCFGR_NTS_MSB         4\n#define SPR_SYS_DMMUCFGR_NTS_BITS        3\n#define SPR_SYS_DMMUCFGR_NTS_MASK        U(0x0000001c)\n#define SPR_SYS_DMMUCFGR_NTS_GET(x)      (((x) >> 2) & U(0x00000007))\n#define SPR_SYS_DMMUCFGR_NTS_SET(x, y)   (((x) & U(0xffffffe3)) | \\\n\t                                  ((y) << 2))\n\n/* Number of ATB Entries */\n#define SPR_SYS_DMMUCFGR_NAE_LSB         5\n#define SPR_SYS_DMMUCFGR_NAE_MSB         7\n#define SPR_SYS_DMMUCFGR_NAE_BITS        3\n#define SPR_SYS_DMMUCFGR_NAE_MASK        U(0x000000e0)\n#define SPR_SYS_DMMUCFGR_NAE_GET(x)      (((x) >> 5) & U(0x00000007))\n#define SPR_SYS_DMMUCFGR_NAE_SET(x, y)   (((x) & U(0xffffff1f)) | \\\n\t                                  ((y) << 5))\n\n/* Control Register Implemented */\n#define SPR_SYS_DMMUCFGR_CRI_OFFSET      8\n#define SPR_SYS_DMMUCFGR_CRI_MASK        0x00000100\n#define SPR_SYS_DMMUCFGR_CRI_GET(x)      (((x) >> 8) & 0x1)\n#define SPR_SYS_DMMUCFGR_CRI_SET(x, y)   (((x) & U(0xfffffeff)) | \\\n\t                                  ((!!(y)) << 8))\n\n/* Protection Register Implemented */\n#define SPR_SYS_DMMUCFGR_PRI_OFFSET      9\n#define SPR_SYS_DMMUCFGR_PRI_MASK        0x00000200\n#define SPR_SYS_DMMUCFGR_PRI_GET(x)      (((x) >> 9) & 0x1)\n#define SPR_SYS_DMMUCFGR_PRI_SET(x, y)   (((x) & U(0xfffffdff)) | \\\n\t                                  ((!!(y)) << 9))\n\n/* TLB Entry Invalidate Register Implemented */\n#define SPR_SYS_DMMUCFGR_TEIRI_OFFSET    10\n#define SPR_SYS_DMMUCFGR_TEIRI_MASK      0x00000400\n#define SPR_SYS_DMMUCFGR_TEIRI_GET(x)    (((x) >> 10) & 0x1)\n#define SPR_SYS_DMMUCFGR_TEIRI_SET(x, y) (((x) & U(0xfffffbff)) | \\\n\t                                  ((!!(y)) << 10))\n\n/* Hardware TLB Reload */\n#define SPR_SYS_DMMUCFGR_HTR_OFFSET      11\n#define SPR_SYS_DMMUCFGR_HTR_MASK        0x00000800\n#define SPR_SYS_DMMUCFGR_HTR_GET(x)      (((x) >> 11) & 0x1)\n#define SPR_SYS_DMMUCFGR_HTR_SET(x, y)   (((x) & U(0xfffff7ff)) | \\\n\t                                  ((!!(y)) << 11))\n\n/* DTLB reloaded in software */\n#define SPR_SYS_DMMUCFGR_HTR_SW          0\n/* DTLB reloaded in hardware */\n#define SPR_SYS_DMMUCFGR_HTR_HW          1\n\n/* Instruction MMU Configuration Register */\n#define SPR_SYS_IMMUCFGR_INDEX           U(0x004)\n#define SPR_SYS_IMMUCFGR_ADDR            U(0x0004)\n\n/* Number of TLB Ways */\n#define SPR_SYS_IMMUCFGR_NTW_LSB         0\n#define SPR_SYS_IMMUCFGR_NTW_MSB         1\n#define SPR_SYS_IMMUCFGR_NTW_BITS        2\n#define SPR_SYS_IMMUCFGR_NTW_MASK        U(0x00000003)\n#define SPR_SYS_IMMUCFGR_NTW_GET(x)      (((x) >> 0) & U(0x00000003))\n#define SPR_SYS_IMMUCFGR_NTW_SET(x, y)   (((x) & U(0xfffffffc)) | \\\n\t                                  ((y) << 0))\n\n/* Number of TLB Sets */\n#define SPR_SYS_IMMUCFGR_NTS_LSB         2\n#define SPR_SYS_IMMUCFGR_NTS_MSB         4\n#define SPR_SYS_IMMUCFGR_NTS_BITS        3\n#define SPR_SYS_IMMUCFGR_NTS_MASK        U(0x0000001c)\n#define SPR_SYS_IMMUCFGR_NTS_GET(x)      (((x) >> 2) & U(0x00000007))\n#define SPR_SYS_IMMUCFGR_NTS_SET(x, y)   (((x) & U(0xffffffe3)) | \\\n\t                                  ((y) << 2))\n\n/* Number of ATB Entries */\n#define SPR_SYS_IMMUCFGR_NAE_LSB         5\n#define SPR_SYS_IMMUCFGR_NAE_MSB         7\n#define SPR_SYS_IMMUCFGR_NAE_BITS        3\n#define SPR_SYS_IMMUCFGR_NAE_MASK        U(0x000000e0)\n#define SPR_SYS_IMMUCFGR_NAE_GET(x)      (((x) >> 5) & U(0x00000007))\n#define SPR_SYS_IMMUCFGR_NAE_SET(x, y)   (((x) & U(0xffffff1f)) | \\\n\t                                  ((y) << 5))\n\n/* Control Register Implemented */\n#define SPR_SYS_IMMUCFGR_CRI_OFFSET      8\n#define SPR_SYS_IMMUCFGR_CRI_MASK        0x00000100\n#define SPR_SYS_IMMUCFGR_CRI_GET(x)      (((x) >> 8) & 0x1)\n#define SPR_SYS_IMMUCFGR_CRI_SET(x, y)   (((x) & U(0xfffffeff)) | \\\n\t                                  ((!!(y)) << 8))\n\n/* Protection Register Implemented */\n#define SPR_SYS_IMMUCFGR_PRI_OFFSET      9\n#define SPR_SYS_IMMUCFGR_PRI_MASK        0x00000200\n#define SPR_SYS_IMMUCFGR_PRI_GET(x)      (((x) >> 9) & 0x1)\n#define SPR_SYS_IMMUCFGR_PRI_SET(x, y)   (((x) & U(0xfffffdff)) | \\\n\t                                  ((!!(y)) << 9))\n\n/* TLB Entry Invalidate Register Implemented */\n#define SPR_SYS_IMMUCFGR_TEIRI_OFFSET    10\n#define SPR_SYS_IMMUCFGR_TEIRI_MASK      0x00000400\n#define SPR_SYS_IMMUCFGR_TEIRI_GET(x)    (((x) >> 10) & 0x1)\n#define SPR_SYS_IMMUCFGR_TEIRI_SET(x, y) (((x) & U(0xfffffbff)) | \\\n\t                                  ((!!(y)) << 10))\n\n/* Hardware TLB Reload */\n#define SPR_SYS_IMMUCFGR_HTR_OFFSET      11\n#define SPR_SYS_IMMUCFGR_HTR_MASK        0x00000800\n#define SPR_SYS_IMMUCFGR_HTR_GET(x)      (((x) >> 11) & 0x1)\n#define SPR_SYS_IMMUCFGR_HTR_SET(x, y)   (((x) & U(0xfffff7ff)) | \\\n\t                                  ((!!(y)) << 11))\n\n/* DTLB reloaded in software */\n#define SPR_SYS_IMMUCFGR_HTR_SW          0\n/* DTLB reloaded in hardware */\n#define SPR_SYS_IMMUCFGR_HTR_HW          1\n\n/* Data Cache Configuration Register */\n#define SPR_SYS_DCCFGR_INDEX             U(0x005)\n#define SPR_SYS_DCCFGR_ADDR              U(0x0005)\n\n/* Number of Cache Ways */\n#define SPR_SYS_DCCFGR_NCW_LSB           0\n#define SPR_SYS_DCCFGR_NCW_MSB           2\n#define SPR_SYS_DCCFGR_NCW_BITS          3\n#define SPR_SYS_DCCFGR_NCW_MASK          U(0x00000007)\n#define SPR_SYS_DCCFGR_NCW_GET(x)        (((x) >> 0) & U(0x00000007))\n#define SPR_SYS_DCCFGR_NCW_SET(x, y)     (((x) & U(0xfffffff8)) | \\\n\t                                  ((y) << 0))\n\n/* Number of Cache Sets */\n#define SPR_SYS_DCCFGR_NCS_LSB           3\n#define SPR_SYS_DCCFGR_NCS_MSB           6\n#define SPR_SYS_DCCFGR_NCS_BITS          4\n#define SPR_SYS_DCCFGR_NCS_MASK          U(0x00000078)\n#define SPR_SYS_DCCFGR_NCS_GET(x)        (((x) >> 3) & U(0x0000000f))\n#define SPR_SYS_DCCFGR_NCS_SET(x, y)     (((x) & U(0xffffff87)) | \\\n\t                                  ((y) << 3))\n\n/* Cache Block Size */\n#define SPR_SYS_DCCFGR_CBS_OFFSET        7\n#define SPR_SYS_DCCFGR_CBS_MASK          0x00000080\n#define SPR_SYS_DCCFGR_CBS_GET(x)        (((x) >> 7) & 0x1)\n#define SPR_SYS_DCCFGR_CBS_SET(x, y)     (((x) & U(0xffffff7f)) | \\\n\t                                  ((!!(y)) << 7))\n\n/* 16 Bytes */\n#define SPR_SYS_DCCFGR_CBS_16            0\n/* 32 Bytes */\n#define SPR_SYS_DCCFGR_CBS_32            1\n\n/* Cache Write Strategy */\n#define SPR_SYS_DCCFGR_CWS_OFFSET        8\n#define SPR_SYS_DCCFGR_CWS_MASK          0x00000100\n#define SPR_SYS_DCCFGR_CWS_GET(x)        (((x) >> 8) & 0x1)\n#define SPR_SYS_DCCFGR_CWS_SET(x, y)     (((x) & U(0xfffffeff)) | \\\n\t                                  ((!!(y)) << 8))\n\n/* Write Through */\n#define SPR_SYS_DCCFGR_CWS_WT            0\n/* Write Back */\n#define SPR_SYS_DCCFGR_CWS_WB            1\n\n/* Cache Control Register Implemented */\n#define SPR_SYS_DCCFGR_CCRI_OFFSET       9\n#define SPR_SYS_DCCFGR_CCRI_MASK         0x00000200\n#define SPR_SYS_DCCFGR_CCRI_GET(x)       (((x) >> 9) & 0x1)\n#define SPR_SYS_DCCFGR_CCRI_SET(x, y)    (((x) & U(0xfffffdff)) | \\\n\t                                  ((!!(y)) << 9))\n\n/* Cache Block Invalidate Register Implemented */\n#define SPR_SYS_DCCFGR_CBIRI_OFFSET      10\n#define SPR_SYS_DCCFGR_CBIRI_MASK        0x00000400\n#define SPR_SYS_DCCFGR_CBIRI_GET(x)      (((x) >> 10) & 0x1)\n#define SPR_SYS_DCCFGR_CBIRI_SET(x, y)   (((x) & U(0xfffffbff)) | \\\n\t                                  ((!!(y)) << 10))\n\n/* Cache Block Prefetch Register Implemented */\n#define SPR_SYS_DCCFGR_CBPRI_OFFSET      11\n#define SPR_SYS_DCCFGR_CBPRI_MASK        0x00000800\n#define SPR_SYS_DCCFGR_CBPRI_GET(x)      (((x) >> 11) & 0x1)\n#define SPR_SYS_DCCFGR_CBPRI_SET(x, y)   (((x) & U(0xfffff7ff)) | \\\n\t                                  ((!!(y)) << 11))\n\n/* Cache Block Lock Register Implemented */\n#define SPR_SYS_DCCFGR_CBLRI_OFFSET      12\n#define SPR_SYS_DCCFGR_CBLRI_MASK        0x00001000\n#define SPR_SYS_DCCFGR_CBLRI_GET(x)      (((x) >> 12) & 0x1)\n#define SPR_SYS_DCCFGR_CBLRI_SET(x, y)   (((x) & U(0xffffefff)) | \\\n\t                                  ((!!(y)) << 12))\n\n/* Cache Block Flush Register Implemented */\n#define SPR_SYS_DCCFGR_CBFRI_OFFSET      13\n#define SPR_SYS_DCCFGR_CBFRI_MASK        0x00002000\n#define SPR_SYS_DCCFGR_CBFRI_GET(x)      (((x) >> 13) & 0x1)\n#define SPR_SYS_DCCFGR_CBFRI_SET(x, y)   (((x) & U(0xffffdfff)) | \\\n\t                                  ((!!(y)) << 13))\n\n/* Cache Block Write-back Register Implemented */\n#define SPR_SYS_DCCFGR_CBWBRI_OFFSET     14\n#define SPR_SYS_DCCFGR_CBWBRI_MASK       0x00004000\n#define SPR_SYS_DCCFGR_CBWBRI_GET(x)     (((x) >> 14) & 0x1)\n#define SPR_SYS_DCCFGR_CBWBRI_SET(x, y)  (((x) & U(0xffffbfff)) | \\\n\t                                  ((!!(y)) << 14))\n\n/* Instruction Cache Configuration Register */\n#define SPR_SYS_ICCFGR_INDEX             U(0x006)\n#define SPR_SYS_ICCFGR_ADDR              U(0x0006)\n\n/* Number of Cache Ways */\n#define SPR_SYS_ICCFGR_NCW_LSB           0\n#define SPR_SYS_ICCFGR_NCW_MSB           2\n#define SPR_SYS_ICCFGR_NCW_BITS          3\n#define SPR_SYS_ICCFGR_NCW_MASK          U(0x00000007)\n#define SPR_SYS_ICCFGR_NCW_GET(x)        (((x) >> 0) & U(0x00000007))\n#define SPR_SYS_ICCFGR_NCW_SET(x, y)     (((x) & U(0xfffffff8)) | \\\n\t                                  ((y) << 0))\n\n/* Number of Cache Sets */\n#define SPR_SYS_ICCFGR_NCS_LSB           3\n#define SPR_SYS_ICCFGR_NCS_MSB           6\n#define SPR_SYS_ICCFGR_NCS_BITS          4\n#define SPR_SYS_ICCFGR_NCS_MASK          U(0x00000078)\n#define SPR_SYS_ICCFGR_NCS_GET(x)        (((x) >> 3) & U(0x0000000f))\n#define SPR_SYS_ICCFGR_NCS_SET(x, y)     (((x) & U(0xffffff87)) | \\\n\t                                  ((y) << 3))\n\n/* Cache Block Size */\n#define SPR_SYS_ICCFGR_CBS_OFFSET        7\n#define SPR_SYS_ICCFGR_CBS_MASK          0x00000080\n#define SPR_SYS_ICCFGR_CBS_GET(x)        (((x) >> 7) & 0x1)\n#define SPR_SYS_ICCFGR_CBS_SET(x, y)     (((x) & U(0xffffff7f)) | \\\n\t                                  ((!!(y)) << 7))\n\n/* 16 Bytes */\n#define SPR_SYS_ICCFGR_CBS_16            0\n/* 32 Bytes */\n#define SPR_SYS_ICCFGR_CBS_32            1\n\n/* Cache Control Register Implemented */\n#define SPR_SYS_ICCFGR_CCRI_OFFSET       9\n#define SPR_SYS_ICCFGR_CCRI_MASK         0x00000200\n#define SPR_SYS_ICCFGR_CCRI_GET(x)       (((x) >> 9) & 0x1)\n#define SPR_SYS_ICCFGR_CCRI_SET(x, y)    (((x) & U(0xfffffdff)) | \\\n\t                                  ((!!(y)) << 9))\n\n/* Cache Block Invalidate Register Implemented */\n#define SPR_SYS_ICCFGR_CBIRI_OFFSET      10\n#define SPR_SYS_ICCFGR_CBIRI_MASK        0x00000400\n#define SPR_SYS_ICCFGR_CBIRI_GET(x)      (((x) >> 10) & 0x1)\n#define SPR_SYS_ICCFGR_CBIRI_SET(x, y)   (((x) & U(0xfffffbff)) | \\\n\t                                  ((!!(y)) << 10))\n\n/* Cache Block Prefetch Register Implemented */\n#define SPR_SYS_ICCFGR_CBPRI_OFFSET      11\n#define SPR_SYS_ICCFGR_CBPRI_MASK        0x00000800\n#define SPR_SYS_ICCFGR_CBPRI_GET(x)      (((x) >> 11) & 0x1)\n#define SPR_SYS_ICCFGR_CBPRI_SET(x, y)   (((x) & U(0xfffff7ff)) | \\\n\t                                  ((!!(y)) << 11))\n\n/* Cache Block Lock Register Implemented */\n#define SPR_SYS_ICCFGR_CBLRI_OFFSET      12\n#define SPR_SYS_ICCFGR_CBLRI_MASK        0x00001000\n#define SPR_SYS_ICCFGR_CBLRI_GET(x)      (((x) >> 12) & 0x1)\n#define SPR_SYS_ICCFGR_CBLRI_SET(x, y)   (((x) & U(0xffffefff)) | \\\n\t                                  ((!!(y)) << 12))\n\n/* Debug Configuration Register */\n#define SPR_SYS_DCFGR_INDEX              U(0x007)\n#define SPR_SYS_DCFGR_ADDR               U(0x0007)\n\n/* Number of Debug Pairs */\n#define SPR_SYS_DCFGR_NDP_LSB            0\n#define SPR_SYS_DCFGR_NDP_MSB            2\n#define SPR_SYS_DCFGR_NDP_BITS           3\n#define SPR_SYS_DCFGR_NDP_MASK           U(0x00000007)\n#define SPR_SYS_DCFGR_NDP_GET(x)         (((x) >> 0) & U(0x00000007))\n#define SPR_SYS_DCFGR_NDP_SET(x, y)      (((x) & U(0xfffffff8)) | \\\n\t                                  ((y) << 0))\n\n/* Watchpoint Counters Implemented */\n#define SPR_SYS_DCFGR_WPCI_OFFSET        3\n#define SPR_SYS_DCFGR_WPCI_MASK          0x00000008\n#define SPR_SYS_DCFGR_WPCI_GET(x)        (((x) >> 3) & 0x1)\n#define SPR_SYS_DCFGR_WPCI_SET(x, y)     (((x) & U(0xfffffff7)) | \\\n\t                                  ((!!(y)) << 3))\n\n/* Performance Counters Configuration */\n#define SPR_SYS_PCCFGR_INDEX             U(0x008)\n#define SPR_SYS_PCCFGR_ADDR              U(0x0008)\n\n/* Number of Performance Counters */\n#define SPR_SYS_PCCFGR_NPC_LSB           0\n#define SPR_SYS_PCCFGR_NPC_MSB           2\n#define SPR_SYS_PCCFGR_NPC_BITS          3\n#define SPR_SYS_PCCFGR_NPC_MASK          U(0x00000007)\n#define SPR_SYS_PCCFGR_NPC_GET(x)        (((x) >> 0) & U(0x00000007))\n#define SPR_SYS_PCCFGR_NPC_SET(x, y)     (((x) & U(0xfffffff8)) | \\\n\t                                  ((y) << 0))\n\n/* Version Register 2 */\n#define SPR_SYS_VR2_INDEX                U(0x009)\n#define SPR_SYS_VR2_ADDR                 U(0x0009)\n\n/* Version */\n#define SPR_SYS_VR2_VER_LSB              0\n#define SPR_SYS_VR2_VER_MSB              23\n#define SPR_SYS_VR2_VER_BITS             24\n#define SPR_SYS_VR2_VER_MASK             U(0x00ffffff)\n#define SPR_SYS_VR2_VER_GET(x)           (((x) >> 0) & U(0x00ffffff))\n#define SPR_SYS_VR2_VER_SET(x, y)        (((x) & U(0xff000000)) | \\\n\t                                  ((y) << 0))\n\n/* CPU Identification Number */\n#define SPR_SYS_VR2_CPUID_LSB            24\n#define SPR_SYS_VR2_CPUID_MSB            31\n#define SPR_SYS_VR2_CPUID_BITS           8\n#define SPR_SYS_VR2_CPUID_MASK           U(0xff000000)\n#define SPR_SYS_VR2_CPUID_GET(x)         (((x) >> 24) & U(0x000000ff))\n#define SPR_SYS_VR2_CPUID_SET(x, y)      (((x) & U(0x00ffffff)) | \\\n\t                                  ((y) << 24))\n\n/* Architecture Version Register */\n#define SPR_SYS_AVR_INDEX                U(0x00a)\n#define SPR_SYS_AVR_ADDR                 U(0x000a)\n\n/* Major Architecture Version Number */\n#define SPR_SYS_AVR_REV_LSB              8\n#define SPR_SYS_AVR_REV_MSB              15\n#define SPR_SYS_AVR_REV_BITS             8\n#define SPR_SYS_AVR_REV_MASK             U(0x0000ff00)\n#define SPR_SYS_AVR_REV_GET(x)           (((x) >> 8) & U(0x000000ff))\n#define SPR_SYS_AVR_REV_SET(x, y)        (((x) & U(0xffff00ff)) | \\\n\t                                  ((y) << 8))\n\n/* Minor Architecture Version Number */\n#define SPR_SYS_AVR_MIN_LSB              16\n#define SPR_SYS_AVR_MIN_MSB              23\n#define SPR_SYS_AVR_MIN_BITS             8\n#define SPR_SYS_AVR_MIN_MASK             U(0x00ff0000)\n#define SPR_SYS_AVR_MIN_GET(x)           (((x) >> 16) & U(0x000000ff))\n#define SPR_SYS_AVR_MIN_SET(x, y)        (((x) & U(0xff00ffff)) | \\\n\t                                  ((y) << 16))\n\n/* Architecture Revision Number */\n#define SPR_SYS_AVR_MAJ_LSB              24\n#define SPR_SYS_AVR_MAJ_MSB              31\n#define SPR_SYS_AVR_MAJ_BITS             8\n#define SPR_SYS_AVR_MAJ_MASK             U(0xff000000)\n#define SPR_SYS_AVR_MAJ_GET(x)           (((x) >> 24) & U(0x000000ff))\n#define SPR_SYS_AVR_MAJ_SET(x, y)        (((x) & U(0x00ffffff)) | \\\n\t                                  ((y) << 24))\n\n/* Exception Vector Base Address Register */\n#define SPR_SYS_EVBAR_INDEX              U(0x00b)\n#define SPR_SYS_EVBAR_ADDR               U(0x000b)\n\n/* Exception Vector Base Address */\n#define SPR_SYS_EVBAR_EVBA_LSB           13\n#define SPR_SYS_EVBAR_EVBA_MSB           31\n#define SPR_SYS_EVBAR_EVBA_BITS          19\n#define SPR_SYS_EVBAR_EVBA_MASK          U(0xffffe000)\n#define SPR_SYS_EVBAR_EVBA_GET(x)        (((x) >> 13) & U(0x0007ffff))\n#define SPR_SYS_EVBAR_EVBA_SET(x, y)     (((x) & U(0x00001fff)) | \\\n\t                                  ((y) << 13))\n\n/* Arithmetic Exception Control Register */\n#define SPR_SYS_AECR_INDEX               U(0x00c)\n#define SPR_SYS_AECR_ADDR                U(0x000c)\n\n/* Carry on Add Exception Enabled */\n#define SPR_SYS_AECR_CYADDE_OFFSET       0\n#define SPR_SYS_AECR_CYADDE_MASK         0x00000001\n#define SPR_SYS_AECR_CYADDE_GET(x)       (((x) >> 0) & 0x1)\n#define SPR_SYS_AECR_CYADDE_SET(x, y)    (((x) & U(0xfffffffe)) | \\\n\t                                  ((!!(y)) << 0))\n\n/* Overflow on Add Exception Enabled */\n#define SPR_SYS_AECR_OVADDE_OFFSET       1\n#define SPR_SYS_AECR_OVADDE_MASK         0x00000002\n#define SPR_SYS_AECR_OVADDE_GET(x)       (((x) >> 1) & 0x1)\n#define SPR_SYS_AECR_OVADDE_SET(x, y)    (((x) & U(0xfffffffd)) | \\\n\t                                  ((!!(y)) << 1))\n\n/* Carry on Multiply Exception Enabled */\n#define SPR_SYS_AECR_CYMULE_OFFSET       2\n#define SPR_SYS_AECR_CYMULE_MASK         0x00000004\n#define SPR_SYS_AECR_CYMULE_GET(x)       (((x) >> 2) & 0x1)\n#define SPR_SYS_AECR_CYMULE_SET(x, y)    (((x) & U(0xfffffffb)) | \\\n\t                                  ((!!(y)) << 2))\n\n/* Overflow on Multiply Exception Enabled */\n#define SPR_SYS_AECR_OVMULE_OFFSET       3\n#define SPR_SYS_AECR_OVMULE_MASK         0x00000008\n#define SPR_SYS_AECR_OVMULE_GET(x)       (((x) >> 3) & 0x1)\n#define SPR_SYS_AECR_OVMULE_SET(x, y)    (((x) & U(0xfffffff7)) | \\\n\t                                  ((!!(y)) << 3))\n\n/* Divide by Zero Exception Enabled */\n#define SPR_SYS_AECR_DBZE_OFFSET         4\n#define SPR_SYS_AECR_DBZE_MASK           0x00000010\n#define SPR_SYS_AECR_DBZE_GET(x)         (((x) >> 4) & 0x1)\n#define SPR_SYS_AECR_DBZE_SET(x, y)      (((x) & U(0xffffffef)) | \\\n\t                                  ((!!(y)) << 4))\n\n/* Carry on MAC Addition Exception Enabled */\n#define SPR_SYS_AECR_CYMACADDE_OFFSET    5\n#define SPR_SYS_AECR_CYMACADDE_MASK      0x00000020\n#define SPR_SYS_AECR_CYMACADDE_GET(x)    (((x) >> 5) & 0x1)\n#define SPR_SYS_AECR_CYMACADDE_SET(x, y) (((x) & U(0xffffffdf)) | \\\n\t                                  ((!!(y)) << 5))\n\n/* Overflow on MAC Addition Exception Enabled */\n#define SPR_SYS_AECR_OVMACADDE_OFFSET    6\n#define SPR_SYS_AECR_OVMACADDE_MASK      0x00000040\n#define SPR_SYS_AECR_OVMACADDE_GET(x)    (((x) >> 6) & 0x1)\n#define SPR_SYS_AECR_OVMACADDE_SET(x, y) (((x) & U(0xffffffbf)) | \\\n\t                                  ((!!(y)) << 6))\n\n/* Arithmetic Exception Status Register */\n#define SPR_SYS_AESR_INDEX               U(0x00d)\n#define SPR_SYS_AESR_ADDR                U(0x000d)\n\n/* Carry on Add Exception */\n#define SPR_SYS_AESR_CYADDE_OFFSET       0\n#define SPR_SYS_AESR_CYADDE_MASK         0x00000001\n#define SPR_SYS_AESR_CYADDE_GET(x)       (((x) >> 0) & 0x1)\n#define SPR_SYS_AESR_CYADDE_SET(x, y)    (((x) & U(0xfffffffe)) | \\\n\t                                  ((!!(y)) << 0))\n\n/* Overflow on Add Exception */\n#define SPR_SYS_AESR_OVADDE_OFFSET       1\n#define SPR_SYS_AESR_OVADDE_MASK         0x00000002\n#define SPR_SYS_AESR_OVADDE_GET(x)       (((x) >> 1) & 0x1)\n#define SPR_SYS_AESR_OVADDE_SET(x, y)    (((x) & U(0xfffffffd)) | \\\n\t                                  ((!!(y)) << 1))\n\n/* Carry on Multiply Exception */\n#define SPR_SYS_AESR_CYMULE_OFFSET       2\n#define SPR_SYS_AESR_CYMULE_MASK         0x00000004\n#define SPR_SYS_AESR_CYMULE_GET(x)       (((x) >> 2) & 0x1)\n#define SPR_SYS_AESR_CYMULE_SET(x, y)    (((x) & U(0xfffffffb)) | \\\n\t                                  ((!!(y)) << 2))\n\n/* Overflow on Multiply Exception */\n#define SPR_SYS_AESR_OVMULE_OFFSET       3\n#define SPR_SYS_AESR_OVMULE_MASK         0x00000008\n#define SPR_SYS_AESR_OVMULE_GET(x)       (((x) >> 3) & 0x1)\n#define SPR_SYS_AESR_OVMULE_SET(x, y)    (((x) & U(0xfffffff7)) | \\\n\t                                  ((!!(y)) << 3))\n\n/* Divide by Zero Exception */\n#define SPR_SYS_AESR_DBZE_OFFSET         4\n#define SPR_SYS_AESR_DBZE_MASK           0x00000010\n#define SPR_SYS_AESR_DBZE_GET(x)         (((x) >> 4) & 0x1)\n#define SPR_SYS_AESR_DBZE_SET(x, y)      (((x) & U(0xffffffef)) | \\\n\t                                  ((!!(y)) << 4))\n\n/* Carry on MAC Addition Exception */\n#define SPR_SYS_AESR_CYMACADDE_OFFSET    5\n#define SPR_SYS_AESR_CYMACADDE_MASK      0x00000020\n#define SPR_SYS_AESR_CYMACADDE_GET(x)    (((x) >> 5) & 0x1)\n#define SPR_SYS_AESR_CYMACADDE_SET(x, y) (((x) & U(0xffffffdf)) | \\\n\t                                  ((!!(y)) << 5))\n\n/* Overflow on MAC Addition Exception */\n#define SPR_SYS_AESR_OVMACADDE_OFFSET    6\n#define SPR_SYS_AESR_OVMACADDE_MASK      0x00000040\n#define SPR_SYS_AESR_OVMACADDE_GET(x)    (((x) >> 6) & 0x1)\n#define SPR_SYS_AESR_OVMACADDE_SET(x, y) (((x) & U(0xffffffbf)) | \\\n\t                                  ((!!(y)) << 6))\n\n/* Next Program Counter */\n#define SPR_SYS_NPC_INDEX                U(0x010)\n#define SPR_SYS_NPC_ADDR                 U(0x0010)\n\n/* Supervision Register */\n#define SPR_SYS_SR_INDEX                 U(0x011)\n#define SPR_SYS_SR_ADDR                  U(0x0011)\n\n/* Supervisor Mode */\n#define SPR_SYS_SR_SM_OFFSET             0\n#define SPR_SYS_SR_SM_MASK               0x00000001\n#define SPR_SYS_SR_SM_GET(x)             (((x) >> 0) & 0x1)\n#define SPR_SYS_SR_SM_SET(x, y)          (((x) & U(0xfffffffe)) | \\\n\t                                  ((!!(y)) << 0))\n\n/* Tick Timer Exception Enabled */\n#define SPR_SYS_SR_TEE_OFFSET            1\n#define SPR_SYS_SR_TEE_MASK              0x00000002\n#define SPR_SYS_SR_TEE_GET(x)            (((x) >> 1) & 0x1)\n#define SPR_SYS_SR_TEE_SET(x, y)         (((x) & U(0xfffffffd)) | \\\n\t                                  ((!!(y)) << 1))\n\n/* Interrupt Exception Enabled */\n#define SPR_SYS_SR_IEE_OFFSET            2\n#define SPR_SYS_SR_IEE_MASK              0x00000004\n#define SPR_SYS_SR_IEE_GET(x)            (((x) >> 2) & 0x1)\n#define SPR_SYS_SR_IEE_SET(x, y)         (((x) & U(0xfffffffb)) | \\\n\t                                  ((!!(y)) << 2))\n\n/* Data Cache Enabled */\n#define SPR_SYS_SR_DCE_OFFSET            3\n#define SPR_SYS_SR_DCE_MASK              0x00000008\n#define SPR_SYS_SR_DCE_GET(x)            (((x) >> 3) & 0x1)\n#define SPR_SYS_SR_DCE_SET(x, y)         (((x) & U(0xfffffff7)) | \\\n\t                                  ((!!(y)) << 3))\n\n/* Instruction Cache Enabled */\n#define SPR_SYS_SR_ICE_OFFSET            4\n#define SPR_SYS_SR_ICE_MASK              0x00000010\n#define SPR_SYS_SR_ICE_GET(x)            (((x) >> 4) & 0x1)\n#define SPR_SYS_SR_ICE_SET(x, y)         (((x) & U(0xffffffef)) | \\\n\t                                  ((!!(y)) << 4))\n\n/* Data MMU Enabled */\n#define SPR_SYS_SR_DME_OFFSET            5\n#define SPR_SYS_SR_DME_MASK              0x00000020\n#define SPR_SYS_SR_DME_GET(x)            (((x) >> 5) & 0x1)\n#define SPR_SYS_SR_DME_SET(x, y)         (((x) & U(0xffffffdf)) | \\\n\t                                  ((!!(y)) << 5))\n\n/* Instruction MMU Enabled */\n#define SPR_SYS_SR_IME_OFFSET            6\n#define SPR_SYS_SR_IME_MASK              0x00000040\n#define SPR_SYS_SR_IME_GET(x)            (((x) >> 6) & 0x1)\n#define SPR_SYS_SR_IME_SET(x, y)         (((x) & U(0xffffffbf)) | \\\n\t                                  ((!!(y)) << 6))\n\n/* Little Endian Enabled */\n#define SPR_SYS_SR_LEE_OFFSET            7\n#define SPR_SYS_SR_LEE_MASK              0x00000080\n#define SPR_SYS_SR_LEE_GET(x)            (((x) >> 7) & 0x1)\n#define SPR_SYS_SR_LEE_SET(x, y)         (((x) & U(0xffffff7f)) | \\\n\t                                  ((!!(y)) << 7))\n\n/* CID Enable */\n#define SPR_SYS_SR_CE_OFFSET             8\n#define SPR_SYS_SR_CE_MASK               0x00000100\n#define SPR_SYS_SR_CE_GET(x)             (((x) >> 8) & 0x1)\n#define SPR_SYS_SR_CE_SET(x, y)          (((x) & U(0xfffffeff)) | \\\n\t                                  ((!!(y)) << 8))\n\n/* Flag */\n#define SPR_SYS_SR_F_OFFSET              9\n#define SPR_SYS_SR_F_MASK                0x00000200\n#define SPR_SYS_SR_F_GET(x)              (((x) >> 9) & 0x1)\n#define SPR_SYS_SR_F_SET(x, y)           (((x) & U(0xfffffdff)) | \\\n\t                                  ((!!(y)) << 9))\n\n/* Carry */\n#define SPR_SYS_SR_CY_OFFSET             10\n#define SPR_SYS_SR_CY_MASK               0x00000400\n#define SPR_SYS_SR_CY_GET(x)             (((x) >> 10) & 0x1)\n#define SPR_SYS_SR_CY_SET(x, y)          (((x) & U(0xfffffbff)) | \\\n\t                                  ((!!(y)) << 10))\n\n/* Overflow */\n#define SPR_SYS_SR_OV_OFFSET             11\n#define SPR_SYS_SR_OV_MASK               0x00000800\n#define SPR_SYS_SR_OV_GET(x)             (((x) >> 11) & 0x1)\n#define SPR_SYS_SR_OV_SET(x, y)          (((x) & U(0xfffff7ff)) | \\\n\t                                  ((!!(y)) << 11))\n\n/* Overflow Exception Enabled */\n#define SPR_SYS_SR_OVE_OFFSET            12\n#define SPR_SYS_SR_OVE_MASK              0x00001000\n#define SPR_SYS_SR_OVE_GET(x)            (((x) >> 12) & 0x1)\n#define SPR_SYS_SR_OVE_SET(x, y)         (((x) & U(0xffffefff)) | \\\n\t                                  ((!!(y)) << 12))\n\n/* Delay-slot Exception */\n#define SPR_SYS_SR_DSX_OFFSET            13\n#define SPR_SYS_SR_DSX_MASK              0x00002000\n#define SPR_SYS_SR_DSX_GET(x)            (((x) >> 13) & 0x1)\n#define SPR_SYS_SR_DSX_SET(x, y)         (((x) & U(0xffffdfff)) | \\\n\t                                  ((!!(y)) << 13))\n\n/* Exception Prefix High */\n#define SPR_SYS_SR_EPH_OFFSET            14\n#define SPR_SYS_SR_EPH_MASK              0x00004000\n#define SPR_SYS_SR_EPH_GET(x)            (((x) >> 14) & 0x1)\n#define SPR_SYS_SR_EPH_SET(x, y)         (((x) & U(0xffffbfff)) | \\\n\t                                  ((!!(y)) << 14))\n\n/* Fixed One */\n#define SPR_SYS_SR_FO_OFFSET             15\n#define SPR_SYS_SR_FO_MASK               0x00008000\n#define SPR_SYS_SR_FO_GET(x)             (((x) >> 15) & 0x1)\n#define SPR_SYS_SR_FO_SET(x, y)          (((x) & U(0xffff7fff)) | \\\n\t                                  ((!!(y)) << 15))\n\n/* SPR User Mode Read Access */\n#define SPR_SYS_SR_SUMRA_OFFSET          16\n#define SPR_SYS_SR_SUMRA_MASK            0x00010000\n#define SPR_SYS_SR_SUMRA_GET(x)          (((x) >> 16) & 0x1)\n#define SPR_SYS_SR_SUMRA_SET(x, y)       (((x) & U(0xfffeffff)) | \\\n\t                                  ((!!(y)) << 16))\n\n/* Context ID */\n#define SPR_SYS_SR_CID_LSB               28\n#define SPR_SYS_SR_CID_MSB               31\n#define SPR_SYS_SR_CID_BITS              4\n#define SPR_SYS_SR_CID_MASK              U(0xf0000000)\n#define SPR_SYS_SR_CID_GET(x)            (((x) >> 28) & U(0x0000000f))\n#define SPR_SYS_SR_CID_SET(x, y)         (((x) & U(0x0fffffff)) | \\\n\t                                  ((y) << 28))\n\n/* Previous Program Counter */\n#define SPR_SYS_PPC_INDEX                U(0x012)\n#define SPR_SYS_PPC_ADDR                 U(0x0012)\n\n/* Floating Point Control Status Register */\n#define SPR_SYS_FPCSR_INDEX              U(0x014)\n#define SPR_SYS_FPCSR_ADDR               U(0x0014)\n\n/* Floating Point Exception Enabled */\n#define SPR_SYS_FPCSR_FPEE_OFFSET        0\n#define SPR_SYS_FPCSR_FPEE_MASK          0x00000001\n#define SPR_SYS_FPCSR_FPEE_GET(x)        (((x) >> 0) & 0x1)\n#define SPR_SYS_FPCSR_FPEE_SET(x, y)     (((x) & U(0xfffffffe)) | \\\n\t                                  ((!!(y)) << 0))\n\n/* Rounding Mode */\n#define SPR_SYS_FPCSR_RM_LSB             1\n#define SPR_SYS_FPCSR_RM_MSB             2\n#define SPR_SYS_FPCSR_RM_BITS            2\n#define SPR_SYS_FPCSR_RM_MASK            U(0x00000006)\n#define SPR_SYS_FPCSR_RM_GET(x)          (((x) >> 1) & U(0x00000003))\n#define SPR_SYS_FPCSR_RM_SET(x, y)       (((x) & U(0xfffffff9)) | \\\n\t                                  ((y) << 1))\n\n/* Round to nearest */\n#define SPR_SYS_FPCSR_RM_NEAREST         0\n/* Round to zero */\n#define SPR_SYS_FPCSR_RM_ZERO            1\n/* Round to infinity+ */\n#define SPR_SYS_FPCSR_RM_INFPLUS         2\n/* Round to infinity- */\n#define SPR_SYS_FPCSR_RM_INFMINUS        3\n\n/* Overflow Flag */\n#define SPR_SYS_FPCSR_OVF_OFFSET         3\n#define SPR_SYS_FPCSR_OVF_MASK           0x00000008\n#define SPR_SYS_FPCSR_OVF_GET(x)         (((x) >> 3) & 0x1)\n#define SPR_SYS_FPCSR_OVF_SET(x, y)      (((x) & U(0xfffffff7)) | \\\n\t                                  ((!!(y)) << 3))\n\n/* Underflow Flag */\n#define SPR_SYS_FPCSR_UNF_OFFSET         4\n#define SPR_SYS_FPCSR_UNF_MASK           0x00000010\n#define SPR_SYS_FPCSR_UNF_GET(x)         (((x) >> 4) & 0x1)\n#define SPR_SYS_FPCSR_UNF_SET(x, y)      (((x) & U(0xffffffef)) | \\\n\t                                  ((!!(y)) << 4))\n\n/* SNAN Flag */\n#define SPR_SYS_FPCSR_SNF_OFFSET         5\n#define SPR_SYS_FPCSR_SNF_MASK           0x00000020\n#define SPR_SYS_FPCSR_SNF_GET(x)         (((x) >> 5) & 0x1)\n#define SPR_SYS_FPCSR_SNF_SET(x, y)      (((x) & U(0xffffffdf)) | \\\n\t                                  ((!!(y)) << 5))\n\n/* QNAN Flag */\n#define SPR_SYS_FPCSR_QNF_OFFSET         6\n#define SPR_SYS_FPCSR_QNF_MASK           0x00000040\n#define SPR_SYS_FPCSR_QNF_GET(x)         (((x) >> 6) & 0x1)\n#define SPR_SYS_FPCSR_QNF_SET(x, y)      (((x) & U(0xffffffbf)) | \\\n\t                                  ((!!(y)) << 6))\n\n/* Zero Flag */\n#define SPR_SYS_FPCSR_ZF_OFFSET          7\n#define SPR_SYS_FPCSR_ZF_MASK            0x00000080\n#define SPR_SYS_FPCSR_ZF_GET(x)          (((x) >> 7) & 0x1)\n#define SPR_SYS_FPCSR_ZF_SET(x, y)       (((x) & U(0xffffff7f)) | \\\n\t                                  ((!!(y)) << 7))\n\n/* Inexact Flag */\n#define SPR_SYS_FPCSR_IXF_OFFSET         8\n#define SPR_SYS_FPCSR_IXF_MASK           0x00000100\n#define SPR_SYS_FPCSR_IXF_GET(x)         (((x) >> 8) & 0x1)\n#define SPR_SYS_FPCSR_IXF_SET(x, y)      (((x) & U(0xfffffeff)) | \\\n\t                                  ((!!(y)) << 8))\n\n/* Invalid Flag */\n#define SPR_SYS_FPCSR_IVF_OFFSET         9\n#define SPR_SYS_FPCSR_IVF_MASK           0x00000200\n#define SPR_SYS_FPCSR_IVF_GET(x)         (((x) >> 9) & 0x1)\n#define SPR_SYS_FPCSR_IVF_SET(x, y)      (((x) & U(0xfffffdff)) | \\\n\t                                  ((!!(y)) << 9))\n\n/* Infinity Flag */\n#define SPR_SYS_FPCSR_INF_OFFSET         10\n#define SPR_SYS_FPCSR_INF_MASK           0x00000400\n#define SPR_SYS_FPCSR_INF_GET(x)         (((x) >> 10) & 0x1)\n#define SPR_SYS_FPCSR_INF_SET(x, y)      (((x) & U(0xfffffbff)) | \\\n\t                                  ((!!(y)) << 10))\n\n/* Divide by Zero Flag */\n#define SPR_SYS_FPCSR_DZF_OFFSET         11\n#define SPR_SYS_FPCSR_DZF_MASK           0x00000800\n#define SPR_SYS_FPCSR_DZF_GET(x)         (((x) >> 11) & 0x1)\n#define SPR_SYS_FPCSR_DZF_SET(x, y)      (((x) & U(0xfffff7ff)) | \\\n\t                                  ((!!(y)) << 11))\n\n/* Implementation-specific Registers */\n#define SPR_SYS_ISR_BASE                 U(0x015)\n#define SPR_SYS_ISR_COUNT                U(0x008)\n#define SPR_SYS_ISR_STEP                 U(0x001)\n#define SPR_SYS_ISR_INDEX(N)             (SPR_SYS_ISR_BASE + \\\n\t                                  (SPR_SYS_ISR_STEP * (N)))\n#define SPR_SYS_ISR_ADDR(N)              ((SPR_SYS_GROUP << SPR_GROUP_LSB) | \\\n\t                                  SPR_SYS_ISR_INDEX(N))\n\n/* Exception PC Registers */\n#define SPR_SYS_EPCR_BASE                U(0x020)\n#define SPR_SYS_EPCR_COUNT               U(0x010)\n#define SPR_SYS_EPCR_STEP                U(0x001)\n#define SPR_SYS_EPCR_INDEX(N)            (SPR_SYS_EPCR_BASE + \\\n\t                                  (SPR_SYS_EPCR_STEP * (N)))\n#define SPR_SYS_EPCR_ADDR(N)             ((SPR_SYS_GROUP << SPR_GROUP_LSB) | \\\n\t                                  SPR_SYS_EPCR_INDEX(N))\n\n/* Exception Effective Address Registers */\n#define SPR_SYS_EEAR_BASE                U(0x030)\n#define SPR_SYS_EEAR_COUNT               U(0x010)\n#define SPR_SYS_EEAR_STEP                U(0x001)\n#define SPR_SYS_EEAR_INDEX(N)            (SPR_SYS_EEAR_BASE + \\\n\t                                  (SPR_SYS_EEAR_STEP * (N)))\n#define SPR_SYS_EEAR_ADDR(N)             ((SPR_SYS_GROUP << SPR_GROUP_LSB) | \\\n\t                                  SPR_SYS_EEAR_INDEX(N))\n\n/* Exception Supervision Registers */\n#define SPR_SYS_ESR_BASE                 U(0x040)\n#define SPR_SYS_ESR_COUNT                U(0x010)\n#define SPR_SYS_ESR_STEP                 U(0x001)\n#define SPR_SYS_ESR_INDEX(N)             (SPR_SYS_ESR_BASE + \\\n\t                                  (SPR_SYS_ESR_STEP * (N)))\n#define SPR_SYS_ESR_ADDR(N)              ((SPR_SYS_GROUP << SPR_GROUP_LSB) | \\\n\t                                  SPR_SYS_ESR_INDEX(N))\n\n/* Supervisor Mode */\n#define SPR_SYS_ESR_SM_OFFSET            0\n#define SPR_SYS_ESR_SM_MASK              0x00000001\n#define SPR_SYS_ESR_SM_GET(x)            (((x) >> 0) & 0x1)\n#define SPR_SYS_ESR_SM_SET(x, y)         (((x) & U(0xfffffffe)) | \\\n\t                                  ((!!(y)) << 0))\n\n/* Tick Timer Exception Enabled */\n#define SPR_SYS_ESR_TEE_OFFSET           1\n#define SPR_SYS_ESR_TEE_MASK             0x00000002\n#define SPR_SYS_ESR_TEE_GET(x)           (((x) >> 1) & 0x1)\n#define SPR_SYS_ESR_TEE_SET(x, y)        (((x) & U(0xfffffffd)) | \\\n\t                                  ((!!(y)) << 1))\n\n/* Interrupt Exception Enabled */\n#define SPR_SYS_ESR_IEE_OFFSET           2\n#define SPR_SYS_ESR_IEE_MASK             0x00000004\n#define SPR_SYS_ESR_IEE_GET(x)           (((x) >> 2) & 0x1)\n#define SPR_SYS_ESR_IEE_SET(x, y)        (((x) & U(0xfffffffb)) | \\\n\t                                  ((!!(y)) << 2))\n\n/* Data Cache Enabled */\n#define SPR_SYS_ESR_DCE_OFFSET           3\n#define SPR_SYS_ESR_DCE_MASK             0x00000008\n#define SPR_SYS_ESR_DCE_GET(x)           (((x) >> 3) & 0x1)\n#define SPR_SYS_ESR_DCE_SET(x, y)        (((x) & U(0xfffffff7)) | \\\n\t                                  ((!!(y)) << 3))\n\n/* Instruction Cache Enabled */\n#define SPR_SYS_ESR_ICE_OFFSET           4\n#define SPR_SYS_ESR_ICE_MASK             0x00000010\n#define SPR_SYS_ESR_ICE_GET(x)           (((x) >> 4) & 0x1)\n#define SPR_SYS_ESR_ICE_SET(x, y)        (((x) & U(0xffffffef)) | \\\n\t                                  ((!!(y)) << 4))\n\n/* Data MMU Enabled */\n#define SPR_SYS_ESR_DME_OFFSET           5\n#define SPR_SYS_ESR_DME_MASK             0x00000020\n#define SPR_SYS_ESR_DME_GET(x)           (((x) >> 5) & 0x1)\n#define SPR_SYS_ESR_DME_SET(x, y)        (((x) & U(0xffffffdf)) | \\\n\t                                  ((!!(y)) << 5))\n\n/* Instruction MMU Enabled */\n#define SPR_SYS_ESR_IME_OFFSET           6\n#define SPR_SYS_ESR_IME_MASK             0x00000040\n#define SPR_SYS_ESR_IME_GET(x)           (((x) >> 6) & 0x1)\n#define SPR_SYS_ESR_IME_SET(x, y)        (((x) & U(0xffffffbf)) | \\\n\t                                  ((!!(y)) << 6))\n\n/* Little Endian Enabled */\n#define SPR_SYS_ESR_LEE_OFFSET           7\n#define SPR_SYS_ESR_LEE_MASK             0x00000080\n#define SPR_SYS_ESR_LEE_GET(x)           (((x) >> 7) & 0x1)\n#define SPR_SYS_ESR_LEE_SET(x, y)        (((x) & U(0xffffff7f)) | \\\n\t                                  ((!!(y)) << 7))\n\n/* CID Enable */\n#define SPR_SYS_ESR_CE_OFFSET            8\n#define SPR_SYS_ESR_CE_MASK              0x00000100\n#define SPR_SYS_ESR_CE_GET(x)            (((x) >> 8) & 0x1)\n#define SPR_SYS_ESR_CE_SET(x, y)         (((x) & U(0xfffffeff)) | \\\n\t                                  ((!!(y)) << 8))\n\n/* Flag */\n#define SPR_SYS_ESR_F_OFFSET             9\n#define SPR_SYS_ESR_F_MASK               0x00000200\n#define SPR_SYS_ESR_F_GET(x)             (((x) >> 9) & 0x1)\n#define SPR_SYS_ESR_F_SET(x, y)          (((x) & U(0xfffffdff)) | \\\n\t                                  ((!!(y)) << 9))\n\n/* Carry */\n#define SPR_SYS_ESR_CY_OFFSET            10\n#define SPR_SYS_ESR_CY_MASK              0x00000400\n#define SPR_SYS_ESR_CY_GET(x)            (((x) >> 10) & 0x1)\n#define SPR_SYS_ESR_CY_SET(x, y)         (((x) & U(0xfffffbff)) | \\\n\t                                  ((!!(y)) << 10))\n\n/* Overflow */\n#define SPR_SYS_ESR_OV_OFFSET            11\n#define SPR_SYS_ESR_OV_MASK              0x00000800\n#define SPR_SYS_ESR_OV_GET(x)            (((x) >> 11) & 0x1)\n#define SPR_SYS_ESR_OV_SET(x, y)         (((x) & U(0xfffff7ff)) | \\\n\t                                  ((!!(y)) << 11))\n\n/* Overflow Exception Enabled */\n#define SPR_SYS_ESR_OVE_OFFSET           12\n#define SPR_SYS_ESR_OVE_MASK             0x00001000\n#define SPR_SYS_ESR_OVE_GET(x)           (((x) >> 12) & 0x1)\n#define SPR_SYS_ESR_OVE_SET(x, y)        (((x) & U(0xffffefff)) | \\\n\t                                  ((!!(y)) << 12))\n\n/* Delay-slot Exception */\n#define SPR_SYS_ESR_DSX_OFFSET           13\n#define SPR_SYS_ESR_DSX_MASK             0x00002000\n#define SPR_SYS_ESR_DSX_GET(x)           (((x) >> 13) & 0x1)\n#define SPR_SYS_ESR_DSX_SET(x, y)        (((x) & U(0xffffdfff)) | \\\n\t                                  ((!!(y)) << 13))\n\n/* Exception Prefix High */\n#define SPR_SYS_ESR_EPH_OFFSET           14\n#define SPR_SYS_ESR_EPH_MASK             0x00004000\n#define SPR_SYS_ESR_EPH_GET(x)           (((x) >> 14) & 0x1)\n#define SPR_SYS_ESR_EPH_SET(x, y)        (((x) & U(0xffffbfff)) | \\\n\t                                  ((!!(y)) << 14))\n\n/* Fixed One */\n#define SPR_SYS_ESR_FO_OFFSET            15\n#define SPR_SYS_ESR_FO_MASK              0x00008000\n#define SPR_SYS_ESR_FO_GET(x)            (((x) >> 15) & 0x1)\n#define SPR_SYS_ESR_FO_SET(x, y)         (((x) & U(0xffff7fff)) | \\\n\t                                  ((!!(y)) << 15))\n\n/* SPR User Mode Read Access */\n#define SPR_SYS_ESR_SUMRA_OFFSET         16\n#define SPR_SYS_ESR_SUMRA_MASK           0x00010000\n#define SPR_SYS_ESR_SUMRA_GET(x)         (((x) >> 16) & 0x1)\n#define SPR_SYS_ESR_SUMRA_SET(x, y)      (((x) & U(0xfffeffff)) | \\\n\t                                  ((!!(y)) << 16))\n\n/* Context ID */\n#define SPR_SYS_ESR_CID_LSB              28\n#define SPR_SYS_ESR_CID_MSB              31\n#define SPR_SYS_ESR_CID_BITS             4\n#define SPR_SYS_ESR_CID_MASK             U(0xf0000000)\n#define SPR_SYS_ESR_CID_GET(x)           (((x) >> 28) & U(0x0000000f))\n#define SPR_SYS_ESR_CID_SET(x, y)        (((x) & U(0x0fffffff)) | \\\n\t                                  ((y) << 28))\n\n/* Core identifier (multicore) */\n#define SPR_SYS_COREID_INDEX             U(0x080)\n#define SPR_SYS_COREID_ADDR              U(0x0080)\n\n/* Number of cores (multicore) */\n#define SPR_SYS_NUMCORES_INDEX           U(0x081)\n#define SPR_SYS_NUMCORES_ADDR            U(0x0081)\n\n/* General Purpose Registers */\n#define SPR_SYS_GPR_BASE                 U(0x400)\n#define SPR_SYS_GPR_COUNT                U(0x100)\n#define SPR_SYS_GPR_STEP                 U(0x001)\n#define SPR_SYS_GPR_INDEX(N)             (SPR_SYS_GPR_BASE + \\\n\t                                  (SPR_SYS_GPR_STEP * (N)))\n#define SPR_SYS_GPR_ADDR(N)              ((SPR_SYS_GROUP << SPR_GROUP_LSB) | \\\n\t                                  SPR_SYS_GPR_INDEX(N))\n\n/******************/\n/* Data MMU Group */\n/******************/\n#define SPR_DMMU_GROUP                  0x01\n\n/* Instruction MMU Control Register */\n#define SPR_DMMU_DMMUCR_INDEX           U(0x000)\n#define SPR_DMMU_DMMUCR_ADDR            U(0x0800)\n\n/* DTLB Flush */\n#define SPR_DMMU_DMMUCR_DTF_OFFSET      0\n#define SPR_DMMU_DMMUCR_DTF_MASK        0x00000001\n#define SPR_DMMU_DMMUCR_DTF_GET(x)      (((x) >> 0) & 0x1)\n#define SPR_DMMU_DMMUCR_DTF_SET(x, y)   (((x) & U(0xfffffffe)) | \\\n\t                                 ((!!(y)) << 0))\n\n/* Page Table Base Pointer */\n#define SPR_DMMU_DMMUCR_PTBP_LSB        10\n#define SPR_DMMU_DMMUCR_PTBP_MSB        31\n#define SPR_DMMU_DMMUCR_PTBP_BITS       22\n#define SPR_DMMU_DMMUCR_PTBP_MASK       U(0xfffffc00)\n#define SPR_DMMU_DMMUCR_PTBP_GET(x)     (((x) >> 10) & U(0x003fffff))\n#define SPR_DMMU_DMMUCR_PTBP_SET(x, y)  (((x) & U(0x000003ff)) | \\\n\t                                 ((y) << 10))\n\n/* Data MMU Protection Register */\n#define SPR_DMMU_DMMUPR_INDEX           U(0x001)\n#define SPR_DMMU_DMMUPR_ADDR            U(0x0801)\n\n/* Supervisor Read Enable 1 */\n#define SPR_DMMU_DMMUPR_SRE1_OFFSET     0\n#define SPR_DMMU_DMMUPR_SRE1_MASK       0x00000001\n#define SPR_DMMU_DMMUPR_SRE1_GET(x)     (((x) >> 0) & 0x1)\n#define SPR_DMMU_DMMUPR_SRE1_SET(x, y)  (((x) & U(0xfffffffe)) | \\\n\t                                 ((!!(y)) << 0))\n\n/* Supervisor Write Enable 1 */\n#define SPR_DMMU_DMMUPR_SWE1_OFFSET     1\n#define SPR_DMMU_DMMUPR_SWE1_MASK       0x00000002\n#define SPR_DMMU_DMMUPR_SWE1_GET(x)     (((x) >> 1) & 0x1)\n#define SPR_DMMU_DMMUPR_SWE1_SET(x, y)  (((x) & U(0xfffffffd)) | \\\n\t                                 ((!!(y)) << 1))\n\n/* User Read Enable 1 */\n#define SPR_DMMU_DMMUPR_URE1_OFFSET     2\n#define SPR_DMMU_DMMUPR_URE1_MASK       0x00000004\n#define SPR_DMMU_DMMUPR_URE1_GET(x)     (((x) >> 2) & 0x1)\n#define SPR_DMMU_DMMUPR_URE1_SET(x, y)  (((x) & U(0xfffffffb)) | \\\n\t                                 ((!!(y)) << 2))\n\n/* User Write Enable 1 */\n#define SPR_DMMU_DMMUPR_UWE1_OFFSET     3\n#define SPR_DMMU_DMMUPR_UWE1_MASK       0x00000008\n#define SPR_DMMU_DMMUPR_UWE1_GET(x)     (((x) >> 3) & 0x1)\n#define SPR_DMMU_DMMUPR_UWE1_SET(x, y)  (((x) & U(0xfffffff7)) | \\\n\t                                 ((!!(y)) << 3))\n\n/* Supervisor Read Enable 2 */\n#define SPR_DMMU_DMMUPR_SRE2_OFFSET     4\n#define SPR_DMMU_DMMUPR_SRE2_MASK       0x00000010\n#define SPR_DMMU_DMMUPR_SRE2_GET(x)     (((x) >> 4) & 0x1)\n#define SPR_DMMU_DMMUPR_SRE2_SET(x, y)  (((x) & U(0xffffffef)) | \\\n\t                                 ((!!(y)) << 4))\n\n/* Supervisor Write Enable 2 */\n#define SPR_DMMU_DMMUPR_SWE2_OFFSET     5\n#define SPR_DMMU_DMMUPR_SWE2_MASK       0x00000020\n#define SPR_DMMU_DMMUPR_SWE2_GET(x)     (((x) >> 5) & 0x1)\n#define SPR_DMMU_DMMUPR_SWE2_SET(x, y)  (((x) & U(0xffffffdf)) | \\\n\t                                 ((!!(y)) << 5))\n\n/* User Read Enable 2 */\n#define SPR_DMMU_DMMUPR_URE2_OFFSET     6\n#define SPR_DMMU_DMMUPR_URE2_MASK       0x00000040\n#define SPR_DMMU_DMMUPR_URE2_GET(x)     (((x) >> 6) & 0x1)\n#define SPR_DMMU_DMMUPR_URE2_SET(x, y)  (((x) & U(0xffffffbf)) | \\\n\t                                 ((!!(y)) << 6))\n\n/* User Write Enable 2 */\n#define SPR_DMMU_DMMUPR_UWE2_OFFSET     7\n#define SPR_DMMU_DMMUPR_UWE2_MASK       0x00000080\n#define SPR_DMMU_DMMUPR_UWE2_GET(x)     (((x) >> 7) & 0x1)\n#define SPR_DMMU_DMMUPR_UWE2_SET(x, y)  (((x) & U(0xffffff7f)) | \\\n\t                                 ((!!(y)) << 7))\n\n/* Supervisor Read Enable 3 */\n#define SPR_DMMU_DMMUPR_SRE3_OFFSET     8\n#define SPR_DMMU_DMMUPR_SRE3_MASK       0x00000100\n#define SPR_DMMU_DMMUPR_SRE3_GET(x)     (((x) >> 8) & 0x1)\n#define SPR_DMMU_DMMUPR_SRE3_SET(x, y)  (((x) & U(0xfffffeff)) | \\\n\t                                 ((!!(y)) << 8))\n\n/* Supervisor Write Enable 3 */\n#define SPR_DMMU_DMMUPR_SWE3_OFFSET     9\n#define SPR_DMMU_DMMUPR_SWE3_MASK       0x00000200\n#define SPR_DMMU_DMMUPR_SWE3_GET(x)     (((x) >> 9) & 0x1)\n#define SPR_DMMU_DMMUPR_SWE3_SET(x, y)  (((x) & U(0xfffffdff)) | \\\n\t                                 ((!!(y)) << 9))\n\n/* User Read Enable 3 */\n#define SPR_DMMU_DMMUPR_URE3_OFFSET     10\n#define SPR_DMMU_DMMUPR_URE3_MASK       0x00000400\n#define SPR_DMMU_DMMUPR_URE3_GET(x)     (((x) >> 10) & 0x1)\n#define SPR_DMMU_DMMUPR_URE3_SET(x, y)  (((x) & U(0xfffffbff)) | \\\n\t                                 ((!!(y)) << 10))\n\n/* User Write Enable 3 */\n#define SPR_DMMU_DMMUPR_UWE3_OFFSET     11\n#define SPR_DMMU_DMMUPR_UWE3_MASK       0x00000800\n#define SPR_DMMU_DMMUPR_UWE3_GET(x)     (((x) >> 11) & 0x1)\n#define SPR_DMMU_DMMUPR_UWE3_SET(x, y)  (((x) & U(0xfffff7ff)) | \\\n\t                                 ((!!(y)) << 11))\n\n/* Supervisor Read Enable 4 */\n#define SPR_DMMU_DMMUPR_SRE4_OFFSET     12\n#define SPR_DMMU_DMMUPR_SRE4_MASK       0x00001000\n#define SPR_DMMU_DMMUPR_SRE4_GET(x)     (((x) >> 12) & 0x1)\n#define SPR_DMMU_DMMUPR_SRE4_SET(x, y)  (((x) & U(0xffffefff)) | \\\n\t                                 ((!!(y)) << 12))\n\n/* Supervisor Write Enable 4 */\n#define SPR_DMMU_DMMUPR_SWE4_OFFSET     13\n#define SPR_DMMU_DMMUPR_SWE4_MASK       0x00002000\n#define SPR_DMMU_DMMUPR_SWE4_GET(x)     (((x) >> 13) & 0x1)\n#define SPR_DMMU_DMMUPR_SWE4_SET(x, y)  (((x) & U(0xffffdfff)) | \\\n\t                                 ((!!(y)) << 13))\n\n/* User Read Enable 4 */\n#define SPR_DMMU_DMMUPR_URE4_OFFSET     14\n#define SPR_DMMU_DMMUPR_URE4_MASK       0x00004000\n#define SPR_DMMU_DMMUPR_URE4_GET(x)     (((x) >> 14) & 0x1)\n#define SPR_DMMU_DMMUPR_URE4_SET(x, y)  (((x) & U(0xffffbfff)) | \\\n\t                                 ((!!(y)) << 14))\n\n/* User Write Enable 4 */\n#define SPR_DMMU_DMMUPR_UWE4_OFFSET     15\n#define SPR_DMMU_DMMUPR_UWE4_MASK       0x00008000\n#define SPR_DMMU_DMMUPR_UWE4_GET(x)     (((x) >> 15) & 0x1)\n#define SPR_DMMU_DMMUPR_UWE4_SET(x, y)  (((x) & U(0xffff7fff)) | \\\n\t                                 ((!!(y)) << 15))\n\n/* Supervisor Read Enable 5 */\n#define SPR_DMMU_DMMUPR_SRE5_OFFSET     16\n#define SPR_DMMU_DMMUPR_SRE5_MASK       0x00010000\n#define SPR_DMMU_DMMUPR_SRE5_GET(x)     (((x) >> 16) & 0x1)\n#define SPR_DMMU_DMMUPR_SRE5_SET(x, y)  (((x) & U(0xfffeffff)) | \\\n\t                                 ((!!(y)) << 16))\n\n/* Supervisor Write Enable 5 */\n#define SPR_DMMU_DMMUPR_SWE5_OFFSET     17\n#define SPR_DMMU_DMMUPR_SWE5_MASK       0x00020000\n#define SPR_DMMU_DMMUPR_SWE5_GET(x)     (((x) >> 17) & 0x1)\n#define SPR_DMMU_DMMUPR_SWE5_SET(x, y)  (((x) & U(0xfffdffff)) | \\\n\t                                 ((!!(y)) << 17))\n\n/* User Read Enable 5 */\n#define SPR_DMMU_DMMUPR_URE5_OFFSET     18\n#define SPR_DMMU_DMMUPR_URE5_MASK       0x00040000\n#define SPR_DMMU_DMMUPR_URE5_GET(x)     (((x) >> 18) & 0x1)\n#define SPR_DMMU_DMMUPR_URE5_SET(x, y)  (((x) & U(0xfffbffff)) | \\\n\t                                 ((!!(y)) << 18))\n\n/* User Write Enable 5 */\n#define SPR_DMMU_DMMUPR_UWE5_OFFSET     19\n#define SPR_DMMU_DMMUPR_UWE5_MASK       0x00080000\n#define SPR_DMMU_DMMUPR_UWE5_GET(x)     (((x) >> 19) & 0x1)\n#define SPR_DMMU_DMMUPR_UWE5_SET(x, y)  (((x) & U(0xfff7ffff)) | \\\n\t                                 ((!!(y)) << 19))\n\n/* Supervisor Read Enable 6 */\n#define SPR_DMMU_DMMUPR_SRE6_OFFSET     20\n#define SPR_DMMU_DMMUPR_SRE6_MASK       0x00100000\n#define SPR_DMMU_DMMUPR_SRE6_GET(x)     (((x) >> 20) & 0x1)\n#define SPR_DMMU_DMMUPR_SRE6_SET(x, y)  (((x) & U(0xffefffff)) | \\\n\t                                 ((!!(y)) << 20))\n\n/* Supervisor Write Enable 6 */\n#define SPR_DMMU_DMMUPR_SWE6_OFFSET     21\n#define SPR_DMMU_DMMUPR_SWE6_MASK       0x00200000\n#define SPR_DMMU_DMMUPR_SWE6_GET(x)     (((x) >> 21) & 0x1)\n#define SPR_DMMU_DMMUPR_SWE6_SET(x, y)  (((x) & U(0xffdfffff)) | \\\n\t                                 ((!!(y)) << 21))\n\n/* User Read Enable 6 */\n#define SPR_DMMU_DMMUPR_URE6_OFFSET     22\n#define SPR_DMMU_DMMUPR_URE6_MASK       0x00400000\n#define SPR_DMMU_DMMUPR_URE6_GET(x)     (((x) >> 22) & 0x1)\n#define SPR_DMMU_DMMUPR_URE6_SET(x, y)  (((x) & U(0xffbfffff)) | \\\n\t                                 ((!!(y)) << 22))\n\n/* User Write Enable 6 */\n#define SPR_DMMU_DMMUPR_UWE6_OFFSET     23\n#define SPR_DMMU_DMMUPR_UWE6_MASK       0x00800000\n#define SPR_DMMU_DMMUPR_UWE6_GET(x)     (((x) >> 23) & 0x1)\n#define SPR_DMMU_DMMUPR_UWE6_SET(x, y)  (((x) & U(0xff7fffff)) | \\\n\t                                 ((!!(y)) << 23))\n\n/* Supervisor Read Enable 7 */\n#define SPR_DMMU_DMMUPR_SRE7_OFFSET     24\n#define SPR_DMMU_DMMUPR_SRE7_MASK       0x01000000\n#define SPR_DMMU_DMMUPR_SRE7_GET(x)     (((x) >> 24) & 0x1)\n#define SPR_DMMU_DMMUPR_SRE7_SET(x, y)  (((x) & U(0xfeffffff)) | \\\n\t                                 ((!!(y)) << 24))\n\n/* Supervisor Write Enable 7 */\n#define SPR_DMMU_DMMUPR_SWE7_OFFSET     25\n#define SPR_DMMU_DMMUPR_SWE7_MASK       0x02000000\n#define SPR_DMMU_DMMUPR_SWE7_GET(x)     (((x) >> 25) & 0x1)\n#define SPR_DMMU_DMMUPR_SWE7_SET(x, y)  (((x) & U(0xfdffffff)) | \\\n\t                                 ((!!(y)) << 25))\n\n/* User Read Enable 7 */\n#define SPR_DMMU_DMMUPR_URE7_OFFSET     26\n#define SPR_DMMU_DMMUPR_URE7_MASK       0x04000000\n#define SPR_DMMU_DMMUPR_URE7_GET(x)     (((x) >> 26) & 0x1)\n#define SPR_DMMU_DMMUPR_URE7_SET(x, y)  (((x) & U(0xfbffffff)) | \\\n\t                                 ((!!(y)) << 26))\n\n/* User Write Enable 7 */\n#define SPR_DMMU_DMMUPR_UWE7_OFFSET     27\n#define SPR_DMMU_DMMUPR_UWE7_MASK       0x08000000\n#define SPR_DMMU_DMMUPR_UWE7_GET(x)     (((x) >> 27) & 0x1)\n#define SPR_DMMU_DMMUPR_UWE7_SET(x, y)  (((x) & U(0xf7ffffff)) | \\\n\t                                 ((!!(y)) << 27))\n\n/* Data TLB Entry Invalidate Register */\n#define SPR_DMMU_DTLBEIR_INDEX          U(0x002)\n#define SPR_DMMU_DTLBEIR_ADDR           U(0x0802)\n\n/* Data ATB Match Registers */\n#define SPR_DMMU_DATBMR_BASE            U(0x004)\n#define SPR_DMMU_DATBMR_COUNT           U(0x004)\n#define SPR_DMMU_DATBMR_STEP            U(0x001)\n#define SPR_DMMU_DATBMR_INDEX(N)        (SPR_DMMU_DATBMR_BASE + \\\n\t                                 (SPR_DMMU_DATBMR_STEP * (N)))\n#define SPR_DMMU_DATBMR_ADDR(N)         ((SPR_DMMU_GROUP << SPR_GROUP_LSB) | \\\n\t                                 SPR_DMMU_DATBMR_INDEX(N))\n\n/* Valid */\n#define SPR_DMMU_DATBMR_V_OFFSET        0\n#define SPR_DMMU_DATBMR_V_MASK          0x00000001\n#define SPR_DMMU_DATBMR_V_GET(x)        (((x) >> 0) & 0x1)\n#define SPR_DMMU_DATBMR_V_SET(x, y)     (((x) & U(0xfffffffe)) | \\\n\t                                 ((!!(y)) << 0))\n\n/* Context ID */\n#define SPR_DMMU_DATBMR_CID_LSB         1\n#define SPR_DMMU_DATBMR_CID_MSB         4\n#define SPR_DMMU_DATBMR_CID_BITS        4\n#define SPR_DMMU_DATBMR_CID_MASK        U(0x0000001e)\n#define SPR_DMMU_DATBMR_CID_GET(x)      (((x) >> 1) & U(0x0000000f))\n#define SPR_DMMU_DATBMR_CID_SET(x, y)   (((x) & U(0xffffffe1)) | \\\n\t                                 ((y) << 1))\n\n/* Page Size */\n#define SPR_DMMU_DATBMR_PS_OFFSET       5\n#define SPR_DMMU_DATBMR_PS_MASK         0x00000020\n#define SPR_DMMU_DATBMR_PS_GET(x)       (((x) >> 5) & 0x1)\n#define SPR_DMMU_DATBMR_PS_SET(x, y)    (((x) & U(0xffffffdf)) | \\\n\t                                 ((!!(y)) << 5))\n\n/* Virtual Page Number */\n#define SPR_DMMU_DATBMR_VPN_LSB         10\n#define SPR_DMMU_DATBMR_VPN_MSB         31\n#define SPR_DMMU_DATBMR_VPN_BITS        22\n#define SPR_DMMU_DATBMR_VPN_MASK        U(0xfffffc00)\n#define SPR_DMMU_DATBMR_VPN_GET(x)      (((x) >> 10) & U(0x003fffff))\n#define SPR_DMMU_DATBMR_VPN_SET(x, y)   (((x) & U(0x000003ff)) | \\\n\t                                 ((y) << 10))\n\n/* Data ATB Translate Registers */\n#define SPR_DMMU_DATBTR_BASE            U(0x008)\n#define SPR_DMMU_DATBTR_COUNT           U(0x004)\n#define SPR_DMMU_DATBTR_STEP            U(0x001)\n#define SPR_DMMU_DATBTR_INDEX(N)        (SPR_DMMU_DATBTR_BASE + \\\n\t                                 (SPR_DMMU_DATBTR_STEP * (N)))\n#define SPR_DMMU_DATBTR_ADDR(N)         ((SPR_DMMU_GROUP << SPR_GROUP_LSB) | \\\n\t                                 SPR_DMMU_DATBTR_INDEX(N))\n\n/* Cache Coherency */\n#define SPR_DMMU_DATBTR_CC_OFFSET       0\n#define SPR_DMMU_DATBTR_CC_MASK         0x00000001\n#define SPR_DMMU_DATBTR_CC_GET(x)       (((x) >> 0) & 0x1)\n#define SPR_DMMU_DATBTR_CC_SET(x, y)    (((x) & U(0xfffffffe)) | \\\n\t                                 ((!!(y)) << 0))\n\n/* Cache Inhibit */\n#define SPR_DMMU_DATBTR_CI_OFFSET       1\n#define SPR_DMMU_DATBTR_CI_MASK         0x00000002\n#define SPR_DMMU_DATBTR_CI_GET(x)       (((x) >> 1) & 0x1)\n#define SPR_DMMU_DATBTR_CI_SET(x, y)    (((x) & U(0xfffffffd)) | \\\n\t                                 ((!!(y)) << 1))\n\n/* Write-back Cache */\n#define SPR_DMMU_DATBTR_WBC_OFFSET      2\n#define SPR_DMMU_DATBTR_WBC_MASK        0x00000004\n#define SPR_DMMU_DATBTR_WBC_GET(x)      (((x) >> 2) & 0x1)\n#define SPR_DMMU_DATBTR_WBC_SET(x, y)   (((x) & U(0xfffffffb)) | \\\n\t                                 ((!!(y)) << 2))\n\n/* Weakly-ordered Memory */\n#define SPR_DMMU_DATBTR_WOM_OFFSET      3\n#define SPR_DMMU_DATBTR_WOM_MASK        0x00000008\n#define SPR_DMMU_DATBTR_WOM_GET(x)      (((x) >> 3) & 0x1)\n#define SPR_DMMU_DATBTR_WOM_SET(x, y)   (((x) & U(0xfffffff7)) | \\\n\t                                 ((!!(y)) << 3))\n\n/* Accessed */\n#define SPR_DMMU_DATBTR_A_OFFSET        4\n#define SPR_DMMU_DATBTR_A_MASK          0x00000010\n#define SPR_DMMU_DATBTR_A_GET(x)        (((x) >> 4) & 0x1)\n#define SPR_DMMU_DATBTR_A_SET(x, y)     (((x) & U(0xffffffef)) | \\\n\t                                 ((!!(y)) << 4))\n\n/* Dirty */\n#define SPR_DMMU_DATBTR_D_OFFSET        5\n#define SPR_DMMU_DATBTR_D_MASK          0x00000020\n#define SPR_DMMU_DATBTR_D_GET(x)        (((x) >> 5) & 0x1)\n#define SPR_DMMU_DATBTR_D_SET(x, y)     (((x) & U(0xffffffdf)) | \\\n\t                                 ((!!(y)) << 5))\n\n/* Supervisor Read Enable */\n#define SPR_DMMU_DATBTR_SRE_OFFSET      6\n#define SPR_DMMU_DATBTR_SRE_MASK        0x00000040\n#define SPR_DMMU_DATBTR_SRE_GET(x)      (((x) >> 6) & 0x1)\n#define SPR_DMMU_DATBTR_SRE_SET(x, y)   (((x) & U(0xffffffbf)) | \\\n\t                                 ((!!(y)) << 6))\n\n/* Supervisor Write Enable */\n#define SPR_DMMU_DATBTR_SWE_OFFSET      7\n#define SPR_DMMU_DATBTR_SWE_MASK        0x00000080\n#define SPR_DMMU_DATBTR_SWE_GET(x)      (((x) >> 7) & 0x1)\n#define SPR_DMMU_DATBTR_SWE_SET(x, y)   (((x) & U(0xffffff7f)) | \\\n\t                                 ((!!(y)) << 7))\n\n/* User Read Enable */\n#define SPR_DMMU_DATBTR_URE_OFFSET      8\n#define SPR_DMMU_DATBTR_URE_MASK        0x00000100\n#define SPR_DMMU_DATBTR_URE_GET(x)      (((x) >> 8) & 0x1)\n#define SPR_DMMU_DATBTR_URE_SET(x, y)   (((x) & U(0xfffffeff)) | \\\n\t                                 ((!!(y)) << 8))\n\n/* User Write Enable */\n#define SPR_DMMU_DATBTR_UWE_OFFSET      9\n#define SPR_DMMU_DATBTR_UWE_MASK        0x00000200\n#define SPR_DMMU_DATBTR_UWE_GET(x)      (((x) >> 9) & 0x1)\n#define SPR_DMMU_DATBTR_UWE_SET(x, y)   (((x) & U(0xfffffdff)) | \\\n\t                                 ((!!(y)) << 9))\n\n/* Physical Page Number */\n#define SPR_DMMU_DATBTR_PPN_LSB         10\n#define SPR_DMMU_DATBTR_PPN_MSB         31\n#define SPR_DMMU_DATBTR_PPN_BITS        22\n#define SPR_DMMU_DATBTR_PPN_MASK        U(0xfffffc00)\n#define SPR_DMMU_DATBTR_PPN_GET(x)      (((x) >> 10) & U(0x003fffff))\n#define SPR_DMMU_DATBTR_PPN_SET(x, y)   (((x) & U(0x000003ff)) | \\\n\t                                 ((y) << 10))\n\n/* Data TLB */\n#define SPR_DMMU_DTLBW_BASE             U(0x200)\n#define SPR_DMMU_DTLBW_COUNT            U(0x004)\n#define SPR_DMMU_DTLBW_STEP             U(0x100)\n#define SPR_DMMU_DTLBW_SUBBASE(N0)      (SPR_DMMU_DTLBW_BASE + \\\n\t                                 (SPR_DMMU_DTLBW_STEP * (N0)))\n\n/* Data TLB Match Registers */\n#define SPR_DMMU_DTLBW_MR_BASE          U(0x000)\n#define SPR_DMMU_DTLBW_MR_COUNT         U(0x080)\n#define SPR_DMMU_DTLBW_MR_STEP          U(0x001)\n\n#define SPR_DMMU_DTLBW_MR_INDEX(N0, N1) (SPR_DMMU_DTLBW_SUBBASE(N0) + \\\n\t                                 SPR_DMMU_DTLBW_MR_BASE + \\\n\t                                 (SPR_DMMU_DTLBW_MR_STEP * (N1)))\n#define SPR_DMMU_DTLBW_MR_ADDR(N0, N1)  ((SPR_DMMU_GROUP << SPR_GROUP_LSB) | \\\n\t                                 SPR_DMMU_DTLBW_MR_INDEX(N0, N1))\n\n/* Valid */\n#define SPR_DMMU_DTLBW_MR_V_OFFSET      0\n#define SPR_DMMU_DTLBW_MR_V_MASK        0x00000001\n#define SPR_DMMU_DTLBW_MR_V_GET(x)      (((x) >> 0) & 0x1)\n#define SPR_DMMU_DTLBW_MR_V_SET(x, y)   (((x) & U(0xfffffffe)) | \\\n\t                                 ((!!(y)) << 0))\n\n/* Page Level 1 */\n#define SPR_DMMU_DTLBW_MR_PL1_OFFSET    1\n#define SPR_DMMU_DTLBW_MR_PL1_MASK      0x00000002\n#define SPR_DMMU_DTLBW_MR_PL1_GET(x)    (((x) >> 1) & 0x1)\n#define SPR_DMMU_DTLBW_MR_PL1_SET(x, y) (((x) & U(0xfffffffd)) | \\\n\t                                 ((!!(y)) << 1))\n\n/* Context ID */\n#define SPR_DMMU_DTLBW_MR_CID_LSB       2\n#define SPR_DMMU_DTLBW_MR_CID_MSB       5\n#define SPR_DMMU_DTLBW_MR_CID_BITS      4\n#define SPR_DMMU_DTLBW_MR_CID_MASK      U(0x0000003c)\n#define SPR_DMMU_DTLBW_MR_CID_GET(x)    (((x) >> 2) & U(0x0000000f))\n#define SPR_DMMU_DTLBW_MR_CID_SET(x, y) (((x) & U(0xffffffc3)) | \\\n\t                                 ((y) << 2))\n\n/* Least Recently Used */\n#define SPR_DMMU_DTLBW_MR_LRU_LSB       6\n#define SPR_DMMU_DTLBW_MR_LRU_MSB       7\n#define SPR_DMMU_DTLBW_MR_LRU_BITS      2\n#define SPR_DMMU_DTLBW_MR_LRU_MASK      U(0x000000c0)\n#define SPR_DMMU_DTLBW_MR_LRU_GET(x)    (((x) >> 6) & U(0x00000003))\n#define SPR_DMMU_DTLBW_MR_LRU_SET(x, y) (((x) & U(0xffffff3f)) | \\\n\t                                 ((y) << 6))\n\n/* Virtual Page Number */\n#define SPR_DMMU_DTLBW_MR_VPN_LSB       13\n#define SPR_DMMU_DTLBW_MR_VPN_MSB       31\n#define SPR_DMMU_DTLBW_MR_VPN_BITS      19\n#define SPR_DMMU_DTLBW_MR_VPN_MASK      U(0xffffe000)\n#define SPR_DMMU_DTLBW_MR_VPN_GET(x)    (((x) >> 13) & U(0x0007ffff))\n#define SPR_DMMU_DTLBW_MR_VPN_SET(x, y) (((x) & U(0x00001fff)) | \\\n\t                                 ((y) << 13))\n\n/* Data TLB Translate Registers */\n#define SPR_DMMU_DTLBW_TR_BASE          U(0x080)\n#define SPR_DMMU_DTLBW_TR_COUNT         U(0x080)\n#define SPR_DMMU_DTLBW_TR_STEP          U(0x001)\n\n#define SPR_DMMU_DTLBW_TR_INDEX(N0, N1) (SPR_DMMU_DTLBW_SUBBASE(N0) + \\\n\t                                 SPR_DMMU_DTLBW_TR_BASE + \\\n\t                                 (SPR_DMMU_DTLBW_TR_STEP * (N1)))\n#define SPR_DMMU_DTLBW_TR_ADDR(N0, N1)  ((SPR_DMMU_GROUP << SPR_GROUP_LSB) | \\\n\t                                 SPR_DMMU_DTLBW_TR_INDEX(N0, N1))\n\n/* Cache Coherency */\n#define SPR_DMMU_DTLBW_TR_CC_OFFSET     0\n#define SPR_DMMU_DTLBW_TR_CC_MASK       0x00000001\n#define SPR_DMMU_DTLBW_TR_CC_GET(x)     (((x) >> 0) & 0x1)\n#define SPR_DMMU_DTLBW_TR_CC_SET(x, y)  (((x) & U(0xfffffffe)) | \\\n\t                                 ((!!(y)) << 0))\n\n/* Cache Inhibit */\n#define SPR_DMMU_DTLBW_TR_CI_OFFSET     1\n#define SPR_DMMU_DTLBW_TR_CI_MASK       0x00000002\n#define SPR_DMMU_DTLBW_TR_CI_GET(x)     (((x) >> 1) & 0x1)\n#define SPR_DMMU_DTLBW_TR_CI_SET(x, y)  (((x) & U(0xfffffffd)) | \\\n\t                                 ((!!(y)) << 1))\n\n/* Write-back Cache */\n#define SPR_DMMU_DTLBW_TR_WBC_OFFSET    2\n#define SPR_DMMU_DTLBW_TR_WBC_MASK      0x00000004\n#define SPR_DMMU_DTLBW_TR_WBC_GET(x)    (((x) >> 2) & 0x1)\n#define SPR_DMMU_DTLBW_TR_WBC_SET(x, y) (((x) & U(0xfffffffb)) | \\\n\t                                 ((!!(y)) << 2))\n\n/* Weakly-ordered Memory */\n#define SPR_DMMU_DTLBW_TR_WOM_OFFSET    3\n#define SPR_DMMU_DTLBW_TR_WOM_MASK      0x00000008\n#define SPR_DMMU_DTLBW_TR_WOM_GET(x)    (((x) >> 3) & 0x1)\n#define SPR_DMMU_DTLBW_TR_WOM_SET(x, y) (((x) & U(0xfffffff7)) | \\\n\t                                 ((!!(y)) << 3))\n\n/* Accessed */\n#define SPR_DMMU_DTLBW_TR_A_OFFSET      4\n#define SPR_DMMU_DTLBW_TR_A_MASK        0x00000010\n#define SPR_DMMU_DTLBW_TR_A_GET(x)      (((x) >> 4) & 0x1)\n#define SPR_DMMU_DTLBW_TR_A_SET(x, y)   (((x) & U(0xffffffef)) | \\\n\t                                 ((!!(y)) << 4))\n\n/* Dirty */\n#define SPR_DMMU_DTLBW_TR_D_OFFSET      5\n#define SPR_DMMU_DTLBW_TR_D_MASK        0x00000020\n#define SPR_DMMU_DTLBW_TR_D_GET(x)      (((x) >> 5) & 0x1)\n#define SPR_DMMU_DTLBW_TR_D_SET(x, y)   (((x) & U(0xffffffdf)) | \\\n\t                                 ((!!(y)) << 5))\n\n/* User Read Enable */\n#define SPR_DMMU_DTLBW_TR_URE_OFFSET    6\n#define SPR_DMMU_DTLBW_TR_URE_MASK      0x00000040\n#define SPR_DMMU_DTLBW_TR_URE_GET(x)    (((x) >> 6) & 0x1)\n#define SPR_DMMU_DTLBW_TR_URE_SET(x, y) (((x) & U(0xffffffbf)) | \\\n\t                                 ((!!(y)) << 6))\n\n/* User Write Enable */\n#define SPR_DMMU_DTLBW_TR_UWE_OFFSET    7\n#define SPR_DMMU_DTLBW_TR_UWE_MASK      0x00000080\n#define SPR_DMMU_DTLBW_TR_UWE_GET(x)    (((x) >> 7) & 0x1)\n#define SPR_DMMU_DTLBW_TR_UWE_SET(x, y) (((x) & U(0xffffff7f)) | \\\n\t                                 ((!!(y)) << 7))\n\n/* Supervisor Read Enable */\n#define SPR_DMMU_DTLBW_TR_SRE_OFFSET    8\n#define SPR_DMMU_DTLBW_TR_SRE_MASK      0x00000100\n#define SPR_DMMU_DTLBW_TR_SRE_GET(x)    (((x) >> 8) & 0x1)\n#define SPR_DMMU_DTLBW_TR_SRE_SET(x, y) (((x) & U(0xfffffeff)) | \\\n\t                                 ((!!(y)) << 8))\n\n/* Supervisor Write Enable */\n#define SPR_DMMU_DTLBW_TR_SWE_OFFSET    9\n#define SPR_DMMU_DTLBW_TR_SWE_MASK      0x00000200\n#define SPR_DMMU_DTLBW_TR_SWE_GET(x)    (((x) >> 9) & 0x1)\n#define SPR_DMMU_DTLBW_TR_SWE_SET(x, y) (((x) & U(0xfffffdff)) | \\\n\t                                 ((!!(y)) << 9))\n\n/* Physical Page Number */\n#define SPR_DMMU_DTLBW_TR_PPN_LSB       13\n#define SPR_DMMU_DTLBW_TR_PPN_MSB       31\n#define SPR_DMMU_DTLBW_TR_PPN_BITS      19\n#define SPR_DMMU_DTLBW_TR_PPN_MASK      U(0xffffe000)\n#define SPR_DMMU_DTLBW_TR_PPN_GET(x)    (((x) >> 13) & U(0x0007ffff))\n#define SPR_DMMU_DTLBW_TR_PPN_SET(x, y) (((x) & U(0x00001fff)) | \\\n\t                                 ((y) << 13))\n\n/*************************/\n/* Instruction MMU Group */\n/*************************/\n#define SPR_IMMU_GROUP                  0x02\n\n/* Instruction MMU Control Register */\n#define SPR_IMMU_IMMUCR_INDEX           U(0x000)\n#define SPR_IMMU_IMMUCR_ADDR            U(0x1000)\n\n/* ITLB Flush */\n#define SPR_IMMU_IMMUCR_ITF_OFFSET      0\n#define SPR_IMMU_IMMUCR_ITF_MASK        0x00000001\n#define SPR_IMMU_IMMUCR_ITF_GET(x)      (((x) >> 0) & 0x1)\n#define SPR_IMMU_IMMUCR_ITF_SET(x, y)   (((x) & U(0xfffffffe)) | \\\n\t                                 ((!!(y)) << 0))\n\n/* Page Table Base Pointer */\n#define SPR_IMMU_IMMUCR_PTBP_LSB        10\n#define SPR_IMMU_IMMUCR_PTBP_MSB        31\n#define SPR_IMMU_IMMUCR_PTBP_BITS       22\n#define SPR_IMMU_IMMUCR_PTBP_MASK       U(0xfffffc00)\n#define SPR_IMMU_IMMUCR_PTBP_GET(x)     (((x) >> 10) & U(0x003fffff))\n#define SPR_IMMU_IMMUCR_PTBP_SET(x, y)  (((x) & U(0x000003ff)) | \\\n\t                                 ((y) << 10))\n\n/* Instruction MMU Protection Register */\n#define SPR_IMMU_IMMUPR_INDEX           U(0x001)\n#define SPR_IMMU_IMMUPR_ADDR            U(0x1001)\n\n/* Supervisor Execute Enable 1 */\n#define SPR_IMMU_IMMUPR_SXE1_OFFSET     0\n#define SPR_IMMU_IMMUPR_SXE1_MASK       0x00000001\n#define SPR_IMMU_IMMUPR_SXE1_GET(x)     (((x) >> 0) & 0x1)\n#define SPR_IMMU_IMMUPR_SXE1_SET(x, y)  (((x) & U(0xfffffffe)) | \\\n\t                                 ((!!(y)) << 0))\n\n/* User Execute Enable 1 */\n#define SPR_IMMU_IMMUPR_UXE1_OFFSET     1\n#define SPR_IMMU_IMMUPR_UXE1_MASK       0x00000002\n#define SPR_IMMU_IMMUPR_UXE1_GET(x)     (((x) >> 1) & 0x1)\n#define SPR_IMMU_IMMUPR_UXE1_SET(x, y)  (((x) & U(0xfffffffd)) | \\\n\t                                 ((!!(y)) << 1))\n\n/* Supervisor Execute Enable 2 */\n#define SPR_IMMU_IMMUPR_SXE2_OFFSET     2\n#define SPR_IMMU_IMMUPR_SXE2_MASK       0x00000004\n#define SPR_IMMU_IMMUPR_SXE2_GET(x)     (((x) >> 2) & 0x1)\n#define SPR_IMMU_IMMUPR_SXE2_SET(x, y)  (((x) & U(0xfffffffb)) | \\\n\t                                 ((!!(y)) << 2))\n\n/* User Execute Enable 2 */\n#define SPR_IMMU_IMMUPR_UXE2_OFFSET     3\n#define SPR_IMMU_IMMUPR_UXE2_MASK       0x00000008\n#define SPR_IMMU_IMMUPR_UXE2_GET(x)     (((x) >> 3) & 0x1)\n#define SPR_IMMU_IMMUPR_UXE2_SET(x, y)  (((x) & U(0xfffffff7)) | \\\n\t                                 ((!!(y)) << 3))\n\n/* Supervisor Execute Enable 3 */\n#define SPR_IMMU_IMMUPR_SXE3_OFFSET     4\n#define SPR_IMMU_IMMUPR_SXE3_MASK       0x00000010\n#define SPR_IMMU_IMMUPR_SXE3_GET(x)     (((x) >> 4) & 0x1)\n#define SPR_IMMU_IMMUPR_SXE3_SET(x, y)  (((x) & U(0xffffffef)) | \\\n\t                                 ((!!(y)) << 4))\n\n/* User Execute Enable 3 */\n#define SPR_IMMU_IMMUPR_UXE3_OFFSET     5\n#define SPR_IMMU_IMMUPR_UXE3_MASK       0x00000020\n#define SPR_IMMU_IMMUPR_UXE3_GET(x)     (((x) >> 5) & 0x1)\n#define SPR_IMMU_IMMUPR_UXE3_SET(x, y)  (((x) & U(0xffffffdf)) | \\\n\t                                 ((!!(y)) << 5))\n\n/* Supervisor Execute Enable 4 */\n#define SPR_IMMU_IMMUPR_SXE4_OFFSET     6\n#define SPR_IMMU_IMMUPR_SXE4_MASK       0x00000040\n#define SPR_IMMU_IMMUPR_SXE4_GET(x)     (((x) >> 6) & 0x1)\n#define SPR_IMMU_IMMUPR_SXE4_SET(x, y)  (((x) & U(0xffffffbf)) | \\\n\t                                 ((!!(y)) << 6))\n\n/* User Execute Enable 4 */\n#define SPR_IMMU_IMMUPR_UXE4_OFFSET     7\n#define SPR_IMMU_IMMUPR_UXE4_MASK       0x00000080\n#define SPR_IMMU_IMMUPR_UXE4_GET(x)     (((x) >> 7) & 0x1)\n#define SPR_IMMU_IMMUPR_UXE4_SET(x, y)  (((x) & U(0xffffff7f)) | \\\n\t                                 ((!!(y)) << 7))\n\n/* Supervisor Execute Enable 5 */\n#define SPR_IMMU_IMMUPR_SXE5_OFFSET     8\n#define SPR_IMMU_IMMUPR_SXE5_MASK       0x00000100\n#define SPR_IMMU_IMMUPR_SXE5_GET(x)     (((x) >> 8) & 0x1)\n#define SPR_IMMU_IMMUPR_SXE5_SET(x, y)  (((x) & U(0xfffffeff)) | \\\n\t                                 ((!!(y)) << 8))\n\n/* User Execute Enable 5 */\n#define SPR_IMMU_IMMUPR_UXE5_OFFSET     9\n#define SPR_IMMU_IMMUPR_UXE5_MASK       0x00000200\n#define SPR_IMMU_IMMUPR_UXE5_GET(x)     (((x) >> 9) & 0x1)\n#define SPR_IMMU_IMMUPR_UXE5_SET(x, y)  (((x) & U(0xfffffdff)) | \\\n\t                                 ((!!(y)) << 9))\n\n/* Supervisor Execute Enable 6 */\n#define SPR_IMMU_IMMUPR_SXE6_OFFSET     10\n#define SPR_IMMU_IMMUPR_SXE6_MASK       0x00000400\n#define SPR_IMMU_IMMUPR_SXE6_GET(x)     (((x) >> 10) & 0x1)\n#define SPR_IMMU_IMMUPR_SXE6_SET(x, y)  (((x) & U(0xfffffbff)) | \\\n\t                                 ((!!(y)) << 10))\n\n/* User Execute Enable 6 */\n#define SPR_IMMU_IMMUPR_UXE6_OFFSET     11\n#define SPR_IMMU_IMMUPR_UXE6_MASK       0x00000800\n#define SPR_IMMU_IMMUPR_UXE6_GET(x)     (((x) >> 11) & 0x1)\n#define SPR_IMMU_IMMUPR_UXE6_SET(x, y)  (((x) & U(0xfffff7ff)) | \\\n\t                                 ((!!(y)) << 11))\n\n/* Supervisor Execute Enable 7 */\n#define SPR_IMMU_IMMUPR_SXE7_OFFSET     12\n#define SPR_IMMU_IMMUPR_SXE7_MASK       0x00001000\n#define SPR_IMMU_IMMUPR_SXE7_GET(x)     (((x) >> 12) & 0x1)\n#define SPR_IMMU_IMMUPR_SXE7_SET(x, y)  (((x) & U(0xffffefff)) | \\\n\t                                 ((!!(y)) << 12))\n\n/* User Execute Enable 7 */\n#define SPR_IMMU_IMMUPR_UXE7_OFFSET     13\n#define SPR_IMMU_IMMUPR_UXE7_MASK       0x00002000\n#define SPR_IMMU_IMMUPR_UXE7_GET(x)     (((x) >> 13) & 0x1)\n#define SPR_IMMU_IMMUPR_UXE7_SET(x, y)  (((x) & U(0xffffdfff)) | \\\n\t                                 ((!!(y)) << 13))\n\n/* Instruction TLB Entry Invalidate Register */\n#define SPR_IMMU_ITLBEIR_INDEX          U(0x002)\n#define SPR_IMMU_ITLBEIR_ADDR           U(0x1002)\n\n/* Instruction ATB Match Registers */\n#define SPR_IMMU_IATBMR_BASE            U(0x004)\n#define SPR_IMMU_IATBMR_COUNT           U(0x004)\n#define SPR_IMMU_IATBMR_STEP            U(0x001)\n#define SPR_IMMU_IATBMR_INDEX(N)        (SPR_IMMU_IATBMR_BASE + \\\n\t                                 (SPR_IMMU_IATBMR_STEP * (N)))\n#define SPR_IMMU_IATBMR_ADDR(N)         ((SPR_IMMU_GROUP << SPR_GROUP_LSB) | \\\n\t                                 SPR_IMMU_IATBMR_INDEX(N))\n\n/* Valid */\n#define SPR_IMMU_IATBMR_V_OFFSET        0\n#define SPR_IMMU_IATBMR_V_MASK          0x00000001\n#define SPR_IMMU_IATBMR_V_GET(x)        (((x) >> 0) & 0x1)\n#define SPR_IMMU_IATBMR_V_SET(x, y)     (((x) & U(0xfffffffe)) | \\\n\t                                 ((!!(y)) << 0))\n\n/* Context ID */\n#define SPR_IMMU_IATBMR_CID_LSB         1\n#define SPR_IMMU_IATBMR_CID_MSB         4\n#define SPR_IMMU_IATBMR_CID_BITS        4\n#define SPR_IMMU_IATBMR_CID_MASK        U(0x0000001e)\n#define SPR_IMMU_IATBMR_CID_GET(x)      (((x) >> 1) & U(0x0000000f))\n#define SPR_IMMU_IATBMR_CID_SET(x, y)   (((x) & U(0xffffffe1)) | \\\n\t                                 ((y) << 1))\n\n/* Page Size */\n#define SPR_IMMU_IATBMR_PS_OFFSET       5\n#define SPR_IMMU_IATBMR_PS_MASK         0x00000020\n#define SPR_IMMU_IATBMR_PS_GET(x)       (((x) >> 5) & 0x1)\n#define SPR_IMMU_IATBMR_PS_SET(x, y)    (((x) & U(0xffffffdf)) | \\\n\t                                 ((!!(y)) << 5))\n\n/* Virtual Page Number */\n#define SPR_IMMU_IATBMR_VPN_LSB         10\n#define SPR_IMMU_IATBMR_VPN_MSB         31\n#define SPR_IMMU_IATBMR_VPN_BITS        22\n#define SPR_IMMU_IATBMR_VPN_MASK        U(0xfffffc00)\n#define SPR_IMMU_IATBMR_VPN_GET(x)      (((x) >> 10) & U(0x003fffff))\n#define SPR_IMMU_IATBMR_VPN_SET(x, y)   (((x) & U(0x000003ff)) | \\\n\t                                 ((y) << 10))\n\n/* Instruction ATB Translate Registers */\n#define SPR_IMMU_IATBTR_BASE            U(0x008)\n#define SPR_IMMU_IATBTR_COUNT           U(0x004)\n#define SPR_IMMU_IATBTR_STEP            U(0x001)\n#define SPR_IMMU_IATBTR_INDEX(N)        (SPR_IMMU_IATBTR_BASE + \\\n\t                                 (SPR_IMMU_IATBTR_STEP * (N)))\n#define SPR_IMMU_IATBTR_ADDR(N)         ((SPR_IMMU_GROUP << SPR_GROUP_LSB) | \\\n\t                                 SPR_IMMU_IATBTR_INDEX(N))\n\n/* Cache Coherency */\n#define SPR_IMMU_IATBTR_CC_OFFSET       0\n#define SPR_IMMU_IATBTR_CC_MASK         0x00000001\n#define SPR_IMMU_IATBTR_CC_GET(x)       (((x) >> 0) & 0x1)\n#define SPR_IMMU_IATBTR_CC_SET(x, y)    (((x) & U(0xfffffffe)) | \\\n\t                                 ((!!(y)) << 0))\n\n/* Cache Inhibit */\n#define SPR_IMMU_IATBTR_CI_OFFSET       1\n#define SPR_IMMU_IATBTR_CI_MASK         0x00000002\n#define SPR_IMMU_IATBTR_CI_GET(x)       (((x) >> 1) & 0x1)\n#define SPR_IMMU_IATBTR_CI_SET(x, y)    (((x) & U(0xfffffffd)) | \\\n\t                                 ((!!(y)) << 1))\n\n/* Write-back Cache */\n#define SPR_IMMU_IATBTR_WBC_OFFSET      2\n#define SPR_IMMU_IATBTR_WBC_MASK        0x00000004\n#define SPR_IMMU_IATBTR_WBC_GET(x)      (((x) >> 2) & 0x1)\n#define SPR_IMMU_IATBTR_WBC_SET(x, y)   (((x) & U(0xfffffffb)) | \\\n\t                                 ((!!(y)) << 2))\n\n/* Weakly-ordered Memory */\n#define SPR_IMMU_IATBTR_WOM_OFFSET      3\n#define SPR_IMMU_IATBTR_WOM_MASK        0x00000008\n#define SPR_IMMU_IATBTR_WOM_GET(x)      (((x) >> 3) & 0x1)\n#define SPR_IMMU_IATBTR_WOM_SET(x, y)   (((x) & U(0xfffffff7)) | \\\n\t                                 ((!!(y)) << 3))\n\n/* Accessed */\n#define SPR_IMMU_IATBTR_A_OFFSET        4\n#define SPR_IMMU_IATBTR_A_MASK          0x00000010\n#define SPR_IMMU_IATBTR_A_GET(x)        (((x) >> 4) & 0x1)\n#define SPR_IMMU_IATBTR_A_SET(x, y)     (((x) & U(0xffffffef)) | \\\n\t                                 ((!!(y)) << 4))\n\n/* Dirty */\n#define SPR_IMMU_IATBTR_D_OFFSET        5\n#define SPR_IMMU_IATBTR_D_MASK          0x00000020\n#define SPR_IMMU_IATBTR_D_GET(x)        (((x) >> 5) & 0x1)\n#define SPR_IMMU_IATBTR_D_SET(x, y)     (((x) & U(0xffffffdf)) | \\\n\t                                 ((!!(y)) << 5))\n\n/* Supervisor Execute Enable */\n#define SPR_IMMU_IATBTR_SRE_OFFSET      6\n#define SPR_IMMU_IATBTR_SRE_MASK        0x00000040\n#define SPR_IMMU_IATBTR_SRE_GET(x)      (((x) >> 6) & 0x1)\n#define SPR_IMMU_IATBTR_SRE_SET(x, y)   (((x) & U(0xffffffbf)) | \\\n\t                                 ((!!(y)) << 6))\n\n/* User Execute Enable */\n#define SPR_IMMU_IATBTR_URE_OFFSET      7\n#define SPR_IMMU_IATBTR_URE_MASK        0x00000080\n#define SPR_IMMU_IATBTR_URE_GET(x)      (((x) >> 7) & 0x1)\n#define SPR_IMMU_IATBTR_URE_SET(x, y)   (((x) & U(0xffffff7f)) | \\\n\t                                 ((!!(y)) << 7))\n\n/* Physical Page Number */\n#define SPR_IMMU_IATBTR_PPN_LSB         10\n#define SPR_IMMU_IATBTR_PPN_MSB         31\n#define SPR_IMMU_IATBTR_PPN_BITS        22\n#define SPR_IMMU_IATBTR_PPN_MASK        U(0xfffffc00)\n#define SPR_IMMU_IATBTR_PPN_GET(x)      (((x) >> 10) & U(0x003fffff))\n#define SPR_IMMU_IATBTR_PPN_SET(x, y)   (((x) & U(0x000003ff)) | \\\n\t                                 ((y) << 10))\n\n/* Instruction TLB */\n#define SPR_IMMU_ITLBW_BASE             U(0x200)\n#define SPR_IMMU_ITLBW_COUNT            U(0x004)\n#define SPR_IMMU_ITLBW_STEP             U(0x100)\n#define SPR_IMMU_ITLBW_SUBBASE(N0)      (SPR_IMMU_ITLBW_BASE + \\\n\t                                 (SPR_IMMU_ITLBW_STEP * (N0)))\n\n/* Instruction TLB Match Registers */\n#define SPR_IMMU_ITLBW_MR_BASE          U(0x000)\n#define SPR_IMMU_ITLBW_MR_COUNT         U(0x080)\n#define SPR_IMMU_ITLBW_MR_STEP          U(0x001)\n\n#define SPR_IMMU_ITLBW_MR_INDEX(N0, N1) (SPR_IMMU_ITLBW_SUBBASE(N0) + \\\n\t                                 SPR_IMMU_ITLBW_MR_BASE + \\\n\t                                 (SPR_IMMU_ITLBW_MR_STEP * (N1)))\n#define SPR_IMMU_ITLBW_MR_ADDR(N0, N1)  ((SPR_IMMU_GROUP << SPR_GROUP_LSB) | \\\n\t                                 SPR_IMMU_ITLBW_MR_INDEX(N0, N1))\n\n/* Valid */\n#define SPR_IMMU_ITLBW_MR_V_OFFSET      0\n#define SPR_IMMU_ITLBW_MR_V_MASK        0x00000001\n#define SPR_IMMU_ITLBW_MR_V_GET(x)      (((x) >> 0) & 0x1)\n#define SPR_IMMU_ITLBW_MR_V_SET(x, y)   (((x) & U(0xfffffffe)) | \\\n\t                                 ((!!(y)) << 0))\n\n/* Page Level 1 */\n#define SPR_IMMU_ITLBW_MR_PL1_OFFSET    1\n#define SPR_IMMU_ITLBW_MR_PL1_MASK      0x00000002\n#define SPR_IMMU_ITLBW_MR_PL1_GET(x)    (((x) >> 1) & 0x1)\n#define SPR_IMMU_ITLBW_MR_PL1_SET(x, y) (((x) & U(0xfffffffd)) | \\\n\t                                 ((!!(y)) << 1))\n\n/* Context ID */\n#define SPR_IMMU_ITLBW_MR_CID_LSB       2\n#define SPR_IMMU_ITLBW_MR_CID_MSB       5\n#define SPR_IMMU_ITLBW_MR_CID_BITS      4\n#define SPR_IMMU_ITLBW_MR_CID_MASK      U(0x0000003c)\n#define SPR_IMMU_ITLBW_MR_CID_GET(x)    (((x) >> 2) & U(0x0000000f))\n#define SPR_IMMU_ITLBW_MR_CID_SET(x, y) (((x) & U(0xffffffc3)) | \\\n\t                                 ((y) << 2))\n\n/* Least Recently Used */\n#define SPR_IMMU_ITLBW_MR_LRU_LSB       6\n#define SPR_IMMU_ITLBW_MR_LRU_MSB       7\n#define SPR_IMMU_ITLBW_MR_LRU_BITS      2\n#define SPR_IMMU_ITLBW_MR_LRU_MASK      U(0x000000c0)\n#define SPR_IMMU_ITLBW_MR_LRU_GET(x)    (((x) >> 6) & U(0x00000003))\n#define SPR_IMMU_ITLBW_MR_LRU_SET(x, y) (((x) & U(0xffffff3f)) | \\\n\t                                 ((y) << 6))\n\n/* Virtual Page Number */\n#define SPR_IMMU_ITLBW_MR_VPN_LSB       13\n#define SPR_IMMU_ITLBW_MR_VPN_MSB       31\n#define SPR_IMMU_ITLBW_MR_VPN_BITS      19\n#define SPR_IMMU_ITLBW_MR_VPN_MASK      U(0xffffe000)\n#define SPR_IMMU_ITLBW_MR_VPN_GET(x)    (((x) >> 13) & U(0x0007ffff))\n#define SPR_IMMU_ITLBW_MR_VPN_SET(x, y) (((x) & U(0x00001fff)) | \\\n\t                                 ((y) << 13))\n\n/* Instruction TLB Translate Registers */\n#define SPR_IMMU_ITLBW_TR_BASE          U(0x080)\n#define SPR_IMMU_ITLBW_TR_COUNT         U(0x080)\n#define SPR_IMMU_ITLBW_TR_STEP          U(0x001)\n\n#define SPR_IMMU_ITLBW_TR_INDEX(N0, N1) (SPR_IMMU_ITLBW_SUBBASE(N0) + \\\n\t                                 SPR_IMMU_ITLBW_TR_BASE + \\\n\t                                 (SPR_IMMU_ITLBW_TR_STEP * (N1)))\n#define SPR_IMMU_ITLBW_TR_ADDR(N0, N1)  ((SPR_IMMU_GROUP << SPR_GROUP_LSB) | \\\n\t                                 SPR_IMMU_ITLBW_TR_INDEX(N0, N1))\n\n/* Cache Coherency */\n#define SPR_IMMU_ITLBW_TR_CC_OFFSET     0\n#define SPR_IMMU_ITLBW_TR_CC_MASK       0x00000001\n#define SPR_IMMU_ITLBW_TR_CC_GET(x)     (((x) >> 0) & 0x1)\n#define SPR_IMMU_ITLBW_TR_CC_SET(x, y)  (((x) & U(0xfffffffe)) | \\\n\t                                 ((!!(y)) << 0))\n\n/* Cache Inhibit */\n#define SPR_IMMU_ITLBW_TR_CI_OFFSET     1\n#define SPR_IMMU_ITLBW_TR_CI_MASK       0x00000002\n#define SPR_IMMU_ITLBW_TR_CI_GET(x)     (((x) >> 1) & 0x1)\n#define SPR_IMMU_ITLBW_TR_CI_SET(x, y)  (((x) & U(0xfffffffd)) | \\\n\t                                 ((!!(y)) << 1))\n\n/* Write-back Cache */\n#define SPR_IMMU_ITLBW_TR_WBC_OFFSET    2\n#define SPR_IMMU_ITLBW_TR_WBC_MASK      0x00000004\n#define SPR_IMMU_ITLBW_TR_WBC_GET(x)    (((x) >> 2) & 0x1)\n#define SPR_IMMU_ITLBW_TR_WBC_SET(x, y) (((x) & U(0xfffffffb)) | \\\n\t                                 ((!!(y)) << 2))\n\n/* Weakly-ordered Memory */\n#define SPR_IMMU_ITLBW_TR_WOM_OFFSET    3\n#define SPR_IMMU_ITLBW_TR_WOM_MASK      0x00000008\n#define SPR_IMMU_ITLBW_TR_WOM_GET(x)    (((x) >> 3) & 0x1)\n#define SPR_IMMU_ITLBW_TR_WOM_SET(x, y) (((x) & U(0xfffffff7)) | \\\n\t                                 ((!!(y)) << 3))\n\n/* Accessed */\n#define SPR_IMMU_ITLBW_TR_A_OFFSET      4\n#define SPR_IMMU_ITLBW_TR_A_MASK        0x00000010\n#define SPR_IMMU_ITLBW_TR_A_GET(x)      (((x) >> 4) & 0x1)\n#define SPR_IMMU_ITLBW_TR_A_SET(x, y)   (((x) & U(0xffffffef)) | \\\n\t                                 ((!!(y)) << 4))\n\n/* Dirty */\n#define SPR_IMMU_ITLBW_TR_D_OFFSET      5\n#define SPR_IMMU_ITLBW_TR_D_MASK        0x00000020\n#define SPR_IMMU_ITLBW_TR_D_GET(x)      (((x) >> 5) & 0x1)\n#define SPR_IMMU_ITLBW_TR_D_SET(x, y)   (((x) & U(0xffffffdf)) | \\\n\t                                 ((!!(y)) << 5))\n\n/* User Execute Enable */\n#define SPR_IMMU_ITLBW_TR_UXE_OFFSET    6\n#define SPR_IMMU_ITLBW_TR_UXE_MASK      0x00000040\n#define SPR_IMMU_ITLBW_TR_UXE_GET(x)    (((x) >> 6) & 0x1)\n#define SPR_IMMU_ITLBW_TR_UXE_SET(x, y) (((x) & U(0xffffffbf)) | \\\n\t                                 ((!!(y)) << 6))\n\n/* Supervisor Execute Enable */\n#define SPR_IMMU_ITLBW_TR_SXE_OFFSET    7\n#define SPR_IMMU_ITLBW_TR_SXE_MASK      0x00000080\n#define SPR_IMMU_ITLBW_TR_SXE_GET(x)    (((x) >> 7) & 0x1)\n#define SPR_IMMU_ITLBW_TR_SXE_SET(x, y) (((x) & U(0xffffff7f)) | \\\n\t                                 ((!!(y)) << 7))\n\n/* Physical Page Number */\n#define SPR_IMMU_ITLBW_TR_PPN_LSB       13\n#define SPR_IMMU_ITLBW_TR_PPN_MSB       31\n#define SPR_IMMU_ITLBW_TR_PPN_BITS      19\n#define SPR_IMMU_ITLBW_TR_PPN_MASK      U(0xffffe000)\n#define SPR_IMMU_ITLBW_TR_PPN_GET(x)    (((x) >> 13) & U(0x0007ffff))\n#define SPR_IMMU_ITLBW_TR_PPN_SET(x, y) (((x) & U(0x00001fff)) | \\\n\t                                 ((y) << 13))\n\n/********************/\n/* Data Cache Group */\n/********************/\n#define SPR_DCACHE_GROUP             0x03\n\n/* Data Cache Control Register */\n#define SPR_DCACHE_DCCR_INDEX        U(0x000)\n#define SPR_DCACHE_DCCR_ADDR         U(0x1800)\n\n/* Enable Ways */\n#define SPR_DCACHE_DCCR_EW_LSB       0\n#define SPR_DCACHE_DCCR_EW_MSB       7\n#define SPR_DCACHE_DCCR_EW_BITS      8\n#define SPR_DCACHE_DCCR_EW_MASK      U(0x000000ff)\n#define SPR_DCACHE_DCCR_EW_GET(x)    (((x) >> 0) & U(0x000000ff))\n#define SPR_DCACHE_DCCR_EW_SET(x, y) (((x) & U(0xffffff00)) | \\\n\t                              ((y) << 0))\n\n/* Data Cache Block Prefetch Register */\n#define SPR_DCACHE_DCBPR_INDEX       U(0x001)\n#define SPR_DCACHE_DCBPR_ADDR        U(0x1801)\n\n/* Data Cache Block Flush Register */\n#define SPR_DCACHE_DCBFR_INDEX       U(0x002)\n#define SPR_DCACHE_DCBFR_ADDR        U(0x1802)\n\n/* Data Cache Block Invalidate Register */\n#define SPR_DCACHE_DCBIR_INDEX       U(0x003)\n#define SPR_DCACHE_DCBIR_ADDR        U(0x1803)\n\n/* Data Cache Block Write-back Register */\n#define SPR_DCACHE_DCBWR_INDEX       U(0x004)\n#define SPR_DCACHE_DCBWR_ADDR        U(0x1804)\n\n/* Data Cache Block Lock Register */\n#define SPR_DCACHE_DCBLR_INDEX       U(0x005)\n#define SPR_DCACHE_DCBLR_ADDR        U(0x1805)\n\n/***************************/\n/* Instruction Cache Group */\n/***************************/\n#define SPR_ICACHE_GROUP             0x04\n\n/* Instruction Cache Control Register */\n#define SPR_ICACHE_ICCR_INDEX        U(0x000)\n#define SPR_ICACHE_ICCR_ADDR         U(0x2000)\n\n/* Enable Ways */\n#define SPR_ICACHE_ICCR_EW_LSB       0\n#define SPR_ICACHE_ICCR_EW_MSB       7\n#define SPR_ICACHE_ICCR_EW_BITS      8\n#define SPR_ICACHE_ICCR_EW_MASK      U(0x000000ff)\n#define SPR_ICACHE_ICCR_EW_GET(x)    (((x) >> 0) & U(0x000000ff))\n#define SPR_ICACHE_ICCR_EW_SET(x, y) (((x) & U(0xffffff00)) | \\\n\t                              ((y) << 0))\n\n/* Instruction Cache Block Prefetch Register */\n#define SPR_ICACHE_ICBPR_INDEX       U(0x001)\n#define SPR_ICACHE_ICBPR_ADDR        U(0x2001)\n\n/* Instruction Cache Block Invalidate Register */\n#define SPR_ICACHE_ICBIR_INDEX       U(0x002)\n#define SPR_ICACHE_ICBIR_ADDR        U(0x2002)\n\n/* Instruction Cache Block Lock Register */\n#define SPR_ICACHE_ICBLR_INDEX       U(0x003)\n#define SPR_ICACHE_ICBLR_ADDR        U(0x2003)\n\n/*********************************/\n/* Multiply and Accumulate Group */\n/*********************************/\n#define SPR_MAC_GROUP       0x05\n\n/* MAC Result Low Word */\n#define SPR_MAC_MACLO_INDEX U(0x001)\n#define SPR_MAC_MACLO_ADDR  U(0x2801)\n\n/* MAC Result High Word */\n#define SPR_MAC_MACHI_INDEX U(0x002)\n#define SPR_MAC_MACHI_ADDR  U(0x2802)\n\n/***************/\n/* Debug Group */\n/***************/\n#define SPR_DEBUG_GROUP               0x06\n\n/* Debug Value Registers */\n#define SPR_DEBUG_DVR_BASE            U(0x000)\n#define SPR_DEBUG_DVR_COUNT           U(0x008)\n#define SPR_DEBUG_DVR_STEP            U(0x001)\n#define SPR_DEBUG_DVR_INDEX(N)        (SPR_DEBUG_DVR_BASE + \\\n\t                               (SPR_DEBUG_DVR_STEP * (N)))\n#define SPR_DEBUG_DVR_ADDR(N)         ((SPR_DEBUG_GROUP << SPR_GROUP_LSB) | \\\n\t                               SPR_DEBUG_DVR_INDEX(N))\n\n/* Debug Control Registers */\n#define SPR_DEBUG_DCR_BASE            U(0x008)\n#define SPR_DEBUG_DCR_COUNT           U(0x008)\n#define SPR_DEBUG_DCR_STEP            U(0x001)\n#define SPR_DEBUG_DCR_INDEX(N)        (SPR_DEBUG_DCR_BASE + \\\n\t                               (SPR_DEBUG_DCR_STEP * (N)))\n#define SPR_DEBUG_DCR_ADDR(N)         ((SPR_DEBUG_GROUP << SPR_GROUP_LSB) | \\\n\t                               SPR_DEBUG_DCR_INDEX(N))\n\n/* DVR/DCR Present */\n#define SPR_DEBUG_DCR_DP_OFFSET       0\n#define SPR_DEBUG_DCR_DP_MASK         0x00000001\n#define SPR_DEBUG_DCR_DP_GET(x)       (((x) >> 0) & 0x1)\n#define SPR_DEBUG_DCR_DP_SET(x, y)    (((x) & U(0xfffffffe)) | \\\n\t                               ((!!(y)) << 0))\n\n/* Compare Condition */\n#define SPR_DEBUG_DCR_CC_LSB          1\n#define SPR_DEBUG_DCR_CC_MSB          3\n#define SPR_DEBUG_DCR_CC_BITS         3\n#define SPR_DEBUG_DCR_CC_MASK         U(0x0000000e)\n#define SPR_DEBUG_DCR_CC_GET(x)       (((x) >> 1) & U(0x00000007))\n#define SPR_DEBUG_DCR_CC_SET(x, y)    (((x) & U(0xfffffff1)) | \\\n\t                               ((y) << 1))\n\n/* Masked */\n#define SPR_DEBUG_DCR_CC_MASKED       0\n/* Equal */\n#define SPR_DEBUG_DCR_CC_EQ           1\n/* Less than */\n#define SPR_DEBUG_DCR_CC_LT           2\n/* Less than or equal */\n#define SPR_DEBUG_DCR_CC_LTE          3\n/* Greater than */\n#define SPR_DEBUG_DCR_CC_GT           4\n/* Greater than or equal */\n#define SPR_DEBUG_DCR_CC_GTE          5\n/* Not equal */\n#define SPR_DEBUG_DCR_CC_NEQ          6\n\n/* Signed Comparison */\n#define SPR_DEBUG_DCR_SC_OFFSET       4\n#define SPR_DEBUG_DCR_SC_MASK         0x00000010\n#define SPR_DEBUG_DCR_SC_GET(x)       (((x) >> 4) & 0x1)\n#define SPR_DEBUG_DCR_SC_SET(x, y)    (((x) & U(0xffffffef)) | \\\n\t                               ((!!(y)) << 4))\n\n/* Compare To */\n#define SPR_DEBUG_DCR_CT_LSB          5\n#define SPR_DEBUG_DCR_CT_MSB          7\n#define SPR_DEBUG_DCR_CT_BITS         3\n#define SPR_DEBUG_DCR_CT_MASK         U(0x000000e0)\n#define SPR_DEBUG_DCR_CT_GET(x)       (((x) >> 5) & U(0x00000007))\n#define SPR_DEBUG_DCR_CT_SET(x, y)    (((x) & U(0xffffff1f)) | \\\n\t                               ((y) << 5))\n\n/* Comparison disabled */\n#define SPR_DEBUG_DCR_CT_DISABLED     0\n/* Instruction fetch EA */\n#define SPR_DEBUG_DCR_CT_FEA          1\n/* Load EA */\n#define SPR_DEBUG_DCR_CT_LEA          2\n/* Store EA */\n#define SPR_DEBUG_DCR_CT_SEA          3\n/* Load data */\n#define SPR_DEBUG_DCR_CT_LD           4\n/* Store data */\n#define SPR_DEBUG_DCR_CT_SD           5\n/* Load/store EA */\n#define SPR_DEBUG_DCR_CT_LSEA         6\n/* Load/store data */\n#define SPR_DEBUG_DCR_CT_LSD          7\n\n/* Debug Mode Register 1 */\n#define SPR_DEBUG_DMR1_INDEX          U(0x010)\n#define SPR_DEBUG_DMR1_ADDR           U(0x3010)\n\n/* Chain Watchpoint 0 */\n#define SPR_DEBUG_DMR1_CW0_LSB        0\n#define SPR_DEBUG_DMR1_CW0_MSB        1\n#define SPR_DEBUG_DMR1_CW0_BITS       2\n#define SPR_DEBUG_DMR1_CW0_MASK       U(0x00000003)\n#define SPR_DEBUG_DMR1_CW0_GET(x)     (((x) >> 0) & U(0x00000003))\n#define SPR_DEBUG_DMR1_CW0_SET(x, y)  (((x) & U(0xfffffffc)) | \\\n\t                               ((y) << 0))\n\n/* Chain Watchpoint 1 */\n#define SPR_DEBUG_DMR1_CW1_LSB        2\n#define SPR_DEBUG_DMR1_CW1_MSB        3\n#define SPR_DEBUG_DMR1_CW1_BITS       2\n#define SPR_DEBUG_DMR1_CW1_MASK       U(0x0000000c)\n#define SPR_DEBUG_DMR1_CW1_GET(x)     (((x) >> 2) & U(0x00000003))\n#define SPR_DEBUG_DMR1_CW1_SET(x, y)  (((x) & U(0xfffffff3)) | \\\n\t                               ((y) << 2))\n\n/* Chain Watchpoint 2 */\n#define SPR_DEBUG_DMR1_CW2_LSB        4\n#define SPR_DEBUG_DMR1_CW2_MSB        5\n#define SPR_DEBUG_DMR1_CW2_BITS       2\n#define SPR_DEBUG_DMR1_CW2_MASK       U(0x00000030)\n#define SPR_DEBUG_DMR1_CW2_GET(x)     (((x) >> 4) & U(0x00000003))\n#define SPR_DEBUG_DMR1_CW2_SET(x, y)  (((x) & U(0xffffffcf)) | \\\n\t                               ((y) << 4))\n\n/* Chain Watchpoint 3 */\n#define SPR_DEBUG_DMR1_CW3_LSB        6\n#define SPR_DEBUG_DMR1_CW3_MSB        7\n#define SPR_DEBUG_DMR1_CW3_BITS       2\n#define SPR_DEBUG_DMR1_CW3_MASK       U(0x000000c0)\n#define SPR_DEBUG_DMR1_CW3_GET(x)     (((x) >> 6) & U(0x00000003))\n#define SPR_DEBUG_DMR1_CW3_SET(x, y)  (((x) & U(0xffffff3f)) | \\\n\t                               ((y) << 6))\n\n/* Chain Watchpoint 4 */\n#define SPR_DEBUG_DMR1_CW4_LSB        9\n#define SPR_DEBUG_DMR1_CW4_MSB        9\n#define SPR_DEBUG_DMR1_CW4_BITS       1\n#define SPR_DEBUG_DMR1_CW4_MASK       U(0x00000200)\n#define SPR_DEBUG_DMR1_CW4_GET(x)     (((x) >> 9) & U(0x00000001))\n#define SPR_DEBUG_DMR1_CW4_SET(x, y)  (((x) & U(0xfffffdff)) | \\\n\t                               ((y) << 9))\n\n/* Chain Watchpoint 5 */\n#define SPR_DEBUG_DMR1_CW5_LSB        10\n#define SPR_DEBUG_DMR1_CW5_MSB        11\n#define SPR_DEBUG_DMR1_CW5_BITS       2\n#define SPR_DEBUG_DMR1_CW5_MASK       U(0x00000c00)\n#define SPR_DEBUG_DMR1_CW5_GET(x)     (((x) >> 10) & U(0x00000003))\n#define SPR_DEBUG_DMR1_CW5_SET(x, y)  (((x) & U(0xfffff3ff)) | \\\n\t                               ((y) << 10))\n\n/* Chain Watchpoint 6 */\n#define SPR_DEBUG_DMR1_CW6_LSB        12\n#define SPR_DEBUG_DMR1_CW6_MSB        13\n#define SPR_DEBUG_DMR1_CW6_BITS       2\n#define SPR_DEBUG_DMR1_CW6_MASK       U(0x00003000)\n#define SPR_DEBUG_DMR1_CW6_GET(x)     (((x) >> 12) & U(0x00000003))\n#define SPR_DEBUG_DMR1_CW6_SET(x, y)  (((x) & U(0xffffcfff)) | \\\n\t                               ((y) << 12))\n\n/* Chain Watchpoint 7 */\n#define SPR_DEBUG_DMR1_CW7_LSB        14\n#define SPR_DEBUG_DMR1_CW7_MSB        15\n#define SPR_DEBUG_DMR1_CW7_BITS       2\n#define SPR_DEBUG_DMR1_CW7_MASK       U(0x0000c000)\n#define SPR_DEBUG_DMR1_CW7_GET(x)     (((x) >> 14) & U(0x00000003))\n#define SPR_DEBUG_DMR1_CW7_SET(x, y)  (((x) & U(0xffff3fff)) | \\\n\t                               ((y) << 14))\n\n/* Chain Watchpoint 8 */\n#define SPR_DEBUG_DMR1_CW8_LSB        16\n#define SPR_DEBUG_DMR1_CW8_MSB        17\n#define SPR_DEBUG_DMR1_CW8_BITS       2\n#define SPR_DEBUG_DMR1_CW8_MASK       U(0x00030000)\n#define SPR_DEBUG_DMR1_CW8_GET(x)     (((x) >> 16) & U(0x00000003))\n#define SPR_DEBUG_DMR1_CW8_SET(x, y)  (((x) & U(0xfffcffff)) | \\\n\t                               ((y) << 16))\n\n/* Chain Watchpoint 9 */\n#define SPR_DEBUG_DMR1_CW9_LSB        18\n#define SPR_DEBUG_DMR1_CW9_MSB        19\n#define SPR_DEBUG_DMR1_CW9_BITS       2\n#define SPR_DEBUG_DMR1_CW9_MASK       U(0x000c0000)\n#define SPR_DEBUG_DMR1_CW9_GET(x)     (((x) >> 18) & U(0x00000003))\n#define SPR_DEBUG_DMR1_CW9_SET(x, y)  (((x) & U(0xfff3ffff)) | \\\n\t                               ((y) << 18))\n\n/* Single-step Trace */\n#define SPR_DEBUG_DMR1_ST_OFFSET      22\n#define SPR_DEBUG_DMR1_ST_MASK        0x00400000\n#define SPR_DEBUG_DMR1_ST_GET(x)      (((x) >> 22) & 0x1)\n#define SPR_DEBUG_DMR1_ST_SET(x, y)   (((x) & U(0xffbfffff)) | \\\n\t                               ((!!(y)) << 22))\n\n/* Branch Trace */\n#define SPR_DEBUG_DMR1_BT_OFFSET      23\n#define SPR_DEBUG_DMR1_BT_MASK        0x00800000\n#define SPR_DEBUG_DMR1_BT_GET(x)      (((x) >> 23) & 0x1)\n#define SPR_DEBUG_DMR1_BT_SET(x, y)   (((x) & U(0xff7fffff)) | \\\n\t                               ((!!(y)) << 23))\n\n/* Debug Mode Register 2 */\n#define SPR_DEBUG_DMR2_INDEX          U(0x011)\n#define SPR_DEBUG_DMR2_ADDR           U(0x3011)\n\n/* Watchpoint Counter Enable 0 */\n#define SPR_DEBUG_DMR2_WCE0_OFFSET    0\n#define SPR_DEBUG_DMR2_WCE0_MASK      0x00000001\n#define SPR_DEBUG_DMR2_WCE0_GET(x)    (((x) >> 0) & 0x1)\n#define SPR_DEBUG_DMR2_WCE0_SET(x, y) (((x) & U(0xfffffffe)) | \\\n\t                               ((!!(y)) << 0))\n\n/* Watchpoint Counter Enable 1 */\n#define SPR_DEBUG_DMR2_WCE1_OFFSET    1\n#define SPR_DEBUG_DMR2_WCE1_MASK      0x00000002\n#define SPR_DEBUG_DMR2_WCE1_GET(x)    (((x) >> 1) & 0x1)\n#define SPR_DEBUG_DMR2_WCE1_SET(x, y) (((x) & U(0xfffffffd)) | \\\n\t                               ((!!(y)) << 1))\n\n/* Assign Watchpoints to Counter */\n#define SPR_DEBUG_DMR2_AWTC_LSB       2\n#define SPR_DEBUG_DMR2_AWTC_MSB       11\n#define SPR_DEBUG_DMR2_AWTC_BITS      10\n#define SPR_DEBUG_DMR2_AWTC_MASK      U(0x00000ffc)\n#define SPR_DEBUG_DMR2_AWTC_GET(x)    (((x) >> 2) & U(0x000003ff))\n#define SPR_DEBUG_DMR2_AWTC_SET(x, y) (((x) & U(0xfffff003)) | \\\n\t                               ((y) << 2))\n\n/* Watchpoints Generating Breakpoint */\n#define SPR_DEBUG_DMR2_WGB_LSB        12\n#define SPR_DEBUG_DMR2_WGB_MSB        21\n#define SPR_DEBUG_DMR2_WGB_BITS       10\n#define SPR_DEBUG_DMR2_WGB_MASK       U(0x003ff000)\n#define SPR_DEBUG_DMR2_WGB_GET(x)     (((x) >> 12) & U(0x000003ff))\n#define SPR_DEBUG_DMR2_WGB_SET(x, y)  (((x) & U(0xffc00fff)) | \\\n\t                               ((y) << 12))\n\n/* Watchpoints Breakpoint Status */\n#define SPR_DEBUG_DMR2_WBS_LSB        22\n#define SPR_DEBUG_DMR2_WBS_MSB        31\n#define SPR_DEBUG_DMR2_WBS_BITS       10\n#define SPR_DEBUG_DMR2_WBS_MASK       U(0xffc00000)\n#define SPR_DEBUG_DMR2_WBS_GET(x)     (((x) >> 22) & U(0x000003ff))\n#define SPR_DEBUG_DMR2_WBS_SET(x, y)  (((x) & U(0x003fffff)) | \\\n\t                               ((y) << 22))\n\n/* Debug Watchpoint Counter Registers */\n#define SPR_DEBUG_DCWR_BASE           U(0x012)\n#define SPR_DEBUG_DCWR_COUNT          U(0x002)\n#define SPR_DEBUG_DCWR_STEP           U(0x001)\n#define SPR_DEBUG_DCWR_INDEX(N)       (SPR_DEBUG_DCWR_BASE + \\\n\t                               (SPR_DEBUG_DCWR_STEP * (N)))\n#define SPR_DEBUG_DCWR_ADDR(N)        ((SPR_DEBUG_GROUP << SPR_GROUP_LSB) | \\\n\t                               SPR_DEBUG_DCWR_INDEX(N))\n\n/* Debug Stop Register */\n#define SPR_DEBUG_DSR_INDEX           U(0x014)\n#define SPR_DEBUG_DSR_ADDR            U(0x3014)\n\n/* Reset Exception */\n#define SPR_DEBUG_DSR_RSTE_OFFSET     0\n#define SPR_DEBUG_DSR_RSTE_MASK       0x00000001\n#define SPR_DEBUG_DSR_RSTE_GET(x)     (((x) >> 0) & 0x1)\n#define SPR_DEBUG_DSR_RSTE_SET(x, y)  (((x) & U(0xfffffffe)) | \\\n\t                               ((!!(y)) << 0))\n\n/* Bus Error Exception */\n#define SPR_DEBUG_DSR_BUSEE_OFFSET    1\n#define SPR_DEBUG_DSR_BUSEE_MASK      0x00000002\n#define SPR_DEBUG_DSR_BUSEE_GET(x)    (((x) >> 1) & 0x1)\n#define SPR_DEBUG_DSR_BUSEE_SET(x, y) (((x) & U(0xfffffffd)) | \\\n\t                               ((!!(y)) << 1))\n\n/* Data Page Fault Exception */\n#define SPR_DEBUG_DSR_DPFE_OFFSET     2\n#define SPR_DEBUG_DSR_DPFE_MASK       0x00000004\n#define SPR_DEBUG_DSR_DPFE_GET(x)     (((x) >> 2) & 0x1)\n#define SPR_DEBUG_DSR_DPFE_SET(x, y)  (((x) & U(0xfffffffb)) | \\\n\t                               ((!!(y)) << 2))\n\n/* Instruction Page Fault Exception */\n#define SPR_DEBUG_DSR_IPFE_OFFSET     3\n#define SPR_DEBUG_DSR_IPFE_MASK       0x00000008\n#define SPR_DEBUG_DSR_IPFE_GET(x)     (((x) >> 3) & 0x1)\n#define SPR_DEBUG_DSR_IPFE_SET(x, y)  (((x) & U(0xfffffff7)) | \\\n\t                               ((!!(y)) << 3))\n\n/* Tick Timer Exception */\n#define SPR_DEBUG_DSR_TTE_OFFSET      4\n#define SPR_DEBUG_DSR_TTE_MASK        0x00000010\n#define SPR_DEBUG_DSR_TTE_GET(x)      (((x) >> 4) & 0x1)\n#define SPR_DEBUG_DSR_TTE_SET(x, y)   (((x) & U(0xffffffef)) | \\\n\t                               ((!!(y)) << 4))\n\n/* Alignment Exception */\n#define SPR_DEBUG_DSR_AE_OFFSET       5\n#define SPR_DEBUG_DSR_AE_MASK         0x00000020\n#define SPR_DEBUG_DSR_AE_GET(x)       (((x) >> 5) & 0x1)\n#define SPR_DEBUG_DSR_AE_SET(x, y)    (((x) & U(0xffffffdf)) | \\\n\t                               ((!!(y)) << 5))\n\n/* Illegal Instruction Exception */\n#define SPR_DEBUG_DSR_IIE_OFFSET      6\n#define SPR_DEBUG_DSR_IIE_MASK        0x00000040\n#define SPR_DEBUG_DSR_IIE_GET(x)      (((x) >> 6) & 0x1)\n#define SPR_DEBUG_DSR_IIE_SET(x, y)   (((x) & U(0xffffffbf)) | \\\n\t                               ((!!(y)) << 6))\n\n/* Interrupt Exception */\n#define SPR_DEBUG_DSR_INTE_OFFSET     7\n#define SPR_DEBUG_DSR_INTE_MASK       0x00000080\n#define SPR_DEBUG_DSR_INTE_GET(x)     (((x) >> 7) & 0x1)\n#define SPR_DEBUG_DSR_INTE_SET(x, y)  (((x) & U(0xffffff7f)) | \\\n\t                               ((!!(y)) << 7))\n\n/* DTLB Miss Exception */\n#define SPR_DEBUG_DSR_DME_OFFSET      8\n#define SPR_DEBUG_DSR_DME_MASK        0x00000100\n#define SPR_DEBUG_DSR_DME_GET(x)      (((x) >> 8) & 0x1)\n#define SPR_DEBUG_DSR_DME_SET(x, y)   (((x) & U(0xfffffeff)) | \\\n\t                               ((!!(y)) << 8))\n\n/* ITLB Miss Exception */\n#define SPR_DEBUG_DSR_IME_OFFSET      9\n#define SPR_DEBUG_DSR_IME_MASK        0x00000200\n#define SPR_DEBUG_DSR_IME_GET(x)      (((x) >> 9) & 0x1)\n#define SPR_DEBUG_DSR_IME_SET(x, y)   (((x) & U(0xfffffdff)) | \\\n\t                               ((!!(y)) << 9))\n\n/* Range Exception */\n#define SPR_DEBUG_DSR_RE_OFFSET       10\n#define SPR_DEBUG_DSR_RE_MASK         0x00000400\n#define SPR_DEBUG_DSR_RE_GET(x)       (((x) >> 10) & 0x1)\n#define SPR_DEBUG_DSR_RE_SET(x, y)    (((x) & U(0xfffffbff)) | \\\n\t                               ((!!(y)) << 10))\n\n/* System Call Exception */\n#define SPR_DEBUG_DSR_SCE_OFFSET      11\n#define SPR_DEBUG_DSR_SCE_MASK        0x00000800\n#define SPR_DEBUG_DSR_SCE_GET(x)      (((x) >> 11) & 0x1)\n#define SPR_DEBUG_DSR_SCE_SET(x, y)   (((x) & U(0xfffff7ff)) | \\\n\t                               ((!!(y)) << 11))\n\n/* Floating Point Exception */\n#define SPR_DEBUG_DSR_FPE_OFFSET      12\n#define SPR_DEBUG_DSR_FPE_MASK        0x00001000\n#define SPR_DEBUG_DSR_FPE_GET(x)      (((x) >> 12) & 0x1)\n#define SPR_DEBUG_DSR_FPE_SET(x, y)   (((x) & U(0xffffefff)) | \\\n\t                               ((!!(y)) << 12))\n\n/* Trap Exception */\n#define SPR_DEBUG_DSR_TE_OFFSET       13\n#define SPR_DEBUG_DSR_TE_MASK         0x00002000\n#define SPR_DEBUG_DSR_TE_GET(x)       (((x) >> 13) & 0x1)\n#define SPR_DEBUG_DSR_TE_SET(x, y)    (((x) & U(0xffffdfff)) | \\\n\t                               ((!!(y)) << 13))\n\n/* Debug Reason Register */\n#define SPR_DEBUG_DRR_INDEX           U(0x015)\n#define SPR_DEBUG_DRR_ADDR            U(0x3015)\n\n/* Reset Exception */\n#define SPR_DEBUG_DRR_RSTE_OFFSET     0\n#define SPR_DEBUG_DRR_RSTE_MASK       0x00000001\n#define SPR_DEBUG_DRR_RSTE_GET(x)     (((x) >> 0) & 0x1)\n#define SPR_DEBUG_DRR_RSTE_SET(x, y)  (((x) & U(0xfffffffe)) | \\\n\t                               ((!!(y)) << 0))\n\n/* Bus Error Exception */\n#define SPR_DEBUG_DRR_BUSEE_OFFSET    1\n#define SPR_DEBUG_DRR_BUSEE_MASK      0x00000002\n#define SPR_DEBUG_DRR_BUSEE_GET(x)    (((x) >> 1) & 0x1)\n#define SPR_DEBUG_DRR_BUSEE_SET(x, y) (((x) & U(0xfffffffd)) | \\\n\t                               ((!!(y)) << 1))\n\n/* Data Page Fault Exception */\n#define SPR_DEBUG_DRR_DPFE_OFFSET     2\n#define SPR_DEBUG_DRR_DPFE_MASK       0x00000004\n#define SPR_DEBUG_DRR_DPFE_GET(x)     (((x) >> 2) & 0x1)\n#define SPR_DEBUG_DRR_DPFE_SET(x, y)  (((x) & U(0xfffffffb)) | \\\n\t                               ((!!(y)) << 2))\n\n/* Instruction Page Fault Exception */\n#define SPR_DEBUG_DRR_IPFE_OFFSET     3\n#define SPR_DEBUG_DRR_IPFE_MASK       0x00000008\n#define SPR_DEBUG_DRR_IPFE_GET(x)     (((x) >> 3) & 0x1)\n#define SPR_DEBUG_DRR_IPFE_SET(x, y)  (((x) & U(0xfffffff7)) | \\\n\t                               ((!!(y)) << 3))\n\n/* Tick Timer Exception */\n#define SPR_DEBUG_DRR_TTE_OFFSET      4\n#define SPR_DEBUG_DRR_TTE_MASK        0x00000010\n#define SPR_DEBUG_DRR_TTE_GET(x)      (((x) >> 4) & 0x1)\n#define SPR_DEBUG_DRR_TTE_SET(x, y)   (((x) & U(0xffffffef)) | \\\n\t                               ((!!(y)) << 4))\n\n/* Alignment Exception */\n#define SPR_DEBUG_DRR_AE_OFFSET       5\n#define SPR_DEBUG_DRR_AE_MASK         0x00000020\n#define SPR_DEBUG_DRR_AE_GET(x)       (((x) >> 5) & 0x1)\n#define SPR_DEBUG_DRR_AE_SET(x, y)    (((x) & U(0xffffffdf)) | \\\n\t                               ((!!(y)) << 5))\n\n/* Illegal Instruction Exception */\n#define SPR_DEBUG_DRR_IIE_OFFSET      6\n#define SPR_DEBUG_DRR_IIE_MASK        0x00000040\n#define SPR_DEBUG_DRR_IIE_GET(x)      (((x) >> 6) & 0x1)\n#define SPR_DEBUG_DRR_IIE_SET(x, y)   (((x) & U(0xffffffbf)) | \\\n\t                               ((!!(y)) << 6))\n\n/* Interrupt Exception */\n#define SPR_DEBUG_DRR_INTE_OFFSET     7\n#define SPR_DEBUG_DRR_INTE_MASK       0x00000080\n#define SPR_DEBUG_DRR_INTE_GET(x)     (((x) >> 7) & 0x1)\n#define SPR_DEBUG_DRR_INTE_SET(x, y)  (((x) & U(0xffffff7f)) | \\\n\t                               ((!!(y)) << 7))\n\n/* DTLB Miss Exception */\n#define SPR_DEBUG_DRR_DME_OFFSET      8\n#define SPR_DEBUG_DRR_DME_MASK        0x00000100\n#define SPR_DEBUG_DRR_DME_GET(x)      (((x) >> 8) & 0x1)\n#define SPR_DEBUG_DRR_DME_SET(x, y)   (((x) & U(0xfffffeff)) | \\\n\t                               ((!!(y)) << 8))\n\n/* ITLB Miss Exception */\n#define SPR_DEBUG_DRR_IME_OFFSET      9\n#define SPR_DEBUG_DRR_IME_MASK        0x00000200\n#define SPR_DEBUG_DRR_IME_GET(x)      (((x) >> 9) & 0x1)\n#define SPR_DEBUG_DRR_IME_SET(x, y)   (((x) & U(0xfffffdff)) | \\\n\t                               ((!!(y)) << 9))\n\n/* Range Exception */\n#define SPR_DEBUG_DRR_RE_OFFSET       10\n#define SPR_DEBUG_DRR_RE_MASK         0x00000400\n#define SPR_DEBUG_DRR_RE_GET(x)       (((x) >> 10) & 0x1)\n#define SPR_DEBUG_DRR_RE_SET(x, y)    (((x) & U(0xfffffbff)) | \\\n\t                               ((!!(y)) << 10))\n\n/* System Call Exception */\n#define SPR_DEBUG_DRR_SCE_OFFSET      11\n#define SPR_DEBUG_DRR_SCE_MASK        0x00000800\n#define SPR_DEBUG_DRR_SCE_GET(x)      (((x) >> 11) & 0x1)\n#define SPR_DEBUG_DRR_SCE_SET(x, y)   (((x) & U(0xfffff7ff)) | \\\n\t                               ((!!(y)) << 11))\n\n/* Floating Point Exception */\n#define SPR_DEBUG_DRR_FPE_OFFSET      12\n#define SPR_DEBUG_DRR_FPE_MASK        0x00001000\n#define SPR_DEBUG_DRR_FPE_GET(x)      (((x) >> 12) & 0x1)\n#define SPR_DEBUG_DRR_FPE_SET(x, y)   (((x) & U(0xffffefff)) | \\\n\t                               ((!!(y)) << 12))\n\n/* Trap Exception */\n#define SPR_DEBUG_DRR_TE_OFFSET       13\n#define SPR_DEBUG_DRR_TE_MASK         0x00002000\n#define SPR_DEBUG_DRR_TE_GET(x)       (((x) >> 13) & 0x1)\n#define SPR_DEBUG_DRR_TE_SET(x, y)    (((x) & U(0xffffdfff)) | \\\n\t                               ((!!(y)) << 13))\n\n/******************************/\n/* Performance Counters Group */\n/******************************/\n#define SPR_PERF_GROUP         0x07\n\n/* Performance Counters Count Registers */\n#define SPR_PERF_PCCR_BASE     U(0x000)\n#define SPR_PERF_PCCR_COUNT    U(0x008)\n#define SPR_PERF_PCCR_STEP     U(0x001)\n#define SPR_PERF_PCCR_INDEX(N) (SPR_PERF_PCCR_BASE + \\\n\t                        (SPR_PERF_PCCR_STEP * (N)))\n#define SPR_PERF_PCCR_ADDR(N)  ((SPR_PERF_GROUP << SPR_GROUP_LSB) | \\\n\t                        SPR_PERF_PCCR_INDEX(N))\n\n/* Performance Counters Mode Registers */\n#define SPR_PERF_PCMR_BASE     U(0x008)\n#define SPR_PERF_PCMR_COUNT    U(0x008)\n#define SPR_PERF_PCMR_STEP     U(0x001)\n#define SPR_PERF_PCMR_INDEX(N) (SPR_PERF_PCMR_BASE + \\\n\t                        (SPR_PERF_PCMR_STEP * (N)))\n#define SPR_PERF_PCMR_ADDR(N)  ((SPR_PERF_GROUP << SPR_GROUP_LSB) | \\\n\t                        SPR_PERF_PCMR_INDEX(N))\n\n/**************************/\n/* Power Management Group */\n/**************************/\n#define SPR_POWER_GROUP     0x08\n\n/* Power Management Register */\n#define SPR_POWER_PMR_INDEX U(0x000)\n#define SPR_POWER_PMR_ADDR  U(0x4000)\n\n/*******************************************/\n/* Programmable Interrupt Controller Group */\n/*******************************************/\n#define SPR_PIC_GROUP       0x09\n\n/* PIC Mask Register */\n#define SPR_PIC_PICMR_INDEX U(0x000)\n#define SPR_PIC_PICMR_ADDR  U(0x4800)\n\n/* PIC Status Register */\n#define SPR_PIC_PICSR_INDEX U(0x002)\n#define SPR_PIC_PICSR_ADDR  U(0x4802)\n\n/********************/\n/* Tick Timer Group */\n/********************/\n#define SPR_TICK_GROUP               0x0a\n\n/* Tick Timer Mode Register */\n#define SPR_TICK_TTMR_INDEX          U(0x000)\n#define SPR_TICK_TTMR_ADDR           U(0x5000)\n\n/* Time Period */\n#define SPR_TICK_TTMR_TP_LSB         0\n#define SPR_TICK_TTMR_TP_MSB         27\n#define SPR_TICK_TTMR_TP_BITS        28\n#define SPR_TICK_TTMR_TP_MASK        U(0x0fffffff)\n#define SPR_TICK_TTMR_TP_GET(x)      (((x) >> 0) & U(0x0fffffff))\n#define SPR_TICK_TTMR_TP_SET(x, y)   (((x) & U(0xf0000000)) | \\\n\t                              ((y) << 0))\n\n/* Interrupt Pending */\n#define SPR_TICK_TTMR_IP_OFFSET      28\n#define SPR_TICK_TTMR_IP_MASK        0x10000000\n#define SPR_TICK_TTMR_IP_GET(x)      (((x) >> 28) & 0x1)\n#define SPR_TICK_TTMR_IP_SET(x, y)   (((x) & U(0xefffffff)) | \\\n\t                              ((!!(y)) << 28))\n\n/* Interrupt Enable */\n#define SPR_TICK_TTMR_IE_OFFSET      29\n#define SPR_TICK_TTMR_IE_MASK        0x20000000\n#define SPR_TICK_TTMR_IE_GET(x)      (((x) >> 29) & 0x1)\n#define SPR_TICK_TTMR_IE_SET(x, y)   (((x) & U(0xdfffffff)) | \\\n\t                              ((!!(y)) << 29))\n\n/* Mode */\n#define SPR_TICK_TTMR_MODE_LSB       30\n#define SPR_TICK_TTMR_MODE_MSB       31\n#define SPR_TICK_TTMR_MODE_BITS      2\n#define SPR_TICK_TTMR_MODE_MASK      U(0xc0000000)\n#define SPR_TICK_TTMR_MODE_GET(x)    (((x) >> 30) & U(0x00000003))\n#define SPR_TICK_TTMR_MODE_SET(x, y) (((x) & U(0x3fffffff)) | \\\n\t                              ((y) << 30))\n\n/* Disabled */\n#define SPR_TICK_TTMR_MODE_DISABLE   0\n/* Restart counting when TTMR[TP]==TTCR */\n#define SPR_TICK_TTMR_MODE_RESTART   1\n/* Stop counting when TTMR[TP]==TTCR */\n#define SPR_TICK_TTMR_MODE_STOP      2\n/* Continue counting when TTMR[TP]==TTCR */\n#define SPR_TICK_TTMR_MODE_CONTINUE  3\n\n/* Tick Timer Count Register */\n#define SPR_TICK_TTCR_INDEX          U(0x001)\n#define SPR_TICK_TTCR_ADDR           U(0x5001)\n\n/*****************************/\n/* Floating Point Unit Group */\n/*****************************/\n#define SPR_FPU_GROUP 0x0b\n\n#endif /* ASM_SPR_H */\n"
  },
  {
    "path": "arch/or1k/include/exception.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef EXCEPTION_H\n#define EXCEPTION_H\n\n#include <stdint.h>\n\n/**\n * Report the exception that caused the firmware to restart, if applicable.\n *\n * @param exception Exception information provided by startup assembly code.\n */\nvoid report_exception(uint32_t exception);\n\n#endif /* EXCEPTION_H */\n"
  },
  {
    "path": "arch/or1k/include/spr.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef SPR_H\n#define SPR_H\n\n#include <stdint.h>\n#include <asm/spr.h>\n\nstatic inline uint32_t\nmfspr(uint16_t addr)\n{\n\tuint32_t value;\n\n\tasm volatile (\"l.mfspr %0, r0, %1\" : \"=r\" (value) : \"K\" (addr));\n\treturn value;\n}\n\nstatic inline void\nmtspr(uint16_t addr, uint32_t value)\n{\n\tasm volatile (\"l.mtspr r0, %1, %0\" : : \"K\" (addr), \"r\" (value));\n}\n\n#endif /* SPR_H */\n"
  },
  {
    "path": "arch/or1k/include/trap.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef TRAP_H\n#define TRAP_H\n\nstatic inline noreturn void\ntrap(void)\n{\n\tasm volatile (\"l.trap 0\");\n\tunreachable();\n}\n\n#endif /* TRAP_H */\n"
  },
  {
    "path": "arch/or1k/math.S",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <macros.S>\n\nfunc udivmod\n\tl.sw\t-8(r1), r18\n\tl.ori\tr18, r3, 0\t\t# Save pointer to dividend\n\tl.sw\t-4(r1), r9\n\tl.lwz\tr3, 0(r3)\t\t# Load dividend\n\tl.jal\t__udivsi3\n\tl.addi\tr1, r1, -8\n\tl.sw\t0(r18), r11\t\t# Replace dividend with quotient\n\tl.addi\tr1, r1, 8\n\tl.lwz\tr9, -4(r1)\n\tl.lwz\tr18, -8(r1)\n\tl.jr\tr9\n\tl.ori\tr11, r12, 0\t\t# Return remainder\nendfunc udivmod\n"
  },
  {
    "path": "arch/or1k/runtime.S",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <macros.S>\n\nfunc __divsi3\n\tl.sflts\tr3, r0\n\tl.sw\t-8(r1), r18\n\tl.bnf\t1f\n\tl.ori\tr18, r0, 0\n\tl.sub\tr3, r0, r3\t\t# Negate x if it is negative\n\tl.addi\tr18, r18, 1\t\t# Increment the flag if x is negative\n1:\tl.sflts\tr4, r0\n\tl.bnf\t2f\n\tl.sw\t-4(r1), r9\n\tl.sub\tr4, r0, r4\t\t# Negate y if it is negative\n\tl.addi\tr18, r18, -1\t\t# Decrement the flag if y is negative\n2:\tl.jal\t__udivsi3\n\tl.addi\tr1, r1, -8\n\tl.sfne\tr18, r0\n\tl.bnf\t3f\n\tl.addi\tr1, r1, 8\n\tl.sub\tr11, r0, r11\t\t# Negate q if the flag is nonzero\n3:\tl.lwz\tr9, -4(r1)\n\tl.jr\tr9\n\tl.lwz\tr18, -8(r1)\nendfunc __divsi3\n\n/*\n * Of the three ORBIS32 32-bit multiplication instructions (l.mul, l.muli, and\n * l.mulu), only l.mul works. By passing \"-msoft-mul\" to the compiler, and\n * delegating to this function, we can force all multiplication to use l.mul.\n */\nfunc __mulsi3\n\tl.jr\tr9\n\tl.mul\tr11, r3, r4\nendfunc __mulsi3\n\n/*\n * Derived from the \"best method for counting bits in a 32-bit integer\" at\n * https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel.\n *\n * Signed multiplication is used because l.mulu is broken in hardware. This is\n * safe because the previous bit masking ensures neither operand is negative.\n */\nfunc __popcountsi2\n\tl.movhi\tr5, 0x5555\t\t# Statement 1:\n\tl.ori\tr5, r5, 0x5555\t\t#\tr5 = 0x55555555\n\tl.srli\tr4, r3, 1\t\t#\tr4 = v >> 1\n\tl.and\tr4, r4, r5\t\t#\tr4 = (v >> 1) & 0x55555555\n\tl.sub\tr3, r3, r4\t\t#\tv = v - ((v >> 1) & 0x55555555)\n\tl.movhi\tr5, 0x3333\t\t# Statement 2:\n\tl.ori\tr5, r5, 0x3333\t\t#\tr5 = 0x33333333\n\tl.srli\tr4, r3, 2\t\t#\tr4 = v >> 2\n\tl.and\tr4, r4, r5\t\t#\tr4 = (v >> 2) & 0x33333333\n\tl.and\tr3, r3, r5\t\t#\tv = v & 0x33333333\n\tl.add\tr3, r3, r4\t\t#\tv += ((v >> 2) & 0x33333333)\n\tl.movhi\tr5, 0x0f0f\t\t# Statement 3:\n\tl.ori\tr5, r5, 0x0f0f\t\t#\tr5 = 0x0f0f0f0f\n\tl.srli\tr4, r3, 4\t\t#\tr4 = v >> 4\n\tl.add\tr4, r3, r4\t\t#\tr4 = v + (v >> 4)\n\tl.and\tr4, r4, r5\t\t#\tr4 = v + (v >> 4) & 0x0f0f0f0f\n\tl.movhi\tr5, 0x0101\n\tl.ori\tr5, r5, 0x0101\t\t#\tr5 = 0x01010101\n\tl.mul\tr11, r4, r5\t\t#\tc = r4 * 0x01010101\n\tl.jr\tr9\n\tl.srli\tr11, r11, 24\t\t#\treturn c >> 24\nendfunc __popcountsi2\n\n/*\n * Optimized implementation of the \"shift divisor method\" algorithm from\n * T. Rodeheffer. Software Integer Division. Microsoft Research, 2008.\n *\n * In addition to returning the quotient in r11, this function also returns\n * the remainder in r12. __umodsi3 simply copies the remainder into r11.\n */\nfunc __udivsi3\t\t\t\t# u32 __udivsi3(u32 x, u32 y) {\n\tl.sfeqi\tr4, 1\t\t\t#\tif (y == 1)\n\tl.bf\t5f\t\t\t#\t\tgoto identity;\n\tl.ori\tr12, r3, 0\t\t#\tu32 r = x;\n\tl.ori\tr5, r4, 0\t\t#\tu32 y0 = y;\n\tl.addi\tr11, r0, 0\t\t#\tu32 q = 0;\n\tl.sfltu\tr3, r4\t\t\t#\tif (x >= y) {\n\tl.bf\t2f\n\tl.sub\tr3, r3, r4\t\t#\t\tx = x−y;\n1:\tl.sfltu\tr3, r4\t\t\t#\t\twhile (x >= y) {\n\tl.bf\t2f\n\tl.sub\tr3, r3, r4\t\t#\t\t\tx = x−y;\n\tl.add\tr4, r4, r4\t\t#\t\t\ty *= 2;\n\tl.j\t1b\t\t\t#\t\t}\n2:\tl.sfltu\tr12, r4\t\t\t#\t} for (;;) {\n\tl.bf\t3f\t\t\t#\t\tif (r >= y) {\n\tl.sfeq\tr4, r5\t\t\t#\t\t[if (y == y0)]\n\tl.sub\tr12, r12, r4\t\t#\t\t\tr = r−y;\n\tl.addi\tr11, r11, 1\t\t#\t\t\tq = q + 1;\n3:\tl.bf\t4f\t\t\t#\t\t} if (y == y0) break;\n\tl.srli\tr4, r4, 1\t\t#\t\ty >>= 1;\n\tl.j\t2b\t\t\t#\t}\n\tl.add\tr11, r11, r11\t\t#\t\tq *= 2;\n4:\tl.jr\tr9\t\t\t#\treturn q;\n\tl.nop\n5:\tl.ori\tr11, r3, 0\t\t# identity:\n\tl.jr\tr9\t\t\t#\treturn x;\n\tl.ori\tr12, r0, 0\t\t#\tr = 0;\nendfunc __udivsi3\t\t\t# }\n\nfunc __umodsi3\n\tl.sw\t-4(r1), r9\n\tl.jal\t__udivsi3\n\tl.addi\tr1, r1, -4\n\tl.addi\tr1, r1, 4\n\tl.lwz\tr9, -4(r1)\n\tl.jr\tr9\n\tl.ori\tr11, r12, 0\nendfunc __umodsi3\n"
  },
  {
    "path": "arch/or1k/scp.ld.S",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <platform/css.h>\n#include <platform/memory.h>\n\n#if CONFIG(COMPILE_TEST)\n#undef  SRAM_A2_SIZE\n#define SRAM_A2_SIZE 0xffffffff\n#endif\n\nOUTPUT_ARCH(or1k)\nOUTPUT_FORMAT(elf32-or1k)\n\nENTRY (start)\n\nMEMORY {\n  SRAM_A2 (rwx): ORIGIN = SRAM_A2_BASE, LENGTH = SRAM_A2_SIZE\n}\n\nSECTIONS\n{\n  ASSERT(FIRMWARE_BASE >= SRAM_A2_BASE, \"Firmware must be placed in SRAM A2\")\n  ASSERT(FIRMWARE_LIMIT <= SRAM_A2_LIMIT, \"Firmware must fit inside SRAM A2\")\n\n  /*\n   * If addresses within the firmware differ only in their lower 16 bits, a\n   * single l.movhi instruction can be shared by multiple symbol references.\n   */\n  ASSERT(FIRMWARE_BASE >> 16 == (FIRMWARE_LIMIT - 1) >> 16,\n         \"Firmware must not cross a 64k address boundary\")\n\n  . = FIRMWARE_BASE;\n\n  .text . : ALIGN(4) {\n    KEEP(*(.text.start))\n    *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.text*)))\n    . = ALIGN(4);\n  } >SRAM_A2\n\n  .rodata . : ALIGN(4) {\n    *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*)))\n    . = ALIGN(4);\n  } >SRAM_A2\n\n  .data . : ALIGN(4) {\n    *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.data*)))\n    . = ALIGN(4);\n  } >SRAM_A2\n\n  /*\n   * With few exceptions, global data should be constant or initialized during\n   * boot. Before changing this value, verify the firmware can recover from a\n   * crash even after the new data is modified.\n   */\n  ASSERT(SIZEOF(.data) == ALIGN(MAX_CLUSTERS * MAX_CORES_PER_CLUSTER + 8, 4),\n         \"Changes to .data persist after an exception!\")\n\n  .bss . : ALIGN(4) {\n    __bss_start = .;\n    *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*)))\n    . = ALIGN(4);\n    __bss_end = .;\n  } >SRAM_A2\n\n  __stack_start = .;\n  . += STACK_SIZE;\n  __stack_end = .;\n\n#if !CONFIG(COMPILE_TEST)\n  ASSERT(. <= FIRMWARE_LIMIT, \"Firmware overflows allocated memory area\")\n  ASSERT(. <= SCPI_MEM_BASE, \"Firmware overflows into SCPI shared memory\")\n#endif\n\n  __scpi_mem = SCPI_MEM_BASE;\n\n  /DISCARD/ : {\n    *(.comment*)\n    *(.eh_frame_hdr*)\n    *(.iplt*)\n    *(.note*)\n    *(.rela*)\n  }\n}\n"
  },
  {
    "path": "arch/or1k/start.S",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <macros.S>\n#include <asm/spr.h>\n\nfunc start\n\t# Save the exception vector address\n\tl.mfspr\tr2, r0, SPR_SYS_PPC_ADDR\n\n\t# Invalidate the instruction cache\n\tl.addi\tr3, r0, 0\n\tl.addi\tr4, r0, 4096\t\t# Cache lines (256) * block size (16)\n1:\tl.mtspr\tr0, r3, SPR_ICACHE_ICBIR_ADDR\n\tl.sfltu\tr3, r4\n\tl.bf\t1b\n\tl.addi\tr3, r3, 16\t\t# Cache block size\n\n\t# Flush the CPU pipeline\n\tl.psync\n\n\t# Enable the instruction cache\n\tl.mfspr\tr3, r0, SPR_SYS_SR_ADDR\n\tl.ori\tr3, r3, SPR_SYS_SR_ICE_MASK\n\tl.mtspr\tr0, r3, SPR_SYS_SR_ADDR\n\n\t# One cache block of nops\n\tl.nop\n\tl.nop\n\tl.nop\n\tl.nop\n\n\t# Clear .bss\n\tl.movhi\tr10, hi(start)\t\t# High word is common to all symbols\n\tl.ori\tr3, r10, lo(__bss_start)\n\tl.ori\tr4, r10, lo(__bss_end)\n1:\tl.sw\t0(r3), r0\n\tl.sfltu\tr3, r4\n\tl.bf\t1b\n\tl.addi\tr3, r3, 4\n\n\t# Prepare function arguments\n\tl.sfltui r2, 0x4000\t\t# Did PC come from an exception vector?\n\tl.bnf\t1f\n\tl.movhi\tr3, 0\t\t\t# Set to zero if not an exception\n\tl.srli\tr3, r2, 8\t\t# Else compute the exception number\n\n\t# Jump to the C entry point\n1:\tl.j\tsystem_state_machine\n\tl.ori\tr1, r10, lo(__stack_end)\nendfunc start\n"
  },
  {
    "path": "common/Kconfig",
    "content": "#\n# Copyright © 2017-2022 The Crust Firmware Authors.\n# SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n#\n\nmenu \"Firmware features\"\n\nconfig PMIC_SHUTDOWN\n\tbool \"Use PMIC for full hardware shutdown\"\n\tdepends on PMIC\n\tdefault y\n\thelp\n\t\tCommand the PMIC to turn off all outputs during the\n\t\tshutdown procedure. This reduces power usage to almost\n\t\tzero, but also stops the firmware. In this state, only a\n\t\tpower button connected directly to the PMIC can turn the\n\t\tsystem back on.\n\n\t\tIf this option is disabled, the shutdown procedure will\n\t\tbe implemented in software only (similar to the suspend\n\t\tprocedure), so the firmware can turn the system back on.\n\n\t\tSay Y if your board is powered by a battery, or N if you\n\t\tneed some other method of turning on the system, such as\n\t\tan IR remote control or a GPIO input.\n\nendmenu\n\nsource \"debug/Kconfig\"\n"
  },
  {
    "path": "common/Makefile",
    "content": "#\n# Copyright © 2017-2022 The Crust Firmware Authors.\n# SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n#\n\nobj-y += debug/\n\nobj-y += debug.o\nobj-y += delay.o\nobj-y += device.o\nobj-y += regulator_list.o\nobj-y += scpi.o\nobj-y += scpi_cmds.o\nobj-y += simple_device.o\nobj-y += system.o\nobj-y += timeout.o\n"
  },
  {
    "path": "common/debug/Kconfig",
    "content": "#\n# Copyright © 2017-2022 The Crust Firmware Authors.\n# SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n#\n\nmenu \"Debugging options\"\n\nconfig ASSERT\n\tbool \"Enable runtime assertion checking\"\n\tdefault y\n\thelp\n\t\tEnable assert() logic to validate assumptions and find\n\t\tbugs at runtime. If in doubt, say Y.\n\nconfig ASSERT_VERBOSE\n\tbool \"Verbose logging of assertion failures\"\n\tdepends on ASSERT\n\thelp\n\t\tWhen an assertion fails, print detailed information\n\t\tabout it to the console. This includes the expression\n\t\tthat was checked, as well as the file and line number of\n\t\tthe call to assert().\n\n\t\tThe address of the failed assertion is printed with or\n\t\twithout this option. Since all of the other details can\n\t\tbe derived from the address and debug info (see below),\n\t\tenabling this option is only necessary when debug info\n\t\tis unavailable.\n\n\t\tNote that this option significantly increases the size\n\t\tof the final firmware binary. If in doubt, say N.\n\nconfig COMPILE_TEST\n\tbool \"Allow compiling a firmware that does not run\"\n\thelp\n\t\tSome combinations of options may not make sense or may\n\t\tnot produce a functional firmware, for example if the\n\t\tfirmware becomes too large, or if it contains multiple\n\t\tdrivers for the same piece of hardware.\n\n\t\tThis is mostly useful for development and automated\n\t\ttesting. Users should say N.\n\nconfig DEBUG_INFO\n\tbool \"Compile the firmware with debug info\"\n\tdefault y\n\thelp\n\t\tWhen compiling the firmware, generate debug information\n\t\tfor use with gdb. These are stripped out of the final\n\t\tfirmware binary, so this option does not affect the\n\t\tloaded firmware size. If in doubt, say Y.\n\nconfig DEBUG_LOG\n\tbool \"Print additional debug-level log messages\"\n\thelp\n\t\tThis enables the debug() logging macro to print verbose\n\t\tinformational messages that may aid in debugging.\n\nconfig DEBUG_MONITOR\n\tbool \"Provide an interactive debug monitor while off/asleep\"\n\thelp\n\t\tWhile the system is off or asleep, accept simple commands\n\t\ton the serial port. Parsing is extremely basic, and line\n\t\tediting is not supported. Available commands are:\n\t\t\tm <address> [value] -- read/write memory\n\t\t\tw -- trigger wakeup\n\n\t\tWith a PMIC present, additional commands are supported:\n\t\t\tp <address> [value] -- read/write PMIC registers\n\nconfig DEBUG_MONITOR_PMIC\n\tbool\n\tdepends on DEBUG_MONITOR\n\tdefault MFD_AXP20X\n\nconfig DEBUG_PRINT_BATTERY\n\tbool \"Print battery consumption periodically while off/asleep\"\n\tdepends on MFD_AXP223 || MFD_AXP803\n\thelp\n\t\tWhile the system is off or asleep and the battery is\n\t\tdischarging, print the battery voltage, discharge\n\t\tcurrent, and calculated power usage every 30 seconds.\n\nconfig DEBUG_PRINT_LATENCY\n\tbool \"Print average latency after each state transition\"\n\thelp\n\t\tAfter each system state transition, calculate the\n\t\taverage latency of the main loop, in AR100 clock cycles.\n\t\tThe latency will be printed after the firmware has\n\t\tperformed 10000 iterations in that state.\n\nconfig DEBUG_PRINT_SPRS\n\tbool \"Print the contents of Special Purpose Registers at boot\"\n\tdepends on ARCH_OR1K\n\thelp\n\t\tThe OpenRISC 1000 architecture defines various Special\n\t\tPurpose Registers, or SPRs, that describe the particular\n\t\tCPU implementation. Enable this option to print a subset\n\t\tof these SPRs in a human-readable format during boot.\n\nconfig DEBUG_RECORD_STEPS\n\tbool \"Record steps of the suspend/resume process in the RTC\"\n\tdepends on !PLATFORM_A83T # No RTC\n\thelp\n\t\tRecord the start of various steps of the suspend and\n\t\tresume processes in one of the RTC's general purpose\n\t\tregisters. This provides an approximation of what the\n\t\tfirmware was doing at the time of a hang. The last step\n\t\twill remain available in the RTC until a clean shutdown\n\t\tor reboot, or until power is removed.\n\nconfig DEBUG_VERIFY_DRAM\n\tbool \"Verify DRAM contents after controller resume\"\n\thelp\n\t\tAfter reinitializing the DRAM controller during system\n\t\tresume, verify that DRAM contents were preserved via a\n\t\tsimple checksum.\n\n\t\tThe algorithm is very simplistic, and only a small\n\t\tportion of DRAM is checked, so there is no guarantee\n\t\tthat corruption will be detected.\n\nendmenu\n"
  },
  {
    "path": "common/debug/Makefile",
    "content": "#\n# Copyright © 2020-2022 The Crust Firmware Authors.\n# SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n#\n\nobj-$(CONFIG_DEBUG_MONITOR)       += monitor.o\nobj-$(CONFIG_DEBUG_PRINT_BATTERY) += battery.o\nobj-$(CONFIG_DEBUG_PRINT_LATENCY) += latency.o\nobj-$(CONFIG_DEBUG_PRINT_SPRS)    += sprs.o\nobj-$(CONFIG_DEBUG_RECORD_STEPS)  += steps.o\nobj-$(CONFIG_DEBUG_VERIFY_DRAM)   += dram.o\n"
  },
  {
    "path": "common/debug/battery.c",
    "content": "/*\n * Copyright © 2020-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <debug.h>\n#include <division.h>\n#include <regmap.h>\n#include <stdint.h>\n#include <timeout.h>\n#include <util.h>\n#include <mfd/axp20x.h>\n\n#define MEASUREMENT_INTERVAL (30 * USEC_PER_SEC) /* 30s */\n\nstatic uint32_t timeout;\n\nvoid\ndebug_print_battery(void)\n{\n\tconst struct regmap *map = &axp20x.map;\n\tuint32_t current, voltage;\n\tuint8_t  hi, lo, val;\n\n\tif (!timeout_expired(timeout))\n\t\treturn;\n\tif (regmap_user_probe(map))\n\t\treturn;\n\n\t/* Battery present? */\n\tif (regmap_read(map, 0x01, &val) || !(val & BIT(5)))\n\t\tgoto err_put_mfd;\n\t/* Battery discharging? */\n\tif (regmap_read(map, 0x00, &val) || (val & BIT(2)))\n\t\tgoto err_put_mfd;\n\n\tif (regmap_read(map, 0x78, &hi))\n\t\tgoto err_put_mfd;\n\tif (regmap_read(map, 0x79, &lo))\n\t\tgoto err_put_mfd;\n\tvoltage = udiv_round(((hi << 4) | (lo & 0xf)) * 1100, 1000);\n\n\tif (regmap_read(map, 0x7c, &hi))\n\t\tgoto err_put_mfd;\n\tif (regmap_read(map, 0x7d, &lo))\n\t\tgoto err_put_mfd;\n\tcurrent = (hi << 4) | (lo & 0xf);\n\n\tinfo(\"Using %u mW (%u mA @ %u mV)\",\n\t     udiv_round(current * voltage, 1000), current, voltage);\n\nerr_put_mfd:\n\tregmap_user_release(map);\n\ttimeout = timeout_set(MEASUREMENT_INTERVAL);\n}\n"
  },
  {
    "path": "common/debug/dram.c",
    "content": "/*\n * Copyright © 2021-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <debug.h>\n#include <mmio.h>\n#include <steps.h>\n#include <util.h>\n\n#define DRAM_BASE  0x40000000\n\n#define MIN_OFFSET sizeof(uint32_t)\n#define MAX_OFFSET BIT(26) /* 64 MiB */\n\nstatic uint32_t saved_checksum;\n\nstatic uint32_t\ndram_calc_checksum(void)\n{\n\tuint32_t checksum = 0;\n\n\tfor (uint32_t offset = MIN_OFFSET; offset < MAX_OFFSET; offset <<= 1) {\n\t\tchecksum += mmio_read_32(DRAM_BASE + 1 * offset);\n\t\tchecksum += mmio_read_32(DRAM_BASE + 3 * offset);\n\t\tchecksum += 1;\n\t\tchecksum *= ~offset;\n\t}\n\n\treturn checksum;\n}\n\nvoid\ndram_save_checksum(void)\n{\n\tsaved_checksum = dram_calc_checksum();\n}\n\nvoid\ndram_verify_checksum(void)\n{\n\trecord_step(STEP_RESUME_DRAM_CHECKSUM);\n\tif (dram_calc_checksum() != saved_checksum)\n\t\tpanic(\"DRAM checksum mismatch!\");\n}\n"
  },
  {
    "path": "common/debug/latency.c",
    "content": "/*\n * Copyright © 2020-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <counter.h>\n#include <debug.h>\n#include <division.h>\n#include <system.h>\n\n#define ITERATIONS 10000\n\nstatic uint32_t cycles;\nstatic uint32_t iterations;\nstatic uint8_t  last_state;\n\nvoid\ndebug_print_latency(uint8_t current_state)\n{\n\tif (current_state != last_state) {\n\t\tcycles     = cycle_counter_read();\n\t\titerations = 0;\n\t\tlast_state = current_state;\n\t} else if (iterations < ITERATIONS && ++iterations == ITERATIONS) {\n\t\tinfo(\"State %u: %u cycles/iteration\", current_state,\n\t\t     udiv_round(cycle_counter_read() - cycles, ITERATIONS));\n\t}\n}\n"
  },
  {
    "path": "common/debug/monitor.c",
    "content": "/*\n * Copyright © 2020-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <debug.h>\n#include <mmio.h>\n#include <regmap.h>\n#include <serial.h>\n#include <stdbool.h>\n#include <stddef.h>\n#include <stdint.h>\n#include <system.h>\n#include <mfd/axp20x.h>\n\n#define MAX_LENGTH 23 /* \"m 0x???????? 0x????????\" */\n\nstatic char buffer[MAX_LENGTH + 1];\nstatic uint8_t length;\n\nstatic bool\nparse_hex(const char **str, uint32_t *num)\n{\n\tuint32_t n    = 0;\n\tconst char *s = *str;\n\tbool ret      = false;\n\n\t/* Skip spaces. */\n\twhile (*s == ' ')\n\t\t++s;\n\n\t/* At least one space must precede the number. */\n\tif (s == *str)\n\t\treturn false;\n\n\t/* Consume as many hex digits as found. */\n\tfor (;;) {\n\t\tuint32_t c = *s | 0x20;\n\t\tuint32_t digit;\n\n\t\tif (c - '0' < 10)\n\t\t\tdigit = c - '0';\n\t\telse if (c - 'a' < 6)\n\t\t\tdigit = c - ('a' - 10);\n\t\telse if (c == 'x')\n\t\t\tdigit = 0;\n\t\telse\n\t\t\tbreak;\n\t\t++s;\n\t\tn   = n << 4 | digit;\n\t\tret = true;\n\t}\n\t*str = s;\n\t*num = n;\n\n\treturn ret;\n}\n\nstatic void\nrun_command(const char *cmd)\n{\n\tuint32_t addr, len;\n\n\tswitch (*cmd++) {\n\tcase 'd':\n\t\t/* Hex dump: \"d xxxxxxxx xxxxxxxx\", arguments in bare hex. */\n\t\tif (parse_hex(&cmd, &addr) && parse_hex(&cmd, &len))\n\t\t\thexdump(addr, len);\n\t\treturn;\n\tcase 'm':\n\t\t/* MMIO: \"m xxxxxxxx\" or \"m xxxxxxxx xxxxxxxx\", bare hex. */\n\t\tif (parse_hex(&cmd, &addr)) {\n\t\t\tuint32_t val;\n\n\t\t\tif (parse_hex(&cmd, &val))\n\t\t\t\tmmio_write_32(addr, val);\n\n\t\t\tlog(\"%08x: %08x\\n\", addr, mmio_read_32(addr));\n\t\t}\n\t\treturn;\n#if CONFIG(DEBUG_MONITOR_PMIC)\n\tcase 'p':\n\t\t/* PMIC: \"p xx\" or \"p xx xx\", bare hex. */\n\t\tif (parse_hex(&cmd, &addr)) {\n\t\t\tconst struct regmap *map = &axp20x.map;\n\t\t\tuint32_t val32;\n\t\t\tuint8_t  val8;\n\n\t\t\tif (regmap_user_probe(map))\n\t\t\t\treturn;\n\n\t\t\tif (parse_hex(&cmd, &val32))\n\t\t\t\tregmap_write(map, addr, val32);\n\n\t\t\tregmap_read(map, addr, &val8);\n\t\t\tlog(\"%02x: %02x\\n\", addr, val8);\n\n\t\t\tregmap_user_release(map);\n\t\t}\n\t\treturn;\n#endif\n\tcase 'w':\n\t\t/* Wake: \"w\". */\n\t\tsystem_wake();\n\t\treturn;\n\t}\n}\n\nvoid\ndebug_monitor(void)\n{\n\tunsigned char c;\n\n\tif (!serial_ready())\n\t\treturn;\n\tif (!(c = serial_getc()))\n\t\treturn;\n\n\tif (c < ' ' || length == MAX_LENGTH) {\n\t\tserial_putc('\\n');\n\t\tif (c == '\\r') {\n\t\t\tbuffer[length] = 0;\n\t\t\trun_command(buffer);\n\t\t}\n\t\tserial_puts(\"> \");\n\t\tlength = 0;\n\t} else {\n\t\tserial_putc(c);\n\t\tbuffer[length++] = c;\n\t}\n}\n"
  },
  {
    "path": "common/debug/sprs.c",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <debug.h>\n#include <spr.h>\n#include <stdint.h>\n\n#define present(val) ((val) ? \"present\" : \"not present\")\n#define yesno(val)   ((val) ? \"yes\" : \"no\")\n\nvoid\ndebug_print_sprs(void)\n{\n\tuint32_t val;\n\n\tval = mfspr(SPR_SYS_VR_ADDR);\n\tinfo(\"Version Register: 0x%08x\", val);\n\tinfo(\"\\tRevision: %u\", SPR_SYS_VR_REV_GET(val));\n\tinfo(\"\\tUpdated Version Registers: %s\",\n\t     present(SPR_SYS_VR_UVRP_GET(val)));\n\tinfo(\"\\tConfiguration Template: 0x%x\", SPR_SYS_VR_CFG_GET(val));\n\tinfo(\"\\tVersion: 0x%x\", SPR_SYS_VR_VER_GET(val));\n\n\tval = mfspr(SPR_SYS_UPR_ADDR);\n\tinfo(\"Unit Present Register: 0x%08x\", val);\n\tinfo(\"\\tUPR: %s\", present(SPR_SYS_UPR_UP_GET(val)));\n\tinfo(\"\\tData Cache: %s\", present(SPR_SYS_UPR_DCP_GET(val)));\n\tinfo(\"\\tInstruction Cache: %s\", present(SPR_SYS_UPR_ICP_GET(val)));\n\tinfo(\"\\tData MMU: %s\", present(SPR_SYS_UPR_DMP_GET(val)));\n\tinfo(\"\\tInstruction MMU: %s\", present(SPR_SYS_UPR_IMP_GET(val)));\n\tinfo(\"\\tMAC: %s\", present(SPR_SYS_UPR_MP_GET(val)));\n\tinfo(\"\\tDebug Unit: %s\", present(SPR_SYS_UPR_DUP_GET(val)));\n\tinfo(\"\\tPerformance Counters Unit: %s\",\n\t     present(SPR_SYS_UPR_PCUP_GET(val)));\n\tinfo(\"\\tPower Management: %s\", present(SPR_SYS_UPR_PICP_GET(val)));\n\tinfo(\"\\tProgrammable Interrupt Controller: %s\",\n\t     present(SPR_SYS_UPR_PMP_GET(val)));\n\tinfo(\"\\tTick Timer: %s\", present(SPR_SYS_UPR_TTP_GET(val)));\n\tinfo(\"\\tCustom Units (mask): 0x%02x\", SPR_SYS_UPR_CUP_GET(val));\n\n\tval = mfspr(SPR_SYS_CPUCFGR_ADDR);\n\tinfo(\"CPU Configuration Register: 0x%08x\", val);\n\tinfo(\"\\tNumber of Shadow GPR Files: %d\",\n\t     SPR_SYS_CPUCFGR_NSGF_GET(val));\n\tinfo(\"\\tCustom GPR File: %s\", yesno(SPR_SYS_CPUCFGR_CGF_GET(val)));\n\tinfo(\"\\tORBIS32 Supported: %s\", yesno(SPR_SYS_CPUCFGR_OB32S_GET(val)));\n\tinfo(\"\\tORBIS64 Supported: %s\", yesno(SPR_SYS_CPUCFGR_OB64S_GET(val)));\n\tinfo(\"\\tORFPX32 Supported: %s\", yesno(SPR_SYS_CPUCFGR_OF32S_GET(val)));\n\tinfo(\"\\tORFPX64 Supported: %s\", yesno(SPR_SYS_CPUCFGR_OF64S_GET(val)));\n\tinfo(\"\\tORVDX64 Supported: %s\", yesno(SPR_SYS_CPUCFGR_OV64S_GET(val)));\n\tinfo(\"\\tDelay Slot: %s\", yesno(!SPR_SYS_CPUCFGR_ND_GET(val)));\n\tinfo(\"\\tArchitecture Version Register: %s\",\n\t     present(SPR_SYS_CPUCFGR_AVRP_GET(val)));\n\tinfo(\"\\tException Vector Base Address Register: %s\",\n\t     present(SPR_SYS_CPUCFGR_EVBARP_GET(val)));\n\tinfo(\"\\tImplementation-Specific Registers (ISR0-7): %s\",\n\t     present(SPR_SYS_CPUCFGR_ISRP_GET(val)));\n\tinfo(\"\\tArithmetic Exception Control/Status Registers: %s\",\n\t     present(SPR_SYS_CPUCFGR_AECSRP_GET(val)));\n\n\tval = mfspr(SPR_SYS_DCCFGR_ADDR);\n\tinfo(\"Data Cache Configuration Register: 0x%08x\", val);\n\tinfo(\"\\tNumber of Cache Ways: %d\", BIT(SPR_SYS_DCCFGR_NCW_GET(val)));\n\tinfo(\"\\tNumber of Cache Sets: %d\", BIT(SPR_SYS_DCCFGR_NCS_GET(val)));\n\tinfo(\"\\tCache Block Size: %d\", BIT(4 + SPR_SYS_DCCFGR_CBS_GET(val)));\n\tinfo(\"\\tCache Write Strategy: %s\",\n\t     SPR_SYS_DCCFGR_CWS_GET(val) ? \"WT\" : \"WB\");\n\tinfo(\"\\tCache Control Register Implemented: %s\",\n\t     yesno(SPR_SYS_DCCFGR_CCRI_GET(val)));\n\tinfo(\"\\tCache Block Invalidate Register Implemented: %s\",\n\t     yesno(SPR_SYS_DCCFGR_CBIRI_GET(val)));\n\tinfo(\"\\tCache Block Prefetch Register Implemented: %s\",\n\t     yesno(SPR_SYS_DCCFGR_CBPRI_GET(val)));\n\tinfo(\"\\tCache Block Lock Register Implemented: %s\",\n\t     yesno(SPR_SYS_DCCFGR_CBLRI_GET(val)));\n\tinfo(\"\\tCache Block Flush Register Implemented: %s\",\n\t     yesno(SPR_SYS_DCCFGR_CBFRI_GET(val)));\n\tinfo(\"\\tCache Block Write-back Register Implemented: %s\",\n\t     yesno(SPR_SYS_DCCFGR_CBWBRI_GET(val)));\n\n\tval = mfspr(SPR_SYS_ICCFGR_ADDR);\n\tinfo(\"Instruction Cache Configuration Register: 0x%08x\", val);\n\tinfo(\"\\tNumber of Cache Ways: %d\", BIT(SPR_SYS_ICCFGR_NCW_GET(val)));\n\tinfo(\"\\tNumber of Cache Sets: %d\", BIT(SPR_SYS_ICCFGR_NCS_GET(val)));\n\tinfo(\"\\tCache Block Size: %d\", BIT(4 + SPR_SYS_ICCFGR_CBS_GET(val)));\n\tinfo(\"\\tCache Control Register Implemented: %s\",\n\t     yesno(SPR_SYS_ICCFGR_CCRI_GET(val)));\n\tinfo(\"\\tCache Block Invalidate Register Implemented: %s\",\n\t     yesno(SPR_SYS_ICCFGR_CBIRI_GET(val)));\n\tinfo(\"\\tCache Block Prefetch Register Implemented: %s\",\n\t     yesno(SPR_SYS_ICCFGR_CBPRI_GET(val)));\n\tinfo(\"\\tCache Block Lock Register Implemented: %s\",\n\t     yesno(SPR_SYS_ICCFGR_CBLRI_GET(val)));\n}\n"
  },
  {
    "path": "common/debug/steps.c",
    "content": "/*\n * Copyright © 2021-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <debug.h>\n#include <mmio.h>\n#include <steps.h>\n#include <platform/devices.h>\n\n#define RTC_GP_DATA_REG(n) (DEV_RTC + 0x0100 + 0x4 * (n))\n#define LAST_EXCEPTION_REG RTC_GP_DATA_REG(2)\n#define LAST_STEP_REG      RTC_GP_DATA_REG(3)\n\nvoid\nrecord_exception(uint32_t exception, uint32_t pc)\n{\n\tmmio_write_32(LAST_EXCEPTION_REG, exception << 24 | pc);\n}\n\nvoid\nrecord_step(uint32_t step)\n{\n\tmmio_write_32(LAST_STEP_REG, step);\n}\n\nvoid\nreport_last_step(void)\n{\n\tuint32_t step = mmio_read_32(LAST_STEP_REG);\n\n\tif (step != STEP_NONE)\n\t\terror(\"Step %04x failed!\", step);\n}\n"
  },
  {
    "path": "common/debug.c",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <ctype.h>\n#include <debug.h>\n#include <division.h>\n#include <serial.h>\n#include <stdarg.h>\n#include <stdbool.h>\n#include <stdint.h>\n\n#define BYTES_PER_ROW  16\n#define BYTES_PER_WORD sizeof(uint32_t)\n\nstatic char *prefixes[LOG_LEVELS] = {\n\t\"SCP/ERR: \",\n\t\"SCP/WRN: \",\n\t\"SCP/INF: \",\n\t\"SCP/DBG: \",\n};\n\nstatic void print_number(uint32_t num, int base, int width, bool zero);\nstatic void print_signed(int32_t num, int base, int width, bool zero);\n\nvoid\nhexdump(uintptr_t addr, uint32_t bytes)\n{\n\tuintptr_t start;\n\n\t/* Always start at a multiple of BYTES_PER_ROW. */\n\taddr &= ~(BYTES_PER_ROW - 1);\n\tfor (start = addr; addr - start < bytes; addr += BYTES_PER_ROW) {\n\t\tuint32_t *words = (uint32_t *)addr;\n\n\t\t/* This assumes BYTES_PER_ROW is 16, which it will always be.\n\t\t * It's more of an informational constant, not a variable. */\n\t\tlog(\"%08x: %08x %08x %08x %08x  \",\n\t\t    addr, words[0], words[1], words[2], words[3]);\n\n\t\t/* The ARISC processor's data lines are swapped in hardware for\n\t\t * compatibility with the little-endian ARM CPUs. To examine\n\t\t * individual bytes, we must reverse each group of 4 bytes. */\n\t\tfor (int i = 0; i < BYTES_PER_ROW; ++i) {\n\t\t\tchar c = ((char *)addr)[i ^ 3];\n\t\t\tserial_putc(isprint(c) ? c : '.');\n\t\t}\n\t\tserial_putc('\\n');\n\t}\n}\n\nvoid\nlog(const char *fmt, ...)\n{\n\tbool zero;\n\tchar c;\n\tint  width;\n\tuintptr_t arg, level;\n\tva_list args;\n\n\tassert(fmt);\n\n\tif (!serial_ready())\n\t\treturn;\n\n\tlevel = *fmt - 1;\n\tif (level < LOG_LEVELS) {\n\t\tserial_puts(prefixes[level]);\n\t\t++fmt;\n\t}\n\tva_start(args, fmt);\n\twhile ((c = *fmt++)) {\n\t\tif (c != '%') {\n\t\t\tserial_putc(c);\n\t\t\tcontinue;\n\t\t}\n\t\tif (*fmt == '%') {\n\t\t\t++fmt;\n\t\t\tserial_putc(c);\n\t\t\tcontinue;\n\t\t}\n\t\targ   = va_arg(args, uintptr_t);\n\t\twidth = 0;\n\t\tzero  = false;\nconversion:\n\t\tswitch ((c = *fmt++)) {\n\t\tcase 'c':\n\t\t\tserial_putc(arg);\n\t\t\tbreak;\n\t\tcase 'd':\n\t\tcase 'i':\n\t\t\tprint_signed(arg, 10, width, zero);\n\t\t\tbreak;\n\t\tcase 'p':\n\t\t\t/* \"%p\" behaves like \"0x%08x\". */\n\t\t\tserial_puts(\"0x\");\n\t\t\tprint_number(arg, 16, 2 * sizeof(arg), true);\n\t\t\tbreak;\n\t\tcase 'x':\n\t\t\tprint_number(arg, 16, width, zero);\n\t\t\tbreak;\n\t\tcase 's':\n\t\t\tassert(arg);\n\t\t\tserial_puts((const char *)arg);\n\t\t\tbreak;\n\t\tcase 'u':\n\t\t\tprint_number(arg, 10, width, zero);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tassert(c);\n\t\t\tif (c == '0' && width == 0)\n\t\t\t\tzero = true;\n\t\t\telse if (isdigit(c))\n\t\t\t\twidth = 10 * width + (c - '0');\n\t\t\tgoto conversion;\n\t\t}\n\t}\n\tva_end(args);\n\tif (level < LOG_LEVELS)\n\t\tserial_putc('\\n');\n}\n\nstatic void\nprint_number(uint32_t num, int base, int width, bool zero)\n{\n\tstatic const char chars[16] = \"0123456789abcdef\";\n\tchar digits[3 * sizeof(num)];\n\tint  i = 0;\n\n\tdo {\n\t\tdigits[i++] = chars[udivmod(&num, base)];\n\t} while (num);\n\twhile (width-- > i)\n\t\tserial_putc(zero ? '0' : ' ');\n\twhile (i--)\n\t\tserial_putc(digits[i]);\n}\n\nstatic void\nprint_signed(int32_t num, int base, int width, bool zero)\n{\n\tif (num < 0) {\n\t\tserial_putc('-');\n\t\tprint_number(-num, base, width ? width - 1 : width, zero);\n\t} else {\n\t\tprint_number(num, base, width, zero);\n\t}\n}\n"
  },
  {
    "path": "common/delay.c",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <delay.h>\n#include <stdint.h>\n#include <timeout.h>\n\nvoid\nudelay(uint32_t useconds)\n{\n\tuint32_t timeout = timeout_set(useconds);\n\n\twhile (!timeout_expired(timeout)) {\n\t\t/* Do nothing. */\n\t}\n}\n"
  },
  {
    "path": "common/device.c",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <debug.h>\n#include <device.h>\n#include <error.h>\n#include <stddef.h>\n\nbool\ndevice_active(const struct device *dev)\n{\n\treturn dev && dev->state->refcount;\n}\n\nint\ndevice_get(const struct device *dev)\n{\n\tint err;\n\n\tif (!dev)\n\t\treturn ENODEV;\n\n\tif (!dev->state->refcount) {\n\t\tif ((err = dev->drv->probe(dev))) {\n\t\t\twarn(\"%s: Probe failed: %d\", dev->name, err);\n\t\t\treturn err;\n\t\t}\n\t\tdebug(\"%s: Probed\", dev->name);\n\t}\n\n\t/* Increment the refcount only after successful initialization. */\n\t++dev->state->refcount;\n\n\treturn SUCCESS;\n}\n\nconst struct device *\ndevice_get_or_null(const struct device *dev)\n{\n\treturn device_get(dev) == SUCCESS ? dev : NULL;\n}\n\nvoid\ndevice_put(const struct device *dev)\n{\n\tif (!dev || --dev->state->refcount)\n\t\treturn;\n\n\tdebug(\"%s: Releasing\", dev->name);\n\tdev->drv->release(dev);\n}\n\nint\ndummy_probe(const struct device *dev UNUSED)\n{\n\treturn SUCCESS;\n}\n\nvoid\ndummy_release(const struct device *dev UNUSED)\n{\n}\n"
  },
  {
    "path": "common/regulator_list.c",
    "content": "/*\n * Copyright © 2020-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <regulator_list.h>\n#include <stddef.h>\n#include <regulator/axp803.h>\n#include <regulator/axp805.h>\n#include <regulator/gpio.h>\n#include <regulator/sy8106a.h>\n\nconst struct regulator_handle cpu_supply = {\n#if CONFIG(REGULATOR_AXP803)\n\t.dev = &axp803_regulator.dev,\n\t.id  = AXP803_REGL_DCDC2,\n#elif CONFIG(REGULATOR_AXP805)\n\t.dev = &axp805_regulator.dev,\n\t.id  = AXP805_REGL_DCDCA,\n#elif CONFIG(REGULATOR_SY8106A)\n\t.dev = &sy8106a.dev,\n#elif CONFIG(REGULATOR_GPIO_CPU)\n\t.dev = &gpio_cpu_regulator.dev,\n#else\n\t.dev = NULL,\n#endif\n};\n\nconst struct regulator_handle dram_supply = {\n#if CONFIG(REGULATOR_AXP803)\n\t.dev = &axp803_regulator.dev,\n\t.id  = AXP803_REGL_DCDC5,\n#elif CONFIG(REGULATOR_AXP805)\n\t.dev = &axp805_regulator.dev,\n\t.id  = AXP805_REGL_DCDCE,\n#elif CONFIG(REGULATOR_GPIO_DRAM)\n\t.dev = &gpio_dram_regulator.dev,\n#else\n\t.dev = NULL,\n#endif\n};\n\nconst struct regulator_handle vcc_pll_supply = {\n#if CONFIG(REGULATOR_AXP803)\n\t.dev = &axp803_regulator.dev,\n\t.id  = AXP803_REGL_ALDO3,\n#elif CONFIG(REGULATOR_AXP805)\n\t.dev = &axp805_regulator.dev,\n\t.id  = AXP805_REGL_BLDO1,\n#elif CONFIG(REGULATOR_GPIO_VCC_PLL)\n\t.dev = &gpio_vcc_pll_regulator.dev,\n#else\n\t.dev = NULL,\n#endif\n};\n\nconst struct regulator_handle vdd_sys_supply = {\n#if CONFIG(REGULATOR_AXP803)\n\t.dev = &axp803_regulator.dev,\n\t.id  = AXP803_REGL_DCDC6,\n#elif CONFIG(REGULATOR_AXP805)\n\t.dev = &axp805_regulator.dev,\n\t.id  = AXP805_REGL_DCDCD,\n#elif CONFIG(REGULATOR_GPIO_VDD_SYS)\n\t.dev = &gpio_vdd_sys_regulator.dev,\n#else\n\t.dev = NULL,\n#endif\n};\n"
  },
  {
    "path": "common/scpi.c",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <debug.h>\n#include <error.h>\n#include <msgbox.h>\n#include <scpi.h>\n#include <stdbool.h>\n#include <stddef.h>\n#include <stdint.h>\n#include <timeout.h>\n\n#define SCPI_MEM_AREA(n) (__scpi_mem[SCPI_CLIENTS - n - 1])\n\n#define SCPI_TX_TIMEOUT  (10 * USEC_PER_MSEC) /* 10ms */\n\n#define RX_CHAN(client)  (2 * (client))\n#define TX_CHAN(client)  (2 * (client) + 1)\n\nstruct scpi_state {\n\tuint32_t timeout;\n\tbool     tx_full;\n};\n\n/** The shared memory area, with an address defined in the linker script. */\nextern struct scpi_mem __scpi_mem[SCPI_CLIENTS];\n\n/** The current state of each client. */\nstatic struct scpi_state scpi_state[SCPI_CLIENTS];\n\n/**\n * Send an SCPI message to the client, recording the timeout for when the\n * client must acknowledge the message.\n */\nstatic void\nscpi_send_message(const struct device *mailbox, uint8_t client,\n                  struct scpi_state *state)\n{\n\tint err;\n\n\t/* Ensure the outgoing message is fully written at this point. */\n\tbarrier();\n\n\t/* Ensure the timeout is updated before triggering transmission. */\n\tstate->timeout = timeout_set(SCPI_TX_TIMEOUT);\n\tstate->tx_full = true;\n\tbarrier();\n\n\t/* Notify the client that the message has been sent. */\n\tif ((err = msgbox_send(mailbox, TX_CHAN(client),\n\t                       SCPI_VIRTUAL_CHANNEL)))\n\t\twarn(\"SCPI%u: Send error: %d\", client, err);\n}\n\nvoid\nscpi_create_message(const struct device *mailbox, uint8_t client,\n                    uint8_t command)\n{\n\tstruct scpi_mem *mem     = &SCPI_MEM_AREA(client);\n\tstruct scpi_state *state = &scpi_state[client];\n\n\tif (state->tx_full)\n\t\treturn;\n\n\t/* Write the message header. */\n\tmem->tx_msg.command = command;\n\tmem->tx_msg.sender  = SCPI_SENDER_SCP;\n\tmem->tx_msg.size    = 0;\n\tmem->tx_msg.status  = SCPI_OK;\n\n\t/* Send the message. */\n\tscpi_send_message(mailbox, client, state);\n}\n\n/**\n * Attempt as much forward progress as possible for a client, by checking\n * for client ACKs and then responding to incoming messages.\n *\n * Dispatch handling of messages to the appropriate function for that specific\n * command. The functions for doing so are defined in a separate file to\n * separate the API functionality from communication/state management code.\n */\nstatic void\nscpi_poll_one_client(const struct device *mailbox, uint8_t client)\n{\n\tstruct scpi_state *state = &scpi_state[client];\n\tuint8_t rx_chan = RX_CHAN(client);\n\tuint8_t tx_chan = TX_CHAN(client);\n\n\t/* Flush any outgoing messages. The TX buffer becomes free when a\n\t * previously-sent message is acknowledged or when it times out. */\n\tif (state->tx_full) {\n\t\tif (msgbox_last_tx_done(mailbox, tx_chan) ||\n\t\t    timeout_expired(state->timeout))\n\t\t\tstate->tx_full = false;\n\t}\n\n\t/* Once the TX buffer is free, we can process new messages, reading\n\t * from the RX buffer and generating responses in the TX buffer. */\n\tif (!state->tx_full) {\n\t\tbool reply_needed = false;\n\t\tuint32_t msg;\n\n\t\t/* Try to grab a new message. All errors are handled by\n\t\t * retrying on the next iteration through the main loop. */\n\t\tif (msgbox_receive(mailbox, rx_chan, &msg) == SUCCESS) {\n\t\t\t/* Only process messages sent with the correct\n\t\t\t * protocol, which SCPI calls a \"virtual channel\". */\n\t\t\tif (msg == SCPI_VIRTUAL_CHANNEL) {\n\t\t\t\tstruct scpi_mem *mem = &SCPI_MEM_AREA(client);\n\n\t\t\t\t/* The handler relays if a reply is needed. */\n\t\t\t\treply_needed = scpi_handle_cmd(client, mem);\n\t\t\t}\n\n\t\t\t/* Acknowledging the message allows the client to reuse\n\t\t\t * the RX buffer, so the handler must run first. */\n\t\t\tmsgbox_ack_rx(mailbox, rx_chan);\n\t\t}\n\n\t\t/* If the TX buffer now contains a reply, send it. */\n\t\tif (reply_needed)\n\t\t\tscpi_send_message(mailbox, client, state);\n\t}\n}\n\nvoid\nscpi_poll(const struct device *mailbox)\n{\n\tfor (uint8_t client = 0; client < SCPI_CLIENTS; ++client)\n\t\tscpi_poll_one_client(mailbox, client);\n}\n"
  },
  {
    "path": "common/scpi_cmds.c",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <bitfield.h>\n#include <css.h>\n#include <debug.h>\n#include <device.h>\n#include <scpi.h>\n#include <stdbool.h>\n#include <stddef.h>\n#include <stdint.h>\n#include <steps.h>\n#include <system.h>\n#include <util.h>\n#include <version.h>\n\nenum {\n\t/** Do not send a reply to this command. */\n\tFLAG_NO_REPLY    = BIT(0),\n\t/** Reject this command from the non-secure message box channel. */\n\tFLAG_SECURE_ONLY = BIT(1),\n};\n\nstruct scpi_cmd {\n\t/** Handler that can process a message and create a dynamic reply. */\n\tint     (*handler)(uint32_t *rx_payload, uint32_t *tx_payload,\n\t                   uint16_t *tx_size);\n\t/** Expected size of received payload. */\n\tuint8_t rx_size;\n\t/** Any combination of flags from above, if applicable. */\n\tuint8_t flags;\n};\n\n/*\n * Handler for SCPI_CMD_SCP_READY: Response to SCP ready.\n */\nstatic int\nscpi_cmd_scp_ready_handler(uint32_t *rx_payload UNUSED,\n                           uint32_t *tx_payload UNUSED,\n                           uint16_t *tx_size UNUSED)\n{\n\treturn SCPI_OK;\n}\n\n/*\n * Handler for SCPI_CMD_GET_SCP_CAP: Get SCP capability.\n */\n#define SCP_FIRMWARE_VERSION(x, y, z) \\\n\t((((x) & 0xff) << 24) | (((y) & 0xff) << 16) | ((z) & 0xffff))\n#define SCPI_PAYLOAD_LIMITS(x, y)   (((x) & 0x01ff) << 16 | ((y) & 0x01ff))\n#define SCPI_PROTOCOL_VERSION(x, y) (((x) & 0xffff) << 16 | ((y) & 0xffff))\nstatic int\nscpi_cmd_get_scp_cap_handler(uint32_t *rx_payload UNUSED,\n                             uint32_t *tx_payload, uint16_t *tx_size)\n{\n\t/* SCPI protocol version. */\n\ttx_payload[0] = SCPI_PROTOCOL_VERSION(1, 2);\n\t/* Payload size limits. */\n\ttx_payload[1] = SCPI_PAYLOAD_LIMITS(SCPI_PAYLOAD_SIZE,\n\t                                    SCPI_PAYLOAD_SIZE);\n\t/* Firmware version. */\n\ttx_payload[2] = SCP_FIRMWARE_VERSION(VERSION_MAJOR,\n\t                                     VERSION_MINOR,\n\t                                     VERSION_PATCH);\n\t/* Commands enabled 0. */\n\ttx_payload[3] = BIT(SCPI_CMD_SCP_READY) |\n\t                BIT(SCPI_CMD_GET_SCP_CAP) |\n\t                BIT(SCPI_CMD_SET_CSS_POWER) |\n\t                BIT(SCPI_CMD_GET_CSS_POWER) |\n\t                BIT(SCPI_CMD_SET_SYS_POWER);\n\t/* Commands enabled 1. */\n\ttx_payload[4] = 0;\n\t/* Commands enabled 2. */\n\ttx_payload[5] = 0;\n\t/* Commands enabled 3. */\n\ttx_payload[6] = 0;\n\n\t*tx_size = 7 * sizeof(*tx_payload);\n\n\treturn SCPI_OK;\n}\n\n/*\n * Handler for SCPI_CMD_SET_CSS_POWER: Set CSS power state.\n *\n * This sets the power state of a single core, its parent cluster, and the CSS.\n */\nstatic int\nscpi_cmd_set_css_power_handler(uint32_t *rx_payload,\n                               uint32_t *tx_payload UNUSED,\n                               uint16_t *tx_size UNUSED)\n{\n\tuint32_t descriptor    = rx_payload[0];\n\tuint32_t core          = bitfield_get(descriptor, 0x00, 4);\n\tuint32_t cluster       = bitfield_get(descriptor, 0x04, 4);\n\tuint32_t core_state    = bitfield_get(descriptor, 0x08, 4);\n\tuint32_t cluster_state = bitfield_get(descriptor, 0x0c, 4);\n\tuint32_t css_state     = bitfield_get(descriptor, 0x10, 4);\n\tint err;\n\n\terr = css_set_power_state(cluster, core, core_state,\n\t                          cluster_state, css_state);\n\tif (err)\n\t\treturn err;\n\n\treturn SCPI_OK;\n}\n\n/*\n * Handler for SCPI_CMD_GET_CSS_POWER: Get CSS power state.\n *\n * This gets the power states of all clusters and all cores they contain.\n */\n#define CLUSTER_ID(x)          ((x) & GENMASK(3, 0))\n#define CLUSTER_POWER_STATE(x) (((x) & GENMASK(3, 0)) << 4)\n#define CORE_POWER_STATES(x)   ((x) << 8)\nstatic int\nscpi_cmd_get_css_power_handler(uint32_t *rx_payload UNUSED,\n                               uint32_t *tx_payload, uint16_t *tx_size)\n{\n\tuint32_t clusters = css_get_cluster_count();\n\tuint16_t descriptor;\n\tint err;\n\n\t/* Each cluster has its own power state descriptor. */\n\tfor (uint32_t i = 0; i < clusters; ++i) {\n\t\tuint32_t state, online_cores;\n\n\t\tif ((err = css_get_power_state(i, &state, &online_cores)))\n\t\t\treturn err;\n\n\t\tdescriptor = CLUSTER_ID(i) |\n\t\t             CLUSTER_POWER_STATE(state) |\n\t\t             CORE_POWER_STATES(online_cores);\n\t\t/* Work around the hardware byte swapping, since this is an\n\t\t * array of elements each aligned to less than 4 bytes. */\n\t\t((uint16_t *)tx_payload)[i ^ 1] = descriptor;\n\t}\n\t*tx_size = clusters * sizeof(descriptor);\n\n\treturn SCPI_OK;\n}\n\n/*\n * Handler for SCPI_CMD_SET_SYS_POWER: Set system power state.\n */\nstatic int\nscpi_cmd_set_sys_power_handler(uint32_t *rx_payload,\n                               uint32_t *tx_payload UNUSED,\n                               uint16_t *tx_size UNUSED)\n{\n\tuint8_t state = rx_payload[0];\n\n\tif (state == SCPI_SYSTEM_SHUTDOWN)\n\t\tsystem_shutdown();\n\telse if (state == SCPI_SYSTEM_REBOOT)\n\t\tsystem_reboot();\n\telse if (state == SCPI_SYSTEM_RESET)\n\t\tsystem_reset();\n\telse\n\t\treturn SCPI_E_PARAM;\n\n\t/* Clear the current step during an orderly state transition. */\n\trecord_step(STEP_NONE);\n\n\treturn SCPI_OK;\n}\n\n/*\n * The list of supported SCPI commands.\n */\nstatic const struct scpi_cmd scpi_cmds[] = {\n\t[SCPI_CMD_SCP_READY] = {\n\t\t.handler = scpi_cmd_scp_ready_handler,\n\t\t.flags   = FLAG_NO_REPLY | FLAG_SECURE_ONLY,\n\t},\n\t[SCPI_CMD_GET_SCP_CAP] = {\n\t\t.handler = scpi_cmd_get_scp_cap_handler,\n\t},\n\t[SCPI_CMD_SET_CSS_POWER] = {\n\t\t.handler = scpi_cmd_set_css_power_handler,\n\t\t.rx_size = sizeof(uint32_t),\n\t\t.flags   = FLAG_NO_REPLY | FLAG_SECURE_ONLY,\n\t},\n\t[SCPI_CMD_GET_CSS_POWER] = {\n\t\t.handler = scpi_cmd_get_css_power_handler,\n\t},\n\t[SCPI_CMD_SET_SYS_POWER] = {\n\t\t.handler = scpi_cmd_set_sys_power_handler,\n\t\t.rx_size = sizeof(uint8_t),\n\t\t.flags   = FLAG_SECURE_ONLY,\n\t},\n};\n\n/*\n * Generic SCPI command handling function.\n */\nbool\nscpi_handle_cmd(uint8_t client, struct scpi_mem *mem)\n{\n\tstruct scpi_msg *rx_msg = &mem->rx_msg;\n\tstruct scpi_msg *tx_msg = &mem->tx_msg;\n\tconst struct scpi_cmd *cmd;\n\n\t/* Initialize the response (defaults for unsupported commands). */\n\ttx_msg->command = rx_msg->command;\n\ttx_msg->sender  = rx_msg->sender;\n\ttx_msg->size    = 0;\n\ttx_msg->status  = SCPI_E_SUPPORT;\n\n\t/* Avoid reading past the end of the array; reply with the error. */\n\tif (rx_msg->command >= ARRAY_SIZE(scpi_cmds))\n\t\treturn true;\n\tcmd = &scpi_cmds[rx_msg->command];\n\n\t/* Update the command status and payload based on the message. */\n\tif ((cmd->flags & FLAG_SECURE_ONLY) && client != SCPI_CLIENT_EL3) {\n\t\t/* Prevent Linux from sending commands that bypass PSCI. */\n\t\ttx_msg->status = SCPI_E_ACCESS;\n\t} else if (rx_msg->size != cmd->rx_size) {\n\t\t/* Check that the request payload matches the expected size. */\n\t\ttx_msg->status = SCPI_E_SIZE;\n\t} else if (cmd->handler) {\n\t\t/* Run the handler for this command to make a response. */\n\t\ttx_msg->status = cmd->handler(rx_msg->payload, tx_msg->payload,\n\t\t                              &tx_msg->size);\n\t} else {\n\t\tdebug(\"SCPI%u: Bad command: %u\", client, rx_msg->command);\n\t}\n\n\t/* Report back if a reply should be sent. */\n\treturn !(cmd->flags & FLAG_NO_REPLY);\n}\n"
  },
  {
    "path": "common/simple_device.c",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <error.h>\n#include <simple_device.h>\n\nint\nsimple_device_probe(const struct device *dev)\n{\n\tconst struct simple_device *self = to_simple_device(dev);\n\tint err;\n\n\tif (self->pins) {\n\t\tif ((err = gpio_get(&self->pins[0])))\n\t\t\treturn err;\n\t\tif ((err = gpio_get(&self->pins[1])))\n\t\t\tgoto err_put_gpio0;\n\t}\n\n\tclock_get(&self->clock);\n\n\treturn SUCCESS;\n\nerr_put_gpio0:\n\tgpio_put(&self->pins[0]);\n\n\treturn err;\n}\n\nvoid\nsimple_device_release(const struct device *dev)\n{\n\tconst struct simple_device *self = to_simple_device(dev);\n\n\tclock_put(&self->clock);\n\tif (self->pins) {\n\t\tgpio_put(&self->pins[1]);\n\t\tgpio_put(&self->pins[0]);\n\t}\n}\n\nvoid\nsimple_device_sync(const struct simple_device *sdev)\n{\n\tuint8_t refcount = sdev->dev.state->refcount;\n\n\tif (clock_get_state(&sdev->clock) == CLOCK_STATE_ENABLED) {\n\t\tif (refcount == 0)\n\t\t\tdevice_get(&sdev->dev);\n\t} else {\n\t\tif (refcount == 1)\n\t\t\tdevice_put(&sdev->dev);\n\t}\n}\n"
  },
  {
    "path": "common/system.c",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <cec.h>\n#include <cir.h>\n#include <counter.h>\n#include <css.h>\n#include <debug.h>\n#include <delay.h>\n#include <device.h>\n#include <dram.h>\n#include <exception.h>\n#include <irq.h>\n#include <pmic.h>\n#include <regulator.h>\n#include <regulator_list.h>\n#include <scpi.h>\n#include <serial.h>\n#include <simple_device.h>\n#include <stddef.h>\n#include <steps.h>\n#include <system.h>\n#include <version.h>\n#include <watchdog.h>\n#include <clock/ccu.h>\n#include <gpio/sunxi-gpio.h>\n#include <msgbox/sunxi-msgbox.h>\n\n#define NEXT_STATE (system_state + 2)\n\n/**\n * The enumeration of possible system states.\n *\n * The first three states are ordered to meet two constraints:\n *   1. BOOT must be nonzero so system_state is stored in .data and\n *      reinitialized only after a SoC reset (not after a firmware restart).\n *   2. REBOOT must be AWAKE+2 for the system_wake() transition.\n *\n * The remaining values are divided into two parallel sequences. The states are\n * ordered such that adding two to the state variable advances to the next\n * step in the sequence. Paired states have similar functions and share code.\n */\nenum {\n\tSS_AWAKE      = 0x0, /**< System is awake; rich OS is running. */\n\tSS_BOOT       = 0x1, /**< First firmware boot after SoC reset. */\n\tSS_REBOOT     = 0x2, /**< Attempting board-level (PMIC) reboot. */\n\n\tSS_SHUTDOWN   = 0x3, /**< Transition from awake to off. */\n\tSS_SUSPEND    = 0x4, /**< Transition from awake to asleep. */\n\n\tSS_OFF        = 0x5, /**< System is off; RAM contents are lost. */\n\tSS_ASLEEP     = 0x6, /**< System is asleep; RAM contents are kept. */\n\n\tSS_PRE_RESET  = 0x7, /**< Common part of reset/resume transition. */\n\tSS_PRE_RESUME = 0x8, /**< Common part of reset/resume transition. */\n\n\tSS_RESET      = 0x9, /**< Transition from off to boot via SoC reset. */\n\tSS_RESUME     = 0xa, /**< Transition from asleep to awake. */\n};\n\n/* This variable is persisted across exception restarts. */\nstatic uint8_t system_state = SS_BOOT;\n\nstatic uint8_t\nselect_suspend_depth(uint8_t current_state)\n{\n\tstatic const struct clock_handle osc24m = { &r_ccu.dev, CLK_OSC24M };\n\n\t/* Bail if the DRAM controller or peripherals need running clocks. */\n\tif (!CONFIG(HAVE_DRAM_SUSPEND) || clock_active(&osc24m))\n\t\treturn SD_NONE;\n\t/* Wakeup sources needing AVCC are only supported while asleep. */\n\tif (current_state != SS_SHUTDOWN && irq_needs_avcc())\n\t\treturn SD_OSC24M;\n\tif (current_state != SS_SHUTDOWN || irq_needs_vdd_sys())\n\t\treturn SD_AVCC;\n\treturn SD_VDD_SYS;\n}\n\nnoreturn void\nsystem_state_machine(uint32_t exception)\n{\n\tconst struct device *cec, *cir, *mailbox, *pmic, *watchdog;\n\tuint8_t initial_state = system_state;\n\tuint8_t suspend_depth;\n\n\tif (initial_state > SS_BOOT) {\n\t\t/*\n\t\t * If the firmware started in any state other than BOOT or\n\t\t * AWAKE, assume the system is off. It could be transitioning\n\t\t * or asleep, but resetting the board after an IRQ is safer\n\t\t * than attempting to resume in an unpredictable environment.\n\t\t */\n\t\tsystem_state = SS_OFF;\n\n\t\t/* Clear out inactive references. */\n\t\tcec      = NULL;\n\t\tcir      = NULL;\n\t\twatchdog = NULL;\n\t\tmailbox  = NULL;\n\t} else {\n\t\t/* Otherwise, perform BOOT actions and switch to AWAKE. */\n\t\tsystem_state = SS_AWAKE;\n\n\t\t/* First, enable watchdog protection. */\n\t\twatchdog = watchdog_get();\n\n\t\t/* Perform one-time device driver initialization. */\n\t\tcycle_counter_init();\n\t\tr_ccu_init();\n\t\tccu_init();\n\t\tcss_init();\n\t\tdram_init();\n\n\t\t/* Acquire runtime-only devices. */\n\t\tmailbox = device_get_or_null(&msgbox.dev);\n\t}\n\n\t/*\n\t * Initialize the serial port. Unless a preinitialized port (UART0) is\n\t * selected, errors occurring before this function call will not be\n\t * logged, and exceptions (such as those caused by assertion failures)\n\t * could result in a silent infinite loop.\n\t *\n\t * Serial communication needs accurate clock frequencies. Specifically,\n\t * IOSC must be calibrated before initializing R_UART, and R_UART\n\t * will only work after an exception restart while off/asleep if the\n\t * calibrated IOSC frequency is retained across the restart.\n\t */\n\tserial_init();\n\n\t/* Log startup messages. */\n\tinfo(\"Crust \" VERSION_STRING);\n\treport_exception(exception);\n\treport_last_step();\n\tdebug_print_sprs();\n\n\t/*\n\t * If the firmware started in the initial state, assume the secure\n\t * monitor is waiting for an SCP_READY message.  Otherwise, assume\n\t * nothing is listening, and skip sending the SCP_READY message to\n\t * avoid filling up the mailbox.\n\t */\n\tif (mailbox && initial_state == SS_BOOT) {\n\t\tscpi_create_message(mailbox, SCPI_CLIENT_EL3,\n\t\t                    SCPI_CMD_SCP_READY);\n\t}\n\n\tfor (;;) {\n\t\tdebug_print_latency(system_state);\n\n\t\tswitch (system_state) {\n\t\tcase SS_AWAKE:\n\t\t\t/* Poll runtime devices. */\n\t\t\tcss_poll();\n\t\t\tif (watchdog)\n\t\t\t\twatchdog_restart(watchdog);\n\n\t\t\t/* Poll runtime services. */\n\t\t\tif (mailbox)\n\t\t\t\tscpi_poll(mailbox);\n\n\t\t\tbreak;\n\t\tcase SS_SHUTDOWN:\n\t\tcase SS_SUSPEND:\n\t\t\tdebug(\"Suspending...\");\n\n\t\t\t/* Synchronize device state with Linux. */\n\t\t\trecord_step(STEP_SUSPEND_DEVICES);\n\t\t\tsimple_device_sync(&pio);\n\t\t\tsimple_device_sync(&r_pio);\n\n\t\t\t/* Release runtime-only devices. */\n\t\t\tdevice_put(mailbox), mailbox = NULL;\n\n\t\t\t/* Acquire wakeup sources. */\n\t\t\tcec = cec_get();\n\t\t\tcir = cir_get();\n\n\t\t\t/* Configure the SoC for minimal power consumption. */\n\t\t\trecord_step(STEP_SUSPEND_DRAM);\n\t\t\tdram_save_checksum();\n\t\t\tdram_suspend();\n\t\t\trecord_step(STEP_SUSPEND_CCU);\n\t\t\tccu_suspend();\n\n\t\t\t/*\n\t\t\t * Disable watchdog protection. Once devices outside\n\t\t\t * the SoC (oscillators and regulators) are disabled,\n\t\t\t * the watchdog cannot successfully reset the SoC.\n\t\t\t */\n\t\t\tdevice_put(watchdog), watchdog = NULL;\n\n\t\t\t/* Gate the rest of the SoC before removing power. */\n\t\t\trecord_step(STEP_SUSPEND_PRCM);\n\t\t\tsuspend_depth = select_suspend_depth(system_state);\n\t\t\tr_ccu_suspend(suspend_depth);\n\n\t\t\t/* Perform PMIC-specific actions. */\n\t\t\trecord_step(STEP_SUSPEND_PMIC);\n\t\t\tif ((pmic = pmic_get())) {\n\t\t\t\tif (system_state == SS_SHUTDOWN &&\n\t\t\t\t    CONFIG(PMIC_SHUTDOWN))\n\t\t\t\t\tpmic_shutdown(pmic);\n\t\t\t\telse\n\t\t\t\t\tpmic_suspend(pmic);\n\t\t\t}\n\n\t\t\t/* Turn off all unnecessary power domains. */\n\t\t\trecord_step(STEP_SUSPEND_REGULATORS);\n\t\t\tregulator_disable(&cpu_supply);\n\t\t\tif (system_state == SS_SHUTDOWN) {\n\t\t\t\tregulator_disable(&dram_supply);\n\t\t\t\tif (suspend_depth >= SD_OSC24M)\n\t\t\t\t\tregulator_disable(&vcc_pll_supply);\n\t\t\t\tif (suspend_depth >= SD_VDD_SYS)\n\t\t\t\t\tregulator_disable(&vdd_sys_supply);\n\t\t\t}\n\n\t\t\t/*\n\t\t\t * The regulator provider is often part of the same\n\t\t\t * device as the PMIC. Reduce churn by doing both PMIC\n\t\t\t * and regulator actions before releasing the PMIC.\n\t\t\t */\n\t\t\tdevice_put(pmic);\n\n\t\t\trecord_step(STEP_SUSPEND_COMPLETE);\n\t\t\tdebug(\"Suspend to %d complete!\", suspend_depth);\n\n\t\t\t/* The system is now off or asleep. */\n\t\t\tsystem_state = NEXT_STATE;\n\t\t\tbreak;\n\t\tcase SS_OFF:\n\t\tcase SS_ASLEEP:\n\t\t\tdebug_monitor();\n\t\t\tdebug_print_battery();\n\n\t\t\t/* Poll wakeup sources. Reset or resume on wakeup. */\n\t\t\tif ((cec && cec_poll(cec)) ||\n\t\t\t    (cir && cir_poll(cir)) ||\n\t\t\t    irq_poll())\n\t\t\t\tsystem_state = NEXT_STATE;\n\n\t\t\tbreak;\n\t\tcase SS_PRE_RESET:\n\t\tcase SS_PRE_RESUME:\n\t\t\t/*\n\t\t\t * Perform PMIC-specific resume actions.\n\t\t\t * The PMIC is expected to restore regulator state.\n\t\t\t * If it fails, manually turn the regulators back on.\n\t\t\t */\n\t\t\trecord_step(STEP_RESUME_PMIC);\n\t\t\tif (!(pmic = pmic_get()) || pmic_resume(pmic)) {\n\t\t\t\trecord_step(STEP_RESUME_REGULATORS);\n\t\t\t\tregulator_enable(&vdd_sys_supply);\n\t\t\t\tregulator_enable(&vcc_pll_supply);\n\t\t\t\tregulator_enable(&dram_supply);\n\t\t\t\tregulator_enable(&cpu_supply);\n\t\t\t}\n\t\t\tdevice_put(pmic);\n\n\t\t\t/* Give regulator outputs time to rise. */\n\t\t\tudelay(5000);\n\n\t\t\t/* Restore SoC-internal power domains. */\n\t\t\trecord_step(STEP_RESUME_PRCM);\n\t\t\tr_ccu_resume();\n\n\t\t\t/* Enable watchdog protection. */\n\t\t\twatchdog = watchdog_get();\n\n\t\t\t/* The system is now ready to reset or resume. */\n\t\t\tsystem_state = NEXT_STATE;\n\t\t\tbreak;\n\t\tcase SS_RESUME:\n\t\t\tdebug(\"Resuming...\");\n\n\t\t\t/* Configure the SoC for full functionality. */\n\t\t\trecord_step(STEP_RESUME_CCU);\n\t\t\tccu_resume();\n\t\t\trecord_step(STEP_RESUME_DRAM);\n\t\t\tdram_resume();\n\t\t\tdram_verify_checksum();\n\n\t\t\t/* Release wakeup sources. */\n\t\t\trecord_step(STEP_RESUME_DEVICES);\n\t\t\tdevice_put(cir), cir = NULL;\n\t\t\tdevice_put(cec), cec = NULL;\n\n\t\t\t/* Acquire runtime-only devices. */\n\t\t\tmailbox = device_get_or_null(&msgbox.dev);\n\n\t\t\t/* Resume execution on the CSS. */\n\t\t\trecord_step(STEP_RESUME_CSS);\n\t\t\tcss_resume();\n\n\t\t\trecord_step(STEP_RESUME_COMPLETE);\n\t\t\tdebug(\"Resume complete!\");\n\n\t\t\t/* The system is now awake. */\n\t\t\tsystem_state = SS_AWAKE;\n\t\t\tbreak;\n\t\tcase SS_REBOOT:\n\t\t\t/* Attempt to reset the board using the PMIC. */\n\t\t\tif ((pmic = pmic_get())) {\n\t\t\t\tpmic_reset(pmic);\n\t\t\t\tdevice_put(pmic);\n\t\t\t}\n\n\t\t\t/* Continue through to resetting the SoC. */\n\t\t\tfallthrough;\n\t\tcase SS_RESET:\n\t\t\t/* Attempt to reset the SoC using the watchdog. */\n\t\t\tif (watchdog)\n\t\t\t\twatchdog_reset_system(watchdog);\n\n\t\t\t/* Continue making reboot/reset attempts. */\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tunreachable();\n\t\t}\n\t}\n}\n\nvoid\nsystem_reboot(void)\n{\n\t/* This transition skips PRE_RESET, so the system must be awake. */\n\tassert(system_state == SS_AWAKE);\n\n\tsystem_state = SS_REBOOT;\n}\n\nvoid\nsystem_reset(void)\n{\n\t/* This transition skips PRE_RESET, so the system must be awake. */\n\tassert(system_state == SS_AWAKE);\n\n\tsystem_state = SS_RESET;\n}\n\nvoid\nsystem_shutdown(void)\n{\n\t/* This transition only makes sense when the system is awake. */\n\tassert(system_state == SS_AWAKE);\n\n\tsystem_state = SS_SHUTDOWN;\n}\n\nvoid\nsystem_suspend(void)\n{\n\t/* This transition only makes sense when the system is awake. */\n\tassert(system_state == SS_AWAKE);\n\n\tsystem_state = SS_SUSPEND;\n}\n\nvoid\nsystem_wake(void)\n{\n\t/*\n\t * Initiate a state transition sequence, starting from\n\t * any of the three stable states:\n\t *   1. AWAKE  => REBOOT    [=> RESET] => BOOT => AWAKE\n\t *   2. OFF    => PRE_RESET  => RESET  => BOOT => AWAKE\n\t *   3. ASLEEP => PRE_RESUME => RESUME         => AWAKE\n\t */\n\tsystem_state = NEXT_STATE;\n}\n"
  },
  {
    "path": "common/timeout.c",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <counter.h>\n#include <debug.h>\n#include <timeout.h>\n#include <platform/time.h>\n\nbool\ntimeout_expired(uint32_t timeout)\n{\n\tuint32_t now = cycle_counter_read();\n\n\t/* If the timeout wrapped, wait until the counter also wraps. */\n\treturn (now ^ timeout) >> 31 == 0 && now >= timeout;\n}\n\nuint32_t\ntimeout_set(uint32_t useconds)\n{\n\tuint32_t cycles = CPUCLK_MHz * useconds;\n\tuint32_t now    = cycle_counter_read();\n\n\t/* Ensure the MSB is zero for the wraparound check above. */\n\tassert(cycles >> 31 == 0);\n\n\treturn now + cycles;\n}\n"
  },
  {
    "path": "configs/a64-olinuxino-emmc_defconfig",
    "content": "CONFIG_PLATFORM_A64=y\nCONFIG_CEC=y\nCONFIG_MFD_AXP20X=y\n"
  },
  {
    "path": "configs/a64-olinuxino_defconfig",
    "content": "CONFIG_PLATFORM_A64=y\nCONFIG_CEC=y\nCONFIG_MFD_AXP20X=y\n"
  },
  {
    "path": "configs/bananapi_m2_plus_h3_defconfig",
    "content": "CONFIG_PLATFORM_H3=y\nCONFIG_CIR=y\nCONFIG_REGULATOR_GPIO_DRAM=y\n"
  },
  {
    "path": "configs/beelink_gs1_defconfig",
    "content": "CONFIG_PLATFORM_H6=y\nCONFIG_CIR=y\nCONFIG_CIR_PROTO_NEC=y\nCONFIG_CIR_WAKE_CODE=0x8051\nCONFIG_CIR_USE_OSC24M=y\nCONFIG_MFD_AXP20X=y\n"
  },
  {
    "path": "configs/beelink_x2_defconfig",
    "content": "CONFIG_PLATFORM_H3=y\nCONFIG_CIR=y\nCONFIG_CIR_PROTO_NEC=y\nCONFIG_CIR_WAKE_CODE=0x8051\nCONFIG_REGULATOR_GPIO_DRAM=y\n"
  },
  {
    "path": "configs/defconfig",
    "content": "CONFIG_PLATFORM_A64=y\n"
  },
  {
    "path": "configs/libretech_all_h3_cc_h3_defconfig",
    "content": "CONFIG_PLATFORM_H3=y\nCONFIG_CIR=y\nCONFIG_REGULATOR_GPIO_DRAM=y\n"
  },
  {
    "path": "configs/libretech_all_h3_cc_h5_defconfig",
    "content": "CONFIG_PLATFORM_A64=y\nCONFIG_SOC_H5=y\nCONFIG_CIR=y\nCONFIG_REGULATOR_GPIO_DRAM=y\n"
  },
  {
    "path": "configs/nanopi_a64_defconfig",
    "content": "CONFIG_PLATFORM_A64=y\nCONFIG_CIR=y\nCONFIG_MFD_AXP20X=y\n"
  },
  {
    "path": "configs/nanopi_m1_defconfig",
    "content": "CONFIG_PLATFORM_H3=y\nCONFIG_CIR=y\nCONFIG_CIR_USE_OSC24M=y\nCONFIG_REGULATOR_GPIO_DRAM=y\n"
  },
  {
    "path": "configs/nanopi_m1_plus_defconfig",
    "content": "CONFIG_PLATFORM_H3=y\nCONFIG_REGULATOR_GPIO_DRAM=y\n"
  },
  {
    "path": "configs/orangepi_2_defconfig",
    "content": "CONFIG_PLATFORM_H3=y\nCONFIG_CIR=y\nCONFIG_REGULATOR_GPIO_DRAM=y\n"
  },
  {
    "path": "configs/orangepi_3_defconfig",
    "content": "CONFIG_PLATFORM_H6=y\nCONFIG_CIR=y\nCONFIG_MFD_AXP20X=y\n"
  },
  {
    "path": "configs/orangepi_lite_defconfig",
    "content": "CONFIG_PLATFORM_H3=y\nCONFIG_REGULATOR_GPIO_DRAM=y\n"
  },
  {
    "path": "configs/orangepi_one_defconfig",
    "content": "CONFIG_PLATFORM_H3=y\nCONFIG_REGULATOR_GPIO_DRAM=y\n"
  },
  {
    "path": "configs/orangepi_pc2_defconfig",
    "content": "CONFIG_PLATFORM_A64=y\nCONFIG_SOC_H5=y\nCONFIG_CIR=y\nCONFIG_CIR_USE_OSC24M=y\nCONFIG_REGULATOR_GPIO_DRAM=y\nCONFIG_REGULATOR_SY8106A=y\n"
  },
  {
    "path": "configs/orangepi_pc_defconfig",
    "content": "CONFIG_PLATFORM_H3=y\nCONFIG_CIR=y\nCONFIG_CIR_USE_OSC24M=y\nCONFIG_REGULATOR_GPIO_DRAM=y\n"
  },
  {
    "path": "configs/orangepi_pc_plus_defconfig",
    "content": "CONFIG_PLATFORM_H3=y\nCONFIG_CIR=y\nCONFIG_CIR_USE_OSC24M=y\nCONFIG_REGULATOR_GPIO_DRAM=y\n"
  },
  {
    "path": "configs/orangepi_plus2e_defconfig",
    "content": "CONFIG_PLATFORM_H3=y\nCONFIG_CIR=y\nCONFIG_CIR_USE_OSC24M=y\nCONFIG_REGULATOR_GPIO_DRAM=y\n"
  },
  {
    "path": "configs/orangepi_plus_defconfig",
    "content": "CONFIG_PLATFORM_H3=y\nCONFIG_CIR=y\nCONFIG_CIR_USE_OSC24M=y\nCONFIG_REGULATOR_GPIO_DRAM=y\n"
  },
  {
    "path": "configs/orangepi_win_defconfig",
    "content": "CONFIG_PLATFORM_A64=y\nCONFIG_CIR=y\nCONFIG_MFD_AXP20X=y\n"
  },
  {
    "path": "configs/orangepi_zero_defconfig",
    "content": "CONFIG_PLATFORM_H3=y\nCONFIG_REGULATOR_GPIO_DRAM=y\n"
  },
  {
    "path": "configs/orangepi_zero_plus_defconfig",
    "content": "CONFIG_PLATFORM_A64=y\nCONFIG_SOC_H5=y\nCONFIG_REGULATOR_GPIO_DRAM=y\n"
  },
  {
    "path": "configs/pine64-lts_defconfig",
    "content": "CONFIG_PLATFORM_A64=y\nCONFIG_CEC=y\nCONFIG_MFD_AXP20X=y\n"
  },
  {
    "path": "configs/pine64_plus_defconfig",
    "content": "CONFIG_PLATFORM_A64=y\nCONFIG_CEC=y\nCONFIG_MFD_AXP20X=y\n"
  },
  {
    "path": "configs/pine_h64_defconfig",
    "content": "CONFIG_PLATFORM_H6=y\nCONFIG_CIR=y\nCONFIG_I2C_PINS_PL0_PL1=y\nCONFIG_MFD_AXP20X=y\n"
  },
  {
    "path": "configs/pinebook_defconfig",
    "content": "CONFIG_PLATFORM_A64=y\nCONFIG_MFD_AXP20X=y\n# CONFIG_SERIAL is not set\n"
  },
  {
    "path": "configs/pinephone_defconfig",
    "content": "CONFIG_PLATFORM_A64=y\nCONFIG_MFD_AXP20X=y\n# CONFIG_SERIAL is not set\n"
  },
  {
    "path": "configs/pinetab_defconfig",
    "content": "CONFIG_PLATFORM_A64=y\nCONFIG_MFD_AXP20X=y\n# CONFIG_SERIAL is not set\n"
  },
  {
    "path": "configs/tanix_tx6_defconfig",
    "content": "CONFIG_PLATFORM_H6=y\nCONFIG_CIR=y\nCONFIG_CIR_PROTO_NECX=y\nCONFIG_CIR_WAKE_CODE=0x40404d\nCONFIG_CIR_USE_OSC24M=y\n"
  },
  {
    "path": "configs/tbs_a711_defconfig",
    "content": "CONFIG_PLATFORM_A83T=y\n"
  },
  {
    "path": "configs/teres_i_defconfig",
    "content": "CONFIG_PLATFORM_A64=y\nCONFIG_MFD_AXP20X=y\n# CONFIG_SERIAL is not set\n"
  },
  {
    "path": "docs/abi.md",
    "content": "# Crust Firmware ABI\n\nCrust, and any firmware that wishes to be compatible with it, interacts with\nother third-party software and firmware components at several ABI boundaries.\nSome of those boundaries were arbitrarily chosen, and are now hardcoded in\nvarious places throughout the ecosystem. This document attempts to enumerate\nthose boundaries and provide the rationale for choosing them.\n\n## Loading the firmware\n\n### Location in SRAM\n\nCrust is loaded into SRAM A2, because that is the SRAM region in the same power\ndomain as the AR100. It is also the SRAM region containing the AR100 exception\nvector area.\n\nOn platforms that use ATF (A64/H5/H6), Crust is allocated the last 16KiB of\nSRAM A2. 16KiB was chosen as the smallest size that an SCP firmware could\nfeasibly be made. It is simultaneously the largest amount of space that could\nbe shaved off of ATF without breaking debug builds (it was previously using all\nof SRAM A2).\n\nCrust was placed at the end of SRAM A2 to avoid changing ATF's load address.\nThis allowed SCP firmware support to be added to ATF over the course of several\nmonths, without requiring any breaking changes.\n\nOn platforms that do not use ATF (32-bit platforms), Crust reserves the right\nto use the entirety of SRAM A2, if needed.\n\nCrust's load address is hardcoded:\n- In Crust, as `FIRMWARE_BASE` in `platform/*/include/platform/memory.h`\n- In ATF, as `SUNXI_SCP_BASE` in `plat/allwinner/common/include/platform_def.h`\n- In U-Boot, as `SCP_ADDR` in `board/sunxi/mksunxi_fit_atf.sh`\n\n### Firmware contents\n\nOther than the first 32-bit word, no assumptions should be made about the\ncontents of the Crust firmware binary.\n\nThe first 32-bit word (the entry point) is stable, because it is the only way\nto use a single entry point for all exception vectors. Other firmware can\nassume that if the first four bytes at Crust's load address are `12 00 40 b4`,\nthen Crust has been loaded into SRAM. Conversely, if the bytes are any other\nvalue, it is safe to assume that Crust has not been loaded.\n\nThis magic value is hardcoded:\n- In Crust, as the first instruction in `common/start.S`\n- In ATF, as `SCP_FIRMWARE_MAGIC` in `plat/allwinner/common/sunxi_pm.c`\n\n### Loading process\n\nCrust is not loaded adjacent to the AR100 exception vector area (which is 4KiB\nbefore the beginning of \"usable\" SRAM A2). Therefore, the exception vectors\ncannot be stored inside the firmware binary, and they must be programmed\nseparately.\n\nSince the opcode for the `l.j` (unconditional jump) instruction is 0, this is\neasy. The value to write is `(entry - vector) >> 2`.\n\nThis process is performed:\n- In Crust, as the loop labeled \"Writing exception vectors\" in `tools/load.c`\n- In ATF, inside `plat_setup_psci_ops()` in `plat/allwinner/common/sunxi_pm.c`\n\n## Communicating via SCPI\n\nSCPI uses two hardware interfaces: a mailbox and a shared memory area.\n\nCrust provides two SCPI communication channels: one for ATF (secure\") and one\nfor Linux (\"non-secure\"). Crust reserves the right to add a third communication\nchannel in the future for a TEE in Secure EL1. Therefore, it must be assumed to\nuse three pairs mailbox channels and three shared memory segments.\n\n### Mailbox\n\nSCP firmware is responsible for enabling the mailbox clock and reset. Other\nmailbox drivers SHOULD enable them if they are not already enabled, but MUST\nNOT disable them once they are enabled.\n\nSCP firmware is responsible for configuring the mailbox channel directions.\nOther mailbox drivers MUST NOT modify the channel direction registers.\n\nCrust has reserved the first six mailbox channels for use with SCPI. While they\nMAY also be used for other protocols, SCPI client drivers are unlikely to\nhandle this cleanly. Channel allocation is as follows:\n\n| Channel | Direction | Use                        |\n|---------|-----------|----------------------------|\n|       0 | AP  → SCP | SCPI (Secure EL3)          |\n|       1 | SCP → AP  | SCPI (Secure EL3)          |\n|       2 | AP  → SCP | SCPI (Non-secure EL1/EL2)  |\n|       3 | SCP → AP  | SCPI (Non-secure EL1/EL2)  |\n|       4 | AP  → SCP | SCPI (Secure EL1) (future) |\n|       5 | SCP → AP  | SCPI (Secure EL1) (future) |\n|       6 | AP  → SCP | Unallocated                |\n|       7 | SCP → AP  | Unallocated                |\n\nThis allocation is defined:\n- In Crust, as `RX_CHAN`/`TX_CHAN` in `common/scpi.c`\n- In ATF, as `RX_CHAN`/`TX_CHAN` in `drivers/allwinner/sunxi_msgbox.c`\n- In Linux, in the `mboxes` property of the `scpi` node in the device tree\n\nSCPI mailbox notifications use the standard virtual channel number 1. This is\ndefined:\n- In Crust, as `SCPI_VIRTUAL_CHANNEL` in `include/lib/scpi_protocol.h`\n- In ATF, as `SCPI_MHU_SLOT_ID` in `drivers/arm/css/scpi/css_scpi.c`\n\n### Shared memory\n\nCrust supports SCPI with a message size of 256 bytes. This is hardcoded:\n- In Crust, as `SCPI_MESSAGE_SIZE` in `include/lib/scpi_protocol.h`\n- In ATF, as `SCPI_SHARED_MEM_AP_TO_SCP` in `drivers/arm/css/scpi/css_scpi.c`\n\nThus, each shared memory segment is 512 bytes long. Shared memory segments grow\ndown from the top of SRAM A2, in the same order as mailbox channels grow up.\n\n| Offset | Direction | Use                        |\n|--------|-----------|----------------------------|\n| -0x100 | AP  → SCP | SCPI (Secure EL3)          |\n| -0x200 | SCP → AP  | SCPI (Secure EL3)          |\n| -0x300 | AP  → SCP | SCPI (Non-secure EL1/EL2)  |\n| -0x400 | SCP → AP  | SCPI (Non-secure EL1/EL2)  |\n| -0x500 | AP  → SCP | SCPI (Secure EL1) (future) |\n| -0x600 | SCP → AP  | SCPI (Secure EL1) (future) |\n\nThese offsets are defined:\n- In Crust, as `SCPI_MEM_AREA` in `common/scpi.c`\n- In ATF, as `PLAT_CSS_SCP_COM_SHARED_MEM_BASE` in\n  `plat/allwinner/common/include/platform_def.h`\n- In Linux, as the `reg` property of the `scp-shmem` node in the device tree\n\nNote that because SRAM A2 is \"secure-only\", Linux may not be able to access it\nwhen the secure mode fuse is blown. In that case, the non-secure shared memory\nwill have to be moved to DRAM or SRAM A1.\n\n### Timeouts\n\nTesting shows that Crust normally responds to SCPI commands within 1ms.\nAcknowledgment of responses is polled in ATF and interrupt-driven in Linux. In\nboth cases, it should be at least as fast. Thus the current timeouts are very\nconservative. The only timeout that is sometimes too short is the ATF polling\ntimeout, when adding many lines of serial debugging to the Crust boot process.\n\nTimeouts are defined:\n- In Crust, as `SCPI_TX_TIMEOUT` in `common/scpi.c` (10ms)\n- In ATF, as `MHU_TIMEOUT_ITERS` in `drivers/allwinner/sunxi_msgbox.c` (1s)\n- In Linux, as `MAX_RX_TIMEOUT` in `drivers/firmware/arm_scpi.c` (30ms)\n\n### Concurrent use\n\nCrust supports concurrent SCPI commands by all clients, but only one command at\na time per client. No further commands from a client will be processed until\nthe previous response is acknowledged.\n\nCurrently, neither ATF nor Linux attempts to send multiple concurrent commands\non a single channel.\n\n### Supported commands\n\nCrust attempts to follow the SCPI specification in advertising the list of\nsupported commands, and implementing them according to spec.\n\n### Sending \"SCP Ready\"\n\nSince the mailbox hardware in sunxi SoCs is a FIFO, not the doorbell that SCPI\nwas designed for, it is important to avoid sending messages that will be\nignored. To this end, Crust only sends the \"SCP Ready\" message when it believes\nthe system is first booting.\n\nCrust assumes the system is booting iff CPU 0 is the only running CPU. This can\nbe wrong, for example if Crust crashed and restarted while Linux was booted and\nall other CPUs were offlined to save power.\n\nIt may be prudent to introduce an explicit handshake with ATF to signal first\nboot.\n\n### Power states\n\nCrust uses the same CPU/CSS power states as defined in the SCPI specification\nappendix:\n\n| State | Meaning   |\n|-------|-----------|\n|     0 | On        |\n|     1 | Retention |\n|     2 | RESERVED  |\n|     3 | Off       |\n\nThese are also defined:\n- In Crust, as `SCPI_CSS_*` in `include/lib/scpi_protocol.h`\n- In ATF, as `scpi_power_state_t` in `include/drivers/arm/css/css_scpi.h`\n\nSystem power states are defined by the SCPI specification.\n\n## Hardware ownership\n\n- Crust owns the shared part and its private half of `HWSPINLOCK` and `MSGBOX`.\n  ATF and Linux MUST NOT modify any part but the ARM private half.\n- Crust owns `R_CPUCFG`, `R_TIMER`, and `R_TWD`. Linux MUST NOT use them. ATF\n  MUST NOT use them except for using `R_CPUCFG` to turn on the AR100.\n- Crust owns all of `R_PRCM` except the clock/reset registers. ATF and Linux\n  MUST NOT use any registers except those controlling clocks/resets.\n- Crust MAY modify `R_RSB` and `R_TWI`, but only during boot or suspend. Linux\n  and ATF MUST reset these devices after resume before attempting to use them.\n- Crust MAY modify `RTC`, but only during boot or suspend, except for the\n  general purpose registers, which may be modified at any time. Use of general\n  purpose registers by ATF, Linux, or Crust MUST be documented.\n- Crust MAY modify `CCU` and `R_PRCM`, but only during boot or suspend, and it\n  MUST restore the original configuration before Linux resumes, except for:\n  - The following bus clocks/resets, which Crust owns: `HWSPINLOCK`, `MSGBOX`,\n    `DRAM`, `R_TWD`\n  - And the following bus clocks/resets, which Crust MAY leave disabled after\n    resume: `R_RSB`, `R_TWI`\n- Crust MAY modify `PIO`, `R_CIR_RX`, `R_PIO`, `R_INTC`, and `R_UART`, but only\n  during boot or suspend, and it MUST restore the original configuration before\n  Linux resumes.\n\n### RTC\n\nCrust uses the following RTC general purpose registers:\n\n| N | Use                               |\n|---|-----------------------------------|\n| 0 | N/A (used by p-boot/u-boot)       |\n| 1 | N/A (used by p-boot/u-boot)       |\n| 2 | Last exception encountered        |\n| 3 | Last suspend/resume step executed |\n"
  },
  {
    "path": "docs/code_of_conduct.md",
    "content": "# Code of Conduct\n\nThis code of conduct outlines expectations for participation in the Crust\nFirmware community, which is committed to providing a welcoming and inspiring\ncommunity for all. People violating this code of conduct may be banned from the\ncommunity.\n\nOur open source community strives to:\n\n* Be friendly and patient: Remember you might not be communicating in someone\n  else's primary spoken or programming language, and others may not have your\n  level of understanding.\n* Be welcoming: Our community welcomes and supports people of all types and\n  backgrounds. This includes, but is not limited to members of any race,\n  ethnicity, culture, national origin, color, immigration status, social and\n  economic class, educational level, sex, sexual orientation, gender identity\n  and expression, age, size, family status, political belief, religion, and\n  mental and physical ability.\n* Be respectful: We are a world-wide community of professionals, and we conduct\n  ourselves professionally. Disagreement is no excuse for poor behavior and\n  poor manners. Disrespectful and unacceptable behavior includes, but is not\n  limited to:\n  * Violent threats or language.\n  * Discriminatory or derogatory jokes and language.\n  * Posting gratuitous, sexually explicit or violent material.\n  * Posting, or threatening to post, people's personally identifying\n    information (\"doxing\").\n  * Insults, especially those using discriminatory terms or slurs.\n  * Behavior that could be perceived as unwanted sexual attention.\n  * Advocating for or encouraging any of the above behaviors.\n* Understand disagreements: Disagreements, both social and technical, are\n  useful learning opportunities. Seek to understand the other viewpoints and\n  resolve differences constructively.\n\nThis code is not exhaustive or complete. It serves to capture our common\nunderstanding of a productive, collaborative environment. We expect the code to\nbe followed in spirit as much as in the letter.\n\nThis document was derived from the [Adélie Linux Code of Conduct][alcoc], which\nis licensed as CC BY-NC-SA 4.0.\n\n[alcoc]: http://www.adelielinux.org/conduct.html\n"
  },
  {
    "path": "docs/issue_template.md",
    "content": "<!-- Please indicate if this is a Bug Report, Feature Request, or Question. -->\n## Type of issue\n\n<!--\nFOR BUG REPORTS:\nPlease describe, using as much detail as possible, the issue encountered and\nthe steps necessary to reproduce the issue. It is also crucial that all\nrelevant output and toolchain versions are included.\n\nIf you are using the Crust build system from the meta repository, please\ninclude the configuration section of the Makefile.\n\nFOR FEATURE REQUESTS:\nPlease describe, using as much detail as possible, the feature you would like\nto see introduced and how you will benefit from its addition.\n\nAdditionally, please indicate if this is a feature you can contribute to\nimplementation of.\n-->\n"
  },
  {
    "path": "docs/pull_request_template.md",
    "content": "<!-- Please include the purpose of changes included in this pull request. -->\n## Purpose\n\n<!-- (Optional) Include considerations or notes for project maintainers and\nreviewers.  -->\n## Considerations for reviewers\n\n<!-- Please add the number of the issue this pull request addresses. If this\npull request addresses multiple issues, please add them as a comma-separated\nlist (i.e. Closes #1, Closes #2, Fixes #3). -->\nCloses #\n"
  },
  {
    "path": "drivers/Kconfig",
    "content": "#\n# Copyright © 2017-2022 The Crust Firmware Authors.\n# SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n#\n\nmenu \"Device drivers\"\n\nsource \"cec/Kconfig\"\nsource \"cir/Kconfig\"\nsource \"clock/Kconfig\"\nsource \"regmap/Kconfig\"\nsource \"mfd/Kconfig\"\nsource \"pmic/Kconfig\"\nsource \"regulator/Kconfig\"\nsource \"serial/Kconfig\"\nsource \"watchdog/Kconfig\"\n\nendmenu\n"
  },
  {
    "path": "drivers/Makefile",
    "content": "#\n# Copyright © 2017-2022 The Crust Firmware Authors.\n# SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n#\n\nobj-$(CONFIG_CEC) += cec/\nobj-$(CONFIG_CIR) += cir/\nobj-y += clock/\nobj-y += counter/\nobj-y += css/\nobj-y += dram/\nobj-y += gpio/\nobj-y += irq/\nobj-y += mfd/\nobj-y += msgbox/\nobj-y += pmic/\nobj-y += regmap/\nobj-y += regulator/\nobj-$(CONFIG_SERIAL) += serial/\nobj-y += watchdog/\n"
  },
  {
    "path": "drivers/cec/Kconfig",
    "content": "#\n# Copyright © 2021-2022 The Crust Firmware Authors.\n# SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n#\n\nconfig CEC\n\tbool \"HDMI CEC\"\n\tdepends on HAVE_HDMI\n\thelp\n\t\tListen for messages from TV or other devices on HDMI CEC bus.\n\t\tThis can be used as a wakeup source. Note: Clocks and resets\n\t\tmust be pre-initialized by rich OS.\n"
  },
  {
    "path": "drivers/cec/Makefile",
    "content": "#\n# Copyright © 2021-2022 The Crust Firmware Authors.\n# SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n#\n\nobj-y += cec.o\n\nobj-y += dw-hdmi-cec.o\n"
  },
  {
    "path": "drivers/cec/cec.c",
    "content": "/*\n * Copyright © 2021-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <cec.h>\n#include <device.h>\n#include <cec/dw-hdmi-cec.h>\n\nconst struct device *\ncec_get(void)\n{\n\treturn device_get_or_null(&hdmi_cec.dev);\n}\n\nuint32_t\ncec_poll(const struct device *dev)\n{\n\tif (!dev)\n\t\treturn 0;\n\n\treturn dw_hdmi_cec_poll(dev);\n}\n"
  },
  {
    "path": "drivers/cec/dw-hdmi-cec.c",
    "content": "/*\n * Copyright © 2021-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <error.h>\n#include <intrusive.h>\n#include <mmio.h>\n#include <util.h>\n#include <cec/dw-hdmi-cec.h>\n#include <clock/ccu.h>\n#include <platform/devices.h>\n\n#define CEC_STAT         0x0106\n#define CEC_MUTE         0x0186\n#define IH_MUTE          0x01ff\n#define CEC_CTRL         0x7d00\n#define CEC_MASK         0x7d02\n#define CEC_POL          0x7d03\n#define CEC_ADDRL        0x7d05\n#define CEC_ADDRH        0x7d06\n#define CEC_TX_CNT       0x7d07\n#define CEC_RX_CNT       0x7d08\n#define CEC_TX_DATA      0x7d10\n#define CEC_RX_DATA      0x7d20\n#define CEC_LOCK         0x7d30\n#define CEC_WKUPCTRL     0x7d31\n\n#define IRQ_WAKEUP       BIT(6)\n#define IRQ_ALL          0xff\n\n#define IH_MUTE_ALL      0x03\n\n#define CEC_CTRL_STANDBY BIT(4)\n\n#define CEC_LOCK_RELEASE 0x00\n\n/* Set Stream Path */\n#define CEC_WKUP_MSG_86  BIT(7)\n/* Active Source */\n#define CEC_WKUP_MSG_82  BIT(6)\n/* System Audio Mode Request */\n#define CEC_WKUP_MSG_70  BIT(5)\n/* User Control Pressed */\n#define CEC_WKUP_MSG_44  BIT(4)\n/* Deck Control */\n#define CEC_WKUP_MSG_42  BIT(3)\n/* Play */\n#define CEC_WKUP_MSG_41  BIT(2)\n/* Text View On */\n#define CEC_WKUP_MSG_0d  BIT(1)\n/* Image View On */\n#define CEC_WKUP_MSG_04  BIT(0)\n\n#define CEC_WKUP_MSG_ALL (CEC_WKUP_MSG_86 | CEC_WKUP_MSG_82 | \\\n\t                  CEC_WKUP_MSG_70 | CEC_WKUP_MSG_44 | \\\n\t                  CEC_WKUP_MSG_42 | CEC_WKUP_MSG_41 | \\\n\t                  CEC_WKUP_MSG_0d | CEC_WKUP_MSG_04)\n\nstruct dw_hdmi_cec_state {\n\tstruct device_state ds;\n\tuint8_t             stash[4];\n};\n\nstatic inline const struct dw_hdmi_cec *\nto_dw_hdmi_cec(const struct device *dev)\n{\n\treturn container_of(dev, const struct dw_hdmi_cec, dev);\n}\n\nstatic inline struct dw_hdmi_cec_state *\ndw_hdmi_cec_state_for(const struct device *dev)\n{\n\treturn container_of(dev->state, struct dw_hdmi_cec_state, ds);\n}\n\nuint32_t\ndw_hdmi_cec_poll(const struct device *dev)\n{\n\tconst struct dw_hdmi_cec *self = to_dw_hdmi_cec(dev);\n\tuint8_t stat;\n\n\tstat = mmio_read_8(self->regs + CEC_STAT);\n\tmmio_write_8(self->regs + CEC_STAT, stat);\n\n\treturn stat & IRQ_WAKEUP;\n}\n\nstatic int\ndw_hdmi_cec_probe(const struct device *dev)\n{\n\tconst struct dw_hdmi_cec *self  = to_dw_hdmi_cec(dev);\n\tstruct dw_hdmi_cec_state *state = dw_hdmi_cec_state_for(dev);\n\n\tclock_get(&self->bus_clock);\n\n\tstate->stash[0] = mmio_read_8(self->regs + CEC_MUTE);\n\tstate->stash[1] = mmio_read_8(self->regs + CEC_MASK);\n\tstate->stash[2] = mmio_read_8(self->regs + CEC_POL);\n\tstate->stash[3] = mmio_read_8(self->regs + IH_MUTE);\n\n\t/* Mute all interrupts */\n\tmmio_write_8(self->regs + IH_MUTE, IH_MUTE_ALL);\n\n\t/* Configure CEC wake up sources */\n\tmmio_write_8(self->regs + CEC_WKUPCTRL, CEC_WKUP_MSG_ALL);\n\n\t/* Allow only wakeup interrupt on posedge */\n\tmmio_write_8(self->regs + CEC_POL, IRQ_WAKEUP);\n\tmmio_write_8(self->regs + CEC_MUTE, (uint8_t) ~IRQ_WAKEUP);\n\tmmio_write_8(self->regs + CEC_MASK, (uint8_t) ~IRQ_WAKEUP);\n\n\t/* Clear any pending interrupt */\n\tmmio_write_8(self->regs + CEC_STAT, IRQ_ALL);\n\n\t/* Release CEC message in RX buffer (if any) */\n\tmmio_write_8(self->regs + CEC_LOCK, CEC_LOCK_RELEASE);\n\n\t/*\n\t * Put CEC controller in automatic mode. It will NACK all messages\n\t * except those, which are allowed in CEC_WKUPCTRL register.\n\t */\n\tmmio_write_8(self->regs + CEC_CTRL, CEC_CTRL_STANDBY);\n\n\t/* Unmute interrupts */\n\tmmio_write_8(self->regs + IH_MUTE, 0x00);\n\n\treturn SUCCESS;\n}\n\nstatic void\ndw_hdmi_cec_release(const struct device *dev)\n{\n\tconst struct dw_hdmi_cec *self  = to_dw_hdmi_cec(dev);\n\tstruct dw_hdmi_cec_state *state = dw_hdmi_cec_state_for(dev);\n\n\t/* Mute all interrupts */\n\tmmio_write_8(self->regs + IH_MUTE, IH_MUTE_ALL);\n\n\t/* Clear wake up sources */\n\tmmio_write_8(self->regs + CEC_WKUPCTRL, 0x00);\n\n\t/* Put controller out of automatic mode */\n\tmmio_write_8(self->regs + CEC_CTRL, 0x00);\n\n\t/* Clear any pending interrupt */\n\tmmio_write_8(self->regs + CEC_STAT, IRQ_ALL);\n\n\t/* Release CEC message in RX buffer (if any) */\n\tmmio_write_8(self->regs + CEC_LOCK, CEC_LOCK_RELEASE);\n\n\t/* restore registers */\n\tmmio_write_8(self->regs + CEC_POL, state->stash[2]);\n\tmmio_write_8(self->regs + CEC_MASK, state->stash[1]);\n\tmmio_write_8(self->regs + CEC_MUTE, state->stash[0]);\n\n\t/* Restoring IH_MUTE must be last, since it enables interrupts */\n\tmmio_write_8(self->regs + IH_MUTE, state->stash[3]);\n\n\tclock_put(&self->bus_clock);\n}\n\nstatic const struct driver dw_hdmi_cec_driver = {\n\t.probe   = dw_hdmi_cec_probe,\n\t.release = dw_hdmi_cec_release,\n};\n\nconst struct dw_hdmi_cec hdmi_cec = {\n\t.dev = {\n\t\t.name  = \"DW HDMI CEC\",\n\t\t.drv   = &dw_hdmi_cec_driver,\n\t\t.state = &(struct dw_hdmi_cec_state) { { 0 } }.ds,\n\t},\n\t.bus_clock = { .dev = &r_ccu.dev, .id = CLK_OSC24M },\n\t.regs      = DEV_HDMI,\n};\n"
  },
  {
    "path": "drivers/cir/Kconfig",
    "content": "#\n# Copyright © 2020-2022 The Crust Firmware Authors.\n# SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n#\n\nconfig CIR\n\tbool \"CIR (infrared) receiver\"\n\tdepends on HAVE_R_CIR\n\thelp\n\t\tListen for input from an infrared remote controller or\n\t\tkeyboard. This can be used as a wakeup source.\n\nif CIR\n\nchoice\n\tbool \"IR protocol\"\n\tdefault CIR_PROTO_RC6\n\nconfig CIR_PROTO_NEC\n\tbool \"NEC\"\n\thelp\n\t\tSelect this if your remote speaks NEC.\n\nconfig CIR_PROTO_NECX\n\tbool \"Extended NEC\"\n\thelp\n\t\tSelect this if your remote speaks extended NEC.\n\nconfig CIR_PROTO_RC6\n\tbool \"RC6\"\n\thelp\n\t\tSelect this for standard RC6 MCE remotes.\n\nendchoice\n\nconfig CIR_WAKE_CODE\n\thex \"Scan code for wakeup\"\n\trange 0x1 0xffffffff\n\tdefault 0x800f040c\n\thelp\n\t\tChoose the scan code that will wake the system when detected.\n\n\t\tThe default value will work with an RC6 MCE remote controller.\n\nconfig CIR_CLK_RATE\n\tint\n\tdefault 125000 if CIR_USE_OSC24M # 24 MHz divided by 192\n\tdefault 32768\n\thelp\n\t\tProvide the sample frequency used for protocol decoding.\n\nconfig CIR_USE_OSC24M\n\tbool \"Use OSC24M as parent clock\"\n\thelp\n\t\tSometimes boards come without external 32768 Hz oscillator\n\t\tand thus RTC use the internal RC oscillator as a source\n\t\tfor generating 32768 Hz clock. However, such clock is\n\t\tnot precise enough for IR signal decoding purposes.\n\n\t\tSet this option to Y if your board doesn't have external\n\t\t32768 Hz oscillator. Note that this increases power\n\t\tconsumption.\n\nconfig R_CIR_RX_PIN\n\tint\n\tdefault  9 if PLATFORM_H6\n\tdefault 11 if PLATFORM_A64 || PLATFORM_H3\n\tdefault 12 if PLATFORM_A83T\n\thelp\n\t\tProvide the Port L pin number used by the CIR receiver.\n\nendif\n"
  },
  {
    "path": "drivers/cir/Makefile",
    "content": "#\n# Copyright © 2020-2022 The Crust Firmware Authors.\n# SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n#\n\nobj-y += cir.o\n\nobj-$(CONFIG_CIR_PROTO_NEC)  += nec.o\nobj-$(CONFIG_CIR_PROTO_NECX) += nec.o\nobj-$(CONFIG_CIR_PROTO_RC6)  += rc6.o\n\nobj-y += sunxi-cir.o\n"
  },
  {
    "path": "drivers/cir/cir.c",
    "content": "/*\n * Copyright © 2020-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <cir.h>\n#include <device.h>\n#include <cir/sunxi-cir.h>\n\nconst struct device *\ncir_get(void)\n{\n\treturn device_get_or_null(&r_cir_rx.dev);\n}\n\nuint32_t\ncir_poll(const struct device *dev)\n{\n\treturn sunxi_cir_poll(dev) == CONFIG_CIR_WAKE_CODE;\n}\n"
  },
  {
    "path": "drivers/cir/cir.h",
    "content": "/*\n * Copyright © 2020-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef CIR_PRIVATE_H\n#define CIR_PRIVATE_H\n\n#include <stdint.h>\n\n/**\n * Possible values for pulse type.\n */\nenum {\n\tCIR_SPACE,\n\tCIR_MARK,\n};\n\n/**\n * Context for CIR pulse decoding.\n */\nstruct cir_dec_ctx {\n\tuint32_t buffer;  /*<< Buffer to store a partial scancode. */\n\tuint32_t counter; /*<< Cumulative pulse width counter. */\n\tuint8_t  bits;    /*<< Number of bits decoded. */\n\tuint8_t  state;   /*<< Internal decoder state. */\n\tuint8_t  pulse;   /*<< Current pulse type (mark or space). */\n\tint8_t   width;   /*<< Current pulse width in clock cycles. */\n};\n\n/**\n * Decode a CIR pulse sequence.\n *\n * The pulse flag and width must be valid each time this function is called.\n * Each call will decode a single pulse, so decoding a complete scancode\n * requires many calls. All but the last in the sequence will return zero.\n *\n * If an error occurs, decoding restarts, but the error is not reported.\n *\n * @return A successfully decoded scancode, or zero.\n */\nuint32_t cir_decode(struct cir_dec_ctx *ctx);\n\n#endif /* CIR_PRIVATE_H */\n"
  },
  {
    "path": "drivers/cir/nec.c",
    "content": "/*\n * Copyright © 2021-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <debug.h>\n#include <division.h>\n#include <stdint.h>\n#include <util.h>\n\n#include \"cir.h\"\n\n#define EQ_MARGIN(val, time, margin) \\\n\t(((time) - (margin)) < (val) && (val) < ((time) + (margin)))\n\n#define NUM_DATA_BITS 32\n\n/* NEC time unit is ~562.5 us, or ~1777 units/s. */\n#define NEC_UNIT_RATE 1777\n\n/* Convert specified number of time units to number of clock cycles. */\n#define NEC_UNITS_TO_CLKS(num) \\\n\tUDIV_ROUND((num) * CONFIG_CIR_CLK_RATE, NEC_UNIT_RATE)\n\n#define NEC_LEAD_M        NEC_UNITS_TO_CLKS(16)\n#define NEC_LEAD_S        NEC_UNITS_TO_CLKS(8)\n#define NEC_DATA_M        NEC_UNITS_TO_CLKS(1)\n#define NEC_DATA_S_0      NEC_UNITS_TO_CLKS(1)\n#define NEC_DATA_S_1      NEC_UNITS_TO_CLKS(3)\n\n#define NEC_HALF_MARGIN   (NEC_UNITS_TO_CLKS(1) / 2)\n#define NEC_SINGLE_MARGIN NEC_UNITS_TO_CLKS(1)\n#define NEC_DOUBLE_MARGIN NEC_UNITS_TO_CLKS(2)\n\nenum {\n\tNEC_IDLE,\n\tNEC_HEAD_S,\n\tNEC_PULSE,\n\tNEC_DATA,\n\tNEC_STATES\n};\n\nstatic const uint8_t nec_pulse_states[NEC_STATES] = {\n\t[NEC_IDLE]   = CIR_MARK,\n\t[NEC_HEAD_S] = CIR_SPACE,\n\t[NEC_PULSE]  = CIR_MARK,\n\t[NEC_DATA]   = CIR_SPACE,\n};\n\nuint32_t\ncir_decode(struct cir_dec_ctx *ctx)\n{\n\tuint32_t counter = ctx->counter;\n\tuint32_t ret     = 0;\n\n\t/* Consume samples until the pulse state changes. */\n\tif (nec_pulse_states[ctx->state] == ctx->pulse) {\n\t\tctx->counter += ctx->width;\n\t\tctx->width    = 0;\n\t\treturn 0;\n\t}\n\n\t/* Then reinitialize the cumulative counter for the next state. */\n\tctx->counter = 0;\n\n\tswitch (ctx->state) {\n\tcase NEC_IDLE:\n\t\tif (EQ_MARGIN(counter, NEC_LEAD_M, NEC_DOUBLE_MARGIN))\n\t\t\tctx->state = NEC_HEAD_S;\n\t\telse\n\t\t\tctx->width = 0;\n\t\tbreak;\n\tcase NEC_HEAD_S:\n\t\tif (EQ_MARGIN(counter, NEC_LEAD_S, NEC_SINGLE_MARGIN)) {\n\t\t\tctx->bits   = 0;\n\t\t\tctx->buffer = 0;\n\t\t\tctx->state  = NEC_PULSE;\n\t\t} else {\n\t\t\tctx->state = NEC_IDLE;\n\t\t}\n\t\tbreak;\n\tcase NEC_PULSE:\n\t\tctx->state = NEC_IDLE;\n\t\tif (!EQ_MARGIN(counter, NEC_DATA_M, NEC_HALF_MARGIN))\n\t\t\tbreak;\n\t\tif (ctx->bits == NUM_DATA_BITS) {\n\t\t\t/* Would be nice to check if inverted values match. */\n\t\t\tif (CONFIG(CIR_PROTO_NECX)) {\n\t\t\t\tret = ((ctx->buffer << 16) & GENMASK(23, 16)) |\n\t\t\t\t      (ctx->buffer & GENMASK(15, 8)) |\n\t\t\t\t      ((ctx->buffer >> 16) & GENMASK(7, 0));\n\t\t\t} else {\n\t\t\t\tret = ((ctx->buffer << 8) & GENMASK(15, 8)) |\n\t\t\t\t      ((ctx->buffer >> 16) & GENMASK(7, 0));\n\t\t\t}\n\t\t\tdebug(\"NEC code %06x\", ret);\n\t\t} else {\n\t\t\tctx->state = NEC_DATA;\n\t\t}\n\t\tbreak;\n\tcase NEC_DATA:\n\t\t/* NEC is LSB first. */\n\t\tctx->buffer >>= 1;\n\t\tctx->bits++;\n\t\tctx->state = NEC_PULSE;\n\t\tif (EQ_MARGIN(counter, NEC_DATA_S_1, NEC_HALF_MARGIN))\n\t\t\tctx->buffer |= BIT(31);\n\t\telse if (!EQ_MARGIN(counter, NEC_DATA_S_0, NEC_HALF_MARGIN))\n\t\t\tctx->state = NEC_IDLE;\n\t\tbreak;\n\tdefault:\n\t\tunreachable();\n\t}\n\n\treturn ret;\n}\n"
  },
  {
    "path": "drivers/cir/rc6.c",
    "content": "/*\n * Copyright © 2020-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <debug.h>\n#include <division.h>\n#include <stdint.h>\n#include <util.h>\n\n#include \"cir.h\"\n\n#define NUM_HEADER_BITS       4\n#define NUM_MODE_0_DATA_BITS  16\n#define NUM_MODE_6A_DATA_BITS 32\n\n#define RC6_MAN_MASK          GENMASK(31, 16)\n#define RC6_MAN_MCE           0x800f0000\n\n#define RC6_MODE(header)      ((header) & 7)\n\n/* RC6 time unit is 16 periods @ 36 kHz, ~444 us. */\n#define RC6_CARRIER_FREQ      36000\n#define RC6_UNIT_RATE         (RC6_CARRIER_FREQ / 16)\n\n/* Convert specified number of time units to number of clock cycles. */\n#define RC6_UNITS_TO_CLKS(num) \\\n\tUDIV_ROUND((num) * CONFIG_CIR_CLK_RATE, RC6_UNIT_RATE)\n\nenum {\n\tRC6_IDLE,\n\tRC6_LEADER_S,\n\tRC6_HEADER_P,\n\tRC6_HEADER_N,\n\tRC6_TRAILER_P,\n\tRC6_TRAILER_N,\n\tRC6_DATA_P,\n\tRC6_DATA_N,\n\tRC6_STATES\n};\n\nstatic const int16_t rc6_durations[RC6_STATES] = {\n\t[RC6_IDLE]      = RC6_UNITS_TO_CLKS(6),\n\t[RC6_LEADER_S]  = RC6_UNITS_TO_CLKS(2),\n\t[RC6_HEADER_P]  = RC6_UNITS_TO_CLKS(1),\n\t[RC6_HEADER_N]  = RC6_UNITS_TO_CLKS(1),\n\t[RC6_TRAILER_P] = RC6_UNITS_TO_CLKS(2),\n\t[RC6_TRAILER_N] = RC6_UNITS_TO_CLKS(2),\n\t[RC6_DATA_P]    = RC6_UNITS_TO_CLKS(1),\n\t[RC6_DATA_N]    = RC6_UNITS_TO_CLKS(1),\n};\n\nuint32_t\ncir_decode(struct cir_dec_ctx *ctx)\n{\n\tint32_t duration = rc6_durations[ctx->state];\n\tint32_t epsilon  = ctx->state == RC6_IDLE ?\n\t                   RC6_UNITS_TO_CLKS(1) : RC6_UNITS_TO_CLKS(1) / 2;\n\n\t/* Subtract the expected pulse with from the sample width. */\n\tctx->width -= duration;\n\n\t/*\n\t * If the duration of this pulse is larger than the remaining time in\n\t * the current sample, an error has occurred. Either noise introduced\n\t * a short pulse, or the decoder got out of sync. Restart the decoder.\n\t */\n\tif (ctx->width < -epsilon) {\n\t\tctx->state = RC6_IDLE;\n\t\treturn 0;\n\t}\n\n\t/* Discard the remainder of the sample if less than epsilon remains. */\n\tif (ctx->width <= epsilon)\n\t\tctx->width = 0;\n\n\tswitch (ctx->state) {\n\tcase RC6_IDLE:\n\t\tif (!ctx->pulse)\n\t\t\tbreak;\n\t\t/* Found a leader mark. Initialize the context. */\n\t\tctx->bits   = NUM_HEADER_BITS;\n\t\tctx->buffer = 0;\n\t\tctx->state  = RC6_LEADER_S;\n\t\tbreak;\n\tcase RC6_LEADER_S:\n\t\t/* Expect a space. */\n\t\tctx->state = ctx->pulse ? RC6_IDLE : RC6_HEADER_P;\n\t\tbreak;\n\tcase RC6_HEADER_P:\n\tcase RC6_DATA_P:\n\t\tctx->bits--;\n\t\tctx->buffer = ctx->buffer << 1 | ctx->pulse;\n\t\tctx->state++;\n\t\tbreak;\n\tcase RC6_HEADER_N:\n\t\t/* This pulse must negate the previous pulse. */\n\t\tif (ctx->pulse == (ctx->buffer & 1)) {\n\t\t\tctx->state = RC6_IDLE;\n\t\t} else if (ctx->bits == 0) {\n\t\t\t/* Reinitialize the buffer for decoding data. */\n\t\t\tctx->bits = RC6_MODE(ctx->buffer) == 6 ?\n\t\t\t            NUM_MODE_6A_DATA_BITS :\n\t\t\t            NUM_MODE_0_DATA_BITS;\n\t\t\tctx->buffer = 0;\n\t\t\tctx->state  = RC6_TRAILER_P;\n\t\t} else {\n\t\t\tctx->state = RC6_HEADER_P;\n\t\t}\n\t\tbreak;\n\tcase RC6_TRAILER_P:\n\tcase RC6_TRAILER_N:\n\t\tctx->state++;\n\t\tbreak;\n\tcase RC6_DATA_N:\n\t\tctx->state = RC6_IDLE;\n\t\t/* This pulse must negate the previous pulse. */\n\t\tif (ctx->pulse == (ctx->buffer & 1))\n\t\t\tbreak;\n\t\tif (ctx->bits == 0) {\n\t\t\tuint32_t code = ctx->buffer;\n\n\t\t\t/* Remove MCE toggle bit. */\n\t\t\tif ((code & RC6_MAN_MASK) == RC6_MAN_MCE)\n\t\t\t\tcode &= ~BIT(15);\n\t\t\tdebug(\"RC6 code %08x\", code);\n\t\t\treturn code;\n\t\t} else {\n\t\t\tctx->state = RC6_DATA_P;\n\t\t}\n\t\tbreak;\n\tdefault:\n\t\tunreachable();\n\t}\n\n\treturn 0;\n}\n"
  },
  {
    "path": "drivers/cir/sunxi-cir.c",
    "content": "/*\n * Copyright © 2020-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <error.h>\n#include <mmio.h>\n#include <util.h>\n#include <cir/sunxi-cir.h>\n#include <clock/ccu.h>\n#include <gpio/sunxi-gpio.h>\n#include <platform/devices.h>\n#include <platform/prcm.h>\n\n#include \"cir.h\"\n\n#define CIR_RXCTL  0x00\n#define CIR_RXPCFG 0x10\n#define CIR_RXFIFO 0x20\n#define CIR_RXINT  0x2c\n#define CIR_RXSTA  0x30\n#define CIR_RXCFG  0x34\n\nstruct sunxi_cir_state {\n\tstruct device_state ds;\n\tstruct cir_dec_ctx  dec_ctx;\n\tuint32_t            clk_stash;\n};\n\nstatic inline const struct sunxi_cir *\nto_sunxi_cir(const struct device *dev)\n{\n\treturn container_of(dev, const struct sunxi_cir, dev);\n}\n\nstatic inline struct sunxi_cir_state *\nsunxi_cir_state_for(const struct device *dev)\n{\n\treturn container_of(dev->state, struct sunxi_cir_state, ds);\n}\n\nuint32_t\nsunxi_cir_poll(const struct device *dev)\n{\n\tconst struct sunxi_cir *self  = to_sunxi_cir(dev);\n\tstruct sunxi_cir_state *state = sunxi_cir_state_for(dev);\n\tstruct cir_dec_ctx *dec_ctx   = &state->dec_ctx;\n\n\t/* Feed the decoder data as needed and as it becomes available. */\n\tif (dec_ctx->width <= 0) {\n\t\t/* If no data is available, do not call the decoder. */\n\t\tif (!(mmio_read_32(self->regs + CIR_RXSTA) >> 8))\n\t\t\treturn 0;\n\n\t\tuint32_t sample = mmio_read_32(self->regs + CIR_RXFIFO);\n\t\tdec_ctx->pulse = sample >> 7;\n\t\tdec_ctx->width = sample & GENMASK(6, 0);\n\t}\n\n\treturn cir_decode(dec_ctx);\n}\n\nstatic int\nsunxi_cir_probe(const struct device *dev)\n{\n\tconst struct sunxi_cir *self  = to_sunxi_cir(dev);\n\tstruct sunxi_cir_state *state = sunxi_cir_state_for(dev);\n\tint err;\n\n\tif ((err = gpio_get(&self->pin)))\n\t\treturn err;\n\n\t/* Set module clock parent and divider. */\n\tstate->clk_stash = mmio_read_32(R_CIR_RX_CLK_REG);\n\tmmio_write_32(R_CIR_RX_CLK_REG,\n\t              CONFIG(CIR_USE_OSC24M) ? 0x01000002 : 0x0);\n\tclock_get(&self->bus_clock);\n\tclock_get(&self->mod_clock);\n\n\t/* Configure thresholds and sample clock. */\n\tmmio_write_32(self->regs + CIR_RXCFG,\n\t              CONFIG(CIR_USE_OSC24M) ? 0x00001404 : 0x010f0310);\n\n\t/* Enable CIR module. */\n\tmmio_write_32(self->regs + CIR_RXCTL, 0x33);\n\n\treturn SUCCESS;\n}\n\nstatic void\nsunxi_cir_release(const struct device *dev)\n{\n\tconst struct sunxi_cir *self  = to_sunxi_cir(dev);\n\tstruct sunxi_cir_state *state = sunxi_cir_state_for(dev);\n\n\tclock_put(&self->mod_clock);\n\tclock_put(&self->bus_clock);\n\tmmio_write_32(R_CIR_RX_CLK_REG, state->clk_stash);\n\tgpio_put(&self->pin);\n}\n\nstatic const struct driver sunxi_cir_driver = {\n\t.probe   = sunxi_cir_probe,\n\t.release = sunxi_cir_release,\n};\n\nconst struct sunxi_cir r_cir_rx = {\n\t.dev = {\n\t\t.name  = \"r_cir_rx\",\n\t\t.drv   = &sunxi_cir_driver,\n\t\t.state = &(struct sunxi_cir_state) { { 0 } }.ds,\n\t},\n\t.bus_clock = { .dev = &r_ccu.dev, .id = CLK_BUS_R_CIR },\n\t.mod_clock = { .dev = &r_ccu.dev, .id = CLK_R_CIR },\n\t.pin       = {\n\t\t.dev   = &r_pio.dev,\n\t\t.id    = SUNXI_GPIO_PIN(0, CONFIG_R_CIR_RX_PIN),\n\t\t.drive = DRIVE_10mA,\n\t\t.mode  = 2,\n\t\t.pull  = PULL_NONE,\n\t},\n\t.regs = DEV_R_CIR_RX,\n};\n"
  },
  {
    "path": "drivers/clock/Kconfig",
    "content": "#\n# Copyright © 2020 The Crust Firmware Authors.\n# SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n#\n\nchoice\n\tbool \"OSC24M clock source\"\n\tdefault OSC24M_SRC_DCXO if HAVE_DCXO\n\tdefault OSC24M_SRC_X24M\n\nconfig OSC24M_SRC_DCXO\n\tbool \"DCXO\"\n\tdepends on HAVE_DCXO\n\thelp\n\t\tSelect this option if your board has the 24 MHz crystal\n\t\tconnected to the DCXO pads on the SoC.\n\nconfig OSC24M_SRC_X24M\n\tbool \"X24M\"\n\thelp\n\t\tSelect this option if your board has the 24 MHz crystal\n\t\tconnected to the X24M pads on the SoC.\n\nendchoice\n"
  },
  {
    "path": "drivers/clock/Makefile",
    "content": "#\n# Copyright © 2017-2022 The Crust Firmware Authors.\n# SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n#\n\nobj-y += clock.o\n\nobj-y += ccu.o\nobj-y += ccu_helpers.o\nobj-y += r_ccu_common.o\n\nobj-$(CONFIG_PLATFORM_A23)  += sun8i-a23-ccu.o\nobj-$(CONFIG_PLATFORM_A23)  += sun8i-r-ccu.o\nobj-$(CONFIG_PLATFORM_A64)  += sun50i-a64-ccu.o\nobj-$(CONFIG_PLATFORM_A64)  += sun8i-r-ccu.o\nobj-$(CONFIG_PLATFORM_A83T) += sun8i-a83t-ccu.o\nobj-$(CONFIG_PLATFORM_A83T) += sun8i-r-ccu.o\nobj-$(CONFIG_PLATFORM_H3)   += sun8i-h3-ccu.o\nobj-$(CONFIG_PLATFORM_H3)   += sun8i-r-ccu.o\nobj-$(CONFIG_PLATFORM_H6)   += sun50i-h6-ccu.o\nobj-$(CONFIG_PLATFORM_H6)   += sun50i-h6-r-ccu.o\n"
  },
  {
    "path": "drivers/clock/ccu.c",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <bitmap.h>\n#include <clock.h>\n#include <device.h>\n#include <error.h>\n#include <intrusive.h>\n#include <stdbool.h>\n#include <clock/ccu.h>\n\n#include \"ccu.h\"\n\nstatic inline const struct ccu *\nto_ccu(const struct device *dev)\n{\n\treturn container_of(dev, const struct ccu, dev);\n}\n\nconst struct clock_handle *\nccu_get_null_parent(const struct ccu *self UNUSED,\n                    const struct ccu_clock *clk UNUSED)\n{\n\treturn NULL;\n}\n\nstatic const struct clock_handle *\nccu_get_parent(const struct clock_handle *clock)\n{\n\tconst struct ccu *self      = to_ccu(clock->dev);\n\tconst struct ccu_clock *clk = &self->clocks[clock->id];\n\n\treturn clk->get_parent(self, clk);\n}\n\nuint32_t\nccu_get_parent_rate(const struct ccu *self UNUSED,\n                    const struct ccu_clock *clk UNUSED, uint32_t rate)\n{\n\treturn rate;\n}\n\nstatic uint32_t\nccu_get_rate(const struct clock_handle *clock, uint32_t rate)\n{\n\tconst struct ccu *self      = to_ccu(clock->dev);\n\tconst struct ccu_clock *clk = &self->clocks[clock->id];\n\n\t/* Perform clock-specific adjustments to the parent rate. */\n\treturn clk->get_rate(self, clk, rate);\n}\n\nstatic uint32_t\nccu_get_state(const struct clock_handle *clock)\n{\n\tconst struct ccu *self      = to_ccu(clock->dev);\n\tconst struct ccu_clock *clk = &self->clocks[clock->id];\n\tuintptr_t regs = self->regs;\n\n\t/* Check the reset line, if present. */\n\tif (clk->reset && !bitmap_get(regs, clk->reset))\n\t\treturn CLOCK_STATE_DISABLED;\n\t/* Check the clock gate, if present. */\n\tif (clk->gate && !bitmap_get(regs, clk->gate))\n\t\treturn CLOCK_STATE_GATED;\n\n\t/* Otherwise, the clock is enabled. */\n\treturn CLOCK_STATE_ENABLED;\n}\n\nstatic void\nccu_set_state(const struct clock_handle *clock, uint32_t state)\n{\n\tconst struct ccu *self      = to_ccu(clock->dev);\n\tconst struct ccu_clock *clk = &self->clocks[clock->id];\n\tbool enable    = state > CLOCK_STATE_DISABLED;\n\tbool ungate    = state > CLOCK_STATE_GATED;\n\tuintptr_t regs = self->regs;\n\n\t/* Do nothing if the clock is already in the desired state. */\n\tif (ccu_get_state(clock) == state)\n\t\treturn;\n\n\t/* First, (de)assert the reset line. */\n\tif (clk->reset)\n\t\t(enable ? bitmap_set : bitmap_clear)(regs, clk->reset);\n\t/* Once the device is in/out of reset, (un)gate the clock. */\n\tif (clk->gate)\n\t\t(ungate ? bitmap_set : bitmap_clear)(regs, clk->gate);\n\t/* Apply the changes by setting the update bit, if applicable. */\n\tif (clk->update)\n\t\tmmio_set_32(regs + clk->reg, BIT(clk->update));\n\t/* Wait for the lock bit to be set, if applicable. */\n\tif (clk->lock && ungate)\n\t\tmmio_poll_32(regs + clk->reg, BIT(clk->lock));\n}\n\nconst struct clock_driver ccu_driver = {\n\t.drv = {\n\t\t.probe   = dummy_probe,\n\t\t.release = dummy_release,\n\t},\n\t.ops = {\n\t\t.get_parent = ccu_get_parent,\n\t\t.get_rate   = ccu_get_rate,\n\t\t.get_state  = ccu_get_state,\n\t\t.set_state  = ccu_set_state,\n\t},\n};\n"
  },
  {
    "path": "drivers/clock/ccu.h",
    "content": "/*\n * Copyright © 2019-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef CCU_PRIVATE_H\n#define CCU_PRIVATE_H\n\n#include <clock.h>\n#include <stdint.h>\n#include <clock/ccu.h>\n\n#include \"clock.h\"\n\n#define DEFINE_FIXED_PARENT(_name, _dev, _id) \\\n\tUNUSED const struct clock_handle * \\\n\t_name(const struct ccu *self UNUSED, \\\n\t      const struct ccu_clock *clk UNUSED) { \\\n\t\tstatic const struct clock_handle _name ## _handle = { \\\n\t\t\t.dev = &_dev.dev, \\\n\t\t\t.id  = _id, \\\n\t\t}; \\\n\t\treturn &_name ## _handle; \\\n\t}\n\n#define DEFINE_FIXED_RATE(_name, _rate) \\\n\tuint32_t \\\n\t_name(const struct ccu *self UNUSED, \\\n\t      const struct ccu_clock *clk UNUSED, \\\n\t      uint32_t rate UNUSED) { \\\n\t\treturn _rate; \\\n\t}\n\nstruct ccu_clock {\n\t/** Hook for determining the parent clock. */\n\tconst struct clock_handle *(*get_parent)(const struct ccu *self,\n\t                                         const struct ccu_clock *clk);\n\t/** Hook for calculating the clock rate from the parent rate. */\n\tuint32_t                   (*get_rate)(const struct ccu *self,\n\t                                       const struct ccu_clock *clk,\n\t                                       uint32_t rate);\n\t/** Byte offset of the clock configuration register. */\n\tuint16_t reg;\n\t/** Offset of the lock bit inside the register (valid if nonzero). */\n\tuint8_t  lock;\n\t/** Offset of the update bit inside the register (valid if nonzero). */\n\tuint8_t  update;\n\t/** Bit offset of the clock gate (valid if nonzero). */\n\tuint16_t gate;\n\t/** Bit offset of the module reset (valid if nonzero). */\n\tuint16_t reset;\n};\n\n/*\n * ccu.c\n * =====\n */\n\nextern const struct clock_driver ccu_driver;\n\n/**\n * Default .get_parent implementation, returns NULL.\n */\nconst struct clock_handle *ccu_get_null_parent(const struct ccu *self,\n                                               const struct ccu_clock *clk);\n\n/**\n * Default .get_rate implementation, returns the parent's rate unmodified.\n */\nuint32_t ccu_get_parent_rate(const struct ccu *self,\n                             const struct ccu_clock *clk, uint32_t rate);\n\n/*\n * ccu_helpers.c\n * =============\n */\n\nuint32_t ccu_helper_get_rate_m(const struct ccu *self,\n                               const struct ccu_clock *clk, uint32_t rate,\n                               uint32_t m_shift, uint32_t m_width);\nuint32_t ccu_helper_get_rate_mp(const struct ccu *self,\n                                const struct ccu_clock *clk, uint32_t rate,\n                                uint32_t m_shift, uint32_t m_width,\n                                uint32_t p_shift, uint32_t p_width);\nuint32_t ccu_helper_get_rate_p(const struct ccu *self,\n                               const struct ccu_clock *clk, uint32_t rate,\n                               uint32_t p_shift, uint32_t p_width);\n\n/*\n * r_ccu_common.c\n * ==============\n */\n\nuint32_t r_ccu_common_get_iosc_rate(const struct ccu *self,\n                                    const struct ccu_clock *clk,\n                                    uint32_t rate);\nvoid r_ccu_common_suspend(uint8_t depth);\nvoid r_ccu_common_resume(void);\nvoid r_ccu_common_init(void);\n\n#endif /* CCU_PRIVATE_H */\n"
  },
  {
    "path": "drivers/clock/ccu_helpers.c",
    "content": "/*\n * Copyright © 2019-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <bitfield.h>\n#include <mmio.h>\n#include <stdint.h>\n\n#include \"ccu.h\"\n\nuint32_t\nccu_helper_get_rate_m(const struct ccu *self,\n                      const struct ccu_clock *clk, uint32_t rate,\n                      uint32_t m_shift, uint32_t m_width)\n{\n\tuint32_t val = mmio_read_32(self->regs + clk->reg);\n\n\trate /= bitfield_get(val, m_shift, m_width) + 1;\n\n\treturn rate;\n}\n\nuint32_t\nccu_helper_get_rate_mp(const struct ccu *self,\n                       const struct ccu_clock *clk, uint32_t rate,\n                       uint32_t m_shift, uint32_t m_width,\n                       uint32_t p_shift, uint32_t p_width)\n{\n\tuint32_t val = mmio_read_32(self->regs + clk->reg);\n\n\trate  /= bitfield_get(val, m_shift, m_width) + 1;\n\trate >>= bitfield_get(val, p_shift, p_width);\n\n\treturn rate;\n}\n\nuint32_t\nccu_helper_get_rate_p(const struct ccu *self,\n                      const struct ccu_clock *clk, uint32_t rate,\n                      uint32_t p_shift, uint32_t p_width)\n{\n\tuint32_t val = mmio_read_32(self->regs + clk->reg);\n\n\trate >>= bitfield_get(val, p_shift, p_width);\n\n\treturn rate;\n}\n"
  },
  {
    "path": "drivers/clock/clock.c",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <clock.h>\n#include <debug.h>\n#include <device.h>\n#include <error.h>\n#include <intrusive.h>\n#include <stdint.h>\n\n#include \"clock.h\"\n\n/**\n * Get the ops for the controller device providing this clock.\n */\nstatic inline const struct clock_driver_ops *\nclock_ops_for(const struct clock_handle *clock)\n{\n\tconst struct clock_driver *drv =\n\t\tcontainer_of(clock->dev->drv, const struct clock_driver, drv);\n\n\treturn &drv->ops;\n}\n\n/**\n * Get the mutable state for this clock.\n */\nstatic inline struct clock_state *\nclock_state_for(const struct clock_handle *clock)\n{\n\tstruct clock_device_state *state =\n\t\tcontainer_of(clock->dev->state, struct clock_device_state, ds);\n\n\treturn &state->cs[clock->id];\n}\n\nbool\nclock_active(const struct clock_handle *clock)\n{\n\treturn clock_state_for(clock)->refcount;\n}\n\nvoid\nclock_disable(const struct clock_handle *clock)\n{\n\t/* Calling this function is only allowed after calling clock_get(). */\n\tassert(clock_active(clock));\n\n\tclock_ops_for(clock)->set_state(clock, CLOCK_STATE_GATED);\n}\n\nvoid\nclock_enable(const struct clock_handle *clock)\n{\n\tconst struct clock_driver_ops *ops = clock_ops_for(clock);\n\tconst struct clock_handle *parent;\n\n\t/* Calling this function is only allowed after calling clock_get(). */\n\tassert(clock_active(clock));\n\n\t/* If the clock has a parent, ensure the parent is enabled. */\n\tif ((parent = ops->get_parent(clock)))\n\t\tclock_enable(parent);\n\n\tops->set_state(clock, CLOCK_STATE_ENABLED);\n}\n\nvoid\nclock_get(const struct clock_handle *clock)\n{\n\tconst struct clock_driver_ops *ops = clock_ops_for(clock);\n\tstruct clock_state *state = clock_state_for(clock);\n\n\t/* Perform additional setup if this is the first reference. */\n\tif (!state->refcount) {\n\t\tconst struct clock_handle *parent;\n\t\tint err UNUSED;\n\n\t\t/* Ensure the controller's driver is loaded. */\n\t\terr = device_get(clock->dev);\n\t\tassert(err == SUCCESS);\n\n\t\t/* Ensure the clock's parent has an active reference. */\n\t\tif ((parent = ops->get_parent(clock)))\n\t\t\tclock_get(parent);\n\n\t\tdebug(\"%s: Clock %u running at %u Hz\", clock->dev->name,\n\t\t      clock->id, clock_get_rate(clock));\n\t}\n\n\t/* Bump the refcount only after successfully acquiring dependencies. */\n\t++state->refcount;\n\n\t/* Enable the clock. */\n\tclock_enable(clock);\n}\n\nuint32_t\nclock_get_rate(const struct clock_handle *clock)\n{\n\tconst struct clock_driver_ops *ops = clock_ops_for(clock);\n\tconst struct clock_handle *parent;\n\tuint32_t rate = 0;\n\n\t/* Initialize the rate with the parent's rate or a known safe value. */\n\tif ((parent = ops->get_parent(clock)))\n\t\trate = clock_get_rate(parent);\n\n\t/* Call the driver function to calculate this clock's rate. */\n\treturn ops->get_rate(clock, rate);\n}\n\nuint32_t\nclock_get_state(const struct clock_handle *clock)\n{\n\tconst struct clock_driver_ops *ops = clock_ops_for(clock);\n\tconst struct clock_handle *parent;\n\tuint32_t parent_state;\n\n\t/* If the clock has a parent, check the parent's state. */\n\tif ((parent = ops->get_parent(clock))) {\n\t\tparent_state = clock_get_state(parent);\n\n\t\t/* If the parent is not enabled, this clock has that state. */\n\t\tif (parent_state != CLOCK_STATE_ENABLED)\n\t\t\treturn parent_state;\n\t}\n\n\t/* Call the driver function to check this clock's state. */\n\treturn ops->get_state(clock);\n}\n\nvoid\nclock_put(const struct clock_handle *clock)\n{\n\tconst struct clock_driver_ops *ops = clock_ops_for(clock);\n\tconst struct clock_handle *parent;\n\tstruct clock_state *state = clock_state_for(clock);\n\n\t/* Calling this function is only allowed after calling clock_get(). */\n\tassert(state->refcount);\n\n\t/* Do nothing if there are other consumers of this clock. */\n\tif (--state->refcount)\n\t\treturn;\n\n\tdebug(\"%s: Releasing clock %u\", clock->dev->name, clock->id);\n\n\t/* Completely disable the clock once the last consumer is gone. */\n\tops->set_state(clock, CLOCK_STATE_DISABLED);\n\n\t/* Drop the reference to the parent clock. */\n\tif ((parent = ops->get_parent(clock)))\n\t\tclock_put(parent);\n\n\t/* Drop the reference to the controller device. */\n\tdevice_put(clock->dev);\n}\n"
  },
  {
    "path": "drivers/clock/clock.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef CLOCK_PRIVATE_H\n#define CLOCK_PRIVATE_H\n\n#include <clock.h>\n#include <device.h>\n#include <stdint.h>\n\n#define CLOCK_DEVICE_STATE_INIT(n) \\\n\t(struct device_state *) \\\n\t&(char[sizeof_struct(struct clock_device_state, cs, n)]) { 0 }\n\nstruct clock_state {\n\tuint8_t refcount;\n};\n\nstruct clock_device_state {\n\tstruct device_state ds;\n\tstruct clock_state  cs[];\n};\n\nstruct clock_driver_ops {\n\tconst struct clock_handle *\n\t         (*get_parent)(const struct clock_handle *clock);\n\tuint32_t (*get_rate)(const struct clock_handle *clock, uint32_t rate);\n\tuint32_t (*get_state)(const struct clock_handle *clock);\n\tvoid     (*set_state)(const struct clock_handle *clock,\n\t                      uint32_t state);\n};\n\nstruct clock_driver {\n\tstruct driver           drv;\n\tstruct clock_driver_ops ops;\n};\n\n#endif /* CLOCK_PRIVATE_H */\n"
  },
  {
    "path": "drivers/clock/r_ccu_common.c",
    "content": "/*\n * Copyright © 2019-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <counter.h>\n#include <delay.h>\n#include <mmio.h>\n#include <stdint.h>\n#include <system.h>\n#include <platform/devices.h>\n#include <platform/prcm.h>\n#include <platform/time.h>\n\n#include \"ccu.h\"\n\n#define PLL_CTRL_REG1_MASK (PLL_CTRL_REG1_KEY_FIELD | \\\n\t                    PLL_CTRL_REG1_CRYSTAL_EN | \\\n\t                    PLL_CTRL_REG1_LDO_EN)\n\n/* Persist this var as r_ccu_init() may not be called after an exception. */\nstatic uint32_t iosc_rate = CPUCLK_Hz;\n\nDEFINE_FIXED_RATE(r_ccu_common_get_iosc_rate, iosc_rate)\n\n/**\n * Write a value to the lockable bits in PLL_CTRL_REG1.\n */\nstatic void\nwrite_pll_ctrl_reg1(uint32_t new)\n{\n\tuint32_t val = mmio_read_32(PLL_CTRL_REG1) & ~PLL_CTRL_REG1_MASK;\n\n\t/* Unlock if locked, otherwise write value. */\n\tmmio_write_32(PLL_CTRL_REG1, val | new | PLL_CTRL_REG1_KEY);\n\t/* Write value if just unlocked, otherwise write same; lock. */\n\tmmio_write_32(PLL_CTRL_REG1, val | new);\n}\n\nvoid\nr_ccu_common_suspend(uint8_t depth)\n{\n\tif (depth == SD_NONE)\n\t\treturn;\n\n\tif (CONFIG(OSC24M_SRC_X24M)) {\n\t\twrite_pll_ctrl_reg1(PLL_CTRL_REG1_LDO_EN);\n\t\tudelay(1);\n\t}\n\twrite_pll_ctrl_reg1(0);\n\tif (depth == SD_OSC24M)\n\t\treturn;\n\n\tmmio_set_32(VDD_SYS_PWROFF_GATING_REG, AVCC_GATING);\n\tif (depth == SD_AVCC)\n\t\treturn;\n\n\tmmio_set_32(VDD_SYS_PWROFF_GATING_REG, VDD_CPUS_GATING);\n\tmmio_write_32(VDD_SYS_RESET_REG, 0);\n\tif (depth == SD_VDD_SYS)\n\t\treturn;\n}\n\nvoid WEAK ATTRIBUTE(alias(\"r_ccu_common_suspend\"))\nr_ccu_suspend(uint8_t depth);\n\nvoid\nr_ccu_common_resume(void)\n{\n\t/*\n\t * The suspend/resume steps are incremental and idempotent. There is no\n\t * need to branch based on the suspend depth; just run them all. This\n\t * simplifies handling a firmware restart where the depth is unknown.\n\t */\n\tmmio_write_32(VDD_SYS_RESET_REG, VDD_SYS_RESET);\n\tmmio_clr_32(VDD_SYS_PWROFF_GATING_REG, VDD_CPUS_GATING | AVCC_GATING);\n\tif (!mmio_get_32(PLL_CTRL_REG1, PLL_CTRL_REG1_LDO_EN)) {\n\t\twrite_pll_ctrl_reg1(PLL_CTRL_REG1_LDO_EN);\n\t\tif (CONFIG(OSC24M_SRC_X24M)) {\n\t\t\tudelay(2000);\n\t\t\twrite_pll_ctrl_reg1(PLL_CTRL_REG1_CRYSTAL_EN |\n\t\t\t                    PLL_CTRL_REG1_LDO_EN);\n\t\t}\n\t}\n}\n\nvoid WEAK ATTRIBUTE(alias(\"r_ccu_common_resume\"))\nr_ccu_resume(void);\n\nvoid\nr_ccu_common_init(void)\n{\n\tuint32_t after, before, end, now;\n\n\t/* Cycle until the interval will not span a counter wraparound. */\n\tdo {\n\t\tbefore = cycle_counter_read();\n\t\tbarrier();\n\t\tnow = system_counter_read();\n\t\tend = now + (REFCLK_HZ >> 9);\n\t} while (end < now);\n\n\t/* Cycle until the end of the interval. */\n\tdo {\n\t\tafter = cycle_counter_read();\n\t\t/* Ensure the counters are read in a consistent order. */\n\t\tbarrier();\n\t\tnow = system_counter_read();\n\t} while (now < end);\n\n\t/*\n\t * Convert the number of IOSC cycles in 1/512 second to Hz. 512 is\n\t * chosen because it is the largest power-of-two factor of 24MHz, the\n\t * reference clock frequency.\n\t */\n\tiosc_rate = (after - before) << 9;\n}\n"
  },
  {
    "path": "drivers/clock/sun50i-a64-ccu.c",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <bitfield.h>\n#include <bitmap.h>\n#include <clock.h>\n#include <device.h>\n#include <error.h>\n#include <stdint.h>\n#include <clock/ccu.h>\n#include <platform/devices.h>\n\n#include \"ccu.h\"\n\n#define CPUX_AXI_CFG_REG  0x0050\n#define AHB1_APB1_CFG_REG 0x0054\n#define APB2_CFG_REG      0x0058\n#define AHB2_CFG_REG      0x005c\n\n#define CPUX_CLK_SRC(x)   ((x) << 16)\n#define CPUX_APB_CLK_M(x) ((x) << 8)\n#define CPUX_AXI_CLK_M(x) ((x) << 0)\n\n#define AHB1_CLK_SRC(x)   ((x) << 12)\n#define APB1_CLK_DIV(x)   ((x) << 8)\n#define AHB1_PRE_DIV(x)   ((x) << 6)\n#define AHB1_CLK_P(x)     ((x) << 4)\n\n#define APB2_CLK_SRC(x)   ((x) << 24)\n#define APB2_CLK_P(x)     ((x) << 16)\n#define APB2_CLK_M(x)     ((x) << 0)\n\n#define AHB2_CLK_SRC(n)   ((n) << 0)\n\nstatic DEFINE_FIXED_RATE(ccu_get_pll_periph0_rate, 600000000U)\n\n/*\n * While APB2 has a mux, assume its parent is OSC24M. Reparenting APB2\n * to PLL_PERIPH0 in Linux for faster UART clocks is unsupported.\n */\nstatic DEFINE_FIXED_PARENT(ccu_get_apb2_parent, r_ccu, CLK_OSC24M)\nstatic DEFINE_FIXED_PARENT(ccu_get_apb2, ccu, CLK_APB2)\n\nstatic const struct clock_handle ccu_dram_parents[] = {\n\t{\n\t\t.dev = &ccu.dev,\n\t\t.id  = CLK_PLL_DDR0,\n\t},\n#if CONFIG(SOC_A64)\n\t{\n\t\t.dev = &ccu.dev,\n\t\t.id  = CLK_PLL_DDR1,\n\t},\n#else\n\t{\n\t\t.dev = &ccu.dev,\n\t\t.id  = CLK_PLL_PERIPH0, /* 2x */\n\t},\n#endif\n};\n\nstatic const struct clock_handle *\nccu_get_dram_parent(const struct ccu *self, const struct ccu_clock *clk)\n{\n\tuint32_t val = mmio_read_32(self->regs + clk->reg);\n\n\treturn &ccu_dram_parents[bitfield_get(val, 20, 1)];\n}\n\nstatic const struct ccu_clock ccu_clocks[SUN50I_A64_CCU_CLOCKS] = {\n\t[CLK_PLL_CPUX] = {\n\t\t.get_parent = ccu_get_null_parent,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t\t.reg        = 0x0000,\n\t\t.lock       = 28,\n\t\t.gate       = BITMAP_INDEX(0x0000, 31),\n\t},\n\t[CLK_PLL_DDR0] = {\n\t\t.get_parent = ccu_get_null_parent,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t\t.reg        = 0x0020,\n\t\t.lock       = 28,\n\t\t.update     = 20,\n\t\t.gate       = BITMAP_INDEX(0x0020, 31),\n\t},\n\t[CLK_PLL_PERIPH0] = {\n\t\t.get_parent = ccu_get_null_parent,\n\t\t.get_rate   = ccu_get_pll_periph0_rate,\n\t},\n#if CONFIG(SOC_A64)\n\t[CLK_PLL_DDR1] = {\n\t\t.get_parent = ccu_get_null_parent,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t\t.reg        = 0x004c,\n\t\t.lock       = 28,\n\t\t.update     = 30,\n\t\t.gate       = BITMAP_INDEX(0x004c, 31),\n\t},\n#endif\n\t[CLK_APB2] = {\n\t\t.get_parent = ccu_get_apb2_parent,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t},\n\t/* Reset requires re-training DRAM, so ignore it. */\n\t[CLK_BUS_DRAM] = {\n\t\t.get_parent = ccu_get_null_parent,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t\t.gate       = BITMAP_INDEX(0x0060, 14),\n\t},\n\t[CLK_BUS_MSGBOX] = {\n\t\t.get_parent = ccu_get_null_parent,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t\t.gate       = BITMAP_INDEX(0x0064, 21),\n\t\t.reset      = BITMAP_INDEX(0x02c4, 21),\n\t},\n\t[CLK_BUS_PIO] = {\n\t\t.get_parent = ccu_get_null_parent,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t\t.gate       = BITMAP_INDEX(0x0068, 5),\n\t},\n#if CONFIG(SERIAL_DEV_UART0)\n\t[CLK_BUS_UART0] = {\n\t\t.get_parent = ccu_get_apb2,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t\t.gate       = BITMAP_INDEX(0x006c, 16),\n\t\t.reset      = BITMAP_INDEX(0x02d8, 16),\n\t},\n#elif CONFIG(SERIAL_DEV_UART1)\n\t[CLK_BUS_UART1] = {\n\t\t.get_parent = ccu_get_apb2,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t\t.gate       = BITMAP_INDEX(0x006c, 17),\n\t\t.reset      = BITMAP_INDEX(0x02d8, 17),\n\t},\n#elif CONFIG(SERIAL_DEV_UART2)\n\t[CLK_BUS_UART2] = {\n\t\t.get_parent = ccu_get_apb2,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t\t.gate       = BITMAP_INDEX(0x006c, 18),\n\t\t.reset      = BITMAP_INDEX(0x02d8, 18),\n\t},\n#elif CONFIG(SERIAL_DEV_UART3)\n\t[CLK_BUS_UART3] = {\n\t\t.get_parent = ccu_get_apb2,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t\t.gate       = BITMAP_INDEX(0x006c, 19),\n\t\t.reset      = BITMAP_INDEX(0x02d8, 19),\n\t},\n#elif CONFIG(SERIAL_DEV_UART4) /* depends on SOC_A64 */\n\t[CLK_BUS_UART4] = {\n\t\t.get_parent = ccu_get_apb2,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t\t.gate       = BITMAP_INDEX(0x006c, 20),\n\t\t.reset      = BITMAP_INDEX(0x02d8, 20),\n\t},\n#endif\n\t[CLK_DRAM] = {\n\t\t.get_parent = ccu_get_dram_parent,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t\t.reg        = 0x00f4,\n\t\t.update     = 16,\n\t\t.reset      = BITMAP_INDEX(0x00f4, 31),\n\t},\n\t[CLK_MBUS] = {\n\t\t.get_parent = ccu_get_null_parent,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t\t.gate       = BITMAP_INDEX(0x015c, 31),\n#if !CONFIG(SOC_H5)\n\t\t/* MBUS reset intermittently breaks DRAM resume on H5. */\n\t\t.reset = BITMAP_INDEX(0x00fc, 31),\n#endif\n\t},\n};\n\nconst struct ccu ccu = {\n\t.dev = {\n\t\t.name  = \"ccu\",\n\t\t.drv   = &ccu_driver.drv,\n\t\t.state = CLOCK_DEVICE_STATE_INIT(SUN50I_A64_CCU_CLOCKS),\n\t},\n\t.clocks = ccu_clocks,\n\t.regs   = DEV_CCU,\n};\n\nstatic const struct clock_handle pll_cpux = {\n\t.dev = &ccu.dev,\n\t.id  = CLK_PLL_CPUX,\n};\n\nvoid\nccu_suspend(void)\n{\n\t/* Set AHB1 to LOSC/1 (32kHz), APB1 to AHB1/2 (16kHz). */\n\tmmio_write_32(DEV_CCU + AHB1_APB1_CFG_REG,\n\t              AHB1_CLK_SRC(0) |\n\t              APB1_CLK_DIV(1) |\n\t              AHB1_PRE_DIV(2) |\n\t              AHB1_CLK_P(0));\n\n\t/* Set AHB2 to AHB1/1 (32kHz). */\n\tmmio_write_32(DEV_CCU + AHB2_CFG_REG,\n\t              AHB2_CLK_SRC(0));\n\n\tclock_put(&pll_cpux);\n}\n\nvoid\nccu_suspend_cluster(uint32_t cluster UNUSED)\n{\n\t/* Set CPUX to LOSC (32kHz), APB to CPUX/4, AXI to CPUX/3. */\n\tmmio_write_32(DEV_CCU + CPUX_AXI_CFG_REG,\n\t              CPUX_CLK_SRC(0) |\n\t              CPUX_APB_CLK_M(3) |\n\t              CPUX_AXI_CLK_M(2));\n}\n\nvoid\nccu_resume(void)\n{\n\tclock_get(&pll_cpux);\n\n\t/* Set AHB1 to PLL_PERIPH0/3 (200MHz), APB1 to AHB1/2 (100MHz). */\n\tmmio_write_32(DEV_CCU + AHB1_APB1_CFG_REG,\n\t              AHB1_CLK_SRC(3) |\n\t              APB1_CLK_DIV(1) |\n\t              AHB1_PRE_DIV(2) |\n\t              AHB1_CLK_P(0));\n\n\t/* Set AHB2 to PLL_PERIPH0/2 (300MHz). */\n\tmmio_write_32(DEV_CCU + AHB2_CFG_REG,\n\t              AHB2_CLK_SRC(1));\n}\n\nvoid\nccu_resume_cluster(uint32_t cluster UNUSED)\n{\n\t/* Set CPUX to PLL_CPUX, APB to CPUX/4, AXI to CPUX/3. */\n\tmmio_write_32(DEV_CCU + CPUX_AXI_CFG_REG,\n\t              CPUX_CLK_SRC(2) |\n\t              CPUX_APB_CLK_M(3) |\n\t              CPUX_AXI_CLK_M(2));\n}\n\nvoid\nccu_init(void)\n{\n\t/* Set APB2 to OSC24M/1 (24MHz). */\n\tmmio_write_32(DEV_CCU + APB2_CFG_REG,\n\t              APB2_CLK_SRC(1) |\n\t              APB2_CLK_P(0) |\n\t              APB2_CLK_M(0));\n\n\tccu_resume();\n\tccu_resume_cluster(0);\n}\n"
  },
  {
    "path": "drivers/clock/sun50i-h6-ccu.c",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <bitmap.h>\n#include <clock.h>\n#include <device.h>\n#include <stdint.h>\n#include <clock/ccu.h>\n#include <platform/devices.h>\n\n#include \"ccu.h\"\n\n#define CPUX_AXI_CFG_REG  0x0500\n#define PSI_CFG_REG       0x0510\n#define AHB3_CFG_REG      0x051c\n#define APB1_CFG_REG      0x0520\n#define APB2_CFG_REG      0x0524\n\n#define CPUX_CLK_SRC(x)   ((x) << 24)\n#define CPUX_APB_CLK_M(x) ((x) << 8)\n#define CPUX_AXI_CLK_M(x) ((x) << 0)\n\n#define PSI_CLK_SRC(x)    ((x) << 24)\n#define PSI_CLK_P(x)      ((x) << 8)\n#define PSI_CLK_M(x)      ((x) << 0)\n\n#define AHB3_CLK_SRC(x)   ((x) << 24)\n#define AHB3_CLK_P(x)     ((x) << 8)\n#define AHB3_CLK_M(x)     ((x) << 0)\n\n#define APB1_CLK_SRC(x)   ((x) << 24)\n#define APB1_CLK_P(x)     ((x) << 8)\n#define APB1_CLK_M(x)     ((x) << 0)\n\n#define APB2_CLK_SRC(x)   ((x) << 24)\n#define APB2_CLK_P(x)     ((x) << 8)\n#define APB2_CLK_M(x)     ((x) << 0)\n\nstatic DEFINE_FIXED_RATE(ccu_get_pll_periph0_rate, 600000000U)\n\nstatic DEFINE_FIXED_PARENT(ccu_get_pll_ddr0, ccu, CLK_PLL_DDR0)\n\n/*\n * While APB2 has a mux, assume its parent is OSC24M. Reparenting APB2\n * to PLL_PERIPH0 in Linux for faster UART clocks is unsupported.\n */\nstatic DEFINE_FIXED_PARENT(ccu_get_apb2_parent, r_ccu, CLK_OSC24M)\nstatic DEFINE_FIXED_PARENT(ccu_get_apb2, ccu, CLK_APB2)\n\nstatic const struct ccu_clock ccu_clocks[SUN50I_H6_CCU_CLOCKS] = {\n\t[CLK_PLL_DDR0] = {\n\t\t.get_parent = ccu_get_null_parent,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t\t.reg        = 0x0010,\n\t\t.lock       = 28,\n\t\t.gate       = BITMAP_INDEX(0x0010, 31),\n\t},\n\t[CLK_PLL_PERIPH0] = {\n\t\t.get_parent = ccu_get_null_parent,\n\t\t.get_rate   = ccu_get_pll_periph0_rate,\n\t},\n\t[CLK_APB2] = {\n\t\t.get_parent = ccu_get_apb2_parent,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t},\n\t[CLK_MBUS] = {\n\t\t.get_parent = ccu_get_null_parent,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t\t.gate       = BITMAP_INDEX(0x0540, 31),\n\t\t.reset      = BITMAP_INDEX(0x0540, 30),\n\t},\n\t[CLK_BUS_MSGBOX] = {\n\t\t.get_parent = ccu_get_null_parent,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t\t.gate       = BITMAP_INDEX(0x071c, 0),\n\t\t.reset      = BITMAP_INDEX(0x071c, 16),\n\t},\n\t[CLK_DRAM] = {\n\t\t.get_parent = ccu_get_pll_ddr0,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t\t.reg        = 0x0800,\n\t\t.update     = 27,\n\t\t.reset      = BITMAP_INDEX(0x0800, 30),\n\t},\n\t/* Reset requires re-training DRAM, so ignore it. */\n\t[CLK_BUS_DRAM] = {\n\t\t.get_parent = ccu_get_null_parent,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t\t.gate       = BITMAP_INDEX(0x080c, 0),\n\t},\n\t[CLK_BUS_PIO] = {\n\t\t.get_parent = ccu_get_null_parent,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t},\n#if CONFIG(SERIAL_DEV_UART0)\n\t[CLK_BUS_UART0] = {\n\t\t.get_parent = ccu_get_apb2,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t\t.gate       = BITMAP_INDEX(0x090c, 0),\n\t\t.reset      = BITMAP_INDEX(0x090c, 16),\n\t},\n#elif CONFIG(SERIAL_DEV_UART1)\n\t[CLK_BUS_UART1] = {\n\t\t.get_parent = ccu_get_apb2,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t\t.gate       = BITMAP_INDEX(0x090c, 1),\n\t\t.reset      = BITMAP_INDEX(0x090c, 17),\n\t},\n#elif CONFIG(SERIAL_DEV_UART2)\n\t[CLK_BUS_UART2] = {\n\t\t.get_parent = ccu_get_apb2,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t\t.gate       = BITMAP_INDEX(0x090c, 2),\n\t\t.reset      = BITMAP_INDEX(0x090c, 18),\n\t},\n#elif CONFIG(SERIAL_DEV_UART3)\n\t[CLK_BUS_UART3] = {\n\t\t.get_parent = ccu_get_apb2,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t\t.gate       = BITMAP_INDEX(0x090c, 3),\n\t\t.reset      = BITMAP_INDEX(0x090c, 19),\n\t},\n#endif\n};\n\nconst struct ccu ccu = {\n\t.dev = {\n\t\t.name  = \"ccu\",\n\t\t.drv   = &ccu_driver.drv,\n\t\t.state = CLOCK_DEVICE_STATE_INIT(SUN50I_H6_CCU_CLOCKS),\n\t},\n\t.clocks = ccu_clocks,\n\t.regs   = DEV_CCU,\n};\n\nvoid\nccu_suspend(void)\n{\n\t/* Set PSI/AHB1/AHB2 to LOSC/1 (32kHz). */\n\tmmio_write_32(DEV_CCU + PSI_CFG_REG,\n\t              PSI_CLK_SRC(1) |\n\t              PSI_CLK_P(0) |\n\t              PSI_CLK_M(0));\n\n\t/* Set AHB3 to LOSC/1 (32kHz). */\n\tmmio_write_32(DEV_CCU + AHB3_CFG_REG,\n\t              AHB3_CLK_SRC(1) |\n\t              AHB3_CLK_P(0) |\n\t              AHB3_CLK_M(0));\n\n\t/* Set APB1 to LOSC/2 (16kHz). */\n\tmmio_write_32(DEV_CCU + APB1_CFG_REG,\n\t              APB1_CLK_SRC(1) |\n\t              APB1_CLK_P(1) |\n\t              APB1_CLK_M(0));\n}\n\nvoid\nccu_suspend_cluster(uint32_t cluster UNUSED)\n{\n\t/* Set CPUX to LOSC (32kHz), APB to CPUX/4, AXI to CPUX/3. */\n\tmmio_write_32(DEV_CCU + CPUX_AXI_CFG_REG,\n\t              CPUX_CLK_SRC(1) |\n\t              CPUX_APB_CLK_M(3) |\n\t              CPUX_AXI_CLK_M(2));\n}\n\nvoid\nccu_resume(void)\n{\n\t/* Set PSI/AHB1/AHB2 to PLL_PERIPH0/3 (200MHz). */\n\tmmio_write_32(DEV_CCU + PSI_CFG_REG,\n\t              PSI_CLK_SRC(3) |\n\t              PSI_CLK_P(0) |\n\t              PSI_CLK_M(2));\n\n\t/* Set AHB3 to PLL_PERIPH0/3 (200MHz). */\n\tmmio_write_32(DEV_CCU + AHB3_CFG_REG,\n\t              AHB3_CLK_SRC(3) |\n\t              AHB3_CLK_P(0) |\n\t              AHB3_CLK_M(2));\n\n\t/* Set APB1 to PLL_PERIPH0/6 (100MHz). */\n\tmmio_write_32(DEV_CCU + APB1_CFG_REG,\n\t              APB1_CLK_SRC(3) |\n\t              APB1_CLK_P(1) |\n\t              APB1_CLK_M(2));\n}\n\nvoid\nccu_resume_cluster(uint32_t cluster UNUSED)\n{\n\t/* Set CPUX to PLL_CPUX, APB to CPUX/4, AXI to CPUX/3. */\n\tmmio_write_32(DEV_CCU + CPUX_AXI_CFG_REG,\n\t              CPUX_CLK_SRC(3) |\n\t              CPUX_APB_CLK_M(3) |\n\t              CPUX_AXI_CLK_M(2));\n}\n\nvoid\nccu_init(void)\n{\n\t/* Set APB2 to OSC24M/1 (24MHz). */\n\tmmio_write_32(DEV_CCU + APB2_CFG_REG,\n\t              APB2_CLK_SRC(0) |\n\t              APB2_CLK_P(0) |\n\t              APB2_CLK_M(0));\n\n\tccu_resume();\n\tccu_resume_cluster(0);\n}\n"
  },
  {
    "path": "drivers/clock/sun50i-h6-r-ccu.c",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <bitfield.h>\n#include <bitmap.h>\n#include <clock.h>\n#include <debug.h>\n#include <device.h>\n#include <mmio.h>\n#include <stddef.h>\n#include <stdint.h>\n#include <clock/ccu.h>\n#include <platform/devices.h>\n#include <platform/prcm.h>\n\n#include \"ccu.h\"\n\nstatic DEFINE_FIXED_RATE(r_ccu_get_osc24m_rate, 24000000U)\nstatic DEFINE_FIXED_RATE(r_ccu_get_osc32k_rate, 32768U)\n\nstatic const struct clock_handle r_ccu_bus_parents[] = {\n\t{\n\t\t.dev = &r_ccu.dev,\n\t\t.id  = CLK_OSC24M,\n\t},\n\t{\n\t\t.dev = &r_ccu.dev,\n\t\t.id  = CLK_OSC32K,\n\t},\n\t{\n\t\t.dev = &r_ccu.dev,\n\t\t.id  = CLK_IOSC,\n\t},\n\t{\n\t\t.dev = &ccu.dev,\n\t\t.id  = CLK_PLL_PERIPH0,\n\t},\n};\n\nstatic const struct clock_handle *\nr_ccu_get_bus_parent(const struct ccu *self,\n                     const struct ccu_clock *clk)\n{\n\tuint32_t val = mmio_read_32(self->regs + clk->reg);\n\n\treturn &r_ccu_bus_parents[bitfield_get(val, 24, 2)];\n}\n\nstatic uint32_t\nr_ccu_get_mp_rate(const struct ccu *self,\n                  const struct ccu_clock *clk, uint32_t rate)\n{\n\t/* For AR100 and R_APB2, this assumes the pre-divider for PLL_PERIPH0\n\t * (parent 3) will only be set if parent 3 is selected in the mux. */\n\treturn ccu_helper_get_rate_mp(self, clk, rate, 0, 5, 8, 2);\n}\n\nstatic DEFINE_FIXED_PARENT(r_ccu_get_ar100, r_ccu, CLK_AR100)\nstatic DEFINE_FIXED_PARENT(r_ccu_get_r_ahb, r_ccu, CLK_R_AHB)\n\nstatic uint32_t\nr_ccu_get_r_apb1_rate(const struct ccu *self,\n                      const struct ccu_clock *clk, uint32_t rate)\n{\n\treturn ccu_helper_get_rate_m(self, clk, rate, 0, 2);\n}\n\nstatic DEFINE_FIXED_PARENT(r_ccu_get_r_apb1, r_ccu, CLK_R_APB1)\nstatic DEFINE_FIXED_PARENT(r_ccu_get_r_apb2, r_ccu, CLK_R_APB2)\n\nstatic const struct clock_handle r_ccu_module_parents[] = {\n\t{\n\t\t.dev = &r_ccu.dev,\n\t\t.id  = CLK_OSC32K,\n\t},\n\t{\n\t\t.dev = &r_ccu.dev,\n\t\t.id  = CLK_OSC24M,\n\t},\n};\n\nstatic const struct clock_handle *\nr_ccu_get_module_parent(const struct ccu *self,\n                        const struct ccu_clock *clk)\n{\n\tuint32_t val = mmio_read_32(self->regs + clk->reg);\n\n\treturn &r_ccu_module_parents[bitfield_get(val, 24, 1)];\n}\n\nstatic const struct ccu_clock r_ccu_clocks[SUN50I_H6_R_CCU_CLOCKS] = {\n\t[CLK_IOSC] = {\n\t\t.get_parent = ccu_get_null_parent,\n\t\t.get_rate   = r_ccu_common_get_iosc_rate,\n\t},\n\t[CLK_OSC24M] = {\n\t\t.get_parent = ccu_get_null_parent,\n\t\t.get_rate   = r_ccu_get_osc24m_rate,\n\t},\n\t[CLK_OSC32K] = {\n\t\t.get_parent = ccu_get_null_parent,\n\t\t.get_rate   = r_ccu_get_osc32k_rate,\n\t},\n\t[CLK_AR100] = {\n\t\t.get_parent = r_ccu_get_bus_parent,\n\t\t.get_rate   = r_ccu_get_mp_rate,\n\t\t.reg        = 0x0000,\n\t},\n\t[CLK_R_AHB] = {\n\t\t.get_parent = r_ccu_get_ar100,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t},\n\t[CLK_R_APB1] = {\n\t\t.get_parent = r_ccu_get_r_ahb,\n\t\t.get_rate   = r_ccu_get_r_apb1_rate,\n\t\t.reg        = 0x000c,\n\t},\n\t[CLK_R_APB2] = {\n\t\t.get_parent = r_ccu_get_bus_parent,\n\t\t.get_rate   = r_ccu_get_mp_rate,\n\t\t.reg        = 0x0010,\n\t},\n\t[CLK_BUS_R_PIO] = {\n\t\t.get_parent = r_ccu_get_r_apb1,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t},\n\t[CLK_BUS_R_TIMER] = {\n\t\t.get_parent = r_ccu_get_r_apb1,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t\t.gate       = BITMAP_INDEX(0x011c, 0),\n\t\t.reset      = BITMAP_INDEX(0x011c, 16),\n\t},\n\t[CLK_BUS_R_TWD] = {\n\t\t/* Parent omitted to allow enabling before CCU init. */\n\t\t.get_parent = ccu_get_null_parent,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t\t.gate       = BITMAP_INDEX(0x012c, 0),\n\t\t.reset      = BITMAP_INDEX(0x012c, 16),\n\t},\n\t[CLK_BUS_R_PWM] = {\n\t\t.get_parent = r_ccu_get_r_apb1,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t\t.gate       = BITMAP_INDEX(0x013c, 0),\n\t\t.reset      = BITMAP_INDEX(0x013c, 16),\n\t},\n\t[CLK_BUS_R_UART] = {\n\t\t.get_parent = r_ccu_get_r_apb2,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t\t.gate       = BITMAP_INDEX(0x018c, 0),\n\t\t.reset      = BITMAP_INDEX(0x018c, 16),\n\t},\n\t[CLK_BUS_R_I2C] = {\n\t\t.get_parent = r_ccu_get_r_apb2,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t\t.gate       = BITMAP_INDEX(0x019c, 0),\n\t\t.reset      = BITMAP_INDEX(0x019c, 16),\n\t},\n\t[CLK_BUS_R_RSB] = {\n\t\t.get_parent = r_ccu_get_r_apb2,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t\t.gate       = BITMAP_INDEX(0x01bc, 0),\n\t\t.reset      = BITMAP_INDEX(0x01bc, 16),\n\t},\n\t[CLK_BUS_R_CIR] = {\n\t\t.get_parent = r_ccu_get_r_apb1,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t\t.gate       = BITMAP_INDEX(0x01cc, 0),\n\t\t.reset      = BITMAP_INDEX(0x01cc, 16),\n\t},\n\t[CLK_BUS_R_W1] = {\n\t\t.get_parent = r_ccu_get_r_apb1,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t\t.gate       = BITMAP_INDEX(0x01ec, 0),\n\t\t.reset      = BITMAP_INDEX(0x01ec, 16),\n\t},\n\t[CLK_R_CIR] = {\n\t\t.get_parent = r_ccu_get_module_parent,\n\t\t.get_rate   = r_ccu_get_mp_rate,\n\t\t.reg        = 0x01c0,\n\t\t.gate       = BITMAP_INDEX(0x01c0, 31),\n\t},\n\t[CLK_R_W1] = {\n\t\t.get_parent = r_ccu_get_module_parent,\n\t\t.get_rate   = r_ccu_get_mp_rate,\n\t\t.reg        = 0x01e0,\n\t\t.gate       = BITMAP_INDEX(0x01e0, 31),\n\t},\n};\n\nconst struct ccu r_ccu = {\n\t.dev = {\n\t\t.name  = \"r_ccu\",\n\t\t.drv   = &ccu_driver.drv,\n\t\t.state = CLOCK_DEVICE_STATE_INIT(SUN50I_H6_R_CCU_CLOCKS),\n\t},\n\t.clocks = r_ccu_clocks,\n\t.regs   = DEV_R_PRCM,\n};\n\nvoid\nr_ccu_init(void)\n{\n\t/* Set CPUS to IOSC/1 (16MHz). */\n\tmmio_write_32(CPUS_CLK_REG,\n\t              CPUS_CLK_REG_CLK_SRC(2) |\n\t              CPUS_CLK_REG_PRE_DIV(0) |\n\t              CPUS_CLK_REG_DIV_P(0));\n\n\t/* Set R_APB2 to IOSC/1 (16MHz). */\n\tmmio_write_32(R_APB2_CLK_REG,\n\t              R_APB2_CLK_REG_CLK_SRC(2) |\n\t              R_APB2_CLK_REG_PRE_DIV(0) |\n\t              R_APB2_CLK_REG_DIV_P(0));\n\n\tr_ccu_common_init();\n}\n"
  },
  {
    "path": "drivers/clock/sun8i-a23-ccu.c",
    "content": "/*\n * Copyright © 2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <bitfield.h>\n#include <bitmap.h>\n#include <clock.h>\n#include <device.h>\n#include <stdint.h>\n#include <clock/ccu.h>\n#include <platform/devices.h>\n\n#include \"ccu.h\"\n\n#define CPUX_AXI_CFG_REG  0x0050\n#define AHB1_APB1_CFG_REG 0x0054\n#define APB2_CFG_REG      0x0058\n\n#define CPUX_CLK_SRC(x)   ((x) << 16)\n#define CPUX_APB_CLK_M(x) ((x) << 8)\n#define CPUX_AXI_CLK_M(x) ((x) << 0)\n\n#define AHB1_CLK_SRC(x)   ((x) << 12)\n#define APB1_CLK_DIV(x)   ((x) << 8)\n#define AHB1_PRE_DIV(x)   ((x) << 6)\n#define AHB1_CLK_P(x)     ((x) << 4)\n\n#define APB2_CLK_SRC(x)   ((x) << 24)\n#define APB2_CLK_P(x)     ((x) << 16)\n#define APB2_CLK_M(x)     ((x) << 0)\n\nstatic DEFINE_FIXED_RATE(ccu_get_pll_periph0_rate, 600000000U)\n\n/*\n * While APB2 has a mux, assume its parent is OSC24M. Reparenting APB2\n * to PLL_PERIPH0 in Linux for faster UART clocks is unsupported.\n */\nstatic DEFINE_FIXED_PARENT(ccu_get_apb2_parent, r_ccu, CLK_OSC24M)\nstatic DEFINE_FIXED_PARENT(ccu_get_apb2, ccu, CLK_APB2)\n\nstatic const struct clock_handle ccu_dram_parents[] = {\n\t{\n\t\t.dev = &ccu.dev,\n\t\t.id  = CLK_PLL_DDR0,\n\t},\n\t{\n\t\t.dev = &ccu.dev,\n\t\t.id  = CLK_PLL_DDR1,\n\t},\n};\n\nstatic const struct clock_handle *\nccu_get_dram_parent(const struct ccu *self, const struct ccu_clock *clk UNUSED)\n{\n\tuint32_t val = mmio_read_32(self->regs + 0x00f8);\n\n\treturn &ccu_dram_parents[bitfield_get(val, 20, 1)];\n}\n\nstatic const struct ccu_clock ccu_clocks[SUN8I_A23_CCU_CLOCKS] = {\n\t[CLK_PLL_CPUX] = {\n\t\t.get_parent = ccu_get_null_parent,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t\t.reg        = 0x0000,\n\t\t.lock       = 28,\n\t\t.gate       = BITMAP_INDEX(0x0000, 31),\n\t},\n\t[CLK_PLL_DDR0] = {\n\t\t.get_parent = ccu_get_null_parent,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t\t.reg        = 0x0020,\n\t\t.lock       = 28,\n\t\t.update     = 20,\n\t\t.gate       = BITMAP_INDEX(0x0020, 31),\n\t},\n\t[CLK_PLL_PERIPH0] = {\n\t\t.get_parent = ccu_get_null_parent,\n\t\t.get_rate   = ccu_get_pll_periph0_rate,\n\t},\n\t[CLK_PLL_DDR1] = {\n\t\t.get_parent = ccu_get_null_parent,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t\t.reg        = 0x004c,\n\t\t.lock       = 28,\n\t\t.update     = 30,\n\t\t.gate       = BITMAP_INDEX(0x004c, 31),\n\t},\n\t[CLK_APB2] = {\n\t\t.get_parent = ccu_get_apb2_parent,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t},\n\t/* Reset requires re-training DRAM, so ignore it. */\n\t[CLK_BUS_DRAM] = {\n\t\t.get_parent = ccu_get_null_parent,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t\t.gate       = BITMAP_INDEX(0x0060, 14),\n\t},\n\t[CLK_BUS_MSGBOX] = {\n\t\t.get_parent = ccu_get_null_parent,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t\t.gate       = BITMAP_INDEX(0x0064, 21),\n\t\t.reset      = BITMAP_INDEX(0x02c4, 21),\n\t},\n\t[CLK_BUS_PIO] = {\n\t\t.get_parent = ccu_get_null_parent,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t\t.gate       = BITMAP_INDEX(0x0068, 5),\n\t},\n#if CONFIG(SERIAL_DEV_UART0)\n\t[CLK_BUS_UART0] = {\n\t\t.get_parent = ccu_get_apb2,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t\t.gate       = BITMAP_INDEX(0x006c, 16),\n\t\t.reset      = BITMAP_INDEX(0x02d8, 16),\n\t},\n#elif CONFIG(SERIAL_DEV_UART1)\n\t[CLK_BUS_UART1] = {\n\t\t.get_parent = ccu_get_apb2,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t\t.gate       = BITMAP_INDEX(0x006c, 17),\n\t\t.reset      = BITMAP_INDEX(0x02d8, 17),\n\t},\n#elif CONFIG(SERIAL_DEV_UART2)\n\t[CLK_BUS_UART2] = {\n\t\t.get_parent = ccu_get_apb2,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t\t.gate       = BITMAP_INDEX(0x006c, 18),\n\t\t.reset      = BITMAP_INDEX(0x02d8, 18),\n\t},\n#elif CONFIG(SERIAL_DEV_UART3)\n\t[CLK_BUS_UART3] = {\n\t\t.get_parent = ccu_get_apb2,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t\t.gate       = BITMAP_INDEX(0x006c, 19),\n\t\t.reset      = BITMAP_INDEX(0x02d8, 19),\n\t},\n#elif CONFIG(SERIAL_DEV_UART4) /* depends on SOC_A23 */\n\t[CLK_BUS_UART4] = {\n\t\t.get_parent = ccu_get_apb2,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t\t.gate       = BITMAP_INDEX(0x006c, 20),\n\t\t.reset      = BITMAP_INDEX(0x02d8, 20),\n\t},\n#endif\n\t[CLK_DRAM] = {\n\t\t.get_parent = ccu_get_dram_parent,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t\t.reg        = 0x00f4,\n\t\t.update     = 16,\n\t\t.reset      = BITMAP_INDEX(0x00f4, 31),\n\t},\n\t[CLK_MBUS] = {\n\t\t.get_parent = ccu_get_null_parent,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t\t.gate       = BITMAP_INDEX(0x015c, 31),\n\t\t.reset      = BITMAP_INDEX(0x00fc, 31),\n\t},\n};\n\nconst struct ccu ccu = {\n\t.dev = {\n\t\t.name  = \"ccu\",\n\t\t.drv   = &ccu_driver.drv,\n\t\t.state = CLOCK_DEVICE_STATE_INIT(SUN8I_A23_CCU_CLOCKS),\n\t},\n\t.clocks = ccu_clocks,\n\t.regs   = DEV_CCU,\n};\n\nstatic const struct clock_handle pll_cpux = {\n\t.dev = &ccu.dev,\n\t.id  = CLK_PLL_CPUX,\n};\n\nvoid\nccu_suspend(void)\n{\n\t/* Set AHB1 to LOSC/1 (32kHz), APB1 to AHB1/2 (16kHz). */\n\tmmio_write_32(DEV_CCU + AHB1_APB1_CFG_REG,\n\t              AHB1_CLK_SRC(0) |\n\t              APB1_CLK_DIV(1) |\n\t              AHB1_PRE_DIV(2) |\n\t              AHB1_CLK_P(0));\n\n\tclock_put(&pll_cpux);\n}\n\nvoid\nccu_suspend_cluster(uint32_t cluster UNUSED)\n{\n\t/* Set CPUX to LOSC (32kHz), APB to CPUX/4, AXI to CPUX/3. */\n\tmmio_write_32(DEV_CCU + CPUX_AXI_CFG_REG,\n\t              CPUX_CLK_SRC(0) |\n\t              CPUX_APB_CLK_M(3) |\n\t              CPUX_AXI_CLK_M(2));\n}\n\nvoid\nccu_resume(void)\n{\n\tclock_get(&pll_cpux);\n\n\t/* Set AHB1 to PLL_PERIPH0/3 (200MHz), APB1 to AHB1/2 (100MHz). */\n\tmmio_write_32(DEV_CCU + AHB1_APB1_CFG_REG,\n\t              AHB1_CLK_SRC(3) |\n\t              APB1_CLK_DIV(1) |\n\t              AHB1_PRE_DIV(2) |\n\t              AHB1_CLK_P(0));\n}\n\nvoid\nccu_resume_cluster(uint32_t cluster UNUSED)\n{\n\t/* Set CPUX to PLL_CPUX, APB to CPUX/4, AXI to CPUX/3. */\n\tmmio_write_32(DEV_CCU + CPUX_AXI_CFG_REG,\n\t              CPUX_CLK_SRC(2) |\n\t              CPUX_APB_CLK_M(3) |\n\t              CPUX_AXI_CLK_M(2));\n}\n\nvoid\nccu_init(void)\n{\n\t/* Set APB2 to OSC24M/1 (24MHz). */\n\tmmio_write_32(DEV_CCU + APB2_CFG_REG,\n\t              APB2_CLK_SRC(1) |\n\t              APB2_CLK_P(0) |\n\t              APB2_CLK_M(0));\n\n\tccu_resume();\n\tccu_resume_cluster(0);\n}\n"
  },
  {
    "path": "drivers/clock/sun8i-a83t-ccu.c",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <bitmap.h>\n#include <clock.h>\n#include <device.h>\n#include <stdint.h>\n#include <clock/ccu.h>\n#include <platform/devices.h>\n\n#include \"ccu.h\"\n\n#define APB2_CFG_REG    0x0058\n\n#define APB2_CLK_SRC(x) ((x) << 24)\n#define APB2_CLK_P(x)   ((x) << 16)\n#define APB2_CLK_M(x)   ((x) << 0)\n\nstatic DEFINE_FIXED_RATE(ccu_get_pll_periph0_rate, 600000000U)\n\n/*\n * While APB2 has a mux, assume its parent is OSC24M. Reparenting APB2\n * to PLL_PERIPH0 in Linux for faster UART clocks is unsupported.\n */\nstatic DEFINE_FIXED_PARENT(ccu_get_apb2_parent, r_ccu, CLK_OSC24M)\nstatic DEFINE_FIXED_PARENT(ccu_get_apb2, ccu, CLK_APB2)\n\nstatic const struct ccu_clock ccu_clocks[SUN8I_A83T_CCU_CLOCKS] = {\n\t[CLK_PLL_PERIPH0] = {\n\t\t.get_parent = ccu_get_null_parent,\n\t\t.get_rate   = ccu_get_pll_periph0_rate,\n\t},\n\t[CLK_APB2] = {\n\t\t.get_parent = ccu_get_apb2_parent,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t},\n\t[CLK_BUS_MSGBOX] = {\n\t\t.get_parent = ccu_get_null_parent,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t\t.gate       = BITMAP_INDEX(0x0064, 21),\n\t\t.reset      = BITMAP_INDEX(0x02c4, 21),\n\t},\n\t[CLK_BUS_PIO] = {\n\t\t.get_parent = ccu_get_null_parent,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t\t.gate       = BITMAP_INDEX(0x0068, 5),\n\t},\n#if CONFIG(SERIAL_DEV_UART0)\n\t[CLK_BUS_UART0] = {\n\t\t.get_parent = ccu_get_apb2,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t\t.gate       = BITMAP_INDEX(0x006c, 16),\n\t\t.reset      = BITMAP_INDEX(0x02d8, 16),\n\t},\n#elif CONFIG(SERIAL_DEV_UART1)\n\t[CLK_BUS_UART1] = {\n\t\t.get_parent = ccu_get_apb2,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t\t.gate       = BITMAP_INDEX(0x006c, 17),\n\t\t.reset      = BITMAP_INDEX(0x02d8, 17),\n\t},\n#elif CONFIG(SERIAL_DEV_UART2)\n\t[CLK_BUS_UART2] = {\n\t\t.get_parent = ccu_get_apb2,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t\t.gate       = BITMAP_INDEX(0x006c, 18),\n\t\t.reset      = BITMAP_INDEX(0x02d8, 18),\n\t},\n#elif CONFIG(SERIAL_DEV_UART3)\n\t[CLK_BUS_UART3] = {\n\t\t.get_parent = ccu_get_apb2,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t\t.gate       = BITMAP_INDEX(0x006c, 19),\n\t\t.reset      = BITMAP_INDEX(0x02d8, 19),\n\t},\n#elif CONFIG(SERIAL_DEV_UART4)\n\t[CLK_BUS_UART4] = {\n\t\t.get_parent = ccu_get_apb2,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t\t.gate       = BITMAP_INDEX(0x006c, 20),\n\t\t.reset      = BITMAP_INDEX(0x02d8, 20),\n\t},\n#endif\n};\n\nconst struct ccu ccu = {\n\t.dev = {\n\t\t.name  = \"ccu\",\n\t\t.drv   = &ccu_driver.drv,\n\t\t.state = CLOCK_DEVICE_STATE_INIT(SUN8I_A83T_CCU_CLOCKS),\n\t},\n\t.clocks = ccu_clocks,\n\t.regs   = DEV_CCU,\n};\n\nvoid\nccu_suspend(void)\n{\n}\n\nvoid\nccu_suspend_cluster(uint32_t cluster UNUSED)\n{\n}\n\nvoid\nccu_resume(void)\n{\n}\n\nvoid\nccu_resume_cluster(uint32_t cluster UNUSED)\n{\n}\n\nvoid\nccu_init(void)\n{\n\t/* Set APB2 to OSC24M/1 (24MHz). */\n\tmmio_write_32(DEV_CCU + APB2_CFG_REG,\n\t              APB2_CLK_SRC(1) |\n\t              APB2_CLK_P(0) |\n\t              APB2_CLK_M(0));\n\n\tccu_resume();\n\tccu_resume_cluster(0);\n}\n"
  },
  {
    "path": "drivers/clock/sun8i-h3-ccu.c",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <bitfield.h>\n#include <bitmap.h>\n#include <clock.h>\n#include <device.h>\n#include <error.h>\n#include <stdint.h>\n#include <clock/ccu.h>\n#include <platform/devices.h>\n\n#include \"ccu.h\"\n\n#define CPUX_AXI_CFG_REG  0x0050\n#define AHB1_APB1_CFG_REG 0x0054\n#define APB2_CFG_REG      0x0058\n#define AHB2_CFG_REG      0x005c\n\n#define CPUX_CLK_SRC(x)   ((x) << 16)\n#define CPUX_APB_CLK_M(x) ((x) << 8)\n#define CPUX_AXI_CLK_M(x) ((x) << 0)\n\n#define AHB1_CLK_SRC(x)   ((x) << 12)\n#define APB1_CLK_DIV(x)   ((x) << 8)\n#define AHB1_PRE_DIV(x)   ((x) << 6)\n#define AHB1_CLK_P(x)     ((x) << 4)\n\n#define APB2_CLK_SRC(x)   ((x) << 24)\n#define APB2_CLK_P(x)     ((x) << 16)\n#define APB2_CLK_M(x)     ((x) << 0)\n\n#define AHB2_CLK_SRC(n)   ((n) << 0)\n\nstatic DEFINE_FIXED_RATE(ccu_get_pll_periph0_rate, 600000000U)\n\n/*\n * While APB2 has a mux, assume its parent is OSC24M. Reparenting APB2\n * to PLL_PERIPH0 in Linux for faster UART clocks is unsupported.\n */\nstatic DEFINE_FIXED_PARENT(ccu_get_apb2_parent, r_ccu, CLK_OSC24M)\nstatic DEFINE_FIXED_PARENT(ccu_get_apb2, ccu, CLK_APB2)\n\nstatic const struct clock_handle ccu_dram_parents[] = {\n\t{\n\t\t.dev = &ccu.dev,\n\t\t.id  = CLK_PLL_DDR0,\n\t},\n\t{\n\t\t.dev = &ccu.dev,\n\t\t.id  = CLK_PLL_PERIPH0, /* 2x */\n\t},\n};\n\nstatic const struct clock_handle *\nccu_get_dram_parent(const struct ccu *self,\n                    const struct ccu_clock *clk)\n{\n\tuint32_t val = mmio_read_32(self->regs + clk->reg);\n\n\treturn &ccu_dram_parents[bitfield_get(val, 20, 1)];\n}\n\nstatic const struct ccu_clock ccu_clocks[SUN8I_H3_CCU_CLOCKS] = {\n\t[CLK_PLL_CPUX] = {\n\t\t.get_parent = ccu_get_null_parent,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t\t.reg        = 0x0000,\n\t\t.lock       = 28,\n\t\t.gate       = BITMAP_INDEX(0x0000, 31),\n\t},\n\t[CLK_PLL_DDR0] = {\n\t\t.get_parent = ccu_get_null_parent,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t\t.reg        = 0x0020,\n\t\t.lock       = 28,\n\t\t.update     = 20,\n\t\t.gate       = BITMAP_INDEX(0x0020, 31),\n\t},\n\t[CLK_PLL_PERIPH0] = {\n\t\t.get_parent = ccu_get_null_parent,\n\t\t.get_rate   = ccu_get_pll_periph0_rate,\n\t},\n\t[CLK_APB2] = {\n\t\t.get_parent = ccu_get_apb2_parent,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t},\n\t/* Reset requires re-training DRAM, so ignore it. */\n\t[CLK_BUS_DRAM] = {\n\t\t.get_parent = ccu_get_null_parent,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t\t.gate       = BITMAP_INDEX(0x0060, 14),\n\t},\n\t[CLK_BUS_MSGBOX] = {\n\t\t.get_parent = ccu_get_null_parent,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t\t.gate       = BITMAP_INDEX(0x0064, 21),\n\t\t.reset      = BITMAP_INDEX(0x02c4, 21),\n\t},\n\t[CLK_BUS_PIO] = {\n\t\t.get_parent = ccu_get_null_parent,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t\t.gate       = BITMAP_INDEX(0x0068, 5),\n\t},\n#if CONFIG(SERIAL_DEV_UART0)\n\t[CLK_BUS_UART0] = {\n\t\t.get_parent = ccu_get_apb2,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t\t.gate       = BITMAP_INDEX(0x006c, 16),\n\t\t.reset      = BITMAP_INDEX(0x02d8, 16),\n\t},\n#elif CONFIG(SERIAL_DEV_UART1)\n\t[CLK_BUS_UART1] = {\n\t\t.get_parent = ccu_get_apb2,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t\t.gate       = BITMAP_INDEX(0x006c, 17),\n\t\t.reset      = BITMAP_INDEX(0x02d8, 17),\n\t},\n#elif CONFIG(SERIAL_DEV_UART2)\n\t[CLK_BUS_UART2] = {\n\t\t.get_parent = ccu_get_apb2,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t\t.gate       = BITMAP_INDEX(0x006c, 18),\n\t\t.reset      = BITMAP_INDEX(0x02d8, 18),\n\t},\n#elif CONFIG(SERIAL_DEV_UART3)\n\t[CLK_BUS_UART3] = {\n\t\t.get_parent = ccu_get_apb2,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t\t.gate       = BITMAP_INDEX(0x006c, 19),\n\t\t.reset      = BITMAP_INDEX(0x02d8, 19),\n\t},\n#endif\n\t[CLK_DRAM] = {\n\t\t.get_parent = ccu_get_dram_parent,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t\t.reg        = 0x00f4,\n\t\t.update     = 16,\n\t\t.reset      = BITMAP_INDEX(0x00f4, 31),\n\t},\n\t/* MBUS reset breaks DRAM resume on H3. */\n\t[CLK_MBUS] = {\n\t\t.get_parent = ccu_get_null_parent,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t\t.gate       = BITMAP_INDEX(0x015c, 31),\n\t},\n};\n\nconst struct ccu ccu = {\n\t.dev = {\n\t\t.name  = \"ccu\",\n\t\t.drv   = &ccu_driver.drv,\n\t\t.state = CLOCK_DEVICE_STATE_INIT(SUN8I_H3_CCU_CLOCKS),\n\t},\n\t.clocks = ccu_clocks,\n\t.regs   = DEV_CCU,\n};\n\nstatic const struct clock_handle pll_cpux = {\n\t.dev = &ccu.dev,\n\t.id  = CLK_PLL_CPUX,\n};\n\nvoid\nccu_suspend(void)\n{\n\t/* Set AHB1 to LOSC/1 (32kHz), APB1 to AHB1/2 (16kHz). */\n\tmmio_write_32(DEV_CCU + AHB1_APB1_CFG_REG,\n\t              AHB1_CLK_SRC(0) |\n\t              APB1_CLK_DIV(1) |\n\t              AHB1_PRE_DIV(2) |\n\t              AHB1_CLK_P(0));\n\n\t/* Set AHB2 to AHB1/1 (32kHz). */\n\tmmio_write_32(DEV_CCU + AHB2_CFG_REG,\n\t              AHB2_CLK_SRC(0));\n\n\tclock_put(&pll_cpux);\n}\n\nvoid\nccu_suspend_cluster(uint32_t cluster UNUSED)\n{\n\t/* Set CPUX to LOSC (32kHz), APB to CPUX/4, AXI to CPUX/3. */\n\tmmio_write_32(DEV_CCU + CPUX_AXI_CFG_REG,\n\t              CPUX_CLK_SRC(0) |\n\t              CPUX_APB_CLK_M(3) |\n\t              CPUX_AXI_CLK_M(2));\n}\n\nvoid\nccu_resume(void)\n{\n\tclock_get(&pll_cpux);\n\n\t/* Set AHB1 to PLL_PERIPH0/3 (200MHz), APB1 to AHB1/2 (100MHz). */\n\tmmio_write_32(DEV_CCU + AHB1_APB1_CFG_REG,\n\t              AHB1_CLK_SRC(3) |\n\t              APB1_CLK_DIV(1) |\n\t              AHB1_PRE_DIV(2) |\n\t              AHB1_CLK_P(0));\n\n\t/* Set AHB2 to PLL_PERIPH0/2 (300MHz). */\n\tmmio_write_32(DEV_CCU + AHB2_CFG_REG,\n\t              AHB2_CLK_SRC(1));\n}\n\nvoid\nccu_resume_cluster(uint32_t cluster UNUSED)\n{\n\t/* Set CPUX to PLL_CPUX, APB to CPUX/4, AXI to CPUX/3. */\n\tmmio_write_32(DEV_CCU + CPUX_AXI_CFG_REG,\n\t              CPUX_CLK_SRC(2) |\n\t              CPUX_APB_CLK_M(3) |\n\t              CPUX_AXI_CLK_M(2));\n}\n\nvoid\nccu_init(void)\n{\n\t/* Set APB2 to OSC24M/1 (24MHz). */\n\tmmio_write_32(DEV_CCU + APB2_CFG_REG,\n\t              APB2_CLK_SRC(1) |\n\t              APB2_CLK_P(0) |\n\t              APB2_CLK_M(0));\n\n\tccu_resume();\n\tccu_resume_cluster(0);\n}\n"
  },
  {
    "path": "drivers/clock/sun8i-r-ccu.c",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <bitfield.h>\n#include <bitmap.h>\n#include <clock.h>\n#include <debug.h>\n#include <device.h>\n#include <mmio.h>\n#include <stddef.h>\n#include <stdint.h>\n#include <clock/ccu.h>\n#include <platform/devices.h>\n#include <platform/prcm.h>\n\n#include \"ccu.h\"\n\nstatic DEFINE_FIXED_RATE(r_ccu_get_osc24m_rate, 24000000U)\nstatic DEFINE_FIXED_RATE(r_ccu_get_osc32k_rate, 32768U)\n\nstatic const struct clock_handle r_ccu_ar100_parents[] = {\n\t{\n\t\t.dev = &r_ccu.dev,\n\t\t.id  = CLK_OSC32K,\n\t},\n\t{\n\t\t.dev = &r_ccu.dev,\n\t\t.id  = CLK_OSC24M,\n\t},\n\t{\n\t\t.dev = &ccu.dev,\n\t\t.id  = CLK_PLL_PERIPH0,\n\t},\n\t{\n\t\t.dev = &r_ccu.dev,\n\t\t.id  = CLK_IOSC,\n\t},\n};\n\nstatic const struct clock_handle *\nr_ccu_get_ar100_parent(const struct ccu *self,\n                       const struct ccu_clock *clk)\n{\n\tuint32_t val = mmio_read_32(self->regs + clk->reg);\n\n\treturn &r_ccu_ar100_parents[bitfield_get(val, 16, 2)];\n}\n\nstatic uint32_t\nr_ccu_get_ar100_rate(const struct ccu *self,\n                     const struct ccu_clock *clk, uint32_t rate)\n{\n\t/* This assumes the pre-divider for PLL_PERIPH0 (parent 2)\n\t * will only be set if parent 2 is selected in the mux. */\n\treturn ccu_helper_get_rate_mp(self, clk, rate, 8, 5, 4, 2);\n}\n\nstatic DEFINE_FIXED_PARENT(r_ccu_get_ar100, r_ccu, CLK_AR100)\nstatic DEFINE_FIXED_PARENT(r_ccu_get_ahb0, r_ccu, CLK_AHB0)\n\nstatic uint32_t\nr_ccu_get_apb0_rate(const struct ccu *self,\n                    const struct ccu_clock *clk, uint32_t rate)\n{\n\treturn ccu_helper_get_rate_m(self, clk, rate, 0, 2);\n}\n\nstatic DEFINE_FIXED_PARENT(r_ccu_get_apb0, r_ccu, CLK_APB0)\n\nstatic const struct clock_handle r_ccu_r_cir_parents[] = {\n\t{\n\t\t.dev = &r_ccu.dev,\n\t\t.id  = CLK_OSC32K,\n\t},\n\t{\n\t\t.dev = &r_ccu.dev,\n\t\t.id  = CLK_OSC24M,\n\t},\n};\n\nstatic const struct clock_handle *\nccu_get_r_cir_parent(const struct ccu *self,\n                     const struct ccu_clock *clk)\n{\n\tuint32_t val = mmio_read_32(self->regs + clk->reg);\n\n\treturn &r_ccu_r_cir_parents[bitfield_get(val, 24, 1)];\n}\n\nstatic uint32_t\nccu_get_r_cir_rate(const struct ccu *self,\n                   const struct ccu_clock *clk, uint32_t rate)\n{\n\treturn ccu_helper_get_rate_mp(self, clk, rate, 0, 4, 16, 2);\n}\n\nstatic const struct ccu_clock r_ccu_clocks[SUN8I_R_CCU_CLOCKS] = {\n\t[CLK_IOSC] = {\n\t\t.get_parent = ccu_get_null_parent,\n\t\t.get_rate   = r_ccu_common_get_iosc_rate,\n\t},\n\t[CLK_OSC24M] = {\n\t\t.get_parent = ccu_get_null_parent,\n\t\t.get_rate   = r_ccu_get_osc24m_rate,\n\t},\n\t[CLK_OSC32K] = {\n\t\t.get_parent = ccu_get_null_parent,\n\t\t.get_rate   = r_ccu_get_osc32k_rate,\n\t},\n\t[CLK_AR100] = {\n\t\t.get_parent = r_ccu_get_ar100_parent,\n\t\t.get_rate   = r_ccu_get_ar100_rate,\n\t\t.reg        = 0x0000,\n\t},\n\t[CLK_AHB0] = {\n\t\t.get_parent = r_ccu_get_ar100,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t},\n\t[CLK_APB0] = {\n\t\t.get_parent = r_ccu_get_ahb0,\n\t\t.get_rate   = r_ccu_get_apb0_rate,\n\t\t.reg        = 0x000c,\n\t},\n\t[CLK_BUS_R_PIO] = {\n\t\t.get_parent = r_ccu_get_apb0,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t\t.gate       = BITMAP_INDEX(0x0028, 0),\n\t},\n#if CONFIG(HAVE_R_CIR)\n\t[CLK_BUS_R_CIR] = {\n\t\t.get_parent = r_ccu_get_apb0,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t\t.gate       = BITMAP_INDEX(0x0028, 1),\n\t\t.reset      = BITMAP_INDEX(0x00b0, 1),\n\t},\n#endif\n\t[CLK_BUS_R_TIMER] = {\n\t\t.get_parent = r_ccu_get_apb0,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t\t.gate       = BITMAP_INDEX(0x0028, 2),\n\t\t.reset      = BITMAP_INDEX(0x00b0, 2),\n\t},\n#if CONFIG(HAVE_R_RSB)\n\t[CLK_BUS_R_RSB] = {\n\t\t.get_parent = r_ccu_get_apb0,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t\t.gate       = BITMAP_INDEX(0x0028, 3),\n\t\t.reset      = BITMAP_INDEX(0x00b0, 3),\n\t},\n#endif\n\t[CLK_BUS_R_UART] = {\n\t\t.get_parent = r_ccu_get_apb0,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t\t.gate       = BITMAP_INDEX(0x0028, 4),\n\t\t.reset      = BITMAP_INDEX(0x00b0, 4),\n\t},\n\t[CLK_BUS_R_I2C] = {\n\t\t.get_parent = r_ccu_get_apb0,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t\t.gate       = BITMAP_INDEX(0x0028, 6),\n\t\t.reset      = BITMAP_INDEX(0x00b0, 6),\n\t},\n#if CONFIG(HAVE_R_TWD)\n\t[CLK_BUS_R_TWD] = {\n\t\t/* Parent omitted to allow enabling before CCU init. */\n\t\t.get_parent = ccu_get_null_parent,\n\t\t.get_rate   = ccu_get_parent_rate,\n\t\t.gate       = BITMAP_INDEX(0x0028, 7),\n\t},\n#endif\n\t[CLK_R_CIR] = {\n\t\t.get_parent = ccu_get_r_cir_parent,\n\t\t.get_rate   = ccu_get_r_cir_rate,\n\t\t.reg        = 0x0054,\n\t\t.gate       = BITMAP_INDEX(0x0054, 31),\n\t},\n};\n\nconst struct ccu r_ccu = {\n\t.dev = {\n\t\t.name  = \"r_ccu\",\n\t\t.drv   = &ccu_driver.drv,\n\t\t.state = CLOCK_DEVICE_STATE_INIT(SUN8I_R_CCU_CLOCKS),\n\t},\n\t.clocks = r_ccu_clocks,\n\t.regs   = DEV_R_PRCM,\n};\n\nvoid\nr_ccu_init(void)\n{\n\t/* Set CPUS to IOSC/1 (600 kHz or 16MHz). */\n\tmmio_write_32(CPUS_CLK_REG,\n\t              CPUS_CLK_REG_CLK_SRC(3) |\n\t              CPUS_CLK_REG_PRE_DIV(0) |\n\t              CPUS_CLK_REG_DIV_P(0));\n\n\tr_ccu_common_init();\n}\n"
  },
  {
    "path": "drivers/counter/Makefile",
    "content": "#\n# Copyright © 2022 The Crust Firmware Authors.\n# SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n#\n\nobj-$(CONFIG_PLATFORM_A23)  += sun6i-a31-cnt64.o\nobj-$(CONFIG_PLATFORM_A64)  += sun6i-a31-cnt64.o\nobj-$(CONFIG_PLATFORM_A83T) += sun9i-a80-timestamp.o\nobj-$(CONFIG_PLATFORM_H3)   += sun6i-a31-cnt64.o\nobj-$(CONFIG_PLATFORM_H6)   += sun9i-a80-timestamp.o\n"
  },
  {
    "path": "drivers/counter/sun6i-a31-cnt64.c",
    "content": "/*\n * Copyright © 2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <counter.h>\n#include <mmio.h>\n#include <platform/cpucfg.h>\n\nuint32_t\nsystem_counter_read(void)\n{\n\tmmio_write_32(CNT64_CTRL_REG, CNT64_RL_EN);\n\tmmio_pollz_32(CNT64_CTRL_REG, CNT64_RL_EN);\n\n\treturn mmio_read_32(CNT64_LO_REG);\n}\n"
  },
  {
    "path": "drivers/counter/sun9i-a80-timestamp.c",
    "content": "/*\n * Copyright © 2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <counter.h>\n#include <mmio.h>\n#include <platform/devices.h>\n\n#define CNT_LO_REG (DEV_TIMESTAMP_STATUS + 0x0)\n#define CNT_HI_REG (DEV_TIMESTAMP_STATUS + 0x4)\n\nuint32_t\nsystem_counter_read(void)\n{\n\treturn mmio_read_32(CNT_LO_REG);\n}\n"
  },
  {
    "path": "drivers/css/Makefile",
    "content": "#\n# Copyright © 2017-2022 The Crust Firmware Authors.\n# SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n#\n\nobj-y += css.o\nobj-y += css_default.o\nobj-y += css_helpers.o\nobj-y += css_power_state.o\n\nobj-$(CONFIG_PLATFORM_A23) += sun6i-a31-css.o\nobj-$(CONFIG_PLATFORM_A64) += sun50i-a64-css.o\nobj-$(CONFIG_PLATFORM_H3)  += sun6i-a31-css.o\nobj-$(CONFIG_PLATFORM_H6)  += sun50i-h6-css.o\n"
  },
  {
    "path": "drivers/css/css.c",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <css.h>\n#include <debug.h>\n#include <scpi_protocol.h>\n#include <stdint.h>\n#include <steps.h>\n#include <system.h>\n#include <util.h>\n\n#include \"css.h\"\n\n/* The register layout assumes a maximum of two clusters. */\n#define FIQ_BIT BIT(2 * MAX_CORES_PER_CLUSTER)\n#define IRQ_BIT BIT(0)\n\nstatic uint8_t lead_cluster, lead_core;\n\nint\ncss_get_power_state(uint32_t cluster, uint32_t *cluster_state,\n                    uint32_t *online_cores)\n{\n\tuint32_t mask = 0;\n\n\tif (cluster >= css_get_cluster_count())\n\t\treturn SCPI_E_PARAM;\n\n\t*cluster_state = power_state.cluster[cluster];\n\n\tfor (uint32_t core = 0; core < MAX_CORES_PER_CLUSTER; ++core) {\n\t\tif (power_state.core[cluster][core] != SCPI_CSS_OFF)\n\t\t\tmask |= BIT(core);\n\t}\n\t*online_cores = mask;\n\n\treturn SCPI_OK;\n}\n\nint\ncss_set_power_state(uint32_t cluster, uint32_t core, uint32_t core_state,\n                    uint32_t cluster_state, uint32_t css_state)\n{\n\tuint8_t *core_ps    = &power_state.core[cluster][core];\n\tuint8_t *cluster_ps = &power_state.cluster[cluster];\n\tuint8_t *css_ps     = &power_state.css;\n\n\tif (cluster >= css_get_cluster_count())\n\t\treturn SCPI_E_PARAM;\n\tif (core >= css_get_core_count(cluster))\n\t\treturn SCPI_E_PARAM;\n\n\t/*\n\t * This implementation takes advantage of two restrictions on power\n\t * state requests:\n\t *\n\t *   1. A request to suspend a core may only be sent from that core.\n\t *      Therefore, at the time any such request is received, it is safe\n\t *      to assume that the core and all of its ancestor power domains\n\t *      are in the \"on\" state.\n\t *\n\t *   2. No power domain may be in a deeper power state than any of its\n\t *      children. Therefore, any request to turn on a core must also\n\t *      turn on all of its ancestor power domains, regardless of their\n\t *      previous or requested states.\n\t */\n\tif (core_state != SCPI_CSS_ON) {\n\t\tuint8_t *cluster_cores = power_state.core[cluster];\n\t\tuint8_t *css_clusters  = power_state.cluster;\n\n\t\trecord_step(STEP_SUSPEND_CORE);\n\t\tcss_suspend_core(cluster, core, core_state);\n\t\t*core_ps = core_state;\n\n\t\t/* A cluster must be on if any of its cores is on. */\n\t\tfor (uint32_t i = 0; i < css_get_core_count(cluster); ++i) {\n\t\t\tif (cluster_cores[i] < cluster_state)\n\t\t\t\tcluster_state = cluster_cores[i];\n\t\t}\n\t\trecord_step(STEP_SUSPEND_CLUSTER);\n\t\tcss_suspend_cluster(cluster, cluster_state);\n\t\t*cluster_ps = cluster_state;\n\n\t\t/* The CSS must be on if any of its clusters is on. */\n\t\tfor (uint32_t i = 0; i < css_get_cluster_count(); ++i) {\n\t\t\tif (css_clusters[i] < css_state)\n\t\t\t\tcss_state = css_clusters[i];\n\t\t}\n\t\trecord_step(STEP_SUSPEND_CSS);\n\t\tcss_suspend_css(css_state);\n\t\t*css_ps = css_state;\n\n\t\t/* Suspend the system when powering off the CSS. */\n\t\tif (css_state == SCPI_CSS_OFF) {\n\t\t\tsystem_suspend();\n\n\t\t\t/* Remember the last active core. */\n\t\t\tlead_cluster = cluster;\n\t\t\tlead_core    = core;\n\t\t}\n\t} else {\n\t\tcss_resume_css(*css_ps);\n\t\t*css_ps = SCPI_CSS_ON;\n\n\t\tcss_resume_cluster(cluster, *cluster_ps);\n\t\t*cluster_ps = SCPI_CSS_ON;\n\n\t\tcss_resume_core(cluster, core, *core_ps);\n\t\t*core_ps = SCPI_CSS_ON;\n\t}\n\n\treturn SCPI_OK;\n}\n\nstatic void\ncss_wake_one_cpu(uint32_t cluster, uint32_t core)\n{\n\tcss_set_power_state(cluster, core,\n\t                    SCPI_CSS_ON, SCPI_CSS_ON, SCPI_CSS_ON);\n}\n\nvoid\ncss_resume(void)\n{\n\tcss_wake_one_cpu(lead_cluster, lead_core);\n}\n\nvoid\ncss_poll(void)\n{\n\tuint32_t status = css_get_irq_status();\n\n\tfor (uint32_t i = 0; i < css_get_cluster_count(); ++i) {\n\t\t/* Assume each cluster is allocated the same number of bits. */\n\t\tfor (uint32_t j = 0; j < MAX_CORES_PER_CLUSTER; ++j) {\n\t\t\tif ((status & (FIQ_BIT | IRQ_BIT)) &&\n\t\t\t    (power_state.core[i][j] == SCPI_CSS_OFF))\n\t\t\t\tcss_wake_one_cpu(i, j);\n\t\t\t/* Shift the next core status on top of the mask. */\n\t\t\tstatus >>= 1;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "drivers/css/css.h",
    "content": "/*\n * Copyright © 2019-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef CSS_PRIVATE_H\n#define CSS_PRIVATE_H\n\n#include <stdbool.h>\n#include <stdint.h>\n#include <platform/css.h>\n\nstruct power_state {\n\tuint8_t core[MAX_CLUSTERS][MAX_CORES_PER_CLUSTER];\n\tuint8_t cluster[MAX_CLUSTERS];\n\tuint8_t css;\n};\n\nextern struct power_state power_state;\n\n/**\n * Get the number of cores present in a cluster.\n *\n * The number returned cannot be greater than 8.\n *\n * @param cluster The index of the cluster.\n */\nuint32_t css_get_core_count(uint32_t cluster) ATTRIBUTE(const);\n\n/**\n * Get the pending IRQ status for each core in the CSS.\n *\n * Cores with pending IRQs will be woken up.\n *\n * @return Each set bit means some IRQ is pending for that core.\n */\nuint32_t css_get_irq_status(void);\n\n/**\n * Suspend the compute subsystem (CSS).\n *\n * This function assumes that the previous CSS power state was \"on\".\n *\n * @param new_state The new coordinated power state for the CSS.\n */\nvoid css_suspend_css(uint32_t new_state);\n\n/**\n * Prepare the compute subsystem (CSS) to resume execution.\n *\n * @param old_state The previous coordinated power state for the CSS.\n */\nvoid css_resume_css(uint32_t old_state);\n\n/**\n * Suspend a cluster.\n *\n * This function assumes that the previous cluster power state was \"on\".\n *\n * @param cluster   The index of the cluster.\n * @param new_state The new coordinated power state for this cluster.\n */\nvoid css_suspend_cluster(uint32_t cluster, uint32_t new_state);\n\n/**\n * Prepare a cluster to resume execution.\n *\n * @param cluster   The index of the cluster.\n * @param old_state The previous coordinated power state for this cluster.\n */\nvoid css_resume_cluster(uint32_t cluster, uint32_t old_state);\n\n/**\n * Suspend a core.\n *\n * This function assumes that the previous core power state was \"on\".\n *\n * @param cluster   The index of the cluster.\n * @param core      The index of the core within the cluster.\n * @param new_state The new coordinated power state for this core.\n */\nvoid css_suspend_core(uint32_t cluster, uint32_t core, uint32_t new_state);\n\n/**\n * Begin or resume execution on a core.\n *\n * @param cluster   The index of the cluster.\n * @param core      The index of the core within the cluster.\n * @param old_state The previous coordinated power state for this core.\n */\nvoid css_resume_core(uint32_t cluster, uint32_t core, uint32_t old_state);\n\n/**\n * Enable or disable power to a core or cluster power domain.\n *\n * When enabling a power switch, the power domain will be turned on gradually\n * to minimize inrush current and voltage drops.\n *\n * The mapping of cores/clusters to register addresses is platform-dependent.\n *\n * @param addr    The address of the register controlling the power switch.\n * @param enable  Whether to enable or disable the power switch.\n */\nvoid css_set_power_switch(uintptr_t addr, bool enable);\n\n#endif /* CSS_PRIVATE_H */\n"
  },
  {
    "path": "drivers/css/css_default.c",
    "content": "/*\n * Copyright © 2020-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <stdint.h>\n\n#include \"css.h\"\n\n/*\n * Generic implementation using the platform-provided constants.\n */\nuint32_t WEAK\ncss_get_cluster_count(void)\n{\n\treturn MAX_CLUSTERS;\n}\n\nuint32_t WEAK\ncss_get_core_count(uint32_t cluster UNUSED)\n{\n\t/* Assume each cluster contains the same number of cores. */\n\treturn MAX_CORES_PER_CLUSTER;\n}\n\n/*\n * Generic implementation used when no platform support is available.\n */\nuint32_t WEAK\ncss_get_irq_status(void)\n{\n\treturn 0;\n}\n\n/*\n * Generic implementation used when no platform customization is needed.\n */\nvoid WEAK\ncss_suspend_css(uint32_t new_state UNUSED)\n{\n}\n\nvoid WEAK\ncss_resume_css(uint32_t old_state UNUSED)\n{\n}\n\nvoid WEAK\ncss_suspend_cluster(uint32_t cluster UNUSED, uint32_t new_state UNUSED)\n{\n}\n\nvoid WEAK\ncss_resume_cluster(uint32_t cluster UNUSED, uint32_t old_state UNUSED)\n{\n}\n\nvoid WEAK\ncss_suspend_core(uint32_t cluster UNUSED, uint32_t core UNUSED,\n                 uint32_t new_state UNUSED)\n{\n}\n\nvoid WEAK\ncss_resume_core(uint32_t cluster UNUSED, uint32_t core UNUSED,\n                uint32_t old_state UNUSED)\n{\n}\n\nvoid WEAK\ncss_init(void)\n{\n}\n"
  },
  {
    "path": "drivers/css/css_helpers.c",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <delay.h>\n#include <mmio.h>\n#include <stdbool.h>\n#include <stdint.h>\n#include <util.h>\n\n#include \"css.h\"\n\nstatic const uint8_t power_switch_on_sequence[] = {\n\t0xfe, 0xf8, 0xe0, 0xc0, 0x80, 0x00,\n};\n\nvoid\ncss_set_power_switch(uintptr_t addr, bool enable)\n{\n\tif (enable) {\n\t\t/* Avoid killing the power if the switch is already enabled. */\n\t\tif (mmio_read_32(addr) == 0x00)\n\t\t\treturn;\n\n\t\t/* Allwinner's blob uses 10, 20, and 30μs delays, depending on\n\t\t * the iteration. However, the same code works fine in ATF with\n\t\t * no delays. The 10μs delay is here just to be extra safe. */\n\t\tconst uint8_t *sequence = power_switch_on_sequence;\n\t\tdo {\n\t\t\tmmio_write_32(addr, *sequence);\n\t\t\tudelay(10);\n\t\t} while (*sequence++ != 0x00);\n\t} else {\n\t\tmmio_write_32(addr, 0xff);\n\t}\n}\n"
  },
  {
    "path": "drivers/css/css_power_state.c",
    "content": "/*\n * Copyright © 2020-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <scpi_protocol.h>\n\n#include \"css.h\"\n\n#define CONCAT(a, b) a ## b\n\n#define DEC_1        0\n#define DEC_2        1\n#define DEC_3        2\n#define DEC_4        3\n#define DEC(v)       CONCAT(DEC_, v)\n\n#define REP_0(...)\n#define REP_1(...)   __VA_ARGS__\n#define REP_2(...)   REP_1(__VA_ARGS__), __VA_ARGS__\n#define REP_3(...)   REP_2(__VA_ARGS__), __VA_ARGS__\n#define REP_4(...)   REP_3(__VA_ARGS__), __VA_ARGS__\n#define REP(n, ...)  CONCAT(REP_, n)(__VA_ARGS__)\n\nstruct power_state power_state = {\n\t.core = {\n\t\t{\n\t\t\tSCPI_CSS_ON,\n\t\t\tREP(DEC(MAX_CORES_PER_CLUSTER), SCPI_CSS_OFF)\n\t\t},\n\t\tREP(DEC(MAX_CLUSTERS), {\n\t\t\tREP(MAX_CORES_PER_CLUSTER, SCPI_CSS_OFF)\n\t\t})\n\t},\n\t.cluster = {\n\t\tSCPI_CSS_ON,\n\t\tREP(DEC(MAX_CLUSTERS), SCPI_CSS_OFF)\n\t},\n\t.css = SCPI_CSS_ON,\n};\n"
  },
  {
    "path": "drivers/css/sun50i-a64-css.c",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <mmio.h>\n#include <scpi_protocol.h>\n#include <stdint.h>\n#include <clock/ccu.h>\n#include <platform/cpucfg.h>\n#include <platform/prcm.h>\n\n#include \"css.h\"\n\n/* Reset Vector Base Address. */\nstatic uint32_t rvba;\n\nuint32_t\ncss_get_irq_status(void)\n{\n\treturn mmio_read_32(IRQ_FIQ_STATUS_REG);\n}\n\nvoid\ncss_suspend_css(uint32_t new_state)\n{\n\tif (new_state < SCPI_CSS_OFF)\n\t\treturn;\n\n\t/* Assert the CPU subsystem reset (active-low). */\n\tmmio_write_32(CPU_SYS_RESET_REG, 0);\n}\n\nvoid\ncss_resume_css(uint32_t old_state)\n{\n\tif (old_state < SCPI_CSS_OFF)\n\t\treturn;\n\n\t/* Deassert the CPU subsystem reset (active-low). */\n\tmmio_write_32(CPU_SYS_RESET_REG, CPU_SYS_RESET);\n}\n\nvoid\ncss_suspend_cluster(uint32_t cluster, uint32_t new_state)\n{\n\tif (new_state < SCPI_CSS_RETENTION)\n\t\treturn;\n\n\t/* Assert L2FLUSHREQ to clean the cluster L2 cache. */\n\tmmio_set_32(C0_CTRL_REG2, C0_CTRL_REG2_L2FLUSHREQ);\n\t/* Wait for L2FLUSHDONE to go high. */\n\tmmio_poll_32(L2_STATUS_REG, L2_STATUS_REG_L2FLUSHDONE);\n\t/* Deassert L2FLUSHREQ. */\n\tmmio_clr_32(C0_CTRL_REG2, C0_CTRL_REG2_L2FLUSHREQ);\n\t/* Remove the cluster from coherency (assert ACINACTM). */\n\tmmio_write_32(C0_CTRL_REG1, C0_CTRL_REG1_ACINACTM);\n\t/* Wait for the cluster (L2 cache) to be idle. */\n\tmmio_poll_32(C0_CPU_STATUS_REG, C0_CPU_STATUS_REG_STANDBYWFIL2);\n\t/* Lower the cluster clock frequency. */\n\tccu_suspend_cluster(cluster);\n\tif (new_state < SCPI_CSS_OFF)\n\t\treturn;\n\n\t/* Activate the cluster output clamps. */\n\tmmio_set_32(C0_PWROFF_GATING_REG, C0_PWROFF_GATING);\n}\n\nvoid\ncss_resume_cluster(uint32_t cluster, uint32_t old_state)\n{\n\tif (old_state < SCPI_CSS_RETENTION)\n\t\treturn;\n\n\t/* Raise the cluster clock frequency. */\n\tccu_resume_cluster(cluster);\n\tif (old_state < SCPI_CSS_OFF) {\n\t\t/* Enable coherency (deassert ACINACTM). */\n\t\tmmio_write_32(C0_CTRL_REG1, 0);\n\t\treturn;\n\t}\n\n\t/* Release the cluster output clamps. */\n\tmmio_clr_32(C0_PWROFF_GATING_REG, C0_PWROFF_GATING);\n\t/* Program all cores to start in AArch64 mode. */\n\tmmio_write_32(C0_CTRL_REG0,\n\t              C0_CTRL_REG0_SYSBARDISABLE |\n\t              C0_CTRL_REG0_AA64nAA32_MASK);\n\t/* Deassert DBGPWRDUP for all cores. */\n\tmmio_write_32(DBG_REG0, 0);\n\t/* Restore the reset vector base addresses for all cores. */\n\tfor (uint32_t i = 0; i < css_get_core_count(cluster); ++i)\n\t\tmmio_write_32(RVBA_LO_REG(i), rvba);\n}\n\nvoid\ncss_suspend_core(uint32_t cluster UNUSED, uint32_t core, uint32_t new_state)\n{\n\tif (new_state < SCPI_CSS_OFF)\n\t\treturn;\n\n\t/* Wait for the core to be in WFI and ready to shut down. */\n\tmmio_poll_32(C0_CPU_STATUS_REG, C0_CPU_STATUS_REG_STANDBYWFI(core));\n\t/* Deassert DBGPWRDUP (prevent debug access to the core). */\n\tmmio_clr_32(DBG_REG0, DBG_REG0_DBGPWRDUP(core));\n\t/* Core 0 does not have a separate power domain. */\n\tif (core > 0) {\n\t\t/* Activate the core output clamps. */\n\t\tmmio_set_32(C0_PWROFF_GATING_REG, C0_CPUn_PWROFF_GATING(core));\n\t\t/* Remove power from the core power domain. */\n\t\tcss_set_power_switch(C0_CPUn_PWR_SWITCH_REG(core), false);\n\t} else {\n\t\t/* Assert core reset (active-low). */\n\t\tmmio_clr_32(C0_RST_CTRL_REG, C0_RST_CTRL_REG_nCORERESET(core));\n\t\t/* Assert core power-on reset (active-low). */\n\t\tmmio_clr_32(C0_PWRON_RESET_REG,\n\t\t            C0_PWRON_RESET_REG_nCPUPORESET(core));\n\t}\n}\n\nvoid\ncss_resume_core(uint32_t cluster UNUSED, uint32_t core, uint32_t old_state)\n{\n\tif (old_state < SCPI_CSS_OFF)\n\t\treturn;\n\n\t/* Core 0 does not have a separate power domain. */\n\tif (core > 0) {\n\t\t/* Assert core reset (active-low). */\n\t\tmmio_clr_32(C0_RST_CTRL_REG, C0_RST_CTRL_REG_nCORERESET(core));\n\t\t/* Assert core power-on reset (active-low). */\n\t\tmmio_clr_32(C0_PWRON_RESET_REG,\n\t\t            C0_PWRON_RESET_REG_nCPUPORESET(core));\n\t\t/* Turn on power to the core power domain. */\n\t\tcss_set_power_switch(C0_CPUn_PWR_SWITCH_REG(core), true);\n\t\t/* Release the core output clamps. */\n\t\tmmio_clr_32(C0_PWROFF_GATING_REG, C0_CPUn_PWROFF_GATING(core));\n\t}\n\t/* Deassert core power-on reset (active-low). */\n\tmmio_set_32(C0_PWRON_RESET_REG, C0_PWRON_RESET_REG_nCPUPORESET(core));\n\t/* Deassert core reset (active-low). */\n\tmmio_set_32(C0_RST_CTRL_REG, C0_RST_CTRL_REG_nCORERESET(core));\n\t/* Assert DBGPWRDUP (allow debug access to the core). */\n\tmmio_set_32(DBG_REG0, DBG_REG0_DBGPWRDUP(core));\n}\n\nvoid\ncss_init(void)\n{\n\t/* Program all cores to start in AArch64 mode. */\n\tmmio_write_32(C0_CTRL_REG0,\n\t              C0_CTRL_REG0_SYSBARDISABLE |\n\t              C0_CTRL_REG0_AA64nAA32_MASK);\n\t/* Save the power-on reset vector base address from core 0. */\n\trvba = mmio_read_32(RVBA_LO_REG(0));\n}\n"
  },
  {
    "path": "drivers/css/sun50i-h6-css.c",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <mmio.h>\n#include <scpi_protocol.h>\n#include <stdint.h>\n#include <clock/ccu.h>\n#include <platform/cpucfg.h>\n\n#include \"css.h\"\n\n/* Reset Vector Base Address. */\nstatic uint32_t rvba;\n\nuint32_t\ncss_get_irq_status(void)\n{\n\treturn mmio_read_32(CPUIDLE_PEND_REG);\n}\n\nvoid\ncss_suspend_css(uint32_t new_state)\n{\n\tif (new_state < SCPI_CSS_OFF)\n\t\treturn;\n\n\t/* Assert the CPU subsystem reset (active-low). */\n\tmmio_write_32(CPU_SYS_RESET_REG, 0);\n}\n\nvoid\ncss_resume_css(uint32_t old_state)\n{\n\tif (old_state < SCPI_CSS_OFF)\n\t\treturn;\n\n\t/* Deassert the CPU subsystem reset (active-low). */\n\tmmio_write_32(CPU_SYS_RESET_REG, CPU_SYS_RESET);\n}\n\nvoid\ncss_suspend_cluster(uint32_t cluster, uint32_t new_state)\n{\n\tif (new_state < SCPI_CSS_RETENTION)\n\t\treturn;\n\n\t/* Assert L2FLUSHREQ to clean the cluster L2 cache. */\n\tmmio_set_32(C0_CTRL_REG2, C0_CTRL_REG2_L2FLUSHREQ);\n\t/* Wait for L2FLUSHDONE to go high. */\n\tmmio_poll_32(L2_STATUS_REG, L2_STATUS_REG_L2FLUSHDONE);\n\t/* Deassert L2FLUSHREQ. */\n\tmmio_clr_32(C0_CTRL_REG2, C0_CTRL_REG2_L2FLUSHREQ);\n\t/* Remove the cluster from coherency (assert ACINACTM). */\n\tmmio_write_32(C0_CTRL_REG1, C0_CTRL_REG1_ACINACTM);\n\t/* Wait for the cluster (L2 cache) to be idle. */\n\tmmio_poll_32(C0_CPU_STATUS_REG, C0_CPU_STATUS_REG_STANDBYWFIL2);\n\t/* Lower the cluster clock frequency. */\n\tccu_suspend_cluster(cluster);\n\tif (new_state < SCPI_CSS_OFF)\n\t\treturn;\n\n\t/* Activate the cluster output clamps. */\n\tmmio_set_32(C0_PWROFF_GATING_REG, C0_PWROFF_GATING);\n}\n\nvoid\ncss_resume_cluster(uint32_t cluster, uint32_t old_state)\n{\n\tif (old_state < SCPI_CSS_RETENTION)\n\t\treturn;\n\n\t/* Raise the cluster clock frequency. */\n\tccu_resume_cluster(cluster);\n\tif (old_state < SCPI_CSS_OFF) {\n\t\t/* Enable coherency (deassert ACINACTM). */\n\t\tmmio_write_32(C0_CTRL_REG1, 0);\n\t\treturn;\n\t}\n\n\t/* Assert all power-on resets (active-low). */\n\tmmio_write_32(C0_PWRON_RESET_REG, 0);\n\t/* Release the cluster output clamps. */\n\tmmio_clr_32(C0_PWROFF_GATING_REG, C0_PWROFF_GATING);\n\t/* Deassert the cluster hard reset (active-low). */\n\tmmio_write_32(C0_PWRON_RESET_REG, C0_PWRON_RESET_REG_nH_RST);\n\t/* Program all cores to start in AArch64 mode. */\n\tmmio_write_32(C0_CTRL_REG0,\n\t              C0_CTRL_REG0_SYSBARDISABLE |\n\t              C0_CTRL_REG0_AA64nAA32_MASK);\n\t/* Deassert DBGPWRDUP for all cores. */\n\tmmio_write_32(DBG_REG0, 0);\n\t/* Restore the reset vector base addresses for all cores. */\n\tfor (uint32_t i = 0; i < css_get_core_count(cluster); ++i)\n\t\tmmio_write_32(RVBA_LO_REG(i), rvba);\n}\n\nvoid\ncss_suspend_core(uint32_t cluster UNUSED, uint32_t core, uint32_t new_state)\n{\n\tif (new_state < SCPI_CSS_OFF)\n\t\treturn;\n\n\t/* Wait for the core to be in WFI and ready to shut down. */\n\tmmio_poll_32(C0_CPU_STATUS_REG, C0_CPU_STATUS_REG_STANDBYWFI(core));\n\t/* Deassert DBGPWRDUP (prevent debug access to the core). */\n\tmmio_clr_32(DBG_REG0, DBG_REG0_DBGPWRDUP(core));\n\t/* Activate the core output clamps. */\n\tmmio_set_32(C0_PWROFF_GATING_REG, C0_CPUn_PWROFF_GATING(core));\n\t/* Remove power from the core power domain. */\n\tcss_set_power_switch(C0_CPUn_PWR_SWITCH_REG(core), false);\n}\n\nvoid\ncss_resume_core(uint32_t cluster UNUSED, uint32_t core, uint32_t old_state)\n{\n\tif (old_state < SCPI_CSS_OFF)\n\t\treturn;\n\n\t/* Assert core reset (active-low). */\n\tmmio_clr_32(C0_RST_CTRL_REG, C0_RST_CTRL_REG_nCORERESET(core));\n\t/* Assert core power-on reset (active-low). */\n\tmmio_clr_32(C0_PWRON_RESET_REG, C0_PWRON_RESET_REG_nCPUPORESET(core));\n\t/* Turn on power to the core power domain. */\n\tcss_set_power_switch(C0_CPUn_PWR_SWITCH_REG(core), true);\n\t/* Release the core output clamps. */\n\tmmio_clr_32(C0_PWROFF_GATING_REG, C0_CPUn_PWROFF_GATING(core));\n\t/* Deassert core power-on reset (active-low). */\n\tmmio_set_32(C0_PWRON_RESET_REG, C0_PWRON_RESET_REG_nCPUPORESET(core));\n\t/* Deassert core reset (active-low). */\n\tmmio_set_32(C0_RST_CTRL_REG, C0_RST_CTRL_REG_nCORERESET(core));\n\t/* Assert DBGPWRDUP (allow debug access to the core). */\n\tmmio_set_32(DBG_REG0, DBG_REG0_DBGPWRDUP(core));\n}\n\nvoid\ncss_init(void)\n{\n\t/* Program all cores to start in AArch64 mode. */\n\tmmio_write_32(C0_CTRL_REG0,\n\t              C0_CTRL_REG0_SYSBARDISABLE |\n\t              C0_CTRL_REG0_AA64nAA32_MASK);\n\t/* Save the power-on reset vector base address from core 0. */\n\trvba = mmio_read_32(RVBA_LO_REG(0));\n}\n"
  },
  {
    "path": "drivers/css/sun6i-a31-css.c",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <mmio.h>\n#include <scpi_protocol.h>\n#include <stdint.h>\n#include <clock/ccu.h>\n#include <platform/cpucfg.h>\n#include <platform/devices.h>\n#include <platform/prcm.h>\n\n#include \"css.h\"\n\n#define PLL_PERIPH0_CTRL_REG 0x0028\n#define CPUX_AXI_CFG_REG     0x0050\n#define AHB1_APB1_CFG_REG    0x0054\n\n#if CONFIG(PLATFORM_H3)\n\nuint32_t\ncss_get_irq_status(void)\n{\n\treturn mmio_read_32(IRQ_FIQ_STATUS_REG);\n}\n\n#endif\n\nvoid\ncss_suspend_css(uint32_t new_state)\n{\n\tif (new_state < SCPI_CSS_OFF)\n\t\treturn;\n\n\t/* Assert the CPU subsystem reset (active-low). */\n\tmmio_write_32(CPU_SYS_RESET_REG, 0);\n}\n\nvoid\ncss_resume_css(uint32_t old_state)\n{\n\tif (old_state < SCPI_CSS_OFF)\n\t\treturn;\n\n\t/* Deassert the CPU subsystem reset (active-low). */\n\tmmio_write_32(CPU_SYS_RESET_REG, CPU_SYS_RESET);\n}\n\nvoid\ncss_suspend_cluster(uint32_t cluster, uint32_t new_state)\n{\n\tif (new_state < SCPI_CSS_RETENTION)\n\t\treturn;\n\n\t/* Lower the cluster clock frequency. */\n\tccu_suspend_cluster(cluster);\n}\n\nvoid\ncss_resume_cluster(uint32_t cluster, uint32_t old_state)\n{\n\tif (old_state < SCPI_CSS_RETENTION)\n\t\treturn;\n\n\t/* Raise the cluster clock frequency. */\n\tccu_resume_cluster(cluster);\n}\n\nvoid\ncss_suspend_core(uint32_t cluster UNUSED, uint32_t core, uint32_t new_state)\n{\n\tif (new_state < SCPI_CSS_OFF)\n\t\treturn;\n\n\t/* Wait for the core to be in WFI and ready to shut down. */\n\tmmio_poll_32(CPUn_STATUS_REG(core), CPUn_STATUS_REG_STANDBYWFI);\n\t/* Deassert DBGPWRDUP (prevent debug access to the core). */\n\tmmio_clr_32(DBG_CTRL_REG1, DBG_CTRL_REG1_DBGPWRDUP(core));\n\t/* Core 0 does not have a separate power domain. */\n\tif (core > 0) {\n\t\t/* Activate the core output clamps. */\n\t\tmmio_set_32(C0_PWROFF_GATING_REG, C0_CPUn_PWROFF_GATING(core));\n\t\t/* Remove power from the core power domain. */\n\t\tcss_set_power_switch(C0_CPUn_PWR_SWITCH_REG(core), false);\n\t} else {\n\t\t/* Assert core reset and power-on reset (active-low). */\n\t\tmmio_write_32(CPUn_RST_CTRL_REG(core), 0);\n\t}\n}\n\nvoid\ncss_resume_core(uint32_t cluster UNUSED, uint32_t core, uint32_t old_state)\n{\n\tuint32_t bus_clk, cpu_clk;\n\n\tif (old_state < SCPI_CSS_OFF)\n\t\treturn;\n\n\t/* Core 0 does not have a separate power domain. */\n\tif (core > 0) {\n\t\t/* Assert core reset and power-on reset (active-low). */\n\t\tmmio_write_32(CPUn_RST_CTRL_REG(core), 0);\n\t\t/* Turn on power to the core power domain. */\n\t\tcss_set_power_switch(C0_CPUn_PWR_SWITCH_REG(core), true);\n\t\t/* Release the core output clamps. */\n\t\tmmio_clr_32(C0_PWROFF_GATING_REG, C0_CPUn_PWROFF_GATING(core));\n\t} else if (CONFIG(PLATFORM_H3)) {\n\t\t/* Save registers that will be clobbered by the BROM. */\n\t\tcpu_clk = mmio_read_32(DEV_CCU + CPUX_AXI_CFG_REG);\n\t\tbus_clk = mmio_read_32(DEV_CCU + AHB1_APB1_CFG_REG);\n\n\t\t/* Bypass PLL_PERIPH0 so AHB1 frequency does not spike. */\n\t\tmmio_set_32(DEV_CCU + PLL_PERIPH0_CTRL_REG, BIT(25));\n\t}\n\t/* Deassert core reset and power-on reset (active-low). */\n\tmmio_write_32(CPUn_RST_CTRL_REG(core),\n\t              CPUn_RST_CTRL_REG_nCORERESET |\n\t              CPUn_RST_CTRL_REG_nCPUPORESET);\n\tif (core == 0 && CONFIG(PLATFORM_H3)) {\n\t\t/* Spin until the BROM has clobbered the clock registers. */\n\t\tmmio_pollz_32(DEV_CCU + AHB1_APB1_CFG_REG, BIT(13));\n\n\t\t/* Disable PLL_PERIPH0 bypass. */\n\t\tmmio_clr_32(DEV_CCU + PLL_PERIPH0_CTRL_REG, BIT(25));\n\n\t\t/* Restore the clobbered registers. */\n\t\tmmio_write_32(DEV_CCU + CPUX_AXI_CFG_REG, cpu_clk);\n\t\tmmio_write_32(DEV_CCU + AHB1_APB1_CFG_REG, bus_clk);\n\t}\n\t/* Assert DBGPWRDUP (allow debug access to the core). */\n\tmmio_set_32(DBG_CTRL_REG1, DBG_CTRL_REG1_DBGPWRDUP(core));\n}\n\nvoid\ncss_init(void)\n{\n\t/* Enable hardware L1/L2 cache flush for all cores (active-low). */\n\tmmio_clr_32(GEN_CTRL_REG,\n\t            GEN_CTRL_REG_L2RSTDISABLE |\n\t            GEN_CTRL_REG_L1RSTDISABLE_MASK);\n}\n"
  },
  {
    "path": "drivers/dram/Makefile",
    "content": "#\n# Copyright © 2017-2022 The Crust Firmware Authors.\n# SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n#\n\nobj-y += dram.o\n\nobj-$(CONFIG_PLATFORM_A64) += sun8i-h3-dram.o\nobj-$(CONFIG_PLATFORM_H3)  += sun8i-h3-dram.o\nobj-$(CONFIG_PLATFORM_H6)  += sun50i-h6-dram.o\n"
  },
  {
    "path": "drivers/dram/dram.c",
    "content": "/*\n * Copyright © 2020-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <dram.h>\n\nvoid WEAK\ndram_suspend(void)\n{\n}\n\nvoid WEAK\ndram_resume(void)\n{\n}\n\nvoid WEAK\ndram_init(void)\n{\n}\n"
  },
  {
    "path": "drivers/dram/sun50i-h6-dram.c",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <clock.h>\n#include <delay.h>\n#include <mmio.h>\n#include <clock/ccu.h>\n#include <platform/devices.h>\n#include <platform/prcm.h>\n\n#define MC_MAER0              (DEV_DRAMCOM + 0x0020)\n#define MC_MAER0_VALUE        0xffffffff\n#define MC_MAER1              (DEV_DRAMCOM + 0x0024)\n#define MC_MAER1_VALUE        0x000007ff\n#define MC_MAER2              (DEV_DRAMCOM + 0x0028)\n#define MC_MAER2_VALUE        0x0000ffff\n\n#define STATR                 (DEV_DRAMCTL + 0x0004)\n#define STATR_OP_MODE         (0x7 << 0)\n#define STATR_OP_MODE_NORMAL  (0x1 << 0)\n#define STATR_OP_MODE_SELFREF (0x3 << 0)\n\n#define CLKEN                 (DEV_DRAMCTL + 0x000c)\n#define CLKEN_VALUE           0x00008100\n\n#define PWRCTL                (DEV_DRAMCTL + 0x0030)\n#define PWRCTL_SELFREF_EN     (0x1 << 0)\n\n#define PGCR3                 (DEV_DRAMPHY + 0x001c)\n#define PGCR3_CKEN            (0xf << 16)\n#define PGCR3_CKEN_DISABLED   (0x0 << 16)\n#define PGCR3_CKEN_INVERTED   (0x5 << 16)\n#define PGCR3_CKEN_NORMAL     (0xa << 16)\n#define PGCR3_CKNEN           (0xf << 20)\n#define PGCR3_CKNEN_DISABLED  (0x0 << 20)\n#define PGCR3_CKNEN_INVERTED  (0x5 << 20)\n#define PGCR3_CKNEN_NORMAL    (0xa << 20)\n\n/* Clocks needed by this driver. */\nenum {\n\tBUS_DRAM,\n\tDRAM,\n\tMBUS,\n};\n\nstatic const struct clock_handle dram_clocks[] = {\n\t[BUS_DRAM] = {\n\t\t.dev = &ccu.dev,\n\t\t.id  = CLK_BUS_DRAM,\n\t},\n\t[DRAM] = {\n\t\t.dev = &ccu.dev,\n\t\t.id  = CLK_DRAM,\n\t},\n\t[MBUS] = {\n\t\t.dev = &ccu.dev,\n\t\t.id  = CLK_MBUS,\n\t},\n};\n\nvoid\ndram_suspend(void)\n{\n\t/* Enable DRAM controller register access. */\n\tclock_get(&dram_clocks[BUS_DRAM]);\n\n\t/* Disable all controller masters. */\n\tmmio_write_32(MC_MAER0, 0);\n\tmmio_write_32(MC_MAER1, 0);\n\tmmio_write_32(MC_MAER2, 0);\n\t/* Enable DRAM self-refresh. */\n\tmmio_set_32(PWRCTL, PWRCTL_SELFREF_EN);\n\t/* Wait until the DRAM controller enters self-refresh. */\n\tmmio_polleq_32(STATR, STATR_OP_MODE, STATR_OP_MODE_SELFREF);\n\n\t/* Disable CKEN and CKNEN. */\n\tmmio_clrset_32(PGCR3,\n\t               PGCR3_CKEN |\n\t               PGCR3_CKNEN,\n\t               PGCR3_CKEN_DISABLED |\n\t               PGCR3_CKNEN_DISABLED);\n\n\t/* Disable DRAM controller clocks. */\n\tmmio_write_32(CLKEN, 0);\n\tclock_put(&dram_clocks[DRAM]);\n\tclock_put(&dram_clocks[MBUS]);\n\n\t/* Disable further DRAM controller register access. */\n\tclock_put(&dram_clocks[BUS_DRAM]);\n}\n\nvoid\ndram_resume(void)\n{\n\t/* Enable DRAM controller register access. */\n\tclock_get(&dram_clocks[BUS_DRAM]);\n\n\t/* Enable DRAM controller clocks. */\n\tclock_get(&dram_clocks[MBUS]);\n\tclock_get(&dram_clocks[DRAM]);\n\tudelay(10);\n\tmmio_write_32(CLKEN, CLKEN_VALUE);\n\tudelay(10);\n\n\t/* Enable CKEN and CKNEN. */\n\tmmio_clrset_32(PGCR3,\n\t               PGCR3_CKEN |\n\t               PGCR3_CKNEN,\n\t               PGCR3_CKEN_NORMAL |\n\t               PGCR3_CKNEN_NORMAL);\n\n\t/* Disable DRAM self refresh. */\n\tmmio_clr_32(PWRCTL, PWRCTL_SELFREF_EN);\n\t/* Wait until the DRAM controller exits self-refresh. */\n\tmmio_polleq_32(STATR, STATR_OP_MODE, STATR_OP_MODE_NORMAL);\n\t/* Enable all controller masters. */\n\tmmio_write_32(MC_MAER0, MC_MAER0_VALUE);\n\tmmio_write_32(MC_MAER1, MC_MAER1_VALUE);\n\tmmio_write_32(MC_MAER2, MC_MAER2_VALUE);\n\n\t/* Disable further DRAM controller register access. */\n\tclock_put(&dram_clocks[BUS_DRAM]);\n}\n\nvoid\ndram_init(void)\n{\n\t/* Get references to clocks that are already running. */\n\tclock_get(&dram_clocks[MBUS]);\n\tclock_get(&dram_clocks[DRAM]);\n}\n"
  },
  {
    "path": "drivers/dram/sun8i-h3-dram.c",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <clock.h>\n#include <delay.h>\n#include <mmio.h>\n#include <stdint.h>\n#include <util.h>\n#include <clock/ccu.h>\n#include <platform/devices.h>\n#include <platform/prcm.h>\n\n/* mctl_reg-sun8iw11.h:102 */\n#define PWRCTL                  (DEV_DRAMCTL + 0x0004)\n/* mctl_standby-sun8iw11.c:120,878,891 */\n#define PWRCTL_SELFREF_EN       (0x1 << 0)\n/* mctl_standby-sun8iw11.c:121 */\n#define PWRCTL_PORT_DIS         (0x1 << 8)\n\n/* mctl_reg-sun8iw11.h:104 */\n#define CLKEN                   (DEV_DRAMCTL + 0x000c)\n/* dram_sunxi_dw.c:410 */\n#define CLKEN_VALUE             0xc00e\n\n/* mctl_reg-sun8iw11.h:107 */\n#define STATR                   (DEV_DRAMCTL + 0x0018)\n/* mctl_standby-sun8iw11.c:124 */\n#define STATR_OP_MODE           (0x7 << 0)\n#define STATR_OP_MODE_NORMAL    (0x1 << 0)\n#define STATR_OP_MODE_SELFREF   (0x3 << 0)\n\n/* mctl_reg-sun8iw11.h:141 */\n#define PGCR3                   (DEV_DRAMCTL + 0x010c)\n/* mctl_standby-sun8iw11.c:130 */\n#define PGCR3_CKEN              (0xf << 16)\n#define PGCR3_CKEN_DISABLED     (0x0 << 16)\n#define PGCR3_CKEN_INVERTED     (0x5 << 16)\n#define PGCR3_CKEN_NORMAL       (0xa << 16)\n/* mctl_standby-sun8iw11.c:130 */\n#define PGCR3_CKNEN             (0xf << 20)\n#define PGCR3_CKNEN_DISABLED    (0x0 << 20)\n#define PGCR3_CKNEN_INVERTED    (0x5 << 20)\n#define PGCR3_CKNEN_NORMAL      (0xa << 20)\n/* mctl_standby-sun8iw11.c:872-873,904-905,950 */\n#define PGCR3_UNK25             (0x3 << 25)\n\n/* mctl_reg-sun8iw11.h:146 */\n#define ZQCR                    (DEV_DRAMCTL + 0x0140)\n#define ZQCR_ZQPD               (0x1 << 31)\n#define ZQCR_ZQPD_DISABLED      (0x0 << 31)\n#define ZQCR_ZQPD_ENABLED       (0x1 << 31)\n\n/* mctl_reg-sun8iw11.h:160 */\n#define ACIOCR0                 (DEV_DRAMCTL + 0x0208)\n/* mctl_standby-sun8iw11.c:154 */\n#define ACIOCR0_ACPDD           (0x1 << 0)\n#define ACIOCR0_ACPDD_DISABLED  (0x0 << 0)\n#define ACIOCR0_ACPDD_ENABLED   (0x1 << 0)\n/* mctl_standby-sun8iw11.c:154,762 */\n#define ACIOCR0_ACPDR           (0x1 << 1)\n#define ACIOCR0_ACPDR_DISABLED  (0x0 << 1)\n#define ACIOCR0_ACPDR_ENABLED   (0x1 << 1)\n/* mctl_standby-sun8iw11.c:152 */\n#define ACIOCR0_ACOE            (0x1 << 3)\n#define ACIOCR0_ACOE_DISABLED   (0x0 << 3)\n#define ACIOCR0_ACOE_ENABLED    (0x1 << 3)\n/* mctl_standby-sun8iw11.c:153 */\n#define ACIOCR0_ACIOM           (0x1 << 4)\n#define ACIOCR0_ACIOM_SSTL      (0x0 << 4)\n#define ACIOCR0_ACIOM_CMOS      (0x1 << 4)\n/* mctl_standby-sun8iw11.c:151 */\n#define ACIOCR0_CKOE            (0x3 << 6)\n#define ACIOCR0_CKOE_DISABLED   (0x0 << 6)\n#define ACIOCR0_CKOE_ENABLED    (0x3 << 6)\n/* mctl_standby-sun8iw11.c:150 */\n#define ACIOCR0_CKEOE           (0x3 << 8)\n#define ACIOCR0_CKEOE_DISABLED  (0x0 << 8)\n#define ACIOCR0_CKEOE_ENABLED   (0x3 << 8)\n/* mctl_standby-sun8iw11.c:763 */\n#define ACIOCR0_UNK11           (0x1 << 11)\n\n/* mctl_reg-sun8iw11.h:173 */\n#define DXnGCR0(n)              (DEV_DRAMCTL + 0x0344 + 0x80 * (n))\n/* mctl_standby-sun8iw11.c:146,710-711 */\n#define DXnGCR0_DXEN            (0x1 << 0)\n#define DXnGCR0_DXEN_DISABLED   (0x0 << 0)\n#define DXnGCR0_DXEN_ENABLED    (0x1 << 0)\n/* mctl_standby-sun8iw11.c:145,749 */\n#define DXnGCR0_DXIOM           (0x1 << 1)\n#define DXnGCR0_DXIOM_SSTL      (0x0 << 1)\n#define DXnGCR0_DXIOM_CMOS      (0x1 << 1)\n/* mctl_standby-sun8iw11.c:144,750 */\n#define DXnGCR0_DXOEO           (0x3 << 2)\n#define DXnGCR0_DXOEO_DYNAMIC   (0x0 << 2)\n#define DXnGCR0_DXOEO_ENABLED   (0x1 << 2)\n#define DXnGCR0_DXOEO_DISABLED  (0x2 << 2)\n/* mctl_standby-sun8iw11.c:748 */\n#define DXnGCR0_DXODT           (0x3 << 4)\n#define DXnGCR0_DXODT_DYNAMIC   (0x0 << 4)\n#define DXnGCR0_DXODT_ENABLED   (0x1 << 4)\n#define DXnGCR0_DXODT_DISABLED  (0x2 << 4)\n/* mctl_standby-sun8iw11.c:754-755 */\n#define DXnGCR0_UNK09           (0x3 << 9)\n#define DXnGCR0_UNK09_DYNAMIC   (0x0 << 9)\n#define DXnGCR0_UNK09_ENABLED   (0x1 << 9)\n#define DXnGCR0_UNK09_DISABLED  (0x2 << 9)\n/* mctl_standby-sun8iw11.c:143,751 */\n#define DXnGCR0_DXPDR           (0x3 << 12)\n#define DXnGCR0_DXPDR_DYNAMIC   (0x0 << 12)\n#define DXnGCR0_DXPDR_ENABLED   (0x1 << 12)\n#define DXnGCR0_DXPDR_DISABLED  (0x2 << 12)\n/* mctl_standby-sun8iw11.c:143,752 */\n#define DXnGCR0_DXPDD           (0x3 << 14)\n#define DXnGCR0_DXPDD_DYNAMIC   (0x0 << 14)\n#define DXnGCR0_DXPDD_ENABLED   (0x1 << 14)\n#define DXnGCR0_DXPDD_DISABLED  (0x2 << 14)\n/* mctl_standby-sun8iw11.c:141 */\n#define DXnGCR0_DQSRPD          (0x3 << 22)\n#define DXnGCR0_DQSRPD_DYNAMIC  (0x0 << 22)\n#define DXnGCR0_DQSRPD_ENABLED  (0x1 << 22)\n#define DXnGCR0_DQSRPD_DISABLED (0x2 << 22)\n\n/* Clocks needed by this driver. */\nenum {\n\tBUS_DRAM,\n\tMBUS,\n\tDRAM,\n};\n\nstatic const struct clock_handle dram_clocks[] = {\n\t[BUS_DRAM] = {\n\t\t.dev = &ccu.dev,\n\t\t.id  = CLK_BUS_DRAM,\n\t},\n\t[MBUS] = {\n\t\t.dev = &ccu.dev,\n\t\t.id  = CLK_MBUS,\n\t},\n\t[DRAM] = {\n\t\t.dev = &ccu.dev,\n\t\t.id  = CLK_DRAM,\n\t},\n};\n\nstatic uint32_t pwrctl;\n\nvoid\ndram_suspend(void)\n{\n\t/* Enable DRAM controller register access. */\n\tclock_get(&dram_clocks[BUS_DRAM]);\n\n\t/* Disable controller port access and enable DRAM self-refresh. */\n\tpwrctl = mmio_read_32(PWRCTL);\n\tmmio_write_32(PWRCTL, pwrctl | PWRCTL_PORT_DIS | PWRCTL_SELFREF_EN);\n\t/* Wait until the DRAM controller enters self-refresh. */\n\tmmio_polleq_32(STATR, STATR_OP_MODE, STATR_OP_MODE_SELFREF);\n\tudelay(1);\n\t/* Disable CKEN and CKNEN. */\n\tmmio_clrset_32(PGCR3,\n\t               PGCR3_CKEN |\n\t               PGCR3_CKNEN,\n\t               PGCR3_CKEN_DISABLED |\n\t               PGCR3_CKNEN_DISABLED);\n\t/* Configure DX pads. */\n\tfor (uint8_t n = 0; n < 4; ++n) {\n\t\tmmio_clrset_32(DXnGCR0(n),\n\t\t               DXnGCR0_DXIOM |\n\t\t               DXnGCR0_DXOEO |\n\t\t               DXnGCR0_DXPDR |\n\t\t               DXnGCR0_DXPDD |\n\t\t               DXnGCR0_DQSRPD,\n\t\t               DXnGCR0_DXIOM_CMOS |\n\t\t               DXnGCR0_DXOEO_DISABLED |\n\t\t               DXnGCR0_DXPDR_ENABLED |\n\t\t               DXnGCR0_DXPDD_ENABLED |\n\t\t               DXnGCR0_DQSRPD_ENABLED);\n\t}\n\t/* Configure AC pads. */\n\tmmio_clrset_32(ACIOCR0,\n\t               ACIOCR0_ACPDD |\n\t               ACIOCR0_ACPDR |\n\t               ACIOCR0_ACOE |\n\t               ACIOCR0_ACIOM |\n\t               ACIOCR0_CKOE |\n\t               ACIOCR0_CKEOE,\n\t               ACIOCR0_ACPDD_ENABLED |\n\t               ACIOCR0_ACPDR_ENABLED |\n\t               ACIOCR0_ACOE_ENABLED * CONFIG(PLATFORM_H3) |\n\t               ACIOCR0_ACIOM_CMOS |\n\t               ACIOCR0_CKOE_DISABLED |\n\t               ACIOCR0_CKEOE_ENABLED);\n\t/* Enable pad hold. */\n\tudelay(10);\n\tmmio_set_32(VDD_SYS_PWROFF_GATING_REG, GENMASK(1, 0));\n\tudelay(10);\n\t/* Disable DRAM controller clocks. */\n\tmmio_write_32(CLKEN, 0);\n\tclock_put(&dram_clocks[DRAM]);\n\tclock_put(&dram_clocks[MBUS]);\n\n\t/* Disable further DRAM controller register access. */\n\tclock_put(&dram_clocks[BUS_DRAM]);\n}\n\nvoid\ndram_resume(void)\n{\n\t/* Enable DRAM controller register access. */\n\tclock_get(&dram_clocks[BUS_DRAM]);\n\n\t/* Enable DRAM controller clocks. */\n\tclock_get(&dram_clocks[MBUS]);\n\tclock_get(&dram_clocks[DRAM]);\n\tmmio_write_32(CLKEN, CLKEN_VALUE);\n\t/* Configure AC pads. */\n\tmmio_clrset_32(ACIOCR0,\n\t               ACIOCR0_ACPDD |\n\t               ACIOCR0_ACPDR |\n\t               ACIOCR0_ACOE |\n\t               ACIOCR0_ACIOM |\n\t               ACIOCR0_CKOE |\n\t               ACIOCR0_CKEOE,\n\t               ACIOCR0_ACPDD_DISABLED |\n\t               ACIOCR0_ACPDR_ENABLED |\n\t               ACIOCR0_ACOE_ENABLED |\n\t               ACIOCR0_ACIOM_SSTL |\n\t               ACIOCR0_CKOE_ENABLED |\n\t               ACIOCR0_CKEOE_ENABLED);\n\t/* Configure DX pads. */\n\tfor (uint8_t n = 0; n < 4; ++n) {\n\t\tmmio_clrset_32(DXnGCR0(n),\n\t\t               DXnGCR0_DXIOM |\n\t\t               DXnGCR0_DXOEO |\n\t\t               DXnGCR0_DXPDR |\n\t\t               DXnGCR0_DXPDD |\n\t\t               DXnGCR0_DQSRPD,\n\t\t               DXnGCR0_DXIOM_SSTL |\n\t\t               DXnGCR0_DXOEO_DYNAMIC |\n\t\t               DXnGCR0_DXPDR_DYNAMIC |\n\t\t               DXnGCR0_DXPDD_DYNAMIC |\n\t\t               DXnGCR0_DQSRPD_DYNAMIC);\n\t}\n\t/* Enable CKEN and CKNEN. */\n\tmmio_clrset_32(PGCR3,\n\t               PGCR3_CKEN |\n\t               PGCR3_CKNEN,\n\t               PGCR3_CKEN_NORMAL |\n\t               PGCR3_CKNEN_NORMAL);\n\t/* Disable pad hold. */\n\tudelay(10);\n\tmmio_clr_32(VDD_SYS_PWROFF_GATING_REG, GENMASK(1, 0));\n\tudelay(10);\n\t/* Restore self refresh state and enable controller port access. */\n\tmmio_write_32(PWRCTL, pwrctl);\n\n\t/* Disable further DRAM controller register access. */\n\tclock_put(&dram_clocks[BUS_DRAM]);\n}\n\nvoid\ndram_init(void)\n{\n\t/* Get references to clocks that are already running. */\n\tclock_get(&dram_clocks[MBUS]);\n\tclock_get(&dram_clocks[DRAM]);\n}\n"
  },
  {
    "path": "drivers/gpio/Makefile",
    "content": "#\n# Copyright © 2017-2022 The Crust Firmware Authors.\n# SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n#\n\nobj-y += gpio.o\n\nobj-y += sunxi-gpio.o\n"
  },
  {
    "path": "drivers/gpio/gpio.c",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <device.h>\n#include <error.h>\n#include <gpio.h>\n#include <intrusive.h>\n#include <stdint.h>\n\n#include \"gpio.h\"\n\n/**\n * Get the ops for the controller device providing this GPIO pin.\n */\nstatic inline const struct gpio_driver_ops *\ngpio_ops_for(const struct gpio_handle *gpio)\n{\n\tconst struct gpio_driver *drv =\n\t\tcontainer_of(gpio->dev->drv, const struct gpio_driver, drv);\n\n\treturn &drv->ops;\n}\n\nint\ngpio_get(const struct gpio_handle *gpio)\n{\n\tint err;\n\n\t/* Ensure the controller's driver is loaded. */\n\tif ((err = device_get(gpio->dev)))\n\t\treturn err;\n\n\t/* Set the GPIO pin mode, drive strength, and pull-up or pull-down. */\n\tif ((err = gpio_ops_for(gpio)->init_pin(gpio)))\n\t\tgoto err_put_device;\n\n\treturn SUCCESS;\n\nerr_put_device:\n\tdevice_put(gpio->dev);\n\n\treturn err;\n}\n\nint\ngpio_get_value(const struct gpio_handle *gpio, bool *value)\n{\n\treturn gpio_ops_for(gpio)->get_value(gpio, value);\n}\n\nvoid\ngpio_put(const struct gpio_handle *gpio)\n{\n\tdevice_put(gpio->dev);\n}\n\nint\ngpio_set_value(const struct gpio_handle *gpio, bool value)\n{\n\treturn gpio_ops_for(gpio)->set_value(gpio, value);\n}\n"
  },
  {
    "path": "drivers/gpio/gpio.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef GPIO_PRIVATE_H\n#define GPIO_PRIVATE_H\n\n#include <device.h>\n#include <gpio.h>\n#include <stdbool.h>\n\nstruct gpio_driver_ops {\n\tint (*get_value)(const struct gpio_handle *gpio, bool *value);\n\tint (*init_pin)(const struct gpio_handle *gpio);\n\tint (*set_value)(const struct gpio_handle *gpio, bool value);\n};\n\nstruct gpio_driver {\n\tstruct driver          drv;\n\tstruct gpio_driver_ops ops;\n};\n\n#endif /* GPIO_PRIVATE_H */\n"
  },
  {
    "path": "drivers/gpio/sunxi-gpio.c",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <bitfield.h>\n#include <error.h>\n#include <limits.h>\n#include <mmio.h>\n#include <stdbool.h>\n#include <stdint.h>\n#include <clock/ccu.h>\n#include <gpio/sunxi-gpio.h>\n#include <platform/devices.h>\n\n#include \"gpio.h\"\n\n#define MODE_WIDTH           4\n#define MODE_PPW             (WORD_BIT / MODE_WIDTH)\n#define MODE_REG(port, pin)  (0x0000 + 0x24 * (port) + 4 * ((pin) / MODE_PPW))\n#define MODE_BIT(pin)        (MODE_WIDTH * ((pin) % MODE_PPW))\n\n#define DATA_WIDTH           1\n#define DATA_PPW             (WORD_BIT / DATA_WIDTH)\n#define DATA_REG(port)       (0x0010 + 0x24 * (port))\n#define DATA_BIT(pin)        (pin)\n\n#define DRIVE_WIDTH          2\n#define DRIVE_PPW            (WORD_BIT / DRIVE_WIDTH)\n#define DRIVE_REG(port, pin) (0x0014 + 0x24 * (port) + 4 * ((pin) / DRIVE_PPW))\n#define DRIVE_BIT(pin)       (DRIVE_WIDTH * ((pin) % DRIVE_PPW))\n\n#define PULL_WIDTH           2\n#define PULL_PPW             (WORD_BIT / PULL_WIDTH)\n#define PULL_REG(port, pin)  (0x001c + 0x24 * (port) + 4 * ((pin) / PULL_PPW))\n#define PULL_BIT(pin)        (PULL_WIDTH * ((pin) % PULL_PPW))\n\n#define PINS_PER_PORT        32\n#define GET_PORT(gpio)       ((gpio)->id / PINS_PER_PORT)\n#define GET_PIN(gpio)        ((gpio)->id % PINS_PER_PORT)\n\nstatic int\nsunxi_gpio_get_value(const struct gpio_handle *gpio, bool *value)\n{\n\tconst struct simple_device *self = to_simple_device(gpio->dev);\n\tuint8_t port   = GET_PORT(gpio);\n\tuint8_t pin    = GET_PIN(gpio);\n\tuintptr_t regs = self->regs;\n\n\t*value = mmio_get_bitfield_32(regs + DATA_REG(port), DATA_BIT(pin),\n\t                              DATA_WIDTH);\n\n\treturn SUCCESS;\n}\n\nstatic int\nsunxi_gpio_init_pin(const struct gpio_handle *gpio)\n{\n\tconst struct simple_device *self = to_simple_device(gpio->dev);\n\tuint8_t port   = GET_PORT(gpio);\n\tuint8_t pin    = GET_PIN(gpio);\n\tuintptr_t regs = self->regs;\n\n\t/* Set pin function configuration (mode). */\n\tif (gpio->mode != MODE_OUTPUT)\n\t\tmmio_set_bitfield_32(regs + MODE_REG(port, pin), MODE_BIT(pin),\n\t\t                     MODE_WIDTH, gpio->mode);\n\t/* Set pin drive strength. */\n\tmmio_set_bitfield_32(regs + DRIVE_REG(port, pin), DRIVE_BIT(pin),\n\t                     DRIVE_WIDTH, gpio->drive);\n\t/* Set pin pull-up or pull-down. */\n\tmmio_set_bitfield_32(regs + PULL_REG(port, pin), PULL_BIT(pin),\n\t                     PULL_WIDTH, gpio->pull);\n\n\treturn SUCCESS;\n}\n\nstatic int\nsunxi_gpio_set_value(const struct gpio_handle *gpio, bool value)\n{\n\tconst struct simple_device *self = to_simple_device(gpio->dev);\n\tuint8_t port   = GET_PORT(gpio);\n\tuint8_t pin    = GET_PIN(gpio);\n\tuintptr_t regs = self->regs;\n\n\tmmio_set_bitfield_32(regs + DATA_REG(port), DATA_BIT(pin),\n\t                     DATA_WIDTH, value);\n\tmmio_set_bitfield_32(regs + MODE_REG(port, pin), MODE_BIT(pin),\n\t                     MODE_WIDTH, MODE_OUTPUT);\n\n\treturn SUCCESS;\n}\n\nstatic const struct gpio_driver sunxi_gpio_driver = {\n\t.drv = {\n\t\t.probe   = simple_device_probe,\n\t\t.release = simple_device_release,\n\t},\n\t.ops = {\n\t\t.get_value = sunxi_gpio_get_value,\n\t\t.init_pin  = sunxi_gpio_init_pin,\n\t\t.set_value = sunxi_gpio_set_value,\n\t},\n};\n\nconst struct simple_device pio = {\n\t.dev = {\n\t\t.name  = \"pio\",\n\t\t.drv   = &sunxi_gpio_driver.drv,\n\t\t.state = DEVICE_STATE_INIT,\n\t},\n\t.clock = { .dev = &ccu.dev, .id = CLK_BUS_PIO },\n\t.regs  = DEV_PIO,\n};\n\nconst struct simple_device r_pio = {\n\t.dev = {\n\t\t.name  = \"r_pio\",\n\t\t.drv   = &sunxi_gpio_driver.drv,\n\t\t.state = DEVICE_STATE_INIT,\n\t},\n\t.clock = { .dev = &r_ccu.dev, .id = CLK_BUS_R_PIO },\n\t.regs  = DEV_R_PIO,\n};\n"
  },
  {
    "path": "drivers/irq/Makefile",
    "content": "#\n# Copyright © 2017-2022 The Crust Firmware Authors.\n# SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n#\n\nobj-y += irq.o\n\nobj-$(CONFIG_PLATFORM_A23)  += sun6i-a31-r-intc.o\nobj-$(CONFIG_PLATFORM_A64)  += sun6i-a31-r-intc.o\nobj-$(CONFIG_PLATFORM_A83T) += sun6i-a31-r-intc.o\nobj-$(CONFIG_PLATFORM_H3)   += sun6i-a31-r-intc.o\nobj-$(CONFIG_PLATFORM_H6)   += sun6i-a31-r-intc.o\n"
  },
  {
    "path": "drivers/irq/irq.c",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <irq.h>\n#include <stdint.h>\n\nuint32_t WEAK\nirq_needs_avcc(void)\n{\n\treturn 0;\n}\n\nuint32_t WEAK\nirq_needs_vdd_sys(void)\n{\n\treturn 0;\n}\n\nuint32_t WEAK\nirq_poll(void)\n{\n\treturn 0;\n}\n"
  },
  {
    "path": "drivers/irq/sun6i-a31-r-intc.c",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <irq.h>\n#include <mmio.h>\n#include <stdint.h>\n#include <util.h>\n#include <platform/devices.h>\n\n#include \"irq.h\"\n\n#define INTC_VECTOR_REG      0x0000\n#define INTC_BASE_ADDR_REG   0x0004\n#define INTC_PROTECT_REG     0x0008\n#define INTC_NMI_CTRL_REG    0x000c\n#define INTC_IRQ_PEND_REG(n) (0x0010 + 4 * (n))\n#define INTC_IRQ_EN_REG(n)   (0x0040 + 4 * (n))\n#define INTC_IRQ_MASK_REG(n) (0x0050 + 4 * (n))\n#define INTC_IRQ_RESP_REG(n) (0x0060 + 4 * (n))\n#define INTC_MUX_EN_REG(n)   (0x00c0 + 4 * (n))\n\n#define NUM_IRQ_REGS         (CONFIG(PLATFORM_H6) ? 2 : 1)\n#define NUM_MUX_REGS         4\n\n/* Gating AVCC will prevent receiving any of these interrupts. */\nstatic const uint32_t mux_needs_avcc[NUM_MUX_REGS] = {\n#if CONFIG(PLATFORM_A64) || CONFIG(PLATFORM_H3)\n\t[0] = BIT(62 - 32), /* LRADC */\n#else\n\t0 /* No applicable interrupts */\n#endif\n};\n\n/* Gating VDD_SYS will prevent receiving any of these interrupts. */\nstatic const uint32_t mux_needs_vdd_sys[NUM_MUX_REGS] = {\n#if CONFIG(PLATFORM_A64) && CONFIG(SOC_A64)\n\t[0] = BIT(43 - 32) | /* Port B */\n\t      BIT(49 - 32) | /* Port G */\n\t      BIT(53 - 32),  /* Port H */\n#elif CONFIG(PLATFORM_A64) && CONFIG(SOC_H5)\n\t[0] = BIT(43 - 32) | /* Port A */\n\t      BIT(49 - 32) | /* Port F */\n\t      BIT(55 - 32),  /* Port G */\n#elif CONFIG(PLATFORM_A83T)\n\t[0] = BIT(47 - 32) | /* Port B */\n\t      BIT(49 - 32),  /* Port G */\n#elif CONFIG(PLATFORM_H3)\n\t[0] = BIT(43 - 32) | /* Port A */\n\t      BIT(49 - 32),  /* Port G */\n#elif CONFIG(PLATFORM_H6)\n\t[1] = BIT(83 - 64) | /* Port B */\n\t      BIT(85 - 64) | /* Port F */\n\t      BIT(86 - 64) | /* Port G */\n\t      BIT(91 - 64),  /* Port H */\n#else\n\t0 /* No applicable interrupts */\n#endif\n};\n\nuint32_t\nirq_needs_avcc(void)\n{\n\tuint32_t enabled = 0;\n\n\t/* Only read registers with relevant bits. */\n\tfor (int i = 0; i < NUM_MUX_REGS; ++i) {\n\t\tif (!mux_needs_avcc[i])\n\t\t\tcontinue;\n\n\t\tenabled |= mmio_read_32(DEV_R_INTC + INTC_MUX_EN_REG(i)) &\n\t\t           mux_needs_avcc[i];\n\t}\n\n\treturn enabled;\n}\n\nuint32_t\nirq_needs_vdd_sys(void)\n{\n\tuint32_t enabled = 0;\n\n\t/* Only read registers with relevant bits. */\n\tfor (int i = 0; i < NUM_MUX_REGS; ++i) {\n\t\tif (!mux_needs_vdd_sys[i])\n\t\t\tcontinue;\n\n\t\tenabled |= mmio_read_32(DEV_R_INTC + INTC_MUX_EN_REG(i)) &\n\t\t           mux_needs_vdd_sys[i];\n\t}\n\n\treturn enabled;\n}\n\nuint32_t\nirq_poll(void)\n{\n\tuint32_t pending = 0;\n\n\tfor (int i = 0; i < NUM_IRQ_REGS; ++i)\n\t\tpending |= mmio_read_32(DEV_R_INTC + INTC_IRQ_PEND_REG(i));\n\n\treturn pending;\n}\n"
  },
  {
    "path": "drivers/mfd/Kconfig",
    "content": "#\n# Copyright © 2020-2022 The Crust Firmware Authors.\n# SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n#\n\nconfig MFD_AXP20X\n\tbool \"Multi-function driver for X-Powers PMICs\"\n\tdepends on I2C || RSB\n\thelp\n\t\tThis driver enables both the power sequencing and\n\t\tvoltage regulator functionality of an AXP2xx or AXP8xx\n\t\tseries power management IC.\n\ncomment \"X-Powers PMIC will communicate via I2C\"\n\tdepends on MFD_AXP20X && !RSB\n\ncomment \"X-Powers PMIC will communicate via RSB\"\n\tdepends on MFD_AXP20X && RSB\n\nchoice\n\tbool \"X-Powers PMIC variant\"\n\tdepends on MFD_AXP20X\n\tdefault MFD_AXP223 if PLATFORM_A23\n\tdefault MFD_AXP803 if PLATFORM_A64\n\tdefault MFD_AXP805 if PLATFORM_H6\n\nconfig MFD_AXP223\n\tbool \"AXP223\"\n\thelp\n\t\tThis PMIC is usually paired with the A23/A33 SoC.\n\nconfig MFD_AXP803\n\tbool \"AXP803\"\n\thelp\n\t\tThis PMIC is usually paired with the A64 SoC.\n\nconfig MFD_AXP805\n\tbool \"AXP805\"\n\thelp\n\t\tThis PMIC is usually paired with the H6 SoC.\n\nendchoice\n"
  },
  {
    "path": "drivers/mfd/Makefile",
    "content": "#\n# Copyright © 2017-2022 The Crust Firmware Authors.\n# SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n#\n\nobj-$(CONFIG_MFD_AXP20X) += axp20x.o\n"
  },
  {
    "path": "drivers/mfd/axp20x.c",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <device.h>\n#include <error.h>\n#include <regmap.h>\n#include <stdint.h>\n#include <mfd/axp20x.h>\n#include <regmap/sun6i-i2c.h>\n#include <regmap/sunxi-rsb.h>\n\n#define IC_TYPE_REG   0x03\n#define IC_TYPE_MASK  0xcf\n\n#if CONFIG(MFD_AXP223)\n#define IC_TYPE_VALUE 0x06\n#define I2C_ADDRESS   0x34\n#define RSB_ADDRESS   (0x2d << 16 | 0x3a3)\n#elif CONFIG(MFD_AXP803)\n#define IC_TYPE_VALUE 0x41\n#define I2C_ADDRESS   0x34\n#define RSB_ADDRESS   (0x2d << 16 | 0x3a3)\n#elif CONFIG(MFD_AXP805)\n#define IC_TYPE_VALUE 0x40\n#define I2C_ADDRESS   0x36\n#define RSB_ADDRESS   (0x3a << 16 | 0x745)\n#endif\n\nstatic int\naxp20x_probe(const struct device *dev)\n{\n\tconst struct regmap_device *self = to_regmap_device(dev);\n\tuint8_t reg;\n\tint err;\n\n\tif ((err = regmap_device_probe(dev)))\n\t\treturn err;\n\tif ((err = regmap_read(&self->map, IC_TYPE_REG, &reg)))\n\t\tgoto err_release;\n\tif ((reg & IC_TYPE_MASK) != IC_TYPE_VALUE) {\n\t\terr = ENODEV;\n\t\tgoto err_release;\n\t}\n\n\treturn SUCCESS;\n\nerr_release:\n\tregmap_device_release(dev);\n\n\treturn err;\n}\n\nstatic const struct driver axp20x_driver = {\n\t.probe   = axp20x_probe,\n\t.release = regmap_device_release,\n};\n\nconst struct regmap_device axp20x = {\n\t.dev = {\n\t\t.name  = \"axp20x\",\n\t\t.drv   = &axp20x_driver,\n\t\t.state = DEVICE_STATE_INIT,\n\t},\n\t.map = {\n\t\t.dev = CONFIG(RSB) ? &r_rsb.dev : &r_i2c.dev,\n\t\t.id  = CONFIG(RSB) ? RSB_ADDRESS : I2C_ADDRESS,\n\t},\n};\n"
  },
  {
    "path": "drivers/msgbox/Makefile",
    "content": "#\n# Copyright © 2017-2022 The Crust Firmware Authors.\n# SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n#\n\nobj-y += msgbox.o\nobj-y += sunxi-msgbox.o\n"
  },
  {
    "path": "drivers/msgbox/msgbox.c",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <device.h>\n#include <intrusive.h>\n#include <msgbox.h>\n#include <stdbool.h>\n#include <stdint.h>\n\n#include \"msgbox.h\"\n\n/**\n * Get the ops for the msgbox controller device.\n */\nstatic inline const struct msgbox_driver_ops *\nmsgbox_ops_for(const struct device *dev)\n{\n\tconst struct msgbox_driver *drv =\n\t\tcontainer_of(dev->drv, const struct msgbox_driver, drv);\n\n\treturn &drv->ops;\n}\n\nvoid\nmsgbox_ack_rx(const struct device *dev, uint8_t chan)\n{\n\tmsgbox_ops_for(dev)->ack_rx(dev, chan);\n}\n\nbool\nmsgbox_last_tx_done(const struct device *dev, uint8_t chan)\n{\n\treturn msgbox_ops_for(dev)->last_tx_done(dev, chan);\n}\n\nint\nmsgbox_receive(const struct device *dev, uint8_t chan, uint32_t *message)\n{\n\treturn msgbox_ops_for(dev)->receive(dev, chan, message);\n}\n\nint\nmsgbox_send(const struct device *dev, uint8_t chan, uint32_t message)\n{\n\treturn msgbox_ops_for(dev)->send(dev, chan, message);\n}\n"
  },
  {
    "path": "drivers/msgbox/msgbox.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef MSGBOX_PRIVATE_H\n#define MSGBOX_PRIVATE_H\n\n#include <device.h>\n#include <stdbool.h>\n#include <stdint.h>\n\nstruct msgbox_driver_ops {\n\tvoid (*ack_rx)(const struct device *dev, uint8_t chan);\n\tbool (*last_tx_done)(const struct device *dev, uint8_t chan);\n\tint  (*receive)(const struct device *dev, uint8_t chan,\n\t                uint32_t *message);\n\tint  (*send)(const struct device *dev, uint8_t chan,\n\t             uint32_t message);\n};\n\nstruct msgbox_driver {\n\tstruct driver            drv;\n\tstruct msgbox_driver_ops ops;\n};\n\n#endif /* MSGBOX_PRIVATE_H */\n"
  },
  {
    "path": "drivers/msgbox/sunxi-msgbox.c",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <debug.h>\n#include <error.h>\n#include <mmio.h>\n#include <stdbool.h>\n#include <stddef.h>\n#include <util.h>\n#include <clock/ccu.h>\n#include <msgbox/sunxi-msgbox.h>\n#include <platform/devices.h>\n\n#include \"msgbox.h\"\n\n#define CTRL_REG0           0x0000\n#define CTRL_REG1           0x0004\n#define CTRL_NORMAL         0x01100110\n\n#define IRQ_EN_REG          0x0040\n#define IRQ_STAT_REG        0x0050\n#define REMOTE_IRQ_EN_REG   0x0060\n#define REMOTE_IRQ_STAT_REG 0x0070\n#define RX_IRQ(n)           BIT(0 + 2 * (n))\n#define RX_IRQ_MASK         0x5555\n#define TX_IRQ(n)           BIT(1 + 2 * (n))\n#define TX_IRQ_MASK         0xaaaa\n\n#define FIFO_STAT_REG(n)    (0x0100 + 0x4 * (n))\n#define FIFO_STAT_MASK      BIT(0)\n\n#define MSG_STAT_REG(n)     (0x0140 + 0x4 * (n))\n#define MSG_STAT_MASK       GENMASK(2, 0)\n\n#define MSG_DATA_REG(n)     (0x0180 + 0x4 * (n))\n\nstatic bool\nsunxi_msgbox_peek_data(const struct device *dev, uint8_t chan)\n{\n\tconst struct simple_device *self = to_simple_device(dev);\n\n\treturn mmio_read_32(self->regs + MSG_STAT_REG(chan)) & MSG_STAT_MASK;\n}\n\nstatic void\nsunxi_msgbox_ack_rx(const struct device *dev, uint8_t chan)\n{\n\tconst struct simple_device *self = to_simple_device(dev);\n\n\tmmio_write_32(self->regs + IRQ_STAT_REG, RX_IRQ(chan));\n}\n\nstatic bool\nsunxi_msgbox_last_tx_done(const struct device *dev, uint8_t chan)\n{\n\tconst struct simple_device *self = to_simple_device(dev);\n\n\tassert(chan < SUNXI_MSGBOX_CHANS);\n\n\treturn !(mmio_read_32(self->regs + REMOTE_IRQ_STAT_REG) &\n\t         RX_IRQ(chan));\n}\n\nstatic int\nsunxi_msgbox_receive(const struct device *dev, uint8_t chan, uint32_t *msg)\n{\n\tconst struct simple_device *self = to_simple_device(dev);\n\n\tassert(chan < SUNXI_MSGBOX_CHANS);\n\n\t/* Check if a new message is available before reading it. */\n\tif (!sunxi_msgbox_peek_data(dev, chan))\n\t\treturn ENOENT;\n\t*msg = mmio_read_32(self->regs + MSG_DATA_REG(chan));\n\n\treturn SUCCESS;\n}\n\nstatic int\nsunxi_msgbox_send(const struct device *dev, uint8_t chan, uint32_t msg)\n{\n\tconst struct simple_device *self = to_simple_device(dev);\n\n\tassert(chan < SUNXI_MSGBOX_CHANS);\n\n\t/* Reject the message if the FIFO is full. */\n\tif (mmio_read_32(self->regs + FIFO_STAT_REG(chan)) & FIFO_STAT_MASK)\n\t\treturn EBUSY;\n\tmmio_write_32(self->regs + MSG_DATA_REG(chan), msg);\n\n\treturn SUCCESS;\n}\n\nstatic int\nsunxi_msgbox_probe(const struct device *dev)\n{\n\tconst struct simple_device *self = to_simple_device(dev);\n\tint err;\n\n\tif ((err = simple_device_probe(dev)))\n\t\treturn err;\n\n\t/* Set even channels ARM -> SCP and odd channels SCP -> ARM. */\n\tmmio_write_32(self->regs + CTRL_REG0, CTRL_NORMAL);\n\tmmio_write_32(self->regs + CTRL_REG1, CTRL_NORMAL);\n\n\t/* Drain messages in RX channels (required to clear IRQs). */\n\tfor (uint8_t chan = 0; chan < SUNXI_MSGBOX_CHANS; chan += 2) {\n\t\twhile (sunxi_msgbox_peek_data(dev, chan))\n\t\t\tmmio_read_32(self->regs + MSG_DATA_REG(chan));\n\t}\n\n\t/* Disable and clear all IRQ. */\n\tmmio_write_32(self->regs + IRQ_EN_REG, 0);\n\tmmio_write_32(self->regs + IRQ_STAT_REG, GENMASK(15, 0));\n\n\treturn SUCCESS;\n}\n\nstatic const struct msgbox_driver sunxi_msgbox_driver = {\n\t.drv = {\n\t\t.probe   = sunxi_msgbox_probe,\n\t\t.release = simple_device_release,\n\t},\n\t.ops = {\n\t\t.ack_rx       = sunxi_msgbox_ack_rx,\n\t\t.last_tx_done = sunxi_msgbox_last_tx_done,\n\t\t.receive      = sunxi_msgbox_receive,\n\t\t.send         = sunxi_msgbox_send,\n\t},\n};\n\nconst struct simple_device msgbox = {\n\t.dev = {\n\t\t.name  = \"msgbox\",\n\t\t.drv   = &sunxi_msgbox_driver.drv,\n\t\t.state = DEVICE_STATE_INIT,\n\t},\n\t.clock = { .dev = &ccu.dev, .id = CLK_BUS_MSGBOX },\n\t.regs  = DEV_MSGBOX,\n};\n"
  },
  {
    "path": "drivers/pmic/Kconfig",
    "content": "#\n# Copyright © 2017-2022 The Crust Firmware Authors.\n# SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n#\n\nmenu \"Power management controllers\"\n\nconfig PMIC\n\tbool\n\nconfig PMIC_AXP223\n\tbool\n\tselect PMIC\n\tdefault MFD_AXP223\n\nconfig PMIC_AXP803\n\tbool\n\tselect PMIC\n\tdefault MFD_AXP803\n\nconfig PMIC_AXP805\n\tbool\n\tselect PMIC\n\tdefault MFD_AXP805\n\nendmenu\n"
  },
  {
    "path": "drivers/pmic/Makefile",
    "content": "#\n# Copyright © 2017-2022 The Crust Firmware Authors.\n# SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n#\n\nobj-y += pmic.o\n\nobj-$(CONFIG_PMIC_AXP223) += axp20x.o axp223.o\nobj-$(CONFIG_PMIC_AXP803) += axp20x.o axp803.o\nobj-$(CONFIG_PMIC_AXP805) += axp20x.o axp805.o\n"
  },
  {
    "path": "drivers/pmic/axp20x.c",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <regmap.h>\n#include <util.h>\n\n#include \"axp20x.h\"\n\nint\naxp20x_pmic_reset(const struct device *dev)\n{\n\tconst struct axp20x_pmic *self = to_axp20x_pmic(dev);\n\n\t/* Trigger soft power restart. */\n\treturn regmap_set_bits(self->map, WAKEUP_CTRL_REG, BIT(6));\n}\n\nint\naxp20x_pmic_resume(const struct device *dev)\n{\n\tconst struct axp20x_pmic *self = to_axp20x_pmic(dev);\n\n\t/* Trigger soft power resume. */\n\treturn regmap_set_bits(self->map, WAKEUP_CTRL_REG, BIT(5));\n}\n\nint\naxp20x_pmic_shutdown(const struct device *dev)\n{\n\tconst struct axp20x_pmic *self = to_axp20x_pmic(dev);\n\n\t/* Trigger soft power off. */\n\treturn regmap_set_bits(self->map, POWER_DISABLE_REG, BIT(7));\n}\n\nint\naxp20x_pmic_probe(const struct device *dev)\n{\n\tconst struct axp20x_pmic *self = to_axp20x_pmic(dev);\n\n\treturn regmap_user_probe(self->map);\n}\n\nvoid\naxp20x_pmic_release(const struct device *dev)\n{\n\tconst struct axp20x_pmic *self = to_axp20x_pmic(dev);\n\n\tregmap_user_release(self->map);\n}\n"
  },
  {
    "path": "drivers/pmic/axp20x.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef AXP20X_PRIVATE_H\n#define AXP20X_PRIVATE_H\n\n#include <intrusive.h>\n#include <pmic/axp20x.h>\n\n#include \"pmic.h\"\n\n#define WAKEUP_CTRL_REG   0x31\n#define POWER_DISABLE_REG 0x32\n\nstatic inline const struct axp20x_pmic *\nto_axp20x_pmic(const struct device *dev)\n{\n\treturn container_of(dev, const struct axp20x_pmic, dev);\n}\n\n/* Valid for AXP221, AXP223, AXP803. */\nint axp20x_pmic_reset(const struct device *dev);\n\n/* Valid for AXP221, AXP223, AXP803, AXP805, AXP813. */\nint axp20x_pmic_resume(const struct device *dev);\n\n/* Valid for AXP221, AXP223, AXP803, AXP805, AXP813. */\nint axp20x_pmic_shutdown(const struct device *dev);\n\nint axp20x_pmic_probe(const struct device *dev);\nvoid axp20x_pmic_release(const struct device *dev);\n\n#endif /* AXP20X_PRIVATE_H */\n"
  },
  {
    "path": "drivers/pmic/axp223.c",
    "content": "/*\n * Copyright © 2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <regmap.h>\n#include <util.h>\n#include <mfd/axp20x.h>\n#include <pmic/axp223.h>\n\n#include \"axp20x.h\"\n\nstatic int\naxp223_pmic_suspend(const struct device *dev)\n{\n\tconst struct axp20x_pmic *self = to_axp20x_pmic(dev);\n\n\t/* Enable resume, allow IRQs during suspend. */\n\treturn regmap_set_bits(self->map, WAKEUP_CTRL_REG, BIT(4) | BIT(3));\n}\n\nstatic const struct pmic_driver axp223_pmic_driver = {\n\t.drv = {\n\t\t.probe   = axp20x_pmic_probe,\n\t\t.release = axp20x_pmic_release,\n\t},\n\t.ops = {\n\t\t.reset    = axp20x_pmic_reset,\n\t\t.resume   = axp20x_pmic_resume,\n\t\t.shutdown = axp20x_pmic_shutdown,\n\t\t.suspend  = axp223_pmic_suspend,\n\t},\n};\n\nconst struct axp20x_pmic axp223_pmic = {\n\t.dev = {\n\t\t.name  = \"axp223-pmic\",\n\t\t.drv   = &axp223_pmic_driver.drv,\n\t\t.state = DEVICE_STATE_INIT,\n\t},\n\t.map = &axp20x.map,\n};\n"
  },
  {
    "path": "drivers/pmic/axp803.c",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <regmap.h>\n#include <util.h>\n#include <mfd/axp20x.h>\n#include <pmic/axp803.h>\n\n#include \"axp20x.h\"\n\n#define PIN_FUNCTION_REG 0x8f\n\nstatic int\naxp803_pmic_suspend(const struct device *dev)\n{\n\tconst struct axp20x_pmic *self = to_axp20x_pmic(dev);\n\tint err;\n\n\t/* Remember previous voltages when waking up from suspend. */\n\tif ((err = regmap_set_bits(self->map, PIN_FUNCTION_REG, BIT(1))))\n\t\treturn err;\n\n\t/* Enable resume, allow IRQs during suspend. */\n\treturn regmap_set_bits(self->map, WAKEUP_CTRL_REG, BIT(4) | BIT(3));\n}\n\nstatic const struct pmic_driver axp803_pmic_driver = {\n\t.drv = {\n\t\t.probe   = axp20x_pmic_probe,\n\t\t.release = axp20x_pmic_release,\n\t},\n\t.ops = {\n\t\t.reset    = axp20x_pmic_reset,\n\t\t.resume   = axp20x_pmic_resume,\n\t\t.shutdown = axp20x_pmic_shutdown,\n\t\t.suspend  = axp803_pmic_suspend,\n\t},\n};\n\nconst struct axp20x_pmic axp803_pmic = {\n\t.dev = {\n\t\t.name  = \"axp803-pmic\",\n\t\t.drv   = &axp803_pmic_driver.drv,\n\t\t.state = DEVICE_STATE_INIT,\n\t},\n\t.map = &axp20x.map,\n};\n"
  },
  {
    "path": "drivers/pmic/axp805.c",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <regmap.h>\n#include <util.h>\n#include <mfd/axp20x.h>\n#include <pmic/axp805.h>\n\n#include \"axp20x.h\"\n\nstatic int\naxp805_pmic_reset(const struct device *dev)\n{\n\tconst struct axp20x_pmic *self = to_axp20x_pmic(dev);\n\n\t/* Trigger soft power restart. */\n\treturn regmap_set_bits(self->map, POWER_DISABLE_REG, BIT(6));\n}\n\nstatic int\naxp805_pmic_suspend(const struct device *dev)\n{\n\tconst struct axp20x_pmic *self = to_axp20x_pmic(dev);\n\n\t/* Enable resume, remember voltages, and allow IRQs during suspend. */\n\treturn regmap_set_bits(self->map, WAKEUP_CTRL_REG,\n\t                       BIT(6) | BIT(4) | BIT(3));\n}\n\nstatic const struct pmic_driver axp805_pmic_driver = {\n\t.drv = {\n\t\t.probe   = axp20x_pmic_probe,\n\t\t.release = axp20x_pmic_release,\n\t},\n\t.ops = {\n\t\t.reset    = axp805_pmic_reset,\n\t\t.resume   = axp20x_pmic_resume,\n\t\t.shutdown = axp20x_pmic_shutdown,\n\t\t.suspend  = axp805_pmic_suspend,\n\t},\n};\n\nconst struct axp20x_pmic axp805_pmic = {\n\t.dev = {\n\t\t.name  = \"axp805-pmic\",\n\t\t.drv   = &axp805_pmic_driver.drv,\n\t\t.state = DEVICE_STATE_INIT,\n\t},\n\t.map = &axp20x.map,\n};\n"
  },
  {
    "path": "drivers/pmic/pmic.c",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <device.h>\n#include <intrusive.h>\n#include <pmic.h>\n#include <pmic/axp223.h>\n#include <pmic/axp803.h>\n#include <pmic/axp805.h>\n\n#include \"pmic.h\"\n\n/**\n * Get the ops for the pmic controller device.\n */\nstatic inline const struct pmic_driver_ops *\npmic_ops_for(const struct device *dev)\n{\n\tconst struct pmic_driver *drv =\n\t\tcontainer_of(dev->drv, const struct pmic_driver, drv);\n\n\treturn &drv->ops;\n}\n\nconst struct device *\npmic_get(void)\n{\n\tconst struct device *pmic = NULL;\n\n\tif (CONFIG(PMIC_AXP223))\n\t\tpmic = device_get_or_null(&axp223_pmic.dev);\n\tif (CONFIG(PMIC_AXP803))\n\t\tpmic = device_get_or_null(&axp803_pmic.dev);\n\tif (CONFIG(PMIC_AXP805))\n\t\tpmic = device_get_or_null(&axp805_pmic.dev);\n\n\treturn pmic;\n}\n\nint\npmic_reset(const struct device *dev)\n{\n\treturn pmic_ops_for(dev)->reset(dev);\n}\n\nint\npmic_resume(const struct device *dev)\n{\n\treturn pmic_ops_for(dev)->resume(dev);\n}\n\nint\npmic_shutdown(const struct device *dev)\n{\n\treturn pmic_ops_for(dev)->shutdown(dev);\n}\n\nint\npmic_suspend(const struct device *dev)\n{\n\treturn pmic_ops_for(dev)->suspend(dev);\n}\n"
  },
  {
    "path": "drivers/pmic/pmic.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef PMIC_PRIVATE_H\n#define PMIC_PRIVATE_H\n\n#include <device.h>\n#include <pmic.h>\n\nstruct pmic_driver_ops {\n\tint (*reset)(const struct device *dev);\n\tint (*resume)(const struct device *dev);\n\tint (*shutdown)(const struct device *dev);\n\tint (*suspend)(const struct device *dev);\n};\n\nstruct pmic_driver {\n\tstruct driver          drv;\n\tstruct pmic_driver_ops ops;\n};\n\n#endif /* PMIC_PRIVATE_H */\n"
  },
  {
    "path": "drivers/regmap/Kconfig",
    "content": "#\n# Copyright © 2017-2022 The Crust Firmware Authors.\n# SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n#\n\nchoice\n\tbool \"I2C controller pin selection\"\n\tdepends on HAVE_R_I2C\n\tdefault I2C_PINS_NONE if HAVE_R_RSB\n\tdefault I2C_PINS_PL0_PL1\n\thelp\n\t\tChoose which pair of pins is used for the I2C bus.\n\nconfig I2C_PINS_NONE\n\tbool \"None\"\n\thelp\n\t\tSelect this option if your board does not have a PMIC or\n\t\tregulator connected via I2C.\n\n\t\tThis is usually the right choice if your SoC supports RSB.\n\nconfig I2C_PINS_PL0_PL1\n\tbool \"PL0/PL1\"\n\thelp\n\t\tSelect this option if your board has a PMIC or regulator\n\t\tconnected via I2C using the normal set of pins.\n\n\t\tNote that if your SoC contains an RSB controller,\n\t\tchoosing this option will prevent you from using it.\n\nconfig I2C_PINS_PL8_PL9\n\tbool \"PL8/PL9\"\n\tdepends on HAVE_R_RSB\n\thelp\n\t\tSelect this option if your board has a PMIC or regulator\n\t\tconnected via I2C using the alternate set of pins.\n\nendchoice\n\nconfig I2C_PIN_MODE_PL0_PL1\n\tint\n\tdepends on I2C_PINS_PL0_PL1\n\tdefault 3 if HAVE_R_RSB\n\tdefault 2\n\thelp\n\t\tProvide the pin mode that configures PL0/PL1 as I2C SCL/SDA.\n\nconfig I2C\n\tbool\n\tdefault HAVE_R_I2C && (!I2C_PINS_NONE || COMPILE_TEST)\n\thelp\n\t\tThis option is selected if the chosen pin configuration\n\t\tallows the I2C controller to be used.\n\nconfig RSB\n\tbool\n\tdefault HAVE_R_RSB && (!I2C_PINS_PL0_PL1 || COMPILE_TEST)\n\thelp\n\t\tThis option is selected if the chosen pin configuration\n\t\tallows the RSB controller to be used.\n"
  },
  {
    "path": "drivers/regmap/Makefile",
    "content": "#\n# Copyright © 2017-2022 The Crust Firmware Authors.\n# SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n#\n\nobj-y             += regmap.o\nobj-$(CONFIG_I2C) += regmap-i2c.o\n\nobj-$(CONFIG_I2C) += sun6i-i2c.o\nobj-$(CONFIG_RSB) += sunxi-rsb.o\n"
  },
  {
    "path": "drivers/regmap/regmap-i2c.c",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <device.h>\n#include <error.h>\n#include <intrusive.h>\n#include <stdint.h>\n\n#include \"regmap-i2c.h\"\n\n/**\n * Get the ops for the I²C controller device.\n */\nstatic inline const struct regmap_i2c_driver_ops *\nregmap_i2c_ops_for(const struct regmap *map)\n{\n\tconst struct regmap_i2c_driver *drv =\n\t\tcontainer_of(map->dev->drv, const struct regmap_i2c_driver,\n\t\t             drv.drv);\n\n\treturn &drv->ops;\n}\n\nint\nregmap_i2c_prepare(const struct regmap *map)\n{\n\tconst struct regmap_i2c_driver_ops *ops = regmap_i2c_ops_for(map);\n\tuint8_t dummy;\n\tint err;\n\n\t/* Start a read transaction. */\n\tif ((err = ops->start(map, I2C_READ)))\n\t\tgoto abort;\n\n\t/* Read data to avoid putting the device in an inconsistent state. */\n\tif (ops->read(map, &dummy))\n\t\tgoto abort;\n\nabort:\n\t/* Finish the transaction. */\n\tops->stop(map);\n\n\treturn err ? ENODEV : SUCCESS;\n}\n\nint\nregmap_i2c_read(const struct regmap *map, uint8_t reg, uint8_t *val)\n{\n\tconst struct regmap_i2c_driver_ops *ops = regmap_i2c_ops_for(map);\n\tint err;\n\n\t/* Start a write transaction. */\n\tif ((err = ops->start(map, I2C_WRITE)))\n\t\tgoto abort;\n\n\t/* Write the register address. */\n\tif ((err = ops->write(map, reg)))\n\t\tgoto abort;\n\n\t/* Restart as a read transaction. */\n\tif ((err = ops->start(map, I2C_READ)))\n\t\tgoto abort;\n\n\t/* Read the register value. */\n\tif ((err = ops->read(map, val)))\n\t\tgoto abort;\n\nabort:\n\t/* Finish the transaction. */\n\tops->stop(map);\n\n\treturn err;\n}\n\nint\nregmap_i2c_write(const struct regmap *map, uint8_t reg, uint8_t val)\n{\n\tconst struct regmap_i2c_driver_ops *ops = regmap_i2c_ops_for(map);\n\tint err;\n\n\t/* Start a write transaction. */\n\tif ((err = ops->start(map, I2C_WRITE)))\n\t\tgoto abort;\n\n\t/* Write the register address. */\n\tif ((err = ops->write(map, reg)))\n\t\tgoto abort;\n\n\t/* Write the register value. */\n\tif ((err = ops->write(map, val)))\n\t\tgoto abort;\n\nabort:\n\t/* Finish the transaction. */\n\tops->stop(map);\n\n\treturn err;\n}\n"
  },
  {
    "path": "drivers/regmap/regmap-i2c.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef REGMAP_I2C_PRIVATE_H\n#define REGMAP_I2C_PRIVATE_H\n\n#include \"regmap.h\"\n\nenum {\n\tI2C_WRITE = 0,\n\tI2C_READ  = 1,\n};\n\nstruct regmap_i2c_driver_ops {\n\tint  (*read)(const struct regmap *map, uint8_t *data);\n\tint  (*start)(const struct regmap *map, uint8_t direction);\n\tvoid (*stop)(const struct regmap *map);\n\tint  (*write)(const struct regmap *map, uint8_t data);\n};\n\nstruct regmap_i2c_driver {\n\tstruct regmap_driver         drv;\n\tstruct regmap_i2c_driver_ops ops;\n};\n\nint regmap_i2c_prepare(const struct regmap *map);\n\nint regmap_i2c_read(const struct regmap *map, uint8_t reg, uint8_t *val);\n\nint regmap_i2c_write(const struct regmap *map, uint8_t reg, uint8_t val);\n\n#endif /* REGMAP_I2C_PRIVATE_H */\n"
  },
  {
    "path": "drivers/regmap/regmap.c",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <device.h>\n#include <error.h>\n#include <intrusive.h>\n#include <regmap.h>\n#include <stdint.h>\n\n#include \"regmap.h\"\n\n/**\n * Get the ops for the regmap device.\n */\nstatic inline const struct regmap_driver_ops *\nregmap_ops_for(const struct regmap *map)\n{\n\tconst struct regmap_driver *drv =\n\t\tcontainer_of(map->dev->drv, const struct regmap_driver, drv);\n\n\treturn &drv->ops;\n}\n\nint\nregmap_get(const struct regmap *map)\n{\n\tint err;\n\n\t/* Ensure the controller's driver is loaded. */\n\tif ((err = device_get(map->dev)))\n\t\treturn err;\n\n\tif ((err = regmap_ops_for(map)->prepare(map)))\n\t\tgoto err_put_device;\n\n\treturn SUCCESS;\n\nerr_put_device:\n\tdevice_put(map->dev);\n\n\treturn err;\n}\n\nvoid\nregmap_put(const struct regmap *map)\n{\n\tdevice_put(map->dev);\n}\n\nint\nregmap_read(const struct regmap *map, uint8_t reg, uint8_t *val)\n{\n\treturn regmap_ops_for(map)->read(map, reg, val);\n}\n\nint\nregmap_write(const struct regmap *map, uint8_t reg, uint8_t val)\n{\n\treturn regmap_ops_for(map)->write(map, reg, val);\n}\n\nint\nregmap_update_bits(const struct regmap *map, uint8_t reg, uint8_t mask,\n                   uint8_t val)\n{\n\tconst struct regmap_driver_ops *ops = regmap_ops_for(map);\n\tuint8_t tmp;\n\tint err;\n\n\tif ((err = ops->read(map, reg, &tmp)))\n\t\treturn err;\n\n\treturn ops->write(map, reg, tmp ^ ((val ^ tmp) & mask));\n}\n\nint\nregmap_device_probe(const struct device *dev)\n{\n\tconst struct regmap_device *self = to_regmap_device(dev);\n\n\treturn regmap_get(&self->map);\n}\n\nvoid\nregmap_device_release(const struct device *dev)\n{\n\tconst struct regmap_device *self = to_regmap_device(dev);\n\n\tregmap_put(&self->map);\n}\n\nstatic inline const struct device *\nregmap_to_device(const struct regmap *map)\n{\n\treturn &container_of(map, const struct regmap_device, map)->dev;\n}\n\nint\nregmap_user_probe(const struct regmap *map)\n{\n\treturn device_get(regmap_to_device(map));\n}\n\nvoid\nregmap_user_release(const struct regmap *map)\n{\n\tdevice_put(regmap_to_device(map));\n}\n"
  },
  {
    "path": "drivers/regmap/regmap.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef REGMAP_PRIVATE_H\n#define REGMAP_PRIVATE_H\n\n#include <device.h>\n#include <regmap.h>\n#include <stdint.h>\n\nstruct regmap_driver_ops {\n\tint (*prepare)(const struct regmap *map);\n\tint (*read)(const struct regmap *map, uint8_t reg, uint8_t *val);\n\tint (*write)(const struct regmap *map, uint8_t reg, uint8_t val);\n};\n\nstruct regmap_driver {\n\tstruct driver            drv;\n\tstruct regmap_driver_ops ops;\n};\n\n#endif /* REGMAP_PRIVATE_H */\n"
  },
  {
    "path": "drivers/regmap/sun6i-i2c.c",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <delay.h>\n#include <error.h>\n#include <mmio.h>\n#include <regmap.h>\n#include <stdint.h>\n#include <util.h>\n#include <clock/ccu.h>\n#include <gpio/sunxi-gpio.h>\n#include <regmap/sun6i-i2c.h>\n#include <platform/devices.h>\n\n#include \"regmap-i2c.h\"\n\n#define I2C_ADDR_REG  0x00\n#define I2C_XADDR_REG 0x04\n#define I2C_DATA_REG  0x08\n#define I2C_CTRL_REG  0x0c\n#define I2C_STAT_REG  0x10\n#define I2C_CCR_REG   0x14\n#define I2C_SRST_REG  0x18\n#define I2C_EFR_REG   0x1c\n#define I2C_LCR_REG   0x20\n\nenum {\n\tSTART_COND_TX        = 0x08,\n\tSTART_COND_TX_REPEAT = 0x10,\n\tADDR_WRITE_TX_ACK    = 0x18,\n\tADDR_WRITE_TX_NACK   = 0x20,\n\tDATA_TX_ACK          = 0x28,\n\tDATA_TX_NACK         = 0x30,\n\tADDR_READ_TX_ACK     = 0x40,\n\tADDR_READ_TX_NACK    = 0x48,\n\tDATA_RX_ACK          = 0x50,\n\tDATA_RX_NACK         = 0x58,\n\tIDLE                 = 0xf8,\n};\n\nstatic int\nsun6i_i2c_wait_idle(const struct simple_device *self)\n{\n\t/* With a single master on the bus, this should only take one cycle. */\n\tint timeout = 2;\n\n\twhile (mmio_read_32(self->regs + I2C_CTRL_REG) & (BIT(5) | BIT(4))) {\n\t\t/* 10μs is one 100kHz bus cycle. */\n\t\tudelay(10);\n\t\tif (timeout-- == 0)\n\t\t\treturn EIO;\n\t}\n\n\tif (mmio_read_32(self->regs + I2C_STAT_REG) != IDLE)\n\t\treturn EIO;\n\n\treturn SUCCESS;\n}\n\nstatic int\nsun6i_i2c_wait_start(const struct simple_device *self)\n{\n\t/* With a single master on the bus, this should only take one cycle. */\n\tint timeout = 2;\n\n\twhile (mmio_read_32(self->regs + I2C_CTRL_REG) & BIT(5)) {\n\t\t/* 10μs is one 100kHz bus cycle. */\n\t\tudelay(10);\n\t\tif (timeout-- == 0)\n\t\t\treturn EIO;\n\t}\n\n\treturn SUCCESS;\n}\n\nstatic int\nsun6i_i2c_wait_state(const struct simple_device *self, uint8_t state)\n{\n\t/* Wait for up to 8 transfer cycles, one ACK, and one extra cycle. */\n\tint timeout = 10;\n\n\twhile (!(mmio_read_32(self->regs + I2C_CTRL_REG) & BIT(3))) {\n\t\t/* 10μs is one 100kHz bus cycle. */\n\t\tudelay(10);\n\t\tif (timeout-- == 0)\n\t\t\treturn EIO;\n\t}\n\n\tif (mmio_read_32(self->regs + I2C_STAT_REG) != state)\n\t\treturn EIO;\n\n\treturn SUCCESS;\n}\n\nstatic int\nsun6i_i2c_read(const struct regmap *map, uint8_t *data)\n{\n\tconst struct simple_device *self = to_simple_device(map->dev);\n\tint err;\n\n\t/* Disable sending an ACK and trigger a state change. */\n\tmmio_clrset_32(self->regs + I2C_CTRL_REG, BIT(2), BIT(3));\n\n\t/* Wait for data to arrive. */\n\tif ((err = sun6i_i2c_wait_state(self, DATA_RX_NACK)))\n\t\treturn err;\n\n\t/* Read the data. */\n\t*data = mmio_read_32(self->regs + I2C_DATA_REG);\n\n\treturn SUCCESS;\n}\n\nstatic int\nsun6i_i2c_start(const struct regmap *map, uint8_t direction)\n{\n\tconst struct simple_device *self = to_simple_device(map->dev);\n\tuint8_t init_state = mmio_read_32(self->regs + I2C_STAT_REG);\n\tuint8_t state;\n\tint err;\n\n\t/* Send a start condition. */\n\tmmio_set_32(self->regs + I2C_CTRL_REG, BIT(5) | BIT(3));\n\n\t/* Wait for the start condition to be sent. */\n\tif ((err = sun6i_i2c_wait_start(self)))\n\t\treturn err;\n\n\t/* Wait for the start state if the bus was previously idle; otherwise,\n\t * wait for the repeated start state. */\n\tstate = init_state == IDLE ? START_COND_TX : START_COND_TX_REPEAT;\n\tif ((err = sun6i_i2c_wait_state(self, state)))\n\t\treturn err;\n\n\t/* Write the address and direction, then trigger a state change. */\n\tmmio_write_32(self->regs + I2C_DATA_REG, (map->id << 1) | direction);\n\tmmio_set_32(self->regs + I2C_CTRL_REG, BIT(3));\n\n\t/* Check for address acknowledgement. */\n\tstate = direction == I2C_WRITE ? ADDR_WRITE_TX_ACK : ADDR_READ_TX_ACK;\n\tif ((err = sun6i_i2c_wait_state(self, state)))\n\t\treturn err;\n\n\treturn SUCCESS;\n}\n\nstatic void\nsun6i_i2c_stop(const struct regmap *map)\n{\n\tconst struct simple_device *self = to_simple_device(map->dev);\n\n\t/* Send a stop condition. */\n\tmmio_set_32(self->regs + I2C_CTRL_REG, BIT(4) | BIT(3));\n\n\t/* Wait for the bus to go idle. */\n\tsun6i_i2c_wait_idle(self);\n}\n\nstatic int\nsun6i_i2c_write(const struct regmap *map, uint8_t data)\n{\n\tconst struct simple_device *self = to_simple_device(map->dev);\n\tint err;\n\n\t/* Write data, then trigger a state change. */\n\tmmio_write_32(self->regs + I2C_DATA_REG, data);\n\tmmio_set_32(self->regs + I2C_CTRL_REG, BIT(3));\n\n\t/* Wait for data to be sent. */\n\tif ((err = sun6i_i2c_wait_state(self, DATA_TX_ACK)))\n\t\treturn err;\n\n\treturn SUCCESS;\n}\n\nstatic int\nsun6i_i2c_probe(const struct device *dev)\n{\n\tconst struct simple_device *self = to_simple_device(dev);\n\tint err;\n\n\tif ((err = simple_device_probe(dev)))\n\t\treturn err;\n\n\t/* Set I2C bus clock divider for 400 KHz operation. */\n\tmmio_write_32(self->regs + I2C_CCR_REG, 0x00000011);\n\n\t/* Clear slave address (this driver only supports master mode). */\n\tmmio_write_32(self->regs + I2C_ADDR_REG, 0);\n\tmmio_write_32(self->regs + I2C_XADDR_REG, 0);\n\n\t/* Enable I2C bus and stop any current transaction. Disable interrupts\n\t * and don't send an ACK for received bytes. */\n\tmmio_write_32(self->regs + I2C_CTRL_REG, BIT(6) | BIT(4));\n\n\t/* Soft reset the controller. */\n\tmmio_set_32(self->regs + I2C_SRST_REG, BIT(0));\n\n\t/* Wait for the bus to go idle. */\n\tif ((err = sun6i_i2c_wait_idle(self)))\n\t\tgoto err_release;\n\n\treturn SUCCESS;\n\nerr_release:\n\tsimple_device_release(dev);\n\n\treturn err;\n}\n\nstatic const struct regmap_i2c_driver sun6i_i2c_driver = {\n\t.drv = {\n\t\t.drv = {\n\t\t\t.probe   = sun6i_i2c_probe,\n\t\t\t.release = simple_device_release,\n\t\t},\n\t\t.ops = {\n\t\t\t.prepare = regmap_i2c_prepare,\n\t\t\t.read    = regmap_i2c_read,\n\t\t\t.write   = regmap_i2c_write,\n\t\t},\n\t},\n\t.ops = {\n\t\t.read  = sun6i_i2c_read,\n\t\t.start = sun6i_i2c_start,\n\t\t.stop  = sun6i_i2c_stop,\n\t\t.write = sun6i_i2c_write,\n\t},\n};\n\nconst struct simple_device r_i2c = {\n\t.dev = {\n\t\t.name  = \"r_i2c\",\n\t\t.drv   = &sun6i_i2c_driver.drv.drv,\n\t\t.state = DEVICE_STATE_INIT,\n\t},\n\t.clock = { .dev = &r_ccu.dev, .id = CLK_BUS_R_I2C },\n#if CONFIG(I2C_PINS_PL0_PL1)\n\t.pins = SIMPLE_DEVICE_PINS_INIT {\n\t\t{\n\t\t\t.dev   = &r_pio.dev,\n\t\t\t.id    = SUNXI_GPIO_PIN(0, 0),\n\t\t\t.drive = DRIVE_10mA,\n\t\t\t.mode  = CONFIG_I2C_PIN_MODE_PL0_PL1,\n\t\t\t.pull  = PULL_UP,\n\t\t},\n\t\t{\n\t\t\t.dev   = &r_pio.dev,\n\t\t\t.id    = SUNXI_GPIO_PIN(0, 1),\n\t\t\t.drive = DRIVE_10mA,\n\t\t\t.mode  = CONFIG_I2C_PIN_MODE_PL0_PL1,\n\t\t\t.pull  = PULL_UP,\n\t\t},\n\t},\n#elif CONFIG(I2C_PINS_PL8_PL9)\n\t.pins = SIMPLE_DEVICE_PINS_INIT {\n\t\t{\n\t\t\t.dev   = &r_pio.dev,\n\t\t\t.id    = SUNXI_GPIO_PIN(0, 8),\n\t\t\t.drive = DRIVE_10mA,\n\t\t\t.mode  = 2,\n\t\t\t.pull  = PULL_UP,\n\t\t},\n\t\t{\n\t\t\t.dev   = &r_pio.dev,\n\t\t\t.id    = SUNXI_GPIO_PIN(0, 9),\n\t\t\t.drive = DRIVE_10mA,\n\t\t\t.mode  = 2,\n\t\t\t.pull  = PULL_UP,\n\t\t},\n\t},\n#endif\n\t.regs = DEV_R_I2C,\n};\n"
  },
  {
    "path": "drivers/regmap/sunxi-rsb.c",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <error.h>\n#include <mmio.h>\n#include <util.h>\n#include <clock/ccu.h>\n#include <gpio/sunxi-gpio.h>\n#include <regmap/sunxi-rsb.h>\n#include <platform/devices.h>\n\n#include \"regmap.h\"\n\n#define RSB_CTRL_REG   0x00\n#define RSB_CCR_REG    0x04\n#define RSB_INT_EN_REG 0x08\n#define RSB_STAT_REG   0x0c\n#define RSB_ADDR_REG   0x10\n#define RSB_DLEN_REG   0x18\n#define RSB_DATA_REG   0x1c\n#define RSB_LCR_REG    0x24\n#define RSB_PMCR_REG   0x28\n#define RSB_CMD_REG    0x2c\n#define RSB_SADDR_REG  0x30\n\n#define I2C_BCAST_ADDR 0\n\n#define PMIC_MODE_REG  0x3e\n#define PMIC_MODE_VAL  0x7c\n\nenum {\n\tRSB_SRTA = 0xe8,\n\tRSB_RD8  = 0x8b,\n\tRSB_RD16 = 0x9c,\n\tRSB_RD32 = 0xa6,\n\tRSB_WR8  = 0x4e,\n\tRSB_WR16 = 0x59,\n\tRSB_WR32 = 0x63,\n};\n\nstatic int\nsunxi_rsb_do_command(const struct regmap *map, uint32_t cmd)\n{\n\tconst struct simple_device *self = to_simple_device(map->dev);\n\n\tmmio_write_32(self->regs + RSB_CMD_REG, cmd);\n\tmmio_write_32(self->regs + RSB_SADDR_REG, map->id);\n\tmmio_write_32(self->regs + RSB_CTRL_REG, BIT(7));\n\n\tmmio_pollz_32(self->regs + RSB_CTRL_REG, BIT(7));\n\n\treturn mmio_read_32(self->regs + RSB_STAT_REG) == BIT(0)\n\t       ? SUCCESS : EIO;\n}\n\nstatic int\nsunxi_rsb_prepare(const struct regmap *map)\n{\n\t/* Set the device's runtime address. */\n\treturn sunxi_rsb_do_command(map, RSB_SRTA);\n}\n\nstatic int\nsunxi_rsb_read(const struct regmap *map, uint8_t addr, uint8_t *data)\n{\n\tconst struct simple_device *self = to_simple_device(map->dev);\n\tint err;\n\n\tmmio_write_32(self->regs + RSB_ADDR_REG, addr);\n\n\tif ((err = sunxi_rsb_do_command(map, RSB_RD8)))\n\t\treturn err;\n\n\t*data = mmio_read_32(self->regs + RSB_DATA_REG);\n\n\treturn SUCCESS;\n}\n\nstatic int\nsunxi_rsb_write(const struct regmap *map, uint8_t addr, uint8_t data)\n{\n\tconst struct simple_device *self = to_simple_device(map->dev);\n\n\tmmio_write_32(self->regs + RSB_ADDR_REG, addr);\n\tmmio_write_32(self->regs + RSB_DATA_REG, data);\n\n\treturn sunxi_rsb_do_command(map, RSB_WR8);\n}\n\nstatic void\nsunxi_rsb_set_rate(const struct simple_device *self, uint32_t rate)\n{\n\tuint32_t divider = (clock_get_rate(&self->clock) + rate) / (2 * rate);\n\n\tif (divider > 0)\n\t\tdivider = divider - 1;\n\tif (divider > 0xff)\n\t\tdivider = 0xff;\n\n\tmmio_write_32(self->regs + RSB_CCR_REG, 1U << 8 | divider);\n}\n\nstatic int\nsunxi_rsb_probe(const struct device *dev)\n{\n\tconst struct simple_device *self = to_simple_device(dev);\n\tint err;\n\n\tif ((err = simple_device_probe(dev)))\n\t\treturn err;\n\n\t/* Soft-reset the controller. */\n\tmmio_write_32(self->regs + RSB_CTRL_REG, BIT(0));\n\tmmio_pollz_32(self->regs + RSB_CTRL_REG, BIT(0));\n\n\t/* Set the bus clock rate to its default value (3 MHz). */\n\tsunxi_rsb_set_rate(self, 3000000);\n\n\t/* Switch all devices to RSB mode. */\n\tmmio_write_32(self->regs + RSB_PMCR_REG, I2C_BCAST_ADDR |\n\t              PMIC_MODE_REG << 8 | PMIC_MODE_VAL << 16 | BIT(31));\n\tmmio_pollz_32(self->regs + RSB_PMCR_REG, BIT(31));\n\n\treturn SUCCESS;\n}\n\nstatic const struct regmap_driver sunxi_rsb_driver = {\n\t.drv = {\n\t\t.probe   = sunxi_rsb_probe,\n\t\t.release = simple_device_release,\n\t},\n\t.ops = {\n\t\t.prepare = sunxi_rsb_prepare,\n\t\t.read    = sunxi_rsb_read,\n\t\t.write   = sunxi_rsb_write,\n\t},\n};\n\nconst struct simple_device r_rsb = {\n\t.dev = {\n\t\t.name  = \"r_rsb\",\n\t\t.drv   = &sunxi_rsb_driver.drv,\n\t\t.state = DEVICE_STATE_INIT,\n\t},\n\t.clock = { .dev = &r_ccu.dev, .id = CLK_BUS_R_RSB },\n\t.pins  = SIMPLE_DEVICE_PINS_INIT {\n\t\t{\n\t\t\t.dev   = &r_pio.dev,\n\t\t\t.id    = SUNXI_GPIO_PIN(0, 0),\n\t\t\t.drive = DRIVE_30mA,\n\t\t\t.mode  = 2,\n\t\t\t.pull  = PULL_UP,\n\t\t},\n\t\t{\n\t\t\t.dev   = &r_pio.dev,\n\t\t\t.id    = SUNXI_GPIO_PIN(0, 1),\n\t\t\t.drive = DRIVE_30mA,\n\t\t\t.mode  = 2,\n\t\t\t.pull  = PULL_UP,\n\t\t},\n\t},\n\t.regs = DEV_R_RSB,\n};\n"
  },
  {
    "path": "drivers/regulator/Kconfig",
    "content": "#\n# Copyright © 2017-2022 The Crust Firmware Authors.\n# SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n#\n\nmenu \"Regulators (voltage/current)\"\n\nconfig REGULATOR_AXP221\n\tbool\n\tdefault MFD_AXP223\n\nconfig REGULATOR_AXP803\n\tbool\n\tdefault MFD_AXP803\n\nconfig REGULATOR_AXP805\n\tbool\n\tdefault MFD_AXP805\n\nconfig REGULATOR_GPIO\n\tbool\n\nmenuconfig REGULATOR_GPIO_CPU\n\tbool \"GPIO-controlled CPU power supply\"\n\tselect REGULATOR_GPIO\n\thelp\n\t\tSelect this option if your board supplies power to the\n\t\tCPU (VDD-CPUX) via a GPIO-controlled voltage regulator.\n\n\t\tThis regulator will be disabled during both the suspend\n\t\tand shutdown procedures.\n\n\t\tNote: This GPIO pin must NOT also control VDD-SYS.\n\t\tVDD-SYS must remain powered while the system is asleep.\n\nif REGULATOR_GPIO_CPU\n\nconfig REGULATOR_GPIO_CPU_PIN\n\tint \"GPIO pin (port L)\"\n\tdefault 8\n\trange 0 31\n\thelp\n\t\tSelect the GPIO pin used to control the CPU supply.\n\nendif\n\nmenuconfig REGULATOR_GPIO_DRAM\n\tbool \"GPIO-controlled DRAM power supply\"\n\tselect REGULATOR_GPIO\n\thelp\n\t\tSelect this option if your board supplies power to the\n\t\tDRAM (VCC-DRAM) via a GPIO-controlled voltage regulator.\n\n\t\tThis regulator will be disabled during the shutdown\n\t\tprocedure.\n\nif REGULATOR_GPIO_DRAM\n\nconfig REGULATOR_GPIO_DRAM_PIN\n\tint \"GPIO pin (port L)\"\n\tdefault 9\n\trange 0 31\n\thelp\n\t\tSelect the GPIO pin used to control the DRAM supply.\n\nendif\n\nmenuconfig REGULATOR_GPIO_VCC_PLL\n\tbool \"GPIO-controlled VCC-PLL power supply\"\n\tselect REGULATOR_GPIO\n\thelp\n\t\tSelect this option if your board supplies power to the\n\t\tPLLs (VCC-PLL) via a GPIO-controlled voltage regulator.\n\n\t\tThis regulator will be disabled during the shutdown\n\t\tprocedure.\n\nif REGULATOR_GPIO_VCC_PLL\n\nconfig REGULATOR_GPIO_VCC_PLL_PIN\n\tint \"GPIO pin (port L)\"\n\tdefault 0\n\trange 0 31\n\thelp\n\t\tSelect the GPIO pin used to control the VCC-PLL supply.\n\nendif\n\nmenuconfig REGULATOR_GPIO_VDD_SYS\n\tbool \"GPIO-controlled VDD-SYS power supply\"\n\tselect REGULATOR_GPIO\n\thelp\n\t\tSelect this option if your board supplies power to the\n\t\tSoC (VDD-SYS) via a GPIO-controlled voltage regulator.\n\n\t\tThis regulator will be disabled during the shutdown\n\t\tprocedure.\n\nif REGULATOR_GPIO_VDD_SYS\n\nconfig REGULATOR_GPIO_VDD_SYS_PIN\n\tint \"GPIO pin (port L)\"\n\tdefault 8\n\trange 0 31\n\thelp\n\t\tSelect the GPIO pin used to control the VDD-SYS supply.\n\nendif\n\nconfig REGULATOR_SY8106A\n\tbool \"Silergy SY8106A voltage regulator\"\n\tdepends on I2C\n\nendmenu\n"
  },
  {
    "path": "drivers/regulator/Makefile",
    "content": "#\n# Copyright © 2017-2022 The Crust Firmware Authors.\n# SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n#\n\nobj-y += regulator.o\n\nobj-$(CONFIG_REGULATOR_AXP221)  += axp20x.o axp221.o\nobj-$(CONFIG_REGULATOR_AXP803)  += axp20x.o axp803.o\nobj-$(CONFIG_REGULATOR_AXP805)  += axp20x.o axp805.o\nobj-$(CONFIG_REGULATOR_GPIO)    += gpio.o\nobj-$(CONFIG_REGULATOR_SY8106A) += sy8106a.o\n"
  },
  {
    "path": "drivers/regulator/axp20x.c",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <error.h>\n#include <regmap.h>\n\n#include \"axp20x.h\"\n\nstatic int\naxp20x_regulator_get_state(const struct regulator_handle *handle,\n                           bool *enabled)\n{\n\tconst struct axp20x_regulator *self = to_axp20x_regulator(handle->dev);\n\tuint8_t addr = self->info[handle->id].enable_register;\n\tuint8_t mask = self->info[handle->id].enable_mask;\n\tuint8_t val;\n\tint err;\n\n\tif ((err = regmap_read(self->map, addr, &val)))\n\t\treturn err;\n\n\t*enabled = (val & mask);\n\n\treturn SUCCESS;\n}\n\nstatic int\naxp20x_regulator_set_state(const struct regulator_handle *handle, bool enabled)\n{\n\tconst struct axp20x_regulator *self = to_axp20x_regulator(handle->dev);\n\tuint8_t addr = self->info[handle->id].enable_register;\n\tuint8_t mask = self->info[handle->id].enable_mask;\n\n\treturn regmap_update_bits(self->map, addr, mask, enabled ? mask : 0);\n}\n\nstatic int\naxp20x_regulator_probe(const struct device *dev)\n{\n\tconst struct axp20x_regulator *self = to_axp20x_regulator(dev);\n\n\treturn regmap_user_probe(self->map);\n}\n\nstatic void\naxp20x_regulator_release(const struct device *dev)\n{\n\tconst struct axp20x_regulator *self = to_axp20x_regulator(dev);\n\n\tregmap_user_release(self->map);\n}\n\nconst struct regulator_driver axp20x_regulator_driver = {\n\t.drv = {\n\t\t.probe   = axp20x_regulator_probe,\n\t\t.release = axp20x_regulator_release,\n\t},\n\t.ops = {\n\t\t.get_state = axp20x_regulator_get_state,\n\t\t.set_state = axp20x_regulator_set_state,\n\t},\n};\n"
  },
  {
    "path": "drivers/regulator/axp20x.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef AXP20X_PRIVATE_H\n#define AXP20X_PRIVATE_H\n\n#include <intrusive.h>\n#include <stdint.h>\n#include <regulator/axp20x.h>\n\n#include \"regulator.h\"\n\nstruct axp20x_regulator_info {\n\tuint8_t enable_register;\n\tuint8_t enable_mask;\n};\n\nextern const struct regulator_driver axp20x_regulator_driver;\n\nstatic inline const struct axp20x_regulator *\nto_axp20x_regulator(const struct device *dev)\n{\n\treturn container_of(dev, const struct axp20x_regulator, dev);\n}\n\n#endif /* AXP20X_PRIVATE_H */\n"
  },
  {
    "path": "drivers/regulator/axp221.c",
    "content": "/*\n * Copyright © 2023 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <util.h>\n#include <mfd/axp20x.h>\n#include <regulator/axp20x.h>\n#include <regulator/axp221.h>\n\n#include \"axp20x.h\"\n\n#define OUTPUT_POWER_CONTROL1 0x10\n#define OUTPUT_POWER_CONTROL2 0x12\n#define OUTPUT_POWER_CONTROL3 0x13\n\nstatic const struct axp20x_regulator_info axp221_regulators[] = {\n\t[AXP221_REGL_DC5LDO] = {\n\t\t.enable_register = OUTPUT_POWER_CONTROL1,\n\t\t.enable_mask     = BIT(0),\n\t},\n\t[AXP221_REGL_DCDC1] = {\n\t\t.enable_register = OUTPUT_POWER_CONTROL1,\n\t\t.enable_mask     = BIT(1),\n\t},\n\t[AXP221_REGL_DCDC2] = {\n\t\t.enable_register = OUTPUT_POWER_CONTROL1,\n\t\t.enable_mask     = BIT(2),\n\t},\n\t[AXP221_REGL_DCDC3] = {\n\t\t.enable_register = OUTPUT_POWER_CONTROL1,\n\t\t.enable_mask     = BIT(3),\n\t},\n\t[AXP221_REGL_DCDC4] = {\n\t\t.enable_register = OUTPUT_POWER_CONTROL1,\n\t\t.enable_mask     = BIT(4),\n\t},\n\t[AXP221_REGL_DCDC5] = {\n\t\t.enable_register = OUTPUT_POWER_CONTROL1,\n\t\t.enable_mask     = BIT(5),\n\t},\n\t[AXP221_REGL_ALDO1] = {\n\t\t.enable_register = OUTPUT_POWER_CONTROL1,\n\t\t.enable_mask     = BIT(6),\n\t},\n\t[AXP221_REGL_ALDO2] = {\n\t\t.enable_register = OUTPUT_POWER_CONTROL1,\n\t\t.enable_mask     = BIT(7),\n\t},\n\t[AXP221_REGL_ALDO3] = {\n\t\t.enable_register = OUTPUT_POWER_CONTROL3,\n\t\t.enable_mask     = BIT(7),\n\t},\n\t[AXP221_REGL_DLDO1] = {\n\t\t.enable_register = OUTPUT_POWER_CONTROL2,\n\t\t.enable_mask     = BIT(3),\n\t},\n\t[AXP221_REGL_DLDO2] = {\n\t\t.enable_register = OUTPUT_POWER_CONTROL2,\n\t\t.enable_mask     = BIT(4),\n\t},\n\t[AXP221_REGL_DLDO3] = {\n\t\t.enable_register = OUTPUT_POWER_CONTROL2,\n\t\t.enable_mask     = BIT(5),\n\t},\n\t[AXP221_REGL_DLDO4] = {\n\t\t.enable_register = OUTPUT_POWER_CONTROL2,\n\t\t.enable_mask     = BIT(6),\n\t},\n\t[AXP221_REGL_ELDO1] = {\n\t\t.enable_register = OUTPUT_POWER_CONTROL2,\n\t\t.enable_mask     = BIT(0),\n\t},\n\t[AXP221_REGL_ELDO2] = {\n\t\t.enable_register = OUTPUT_POWER_CONTROL2,\n\t\t.enable_mask     = BIT(1),\n\t},\n\t[AXP221_REGL_ELDO3] = {\n\t\t.enable_register = OUTPUT_POWER_CONTROL2,\n\t\t.enable_mask     = BIT(2),\n\t},\n\t[AXP221_REGL_DC1SW] = {\n\t\t.enable_register = OUTPUT_POWER_CONTROL2,\n\t\t.enable_mask     = BIT(7),\n\t},\n};\n\nconst struct axp20x_regulator axp221_regulator = {\n\t.dev = {\n\t\t.name  = \"axp221-regulator\",\n\t\t.drv   = &axp20x_regulator_driver.drv,\n\t\t.state = DEVICE_STATE_INIT,\n\t},\n\t.map  = &axp20x.map,\n\t.info = axp221_regulators,\n};\n"
  },
  {
    "path": "drivers/regulator/axp803.c",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <util.h>\n#include <mfd/axp20x.h>\n#include <regulator/axp20x.h>\n#include <regulator/axp803.h>\n\n#include \"axp20x.h\"\n\n#define OUTPUT_POWER_CONTROL1 0x10\n#define OUTPUT_POWER_CONTROL2 0x12\n#define OUTPUT_POWER_CONTROL3 0x13\n\nstatic const struct axp20x_regulator_info axp803_regulators[] = {\n\t[AXP803_REGL_DCDC1] = {\n\t\t.enable_register = OUTPUT_POWER_CONTROL1,\n\t\t.enable_mask     = BIT(0),\n\t},\n\t[AXP803_REGL_DCDC2] = {\n\t\t.enable_register = OUTPUT_POWER_CONTROL1,\n\t\t.enable_mask     = BIT(1),\n\t},\n\t[AXP803_REGL_DCDC3] = {\n\t\t.enable_register = OUTPUT_POWER_CONTROL1,\n\t\t.enable_mask     = BIT(2),\n\t},\n\t[AXP803_REGL_DCDC4] = {\n\t\t.enable_register = OUTPUT_POWER_CONTROL1,\n\t\t.enable_mask     = BIT(3),\n\t},\n\t[AXP803_REGL_DCDC5] = {\n\t\t.enable_register = OUTPUT_POWER_CONTROL1,\n\t\t.enable_mask     = BIT(4),\n\t},\n\t[AXP803_REGL_DCDC6] = {\n\t\t.enable_register = OUTPUT_POWER_CONTROL1,\n\t\t.enable_mask     = BIT(5),\n\t},\n\t[AXP803_REGL_DC1SW] = {\n\t\t.enable_register = OUTPUT_POWER_CONTROL2,\n\t\t.enable_mask     = BIT(7),\n\t},\n\t[AXP803_REGL_ALDO1] = {\n\t\t.enable_register = OUTPUT_POWER_CONTROL3,\n\t\t.enable_mask     = BIT(5),\n\t},\n\t[AXP803_REGL_ALDO2] = {\n\t\t.enable_register = OUTPUT_POWER_CONTROL3,\n\t\t.enable_mask     = BIT(6),\n\t},\n\t[AXP803_REGL_ALDO3] = {\n\t\t.enable_register = OUTPUT_POWER_CONTROL3,\n\t\t.enable_mask     = BIT(7),\n\t},\n\t[AXP803_REGL_DLDO1] = {\n\t\t.enable_register = OUTPUT_POWER_CONTROL2,\n\t\t.enable_mask     = BIT(3),\n\t},\n\t[AXP803_REGL_DLDO2] = {\n\t\t.enable_register = OUTPUT_POWER_CONTROL2,\n\t\t.enable_mask     = BIT(4),\n\t},\n\t[AXP803_REGL_DLDO3] = {\n\t\t.enable_register = OUTPUT_POWER_CONTROL2,\n\t\t.enable_mask     = BIT(5),\n\t},\n\t[AXP803_REGL_DLDO4] = {\n\t\t.enable_register = OUTPUT_POWER_CONTROL2,\n\t\t.enable_mask     = BIT(6),\n\t},\n\t[AXP803_REGL_ELDO1] = {\n\t\t.enable_register = OUTPUT_POWER_CONTROL2,\n\t\t.enable_mask     = BIT(0),\n\t},\n\t[AXP803_REGL_ELDO2] = {\n\t\t.enable_register = OUTPUT_POWER_CONTROL2,\n\t\t.enable_mask     = BIT(1),\n\t},\n\t[AXP803_REGL_ELDO3] = {\n\t\t.enable_register = OUTPUT_POWER_CONTROL2,\n\t\t.enable_mask     = BIT(2),\n\t},\n\t[AXP803_REGL_FLDO1] = {\n\t\t.enable_register = OUTPUT_POWER_CONTROL3,\n\t\t.enable_mask     = BIT(2),\n\t},\n\t[AXP803_REGL_FLDO2] = {\n\t\t.enable_register = OUTPUT_POWER_CONTROL3,\n\t\t.enable_mask     = BIT(3),\n\t},\n};\n\nconst struct axp20x_regulator axp803_regulator = {\n\t.dev = {\n\t\t.name  = \"axp803-regulator\",\n\t\t.drv   = &axp20x_regulator_driver.drv,\n\t\t.state = DEVICE_STATE_INIT,\n\t},\n\t.map  = &axp20x.map,\n\t.info = axp803_regulators,\n};\n"
  },
  {
    "path": "drivers/regulator/axp805.c",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <util.h>\n#include <mfd/axp20x.h>\n#include <regulator/axp20x.h>\n#include <regulator/axp805.h>\n\n#include \"axp20x.h\"\n\n#define POWER_ONOFF_CTRL_REG1 0x10\n#define POWER_ONOFF_CTRL_REG2 0x11\n\nstatic const struct axp20x_regulator_info axp805_regulators[] = {\n\t[AXP805_REGL_DCDCA] = {\n\t\t.enable_register = POWER_ONOFF_CTRL_REG1,\n\t\t.enable_mask     = BIT(0),\n\t},\n\t[AXP805_REGL_DCDCB] = {\n\t\t.enable_register = POWER_ONOFF_CTRL_REG1,\n\t\t.enable_mask     = BIT(1),\n\t},\n\t[AXP805_REGL_DCDCC] = {\n\t\t.enable_register = POWER_ONOFF_CTRL_REG1,\n\t\t.enable_mask     = BIT(2),\n\t},\n\t[AXP805_REGL_DCDCD] = {\n\t\t.enable_register = POWER_ONOFF_CTRL_REG1,\n\t\t.enable_mask     = BIT(3),\n\t},\n\t[AXP805_REGL_DCDCE] = {\n\t\t.enable_register = POWER_ONOFF_CTRL_REG1,\n\t\t.enable_mask     = BIT(4),\n\t},\n\t[AXP805_REGL_ALDO1] = {\n\t\t.enable_register = POWER_ONOFF_CTRL_REG1,\n\t\t.enable_mask     = BIT(5),\n\t},\n\t[AXP805_REGL_ALDO2] = {\n\t\t.enable_register = POWER_ONOFF_CTRL_REG1,\n\t\t.enable_mask     = BIT(6),\n\t},\n\t[AXP805_REGL_ALDO3] = {\n\t\t.enable_register = POWER_ONOFF_CTRL_REG1,\n\t\t.enable_mask     = BIT(7),\n\t},\n\t[AXP805_REGL_BLDO1] = {\n\t\t.enable_register = POWER_ONOFF_CTRL_REG2,\n\t\t.enable_mask     = BIT(0),\n\t},\n\t[AXP805_REGL_BLDO2] = {\n\t\t.enable_register = POWER_ONOFF_CTRL_REG2,\n\t\t.enable_mask     = BIT(1),\n\t},\n\t[AXP805_REGL_BLDO3] = {\n\t\t.enable_register = POWER_ONOFF_CTRL_REG2,\n\t\t.enable_mask     = BIT(2),\n\t},\n\t[AXP805_REGL_BLDO4] = {\n\t\t.enable_register = POWER_ONOFF_CTRL_REG2,\n\t\t.enable_mask     = BIT(3),\n\t},\n\t[AXP805_REGL_CLDO1] = {\n\t\t.enable_register = POWER_ONOFF_CTRL_REG2,\n\t\t.enable_mask     = BIT(4),\n\t},\n\t[AXP805_REGL_CLDO2] = {\n\t\t.enable_register = POWER_ONOFF_CTRL_REG2,\n\t\t.enable_mask     = BIT(5),\n\t},\n\t[AXP805_REGL_CLDO3] = {\n\t\t.enable_register = POWER_ONOFF_CTRL_REG2,\n\t\t.enable_mask     = BIT(6),\n\t},\n\t[AXP805_REGL_DCSW] = {\n\t\t.enable_register = POWER_ONOFF_CTRL_REG2,\n\t\t.enable_mask     = BIT(7),\n\t},\n};\n\nconst struct axp20x_regulator axp805_regulator = {\n\t.dev = {\n\t\t.name  = \"axp805-regulator\",\n\t\t.drv   = &axp20x_regulator_driver.drv,\n\t\t.state = DEVICE_STATE_INIT,\n\t},\n\t.map  = &axp20x.map,\n\t.info = axp805_regulators,\n};\n"
  },
  {
    "path": "drivers/regulator/gpio.c",
    "content": "/*\n * Copyright © 2020-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <gpio/sunxi-gpio.h>\n#include <regulator/gpio.h>\n\n#include \"regulator.h\"\n\nstatic inline const struct gpio_regulator *\nto_gpio_regulator(const struct device *dev)\n{\n\treturn container_of(dev, const struct gpio_regulator, dev);\n}\n\nstatic int\ngpio_regulator_get_state(const struct regulator_handle *handle, bool *enabled)\n{\n\tconst struct gpio_regulator *self = to_gpio_regulator(handle->dev);\n\n\treturn gpio_get_value(&self->pin, enabled);\n}\n\nstatic int\ngpio_regulator_set_state(const struct regulator_handle *handle, bool enabled)\n{\n\tconst struct gpio_regulator *self = to_gpio_regulator(handle->dev);\n\n\treturn gpio_set_value(&self->pin, enabled);\n}\n\nstatic int\ngpio_regulator_probe(const struct device *dev)\n{\n\tconst struct gpio_regulator *self = to_gpio_regulator(dev);\n\n\treturn gpio_get(&self->pin);\n}\n\nstatic void\ngpio_regulator_release(const struct device *dev)\n{\n\tconst struct gpio_regulator *self = to_gpio_regulator(dev);\n\n\tgpio_put(&self->pin);\n}\n\nstatic const struct regulator_driver gpio_regulator_driver = {\n\t.drv = {\n\t\t.probe   = gpio_regulator_probe,\n\t\t.release = gpio_regulator_release,\n\t},\n\t.ops = {\n\t\t.get_state = gpio_regulator_get_state,\n\t\t.set_state = gpio_regulator_set_state,\n\t},\n};\n\n#if CONFIG(REGULATOR_GPIO_CPU)\nconst struct gpio_regulator gpio_cpu_regulator = {\n\t.dev = {\n\t\t.name  = \"vdd-cpux\",\n\t\t.drv   = &gpio_regulator_driver.drv,\n\t\t.state = DEVICE_STATE_INIT,\n\t},\n\t.pin = {\n\t\t.dev   = &r_pio.dev,\n\t\t.id    = CONFIG_REGULATOR_GPIO_CPU_PIN,\n\t\t.drive = DRIVE_10mA,\n\t\t.mode  = MODE_OUTPUT,\n\t\t.pull  = PULL_NONE,\n\t},\n};\n#endif\n\n#if CONFIG(REGULATOR_GPIO_DRAM)\nconst struct gpio_regulator gpio_dram_regulator = {\n\t.dev = {\n\t\t.name  = \"vcc-dram\",\n\t\t.drv   = &gpio_regulator_driver.drv,\n\t\t.state = DEVICE_STATE_INIT,\n\t},\n\t.pin = {\n\t\t.dev   = &r_pio.dev,\n\t\t.id    = CONFIG_REGULATOR_GPIO_DRAM_PIN,\n\t\t.drive = DRIVE_10mA,\n\t\t.mode  = MODE_OUTPUT,\n\t\t.pull  = PULL_NONE,\n\t},\n};\n#endif\n\n#if CONFIG(REGULATOR_GPIO_VCC_PLL)\nconst struct gpio_regulator gpio_vcc_pll_regulator = {\n\t.dev = {\n\t\t.name  = \"vcc-pll\",\n\t\t.drv   = &gpio_regulator_driver.drv,\n\t\t.state = DEVICE_STATE_INIT,\n\t},\n\t.pin = {\n\t\t.dev   = &r_pio.dev,\n\t\t.id    = CONFIG_REGULATOR_GPIO_VCC_PLL_PIN,\n\t\t.drive = DRIVE_10mA,\n\t\t.mode  = MODE_OUTPUT,\n\t\t.pull  = PULL_NONE,\n\t},\n};\n#endif\n\n#if CONFIG(REGULATOR_GPIO_VDD_SYS)\nconst struct gpio_regulator gpio_vdd_sys_regulator = {\n\t.dev = {\n\t\t.name  = \"vdd-sys\",\n\t\t.drv   = &gpio_regulator_driver.drv,\n\t\t.state = DEVICE_STATE_INIT,\n\t},\n\t.pin = {\n\t\t.dev   = &r_pio.dev,\n\t\t.id    = CONFIG_REGULATOR_GPIO_VDD_SYS_PIN,\n\t\t.drive = DRIVE_10mA,\n\t\t.mode  = MODE_OUTPUT,\n\t\t.pull  = PULL_NONE,\n\t},\n};\n#endif\n"
  },
  {
    "path": "drivers/regulator/regulator.c",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <device.h>\n#include <error.h>\n#include <intrusive.h>\n#include <regulator.h>\n#include <stdbool.h>\n#include <stdint.h>\n\n#include \"regulator.h\"\n\n/**\n * Get the ops for the regulator controller device.\n */\nstatic inline const struct regulator_driver_ops *\nregulator_ops_for(const struct device *dev)\n{\n\tconst struct regulator_driver *drv =\n\t\tcontainer_of(dev->drv, const struct regulator_driver, drv);\n\n\treturn &drv->ops;\n}\n\nstatic int\nregulator_set_state(const struct regulator_handle *handle, bool enable)\n{\n\tint err;\n\n\tif ((err = device_get(handle->dev)))\n\t\treturn err;\n\n\terr = regulator_ops_for(handle->dev)->set_state(handle, enable);\n\n\tdevice_put(handle->dev);\n\n\treturn err;\n}\n\nint\nregulator_disable(const struct regulator_handle *handle)\n{\n\treturn regulator_set_state(handle, false);\n}\n\nint\nregulator_enable(const struct regulator_handle *handle)\n{\n\treturn regulator_set_state(handle, true);\n}\n\nint\nregulator_get_state(const struct regulator_handle *handle, bool *enabled)\n{\n\tint err;\n\n\tif ((err = device_get(handle->dev)))\n\t\treturn err;\n\n\terr = regulator_ops_for(handle->dev)->get_state(handle, enabled);\n\n\tdevice_put(handle->dev);\n\n\treturn err;\n}\n"
  },
  {
    "path": "drivers/regulator/regulator.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef REGULATOR_PRIVATE_H\n#define REGULATOR_PRIVATE_H\n\n#include <device.h>\n#include <stdbool.h>\n#include <stdint.h>\n\nstruct regulator_driver_ops {\n\tint (*get_state)(const struct regulator_handle *handle, bool *enabled);\n\tint (*set_state)(const struct regulator_handle *handle, bool enable);\n};\n\nstruct regulator_driver {\n\tstruct driver               drv;\n\tstruct regulator_driver_ops ops;\n};\n\n#endif /* REGULATOR_PRIVATE_H */\n"
  },
  {
    "path": "drivers/regulator/sy8106a.c",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <error.h>\n#include <regmap.h>\n#include <regulator.h>\n#include <util.h>\n#include <regmap/sun6i-i2c.h>\n#include <regulator/sy8106a.h>\n\n#include \"regulator.h\"\n\n#define VOUT_SEL_REG   0x01\n#define VOUT_COM_REG   0x02\n#define SYS_STATUS_REG 0x06\n\nstatic int\nsy8106a_get_state(const struct regulator_handle *handle, bool *enabled)\n{\n\tconst struct regmap_device *self = to_regmap_device(handle->dev);\n\tuint8_t val;\n\tint err;\n\n\tif ((err = regmap_read(&self->map, VOUT_COM_REG, &val)))\n\t\treturn err;\n\n\t*enabled = !(val & BIT(0));\n\n\treturn SUCCESS;\n}\n\nstatic int\nsy8106a_set_state(const struct regulator_handle *handle, bool enabled)\n{\n\tconst struct regmap_device *self = to_regmap_device(handle->dev);\n\tint err;\n\n\tif ((err = regmap_update_bits(&self->map, VOUT_COM_REG,\n\t                              BIT(0), !enabled)))\n\t\treturn err;\n\n\treturn SUCCESS;\n}\n\nstatic const struct regulator_driver sy8106a_driver = {\n\t.drv = {\n\t\t.probe   = regmap_device_probe,\n\t\t.release = regmap_device_release,\n\t},\n\t.ops = {\n\t\t.get_state = sy8106a_get_state,\n\t\t.set_state = sy8106a_set_state,\n\t},\n};\n\nconst struct regmap_device sy8106a = {\n\t.dev = {\n\t\t.name  = \"sy8106a\",\n\t\t.drv   = &sy8106a_driver.drv,\n\t\t.state = DEVICE_STATE_INIT,\n\t},\n\t.map = {\n\t\t.dev = &r_i2c.dev,\n\t\t.id  = SY8106A_I2C_ADDRESS,\n\t},\n};\n"
  },
  {
    "path": "drivers/serial/Kconfig",
    "content": "#\n# Copyright © 2017-2022 The Crust Firmware Authors.\n# SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n#\n\nconfig SERIAL\n\tbool \"Serial input/output support\"\n\tdefault y\n\thelp\n\t\tUse a serial port (UART) for error logs and debugging.\n\t\tNote that depending on the port and options selected,\n\t\tthis may interfere with other users of that serial port.\n\n\t\tIf you are unsure, use the default port and baud rate.\n\n\t\tFor maximum power savings, select the R_UART device or\n\t\tdisable this option entirely.\n\nif SERIAL\n\nchoice\n\tbool \"Device\"\n\tdefault SERIAL_DEV_UART0\n\nconfig SERIAL_DEV_UART0\n\tbool \"UART0\"\n\nconfig SERIAL_DEV_UART1\n\tbool \"UART1\"\n\nconfig SERIAL_DEV_UART2\n\tbool \"UART2\"\n\nconfig SERIAL_DEV_UART3\n\tbool \"UART3\"\n\nconfig SERIAL_DEV_UART4\n\tbool \"UART4\"\n\tdepends on HAVE_UART4\n\nconfig SERIAL_DEV_R_UART\n\tbool \"R_UART\"\n\nendchoice\n\nconfig SERIAL_BAUD\n\tint \"Baud\" if !SERIAL_DEV_UART0\n\trange 0 1500000\n\tdefault 0 if SERIAL_DEV_UART0\n\tdefault 9600 if SERIAL_DEV_R_UART\n\tdefault 115200\n\thelp\n\t\tIf a positive number is entered, the firmware will set\n\t\tup the serial port with that baud rate before using it.\n\n\t\tIf zero is entered, the firmware will assume the serial\n\t\tport is already configured and keep the existing baud\n\t\trate. Use this option if the port is shared with other\n\t\tusers.\n\nendif\n"
  },
  {
    "path": "drivers/serial/Makefile",
    "content": "#\n# Copyright © 2019-2022 The Crust Firmware Authors.\n# SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n#\n\nobj-y += serial.o uart.o\n\nobj-$(CONFIG_PLATFORM_A23)  += sun8i-a23-uart.o\nobj-$(CONFIG_PLATFORM_A83T) += sun8i-a83t-uart.o\nobj-$(CONFIG_PLATFORM_H3)   += sun8i-h3-uart.o\nobj-$(CONFIG_PLATFORM_H6)   += sun50i-h6-uart.o\nobj-$(CONFIG_SOC_A64)       += sun50i-a64-uart.o\nobj-$(CONFIG_SOC_H5)        += sun8i-h3-uart.o\n"
  },
  {
    "path": "drivers/serial/serial.c",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <mmio.h>\n#include <serial.h>\n\n#include \"uart.h\"\n\nchar\nserial_getc(void)\n{\n\tif (!mmio_get_32(uart.regs + UART_LSR, UART_LSR_DR))\n\t\treturn 0;\n\n\treturn mmio_read_32(uart.regs + UART_RBR);\n}\n\nvoid\nserial_putc(char c)\n{\n\tif (c == '\\n')\n\t\tserial_putc('\\r');\n\tmmio_poll_32(uart.regs + UART_LSR, UART_LSR_THRE);\n\tmmio_write_32(uart.regs + UART_THR, c);\n}\n\nvoid\nserial_puts(const char *s)\n{\n\tchar c;\n\n\twhile ((c = *s++))\n\t\tserial_putc(c);\n}\n\nvoid\nserial_init(void)\n{\n\tdevice_get(&uart.dev);\n}\n\nbool\nserial_ready(void)\n{\n\tbool active = device_active(&uart.dev);\n\n\t/*\n\t * If the UART is shared with other users, its clock may have been\n\t * gated. Ensure the clock is running before accessing the device.\n\t */\n\tif (active)\n\t\tclock_enable(&uart.clock);\n\n\treturn active || CONFIG_SERIAL_BAUD == 0;\n}\n"
  },
  {
    "path": "drivers/serial/sun50i-a64-uart.c",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <clock/ccu.h>\n#include <gpio/sunxi-gpio.h>\n#include <platform/devices.h>\n\n#include \"uart.h\"\n\n#if CONFIG(SERIAL_DEV_UART0)\n\nconst struct simple_device uart = {\n\t.dev = {\n\t\t.name  = \"uart0\",\n\t\t.drv   = &uart_driver,\n\t\t.state = DEVICE_STATE_INIT,\n\t},\n\t.clock = { .dev = &ccu.dev, .id = CLK_BUS_UART0 },\n\t.pins  = SIMPLE_DEVICE_PINS_INIT {\n\t\t{\n\t\t\t.dev   = &pio.dev,\n\t\t\t.id    = SUNXI_GPIO_PIN(1, 8), /* PB8 */\n\t\t\t.drive = DRIVE_10mA,\n\t\t\t.mode  = 4,\n\t\t\t.pull  = PULL_NONE,\n\t\t},\n\t\t{\n\t\t\t.dev   = &pio.dev,\n\t\t\t.id    = SUNXI_GPIO_PIN(1, 9), /* PB9 */\n\t\t\t.drive = DRIVE_10mA,\n\t\t\t.mode  = 4,\n\t\t\t.pull  = PULL_UP,\n\t\t},\n\t},\n\t.regs = DEV_UART0,\n};\n\n#elif CONFIG(SERIAL_DEV_UART1)\n\nconst struct simple_device uart = {\n\t.dev = {\n\t\t.name  = \"uart1\",\n\t\t.drv   = &uart_driver,\n\t\t.state = DEVICE_STATE_INIT,\n\t},\n\t.clock = { .dev = &ccu.dev, .id = CLK_BUS_UART1 },\n\t.pins  = SIMPLE_DEVICE_PINS_INIT {\n\t\t{\n\t\t\t.dev   = &pio.dev,\n\t\t\t.id    = SUNXI_GPIO_PIN(6, 6), /* PG6 */\n\t\t\t.drive = DRIVE_10mA,\n\t\t\t.mode  = 2,\n\t\t\t.pull  = PULL_NONE,\n\t\t},\n\t\t{\n\t\t\t.dev   = &pio.dev,\n\t\t\t.id    = SUNXI_GPIO_PIN(6, 7), /* PG7 */\n\t\t\t.drive = DRIVE_10mA,\n\t\t\t.mode  = 2,\n\t\t\t.pull  = PULL_UP,\n\t\t},\n\t},\n\t.regs = DEV_UART1,\n};\n\n#elif CONFIG(SERIAL_DEV_UART2)\n\nconst struct simple_device uart = {\n\t.dev = {\n\t\t.name  = \"uart2\",\n\t\t.drv   = &uart_driver,\n\t\t.state = DEVICE_STATE_INIT,\n\t},\n\t.clock = { .dev = &ccu.dev, .id = CLK_BUS_UART2 },\n\t.pins  = SIMPLE_DEVICE_PINS_INIT {\n\t\t{\n\t\t\t.dev   = &pio.dev,\n\t\t\t.id    = SUNXI_GPIO_PIN(1, 0), /* PB0 */\n\t\t\t.drive = DRIVE_10mA,\n\t\t\t.mode  = 2,\n\t\t\t.pull  = PULL_NONE,\n\t\t},\n\t\t{\n\t\t\t.dev   = &pio.dev,\n\t\t\t.id    = SUNXI_GPIO_PIN(1, 1), /* PB1 */\n\t\t\t.drive = DRIVE_10mA,\n\t\t\t.mode  = 2,\n\t\t\t.pull  = PULL_UP,\n\t\t},\n\t},\n\t.regs = DEV_UART2,\n};\n\n#elif CONFIG(SERIAL_DEV_UART3)\n\nconst struct simple_device uart = {\n\t.dev = {\n\t\t.name  = \"uart3\",\n\t\t.drv   = &uart_driver,\n\t\t.state = DEVICE_STATE_INIT,\n\t},\n\t.clock = { .dev = &ccu.dev, .id = CLK_BUS_UART3 },\n\t.pins  = SIMPLE_DEVICE_PINS_INIT {\n\t\t{\n\t\t\t.dev   = &pio.dev,\n\t\t\t.id    = SUNXI_GPIO_PIN(7, 4), /* PH4 */\n\t\t\t.drive = DRIVE_10mA,\n\t\t\t.mode  = 2,\n\t\t\t.pull  = PULL_NONE,\n\t\t},\n\t\t{\n\t\t\t.dev   = &pio.dev,\n\t\t\t.id    = SUNXI_GPIO_PIN(7, 5), /* PH5 */\n\t\t\t.drive = DRIVE_10mA,\n\t\t\t.mode  = 2,\n\t\t\t.pull  = PULL_UP,\n\t\t},\n\t},\n\t.regs = DEV_UART3,\n};\n\n#elif CONFIG(SERIAL_DEV_UART4)\n\nconst struct simple_device uart = {\n\t.dev = {\n\t\t.name  = \"uart4\",\n\t\t.drv   = &uart_driver,\n\t\t.state = DEVICE_STATE_INIT,\n\t},\n\t.clock = { .dev = &ccu.dev, .id = CLK_BUS_UART4 },\n\t.pins  = SIMPLE_DEVICE_PINS_INIT {\n\t\t{\n\t\t\t.dev   = &pio.dev,\n\t\t\t.id    = SUNXI_GPIO_PIN(3, 2), /* PD2 */\n\t\t\t.drive = DRIVE_10mA,\n\t\t\t.mode  = 3,\n\t\t\t.pull  = PULL_NONE,\n\t\t},\n\t\t{\n\t\t\t.dev   = &pio.dev,\n\t\t\t.id    = SUNXI_GPIO_PIN(3, 3), /* PD3 */\n\t\t\t.drive = DRIVE_10mA,\n\t\t\t.mode  = 3,\n\t\t\t.pull  = PULL_UP,\n\t\t},\n\t},\n\t.regs = DEV_UART4,\n};\n\n#elif CONFIG(SERIAL_DEV_R_UART)\n\nconst struct simple_device uart = {\n\t.dev = {\n\t\t.name  = \"r_uart\",\n\t\t.drv   = &uart_driver,\n\t\t.state = DEVICE_STATE_INIT,\n\t},\n\t.clock = { .dev = &r_ccu.dev, .id = CLK_BUS_R_UART },\n\t.pins  = SIMPLE_DEVICE_PINS_INIT {\n\t\t{\n\t\t\t.dev   = &r_pio.dev,\n\t\t\t.id    = SUNXI_GPIO_PIN(0, 2), /* PL2 */\n\t\t\t.drive = DRIVE_10mA,\n\t\t\t.mode  = 2,\n\t\t\t.pull  = PULL_NONE,\n\t\t},\n\t\t{\n\t\t\t.dev   = &r_pio.dev,\n\t\t\t.id    = SUNXI_GPIO_PIN(0, 3), /* PL3 */\n\t\t\t.drive = DRIVE_10mA,\n\t\t\t.mode  = 2,\n\t\t\t.pull  = PULL_UP,\n\t\t},\n\t},\n\t.regs = DEV_R_UART,\n};\n\n#endif\n"
  },
  {
    "path": "drivers/serial/sun50i-h6-uart.c",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <clock/ccu.h>\n#include <gpio/sunxi-gpio.h>\n#include <platform/devices.h>\n\n#include \"uart.h\"\n\n#if CONFIG(SERIAL_DEV_UART0)\n\nconst struct simple_device uart = {\n\t.dev = {\n\t\t.name  = \"uart0\",\n\t\t.drv   = &uart_driver,\n\t\t.state = DEVICE_STATE_INIT,\n\t},\n\t.clock = { .dev = &ccu.dev, .id = CLK_BUS_UART0 },\n\t.pins  = SIMPLE_DEVICE_PINS_INIT {\n\t\t{\n\t\t\t.dev   = &pio.dev,\n\t\t\t.id    = SUNXI_GPIO_PIN(7, 0), /* PH0 */\n\t\t\t.drive = DRIVE_10mA,\n\t\t\t.mode  = 2,\n\t\t\t.pull  = PULL_NONE,\n\t\t},\n\t\t{\n\t\t\t.dev   = &pio.dev,\n\t\t\t.id    = SUNXI_GPIO_PIN(7, 1), /* PH1 */\n\t\t\t.drive = DRIVE_10mA,\n\t\t\t.mode  = 2,\n\t\t\t.pull  = PULL_UP,\n\t\t},\n\t},\n\t.regs = DEV_UART0,\n};\n\n#elif CONFIG(SERIAL_DEV_UART1)\n\nconst struct simple_device uart = {\n\t.dev = {\n\t\t.name  = \"uart1\",\n\t\t.drv   = &uart_driver,\n\t\t.state = DEVICE_STATE_INIT,\n\t},\n\t.clock = { .dev = &ccu.dev, .id = CLK_BUS_UART1 },\n\t.pins  = SIMPLE_DEVICE_PINS_INIT {\n\t\t{\n\t\t\t.dev   = &pio.dev,\n\t\t\t.id    = SUNXI_GPIO_PIN(6, 6), /* PG6 */\n\t\t\t.drive = DRIVE_10mA,\n\t\t\t.mode  = 2,\n\t\t\t.pull  = PULL_NONE,\n\t\t},\n\t\t{\n\t\t\t.dev   = &pio.dev,\n\t\t\t.id    = SUNXI_GPIO_PIN(6, 7), /* PG7 */\n\t\t\t.drive = DRIVE_10mA,\n\t\t\t.mode  = 2,\n\t\t\t.pull  = PULL_UP,\n\t\t},\n\t},\n\t.regs = DEV_UART1,\n};\n\n#elif CONFIG(SERIAL_DEV_UART2)\n\nconst struct simple_device uart = {\n\t.dev = {\n\t\t.name  = \"uart2\",\n\t\t.drv   = &uart_driver,\n\t\t.state = DEVICE_STATE_INIT,\n\t},\n\t.clock = { .dev = &ccu.dev, .id = CLK_BUS_UART2 },\n\t.pins  = SIMPLE_DEVICE_PINS_INIT {\n\t\t{\n\t\t\t.dev   = &pio.dev,\n\t\t\t.id    = SUNXI_GPIO_PIN(3, 19), /* PD19 */\n\t\t\t.drive = DRIVE_10mA,\n\t\t\t.mode  = 4,\n\t\t\t.pull  = PULL_NONE,\n\t\t},\n\t\t{\n\t\t\t.dev   = &pio.dev,\n\t\t\t.id    = SUNXI_GPIO_PIN(3, 20), /* PD20 */\n\t\t\t.drive = DRIVE_10mA,\n\t\t\t.mode  = 4,\n\t\t\t.pull  = PULL_UP,\n\t\t},\n\t},\n\t.regs = DEV_UART2,\n};\n\n#elif CONFIG(SERIAL_DEV_UART3)\n\nconst struct simple_device uart = {\n\t.dev = {\n\t\t.name  = \"uart3\",\n\t\t.drv   = &uart_driver,\n\t\t.state = DEVICE_STATE_INIT,\n\t},\n\t.clock = { .dev = &ccu.dev, .id = CLK_BUS_UART3 },\n\t.pins  = SIMPLE_DEVICE_PINS_INIT {\n\t\t{\n\t\t\t.dev   = &pio.dev,\n\t\t\t.id    = SUNXI_GPIO_PIN(3, 23), /* PD23 */\n\t\t\t.drive = DRIVE_10mA,\n\t\t\t.mode  = 4,\n\t\t\t.pull  = PULL_NONE,\n\t\t},\n\t\t{\n\t\t\t.dev   = &pio.dev,\n\t\t\t.id    = SUNXI_GPIO_PIN(3, 24), /* PD24 */\n\t\t\t.drive = DRIVE_10mA,\n\t\t\t.mode  = 4,\n\t\t\t.pull  = PULL_UP,\n\t\t},\n\t},\n\t.regs = DEV_UART3,\n};\n\n#elif CONFIG(SERIAL_DEV_R_UART)\n\nconst struct simple_device uart = {\n\t.dev = {\n\t\t.name  = \"r_uart\",\n\t\t.drv   = &uart_driver,\n\t\t.state = DEVICE_STATE_INIT,\n\t},\n\t.clock = { .dev = &r_ccu.dev, .id = CLK_BUS_R_UART },\n\t.pins  = SIMPLE_DEVICE_PINS_INIT {\n\t\t{\n\t\t\t.dev   = &r_pio.dev,\n\t\t\t.id    = SUNXI_GPIO_PIN(0, 2), /* PL2 */\n\t\t\t.drive = DRIVE_10mA,\n\t\t\t.mode  = 2,\n\t\t\t.pull  = PULL_NONE,\n\t\t},\n\t\t{\n\t\t\t.dev   = &r_pio.dev,\n\t\t\t.id    = SUNXI_GPIO_PIN(0, 3), /* PL3 */\n\t\t\t.drive = DRIVE_10mA,\n\t\t\t.mode  = 2,\n\t\t\t.pull  = PULL_UP,\n\t\t},\n\t},\n\t.regs = DEV_R_UART,\n};\n\n#endif\n"
  },
  {
    "path": "drivers/serial/sun8i-a23-uart.c",
    "content": "/*\n * Copyright © 2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <clock/ccu.h>\n#include <gpio/sunxi-gpio.h>\n#include <platform/devices.h>\n\n#include \"uart.h\"\n\n#if CONFIG(SERIAL_DEV_UART0)\n\nconst struct simple_device uart = {\n\t.dev = {\n\t\t.name  = \"uart0\",\n\t\t.drv   = &uart_driver,\n\t\t.state = DEVICE_STATE_INIT,\n\t},\n\t.clock = { .dev = &ccu.dev, .id = CLK_BUS_UART0 },\n\t.pins  = SIMPLE_DEVICE_PINS_INIT {\n\t\t{\n\t\t\t.dev   = &pio.dev,\n\t\t\t.id    = SUNXI_GPIO_PIN(5, 2), /* PF2 */\n\t\t\t.drive = DRIVE_10mA,\n\t\t\t.mode  = 3,\n\t\t\t.pull  = PULL_NONE,\n\t\t},\n\t\t{\n\t\t\t.dev   = &pio.dev,\n\t\t\t.id    = SUNXI_GPIO_PIN(5, 4), /* PF4 */\n\t\t\t.drive = DRIVE_10mA,\n\t\t\t.mode  = 3,\n\t\t\t.pull  = PULL_UP,\n\t\t},\n\t},\n\t.regs = DEV_UART0,\n};\n\n#elif CONFIG(SERIAL_DEV_UART1)\n\nconst struct simple_device uart = {\n\t.dev = {\n\t\t.name  = \"uart1\",\n\t\t.drv   = &uart_driver,\n\t\t.state = DEVICE_STATE_INIT,\n\t},\n\t.clock = { .dev = &ccu.dev, .id = CLK_BUS_UART1 },\n\t.pins  = SIMPLE_DEVICE_PINS_INIT {\n\t\t{\n\t\t\t.dev   = &pio.dev,\n\t\t\t.id    = SUNXI_GPIO_PIN(6, 6), /* PG6 */\n\t\t\t.drive = DRIVE_10mA,\n\t\t\t.mode  = 2,\n\t\t\t.pull  = PULL_NONE,\n\t\t},\n\t\t{\n\t\t\t.dev   = &pio.dev,\n\t\t\t.id    = SUNXI_GPIO_PIN(6, 7), /* PG7 */\n\t\t\t.drive = DRIVE_10mA,\n\t\t\t.mode  = 2,\n\t\t\t.pull  = PULL_UP,\n\t\t},\n\t},\n\t.regs = DEV_UART1,\n};\n\n#elif CONFIG(SERIAL_DEV_UART2)\n\nconst struct simple_device uart = {\n\t.dev = {\n\t\t.name  = \"uart2\",\n\t\t.drv   = &uart_driver,\n\t\t.state = DEVICE_STATE_INIT,\n\t},\n\t.clock = { .dev = &ccu.dev, .id = CLK_BUS_UART2 },\n\t.pins  = SIMPLE_DEVICE_PINS_INIT {\n\t\t{\n\t\t\t.dev   = &pio.dev,\n\t\t\t.id    = SUNXI_GPIO_PIN(1, 0), /* PB0 */\n\t\t\t.drive = DRIVE_10mA,\n\t\t\t.mode  = 2,\n\t\t\t.pull  = PULL_NONE,\n\t\t},\n\t\t{\n\t\t\t.dev   = &pio.dev,\n\t\t\t.id    = SUNXI_GPIO_PIN(1, 1), /* PB1 */\n\t\t\t.drive = DRIVE_10mA,\n\t\t\t.mode  = 2,\n\t\t\t.pull  = PULL_UP,\n\t\t},\n\t},\n\t.regs = DEV_UART2,\n};\n\n#elif CONFIG(SERIAL_DEV_UART3)\n\nconst struct simple_device uart = {\n\t.dev = {\n\t\t.name  = \"uart3\",\n\t\t.drv   = &uart_driver,\n\t\t.state = DEVICE_STATE_INIT,\n\t},\n\t.clock = { .dev = &ccu.dev, .id = CLK_BUS_UART3 },\n\t.pins  = SIMPLE_DEVICE_PINS_INIT {\n\t\t{\n\t\t\t.dev   = &pio.dev,\n\t\t\t.id    = SUNXI_GPIO_PIN(7, 6), /* PH4 */\n\t\t\t.drive = DRIVE_10mA,\n\t\t\t.mode  = 3,\n\t\t\t.pull  = PULL_NONE,\n\t\t},\n\t\t{\n\t\t\t.dev   = &pio.dev,\n\t\t\t.id    = SUNXI_GPIO_PIN(7, 7), /* PH5 */\n\t\t\t.drive = DRIVE_10mA,\n\t\t\t.mode  = 3,\n\t\t\t.pull  = PULL_UP,\n\t\t},\n\t},\n\t.regs = DEV_UART3,\n};\n\n#elif CONFIG(SERIAL_DEV_UART4)\n\nconst struct simple_device uart = {\n\t.dev = {\n\t\t.name  = \"uart4\",\n\t\t.drv   = &uart_driver,\n\t\t.state = DEVICE_STATE_INIT,\n\t},\n\t.clock = { .dev = &ccu.dev, .id = CLK_BUS_UART4 },\n\t.pins  = SIMPLE_DEVICE_PINS_INIT {\n\t\t{\n\t\t\t.dev   = &pio.dev,\n\t\t\t.id    = SUNXI_GPIO_PIN(0, 4), /* PA4 */\n\t\t\t.drive = DRIVE_10mA,\n\t\t\t.mode  = 3,\n\t\t\t.pull  = PULL_NONE,\n\t\t},\n\t\t{\n\t\t\t.dev   = &pio.dev,\n\t\t\t.id    = SUNXI_GPIO_PIN(0, 5), /* PA5 */\n\t\t\t.drive = DRIVE_10mA,\n\t\t\t.mode  = 3,\n\t\t\t.pull  = PULL_UP,\n\t\t},\n\t},\n\t.regs = DEV_UART4,\n};\n\n#elif CONFIG(SERIAL_DEV_R_UART)\n\nconst struct simple_device uart = {\n\t.dev = {\n\t\t.name  = \"r_uart\",\n\t\t.drv   = &uart_driver,\n\t\t.state = DEVICE_STATE_INIT,\n\t},\n\t.clock = { .dev = &r_ccu.dev, .id = CLK_BUS_R_UART },\n\t.pins  = SIMPLE_DEVICE_PINS_INIT {\n\t\t{\n\t\t\t.dev   = &r_pio.dev,\n\t\t\t.id    = SUNXI_GPIO_PIN(0, 2), /* PL2 */\n\t\t\t.drive = DRIVE_10mA,\n\t\t\t.mode  = 2,\n\t\t\t.pull  = PULL_NONE,\n\t\t},\n\t\t{\n\t\t\t.dev   = &r_pio.dev,\n\t\t\t.id    = SUNXI_GPIO_PIN(0, 3), /* PL3 */\n\t\t\t.drive = DRIVE_10mA,\n\t\t\t.mode  = 2,\n\t\t\t.pull  = PULL_UP,\n\t\t},\n\t},\n\t.regs = DEV_R_UART,\n};\n\n#endif\n"
  },
  {
    "path": "drivers/serial/sun8i-a83t-uart.c",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <clock/ccu.h>\n#include <gpio/sunxi-gpio.h>\n#include <platform/devices.h>\n\n#include \"uart.h\"\n\n#if CONFIG(SERIAL_DEV_UART0)\n\nconst struct simple_device uart = {\n\t.dev = {\n\t\t.name  = \"uart0\",\n\t\t.drv   = &uart_driver,\n\t\t.state = DEVICE_STATE_INIT,\n\t},\n\t.clock = { .dev = &ccu.dev, .id = CLK_BUS_UART0 },\n\t.pins  = SIMPLE_DEVICE_PINS_INIT {\n\t\t{\n\t\t\t.dev   = &pio.dev,\n\t\t\t.id    = SUNXI_GPIO_PIN(1, 9), /* PB9 */\n\t\t\t.drive = DRIVE_10mA,\n\t\t\t.mode  = 2,\n\t\t\t.pull  = PULL_NONE,\n\t\t},\n\t\t{\n\t\t\t.dev   = &pio.dev,\n\t\t\t.id    = SUNXI_GPIO_PIN(1, 10), /* PB10 */\n\t\t\t.drive = DRIVE_10mA,\n\t\t\t.mode  = 2,\n\t\t\t.pull  = PULL_UP,\n\t\t},\n\t},\n\t.regs = DEV_UART0,\n};\n\n#elif CONFIG(SERIAL_DEV_UART1)\n\nconst struct simple_device uart = {\n\t.dev = {\n\t\t.name  = \"uart1\",\n\t\t.drv   = &uart_driver,\n\t\t.state = DEVICE_STATE_INIT,\n\t},\n\t.clock = { .dev = &ccu.dev, .id = CLK_BUS_UART1 },\n\t.pins  = SIMPLE_DEVICE_PINS_INIT {\n\t\t{\n\t\t\t.dev   = &pio.dev,\n\t\t\t.id    = SUNXI_GPIO_PIN(6, 6), /* PG6 */\n\t\t\t.drive = DRIVE_10mA,\n\t\t\t.mode  = 2,\n\t\t\t.pull  = PULL_NONE,\n\t\t},\n\t\t{\n\t\t\t.dev   = &pio.dev,\n\t\t\t.id    = SUNXI_GPIO_PIN(6, 7), /* PG7 */\n\t\t\t.drive = DRIVE_10mA,\n\t\t\t.mode  = 2,\n\t\t\t.pull  = PULL_UP,\n\t\t},\n\t},\n\t.regs = DEV_UART1,\n};\n\n#elif CONFIG(SERIAL_DEV_UART2)\n\nconst struct simple_device uart = {\n\t.dev = {\n\t\t.name  = \"uart2\",\n\t\t.drv   = &uart_driver,\n\t\t.state = DEVICE_STATE_INIT,\n\t},\n\t.clock = { .dev = &ccu.dev, .id = CLK_BUS_UART2 },\n\t.pins  = SIMPLE_DEVICE_PINS_INIT {\n\t\t{\n\t\t\t.dev   = &pio.dev,\n\t\t\t.id    = SUNXI_GPIO_PIN(1, 0), /* PB0 */\n\t\t\t.drive = DRIVE_10mA,\n\t\t\t.mode  = 2,\n\t\t\t.pull  = PULL_NONE,\n\t\t},\n\t\t{\n\t\t\t.dev   = &pio.dev,\n\t\t\t.id    = SUNXI_GPIO_PIN(1, 1), /* PB1 */\n\t\t\t.drive = DRIVE_10mA,\n\t\t\t.mode  = 2,\n\t\t\t.pull  = PULL_UP,\n\t\t},\n\t},\n\t.regs = DEV_UART2,\n};\n\n#elif CONFIG(SERIAL_DEV_UART3)\n\nconst struct simple_device uart = {\n\t.dev = {\n\t\t.name  = \"uart3\",\n\t\t.drv   = &uart_driver,\n\t\t.state = DEVICE_STATE_INIT,\n\t},\n\t.clock = { .dev = &ccu.dev, .id = CLK_BUS_UART3 },\n\t.pins  = SIMPLE_DEVICE_PINS_INIT {\n\t\t{\n\t\t\t.dev   = &pio.dev,\n\t\t\t.id    = SUNXI_GPIO_PIN(6, 10), /* PG10 */\n\t\t\t.drive = DRIVE_10mA,\n\t\t\t.mode  = 3,\n\t\t\t.pull  = PULL_NONE,\n\t\t},\n\t\t{\n\t\t\t.dev   = &pio.dev,\n\t\t\t.id    = SUNXI_GPIO_PIN(6, 11), /* PG11 */\n\t\t\t.drive = DRIVE_10mA,\n\t\t\t.mode  = 3,\n\t\t\t.pull  = PULL_UP,\n\t\t},\n\t},\n\t.regs = DEV_UART3,\n};\n\n#elif CONFIG(SERIAL_DEV_UART4)\n\nconst struct simple_device uart = {\n\t.dev = {\n\t\t.name  = \"uart4\",\n\t\t.drv   = &uart_driver,\n\t\t.state = DEVICE_STATE_INIT,\n\t},\n\t.clock = { .dev = &ccu.dev, .id = CLK_BUS_UART4 },\n\t.pins  = SIMPLE_DEVICE_PINS_INIT {\n\t\t{\n\t\t\t.dev   = &pio.dev,\n\t\t\t.id    = SUNXI_GPIO_PIN(4, 10), /* PE10 */\n\t\t\t.drive = DRIVE_10mA,\n\t\t\t.mode  = 3,\n\t\t\t.pull  = PULL_NONE,\n\t\t},\n\t\t{\n\t\t\t.dev   = &pio.dev,\n\t\t\t.id    = SUNXI_GPIO_PIN(4, 11), /* PE11 */\n\t\t\t.drive = DRIVE_10mA,\n\t\t\t.mode  = 3,\n\t\t\t.pull  = PULL_UP,\n\t\t},\n\t},\n\t.regs = DEV_UART4,\n};\n\n#elif CONFIG(SERIAL_DEV_R_UART)\n\nconst struct simple_device uart = {\n\t.dev = {\n\t\t.name  = \"r_uart\",\n\t\t.drv   = &uart_driver,\n\t\t.state = DEVICE_STATE_INIT,\n\t},\n\t.clock = { .dev = &r_ccu.dev, .id = CLK_BUS_R_UART },\n\t.pins  = SIMPLE_DEVICE_PINS_INIT {\n\t\t{\n\t\t\t.dev   = &r_pio.dev,\n\t\t\t.id    = SUNXI_GPIO_PIN(0, 2), /* PL2 */\n\t\t\t.drive = DRIVE_10mA,\n\t\t\t.mode  = 2,\n\t\t\t.pull  = PULL_NONE,\n\t\t},\n\t\t{\n\t\t\t.dev   = &r_pio.dev,\n\t\t\t.id    = SUNXI_GPIO_PIN(0, 3), /* PL3 */\n\t\t\t.drive = DRIVE_10mA,\n\t\t\t.mode  = 2,\n\t\t\t.pull  = PULL_UP,\n\t\t},\n\t},\n\t.regs = DEV_R_UART,\n};\n\n#endif\n"
  },
  {
    "path": "drivers/serial/sun8i-h3-uart.c",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <clock/ccu.h>\n#include <gpio/sunxi-gpio.h>\n#include <platform/devices.h>\n\n#include \"uart.h\"\n\n#if CONFIG(SERIAL_DEV_UART0)\n\nconst struct simple_device uart = {\n\t.dev = {\n\t\t.name  = \"uart0\",\n\t\t.drv   = &uart_driver,\n\t\t.state = DEVICE_STATE_INIT,\n\t},\n\t.clock = { .dev = &ccu.dev, .id = CLK_BUS_UART0 },\n\t.pins  = SIMPLE_DEVICE_PINS_INIT {\n\t\t{\n\t\t\t.dev   = &pio.dev,\n\t\t\t.id    = SUNXI_GPIO_PIN(0, 4), /* PA4 */\n\t\t\t.drive = DRIVE_10mA,\n\t\t\t.mode  = 2,\n\t\t\t.pull  = PULL_NONE,\n\t\t},\n\t\t{\n\t\t\t.dev   = &pio.dev,\n\t\t\t.id    = SUNXI_GPIO_PIN(0, 5), /* PA5 */\n\t\t\t.drive = DRIVE_10mA,\n\t\t\t.mode  = 2,\n\t\t\t.pull  = PULL_UP,\n\t\t},\n\t},\n\t.regs = DEV_UART0,\n};\n\n#elif CONFIG(SERIAL_DEV_UART1)\n\nconst struct simple_device uart = {\n\t.dev = {\n\t\t.name  = \"uart1\",\n\t\t.drv   = &uart_driver,\n\t\t.state = DEVICE_STATE_INIT,\n\t},\n\t.clock = { .dev = &ccu.dev, .id = CLK_BUS_UART1 },\n\t.pins  = SIMPLE_DEVICE_PINS_INIT {\n\t\t{\n\t\t\t.dev   = &pio.dev,\n\t\t\t.id    = SUNXI_GPIO_PIN(6, 6), /* PG6 */\n\t\t\t.drive = DRIVE_10mA,\n\t\t\t.mode  = 2,\n\t\t\t.pull  = PULL_NONE,\n\t\t},\n\t\t{\n\t\t\t.dev   = &pio.dev,\n\t\t\t.id    = SUNXI_GPIO_PIN(6, 7), /* PG7 */\n\t\t\t.drive = DRIVE_10mA,\n\t\t\t.mode  = 2,\n\t\t\t.pull  = PULL_UP,\n\t\t},\n\t},\n\t.regs = DEV_UART1,\n};\n\n#elif CONFIG(SERIAL_DEV_UART2)\n\nconst struct simple_device uart = {\n\t.dev = {\n\t\t.name  = \"uart2\",\n\t\t.drv   = &uart_driver,\n\t\t.state = DEVICE_STATE_INIT,\n\t},\n\t.clock = { .dev = &ccu.dev, .id = CLK_BUS_UART2 },\n\t.pins  = SIMPLE_DEVICE_PINS_INIT {\n\t\t{\n\t\t\t.dev   = &pio.dev,\n\t\t\t.id    = SUNXI_GPIO_PIN(0, 0), /* PA0 */\n\t\t\t.drive = DRIVE_10mA,\n\t\t\t.mode  = 2,\n\t\t\t.pull  = PULL_NONE,\n\t\t},\n\t\t{\n\t\t\t.dev   = &pio.dev,\n\t\t\t.id    = SUNXI_GPIO_PIN(0, 1), /* PA1 */\n\t\t\t.drive = DRIVE_10mA,\n\t\t\t.mode  = 2,\n\t\t\t.pull  = PULL_UP,\n\t\t},\n\t},\n\t.regs = DEV_UART2,\n};\n\n#elif CONFIG(SERIAL_DEV_UART3)\n\nconst struct simple_device uart = {\n\t.dev = {\n\t\t.name  = \"uart3\",\n\t\t.drv   = &uart_driver,\n\t\t.state = DEVICE_STATE_INIT,\n\t},\n\t.clock = { .dev = &ccu.dev, .id = CLK_BUS_UART3 },\n\t.pins  = SIMPLE_DEVICE_PINS_INIT {\n\t\t{\n\t\t\t.dev   = &pio.dev,\n\t\t\t.id    = SUNXI_GPIO_PIN(0, 13), /* PA13 */\n\t\t\t.drive = DRIVE_10mA,\n\t\t\t.mode  = 3,\n\t\t\t.pull  = PULL_NONE,\n\t\t},\n\t\t{\n\t\t\t.dev   = &pio.dev,\n\t\t\t.id    = SUNXI_GPIO_PIN(0, 14), /* PA14 */\n\t\t\t.drive = DRIVE_10mA,\n\t\t\t.mode  = 3,\n\t\t\t.pull  = PULL_UP,\n\t\t},\n\t},\n\t.regs = DEV_UART3,\n};\n\n#elif CONFIG(SERIAL_DEV_R_UART)\n\nconst struct simple_device uart = {\n\t.dev = {\n\t\t.name  = \"r_uart\",\n\t\t.drv   = &uart_driver,\n\t\t.state = DEVICE_STATE_INIT,\n\t},\n\t.clock = { .dev = &r_ccu.dev, .id = CLK_BUS_R_UART },\n\t.pins  = SIMPLE_DEVICE_PINS_INIT {\n\t\t{\n\t\t\t.dev   = &r_pio.dev,\n\t\t\t.id    = SUNXI_GPIO_PIN(0, 2), /* PL2 */\n\t\t\t.drive = DRIVE_10mA,\n\t\t\t.mode  = 2,\n\t\t\t.pull  = PULL_NONE,\n\t\t},\n\t\t{\n\t\t\t.dev   = &r_pio.dev,\n\t\t\t.id    = SUNXI_GPIO_PIN(0, 3), /* PL3 */\n\t\t\t.drive = DRIVE_10mA,\n\t\t\t.mode  = 2,\n\t\t\t.pull  = PULL_UP,\n\t\t},\n\t},\n\t.regs = DEV_R_UART,\n};\n\n#endif\n"
  },
  {
    "path": "drivers/serial/uart.c",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <division.h>\n#include <error.h>\n#include <mmio.h>\n\n#include \"uart.h\"\n\nstatic int\nuart_probe(const struct device *dev)\n{\n\tconst struct simple_device *self = to_simple_device(dev);\n\tint err;\n\n\tif ((err = simple_device_probe(dev)))\n\t\treturn err;\n\n\tif (CONFIG_SERIAL_BAUD) {\n\t\tuint32_t  rate    = clock_get_rate(&self->clock);\n\t\tuint32_t  divisor = udiv_round(rate, 16 * CONFIG_SERIAL_BAUD);\n\t\tuintptr_t regs    = self->regs;\n\n\t\t/* Set the clock divisor. */\n\t\tmmio_write_32(regs + UART_LCR, UART_LCR_DLAB);\n\t\tmmio_write_32(regs + UART_DLH, divisor >> 8);\n\t\tmmio_write_32(regs + UART_DLL, divisor);\n\n\t\t/* Set the UART to 8 data bits, no parity, 1 stop bit. */\n\t\tmmio_write_32(regs + UART_LCR, UART_LCR_DLS8);\n\n\t\t/* Enable the FIFOs. */\n\t\tmmio_write_32(regs + UART_FCR, UART_FCR_FIFOE);\n\t}\n\n\treturn SUCCESS;\n}\n\nconst struct driver uart_driver = {\n\t.probe   = uart_probe,\n\t.release = simple_device_release,\n};\n"
  },
  {
    "path": "drivers/serial/uart.h",
    "content": "/*\n * Copyright © 2020-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef UART_PRIVATE_H\n#define UART_PRIVATE_H\n\n#include <simple_device.h>\n#include <util.h>\n\nenum {\n\tUART_RBR = 0x0000,\n\tUART_THR = 0x0000,\n\tUART_DLL = 0x0000,\n\tUART_DLH = 0x0004,\n\tUART_FCR = 0x0008,\n\tUART_LCR = 0x000c,\n\tUART_LSR = 0x0014,\n};\n\nenum {\n\tUART_FCR_FIFOE = BIT(0),\n};\n\nenum {\n\tUART_LCR_DLAB = BIT(7),\n\tUART_LCR_DLS8 = GENMASK(1, 0),\n};\n\nenum {\n\tUART_LSR_DR   = BIT(0),\n\tUART_LSR_THRE = BIT(5),\n};\n\nextern const struct driver uart_driver;\nextern const struct simple_device uart;\n\n#endif /* UART_PRIVATE_H */\n"
  },
  {
    "path": "drivers/watchdog/Kconfig",
    "content": "#\n# Copyright © 2022 The Crust Firmware Authors.\n# SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n#\n\nchoice\n\tbool \"Watchdog timer\"\n\tdefault WATCHDOG_SUN9I_A80_TWD if PLATFORM_H6\n\tdefault WATCHDOG_SUN6I_A31_WDT\n\thelp\n\t\tThe firmware is monitored by a watchdog timer. If an\n\t\terror occurs, the watchdog will reset the system instead\n\t\tof allowing it to hang.\n\n\t\tThe watchdog also services user-requested system resets.\n\nconfig WATCHDOG_SUN6I_A31_WDT\n\tbool \"Watchdog (R_WDOG)\"\n\thelp\n\t\tThis driver supports the watchdog in A31 and newer SoCs.\n\n\t\tThis watchdog timer can reset the system after a minimum\n\t\tdelay of one half second.\n\n\t\tDue to a bug in the H6 SoC, this watchdog timer hardware\n\t\tis used by other system software on that platform. When\n\t\tbuilding for an H6 board, do not select this driver\n\t\tunless you know what you are doing.\n\nconfig WATCHDOG_SUN9I_A80_TWD\n\tbool \"Trusted watchdog (R_TWD)\"\n\tdepends on HAVE_R_TWD\n\thelp\n\t\tThis driver supports the trusted watchdog in A80 and\n\t\tnewer SoCs.\n\n\t\tThis watchdog timer can reset the system immediately.\n\n\t\tOlder versions of Linux may interfere with this device,\n\t\tcausing an unexpected reboot during system resume. As a\n\t\tworkaround, select a different watchdog device.\n\nendchoice\n"
  },
  {
    "path": "drivers/watchdog/Makefile",
    "content": "#\n# Copyright © 2017-2022 The Crust Firmware Authors.\n# SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n#\n\nobj-y += watchdog.o\n\nobj-$(CONFIG_WATCHDOG_SUN6I_A31_WDT) += sun6i-a31-wdt.o\nobj-$(CONFIG_WATCHDOG_SUN9I_A80_TWD) += sun9i-a80-twd.o\n"
  },
  {
    "path": "drivers/watchdog/sun6i-a31-wdt.c",
    "content": "/*\n * Copyright © 2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <delay.h>\n#include <error.h>\n#include <intrusive.h>\n#include <mmio.h>\n#include <util.h>\n#include <watchdog/sun6i-a31-wdt.h>\n#include <platform/devices.h>\n\n#include \"watchdog.h\"\n\n#define WDOG_CTRL_REG      0x10\n#define WDOG_CFG_REG       0x14\n#define WDOG_MODE_REG      0x18\n\n#define WDOG_RESTART_KEY   (0xa57 << 1)\n\n#define WDOG_LONG_TIMEOUT  (5 << 4) /* 5.0 seconds */\n#define WDOG_SHORT_TIMEOUT (0 << 4) /* 0.5 seconds */\n\nstatic inline const struct sun6i_a31_wdt *\nto_sun6i_a31_wdt(const struct device *dev)\n{\n\treturn container_of(dev, const struct sun6i_a31_wdt, dev);\n}\n\nstatic void\nsun6i_a31_wdt_reset_system(const struct device *dev)\n{\n\tconst struct sun6i_a31_wdt *self = to_sun6i_a31_wdt(dev);\n\n\tmmio_write_32(self->regs + WDOG_MODE_REG, WDOG_SHORT_TIMEOUT | BIT(0));\n\n\tudelay(1000000);\n}\n\nstatic void\nsun6i_a31_wdt_restart(const struct device *dev)\n{\n\tconst struct sun6i_a31_wdt *self = to_sun6i_a31_wdt(dev);\n\n\tmmio_write_32(self->regs + WDOG_CTRL_REG, WDOG_RESTART_KEY | BIT(0));\n}\n\nstatic int\nsun6i_a31_wdt_probe(const struct device *dev)\n{\n\tconst struct sun6i_a31_wdt *self = to_sun6i_a31_wdt(dev);\n\n\t/* Enable system reset on timeout. */\n\tmmio_write_32(self->regs + WDOG_CFG_REG, 1);\n\n\t/* Start the watchdog with the default (long) timeout. */\n\tmmio_write_32(self->regs + WDOG_MODE_REG, WDOG_LONG_TIMEOUT | BIT(0));\n\n\treturn SUCCESS;\n}\n\nstatic void\nsun6i_a31_wdt_release(const struct device *dev)\n{\n\tconst struct sun6i_a31_wdt *self = to_sun6i_a31_wdt(dev);\n\n\t/* Stop the watchdog. */\n\tmmio_write_32(self->regs + WDOG_MODE_REG, 0);\n}\n\nstatic const struct watchdog_driver sun6i_a31_wdt_driver = {\n\t.drv = {\n\t\t.probe   = sun6i_a31_wdt_probe,\n\t\t.release = sun6i_a31_wdt_release,\n\t},\n\t.ops = {\n\t\t.reset_system = sun6i_a31_wdt_reset_system,\n\t\t.restart      = sun6i_a31_wdt_restart,\n\t},\n};\n\nconst struct sun6i_a31_wdt r_wdog = {\n\t.dev = {\n\t\t.name  = \"r_wdog\",\n\t\t.drv   = &sun6i_a31_wdt_driver.drv,\n\t\t.state = DEVICE_STATE_INIT,\n\t},\n\t.regs = DEV_R_WDOG,\n};\n"
  },
  {
    "path": "drivers/watchdog/sun9i-a80-twd.c",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <delay.h>\n#include <error.h>\n#include <mmio.h>\n#include <util.h>\n#include <clock/ccu.h>\n#include <watchdog/sun9i-a80-twd.h>\n#include <platform/devices.h>\n#include <platform/time.h>\n\n#include \"watchdog.h\"\n\n#define TWD_STATUS_REG  0x00\n#define TWD_CTRL_REG    0x10\n#define TWD_RESTART_REG 0x14\n#define TWD_LOW_CNT_REG 0x20\n#define TWD_INTV_REG    0x30\n\n#define TWD_RESTART_KEY (0xD14 << 16)\n\n#define TWD_TIMEOUT     (5 * REFCLK_HZ) /* 5 seconds */\n\nstatic void\nsun9i_a80_twd_reset_system(const struct device *dev)\n{\n\tconst struct simple_device *self = to_simple_device(dev);\n\n\t/* Set the timeout to the smallest value. 0 is broken on some SoCs. */\n\tmmio_write_32(self->regs + TWD_INTV_REG, 1);\n\n\tudelay(1);\n}\n\nstatic void\nsun9i_a80_twd_restart(const struct device *dev)\n{\n\tconst struct simple_device *self = to_simple_device(dev);\n\n\tmmio_write_32(self->regs + TWD_RESTART_REG, TWD_RESTART_KEY | BIT(0));\n}\n\nstatic int\nsun9i_a80_twd_probe(const struct device *dev)\n{\n\tconst struct simple_device *self = to_simple_device(dev);\n\tuintptr_t regs = self->regs;\n\tint err;\n\n\tif ((err = simple_device_probe(dev)))\n\t\treturn err;\n\n\t/* Clear the watchdog configuration. */\n\tmmio_write_32(regs + TWD_CTRL_REG, BIT(0));\n\tmmio_pollz_32(regs + TWD_CTRL_REG, BIT(0));\n\n\t/* Set counter clock source to OSC24M. */\n\tmmio_set_32(regs + TWD_CTRL_REG, BIT(31));\n\n\t/* Program a conservative default timeout. */\n\tmmio_write_32(regs + TWD_INTV_REG, TWD_TIMEOUT);\n\n\t/* Update the comparator to (counter + timeout). */\n\tsun9i_a80_twd_restart(dev);\n\n\t/* Start the watchdog counter; enable system reset. */\n\tmmio_clrset_32(regs + TWD_CTRL_REG, BIT(1), BIT(9));\n\n\treturn SUCCESS;\n}\n\nstatic void\nsun9i_a80_twd_release(const struct device *dev)\n{\n\tconst struct simple_device *self = to_simple_device(dev);\n\n\t/* Disable system reset; stop the watchdog counter. */\n\tmmio_clrset_32(self->regs + TWD_CTRL_REG, BIT(9), BIT(1));\n\n\tsimple_device_release(dev);\n}\n\nstatic const struct watchdog_driver sun9i_a80_twd_driver = {\n\t.drv = {\n\t\t.probe   = sun9i_a80_twd_probe,\n\t\t.release = sun9i_a80_twd_release,\n\t},\n\t.ops = {\n\t\t.reset_system = sun9i_a80_twd_reset_system,\n\t\t.restart      = sun9i_a80_twd_restart,\n\t},\n};\n\nconst struct simple_device r_twd = {\n\t.dev = {\n\t\t.name  = \"r_twd\",\n\t\t.drv   = &sun9i_a80_twd_driver.drv,\n\t\t.state = DEVICE_STATE_INIT,\n\t},\n\t.clock = { .dev = &r_ccu.dev, .id = CLK_BUS_R_TWD },\n\t.regs  = DEV_R_TWD,\n};\n"
  },
  {
    "path": "drivers/watchdog/watchdog.c",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <device.h>\n#include <intrusive.h>\n#include <stdint.h>\n#include <watchdog.h>\n#include <watchdog/sun6i-a31-wdt.h>\n#include <watchdog/sun9i-a80-twd.h>\n\n#include \"watchdog.h\"\n\n/**\n * Get the ops for the watchdog controller device.\n */\nstatic inline const struct watchdog_driver_ops *\nwatchdog_ops_for(const struct device *dev)\n{\n\tconst struct watchdog_driver *drv =\n\t\tcontainer_of(dev->drv, const struct watchdog_driver, drv);\n\n\treturn &drv->ops;\n}\n\nconst struct device *\nwatchdog_get(void)\n{\n\tconst struct device *watchdog = NULL;\n\n\tif (CONFIG(WATCHDOG_SUN6I_A31_WDT))\n\t\twatchdog = device_get_or_null(&r_wdog.dev);\n\tif (CONFIG(WATCHDOG_SUN9I_A80_TWD))\n\t\twatchdog = device_get_or_null(&r_twd.dev);\n\n\treturn watchdog;\n}\n\nvoid\nwatchdog_reset_system(const struct device *dev)\n{\n\twatchdog_ops_for(dev)->reset_system(dev);\n}\n\nvoid\nwatchdog_restart(const struct device *dev)\n{\n\twatchdog_ops_for(dev)->restart(dev);\n}\n"
  },
  {
    "path": "drivers/watchdog/watchdog.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef WATCHDOG_PRIVATE_H\n#define WATCHDOG_PRIVATE_H\n\n#include <device.h>\n#include <stdint.h>\n\nstruct watchdog_driver_ops {\n\tvoid (*reset_system)(const struct device *dev);\n\tvoid (*restart)(const struct device *dev);\n};\n\nstruct watchdog_driver {\n\tstruct driver              drv;\n\tstruct watchdog_driver_ops ops;\n};\n\n#endif /* WATCHDOG_PRIVATE_H */\n"
  },
  {
    "path": "include/common/debug.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef COMMON_DEBUG_H\n#define COMMON_DEBUG_H\n\n#include <stdint.h>\n#include <trap.h>\n\n#define LOG_STRING_ERROR   \"\\x01\"\n#define LOG_STRING_WARNING \"\\x02\"\n#define LOG_STRING_INFO    \"\\x03\"\n#define LOG_STRING_DEBUG   \"\\x04\"\n\n#if CONFIG(ASSERT)\n#if CONFIG(ASSERT_VERBOSE)\n#define assert(e) ((void)((e) || (error(\"Assertion failed: %s (%s:%d)\", #e, \\\n\t                                __FILE__, __LINE__), trap(), 0)))\n#else\n#define assert(e) ((void)((e) || (trap(), 0)))\n#endif\n#else\n#define assert(e) ((void)0)\n#endif\n\nenum {\n\tLOG_LEVEL_ERROR,\n\tLOG_LEVEL_WARNING,\n\tLOG_LEVEL_INFO,\n\tLOG_LEVEL_DEBUG,\n\tLOG_LEVELS\n};\n\nvoid hexdump(uintptr_t addr, uint32_t bytes);\nvoid log(const char *fmt, ...) ATTRIBUTE(format(printf, 1, 2));\n\n#define panic(...) (error(__VA_ARGS__), trap())\n#define error(...) log(LOG_STRING_ERROR __VA_ARGS__)\n#define warn(...)  log(LOG_STRING_WARNING __VA_ARGS__)\n#define info(...)  log(LOG_STRING_INFO __VA_ARGS__)\n#if CONFIG(DEBUG_LOG)\n#define debug(...) log(LOG_STRING_DEBUG __VA_ARGS__)\n#else\n#define debug(...) ((void)0)\n#endif\n\n#if CONFIG(DEBUG_MONITOR)\n\nvoid debug_monitor(void);\n\n#else\n\nstatic inline void\ndebug_monitor(void)\n{\n}\n\n#endif\n\n#if CONFIG(DEBUG_PRINT_BATTERY)\n\nvoid debug_print_battery(void);\n\n#else\n\nstatic inline void\ndebug_print_battery(void)\n{\n}\n\n#endif\n\n#if CONFIG(DEBUG_PRINT_LATENCY)\n\nvoid debug_print_latency(uint8_t current_state);\n\n#else\n\nstatic inline void\ndebug_print_latency(uint8_t current_state UNUSED)\n{\n}\n\n#endif\n\n#if CONFIG(DEBUG_PRINT_SPRS)\n\nvoid debug_print_sprs(void);\n\n#else\n\nstatic inline void\ndebug_print_sprs(void)\n{\n}\n\n#endif\n\n#if CONFIG(DEBUG_VERIFY_DRAM)\n\nvoid dram_save_checksum(void);\nvoid dram_verify_checksum(void);\n\n#else\n\nstatic inline void\ndram_save_checksum(void)\n{\n}\n\nstatic inline void\ndram_verify_checksum(void)\n{\n}\n\n#endif\n\n#endif /* COMMON_DEBUG_H */\n"
  },
  {
    "path": "include/common/delay.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef COMMON_DELAY_H\n#define COMMON_DELAY_H\n\n#include <stdint.h>\n\n/**\n * Spin (do nothing) for at least the given number of microseconds.\n *\n * @param useconds The number of microseconds to delay for.\n */\nvoid udelay(uint32_t useconds);\n\n#endif /* COMMON_DELAY_H */\n"
  },
  {
    "path": "include/common/device.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef COMMON_DEVICE_H\n#define COMMON_DEVICE_H\n\n#include <stdbool.h>\n#include <stdint.h>\n\n/**\n * Default initializer for the device state pointer.\n *\n * The state pointer must be initialized for all devices. If additional mutable\n * state is needed, wrap struct device_state intrusively. Otherwise, use this\n * macro.\n */\n#define DEVICE_STATE_INIT &(struct device_state) { 0 }\n\nstruct device_state;\nstruct driver;\n\nstruct device {\n\t/** A unique name for this device. */\n\tconst char          *name;\n\t/** The driver for this device. */\n\tconst struct driver *drv;\n\t/** Mutable state for this device. */\n\tstruct device_state *state;\n};\n\nstruct device_state {\n\t/** Reference count for this device. */\n\tuint8_t refcount;\n};\n\nstruct driver {\n\t/** A function called to detect and initialize new devices. */\n\tint  (*probe)(const struct device *dev);\n\t/** A function called to uninitialize devices and free resources. */\n\tvoid (*release)(const struct device *dev);\n};\n\n/**\n * Determine if a device is active (if it has any outstanding references).\n *\n * @param dev A device.\n * @return    The state of the device.\n */\nbool device_active(const struct device *dev);\n\n/**\n * Get a reference to a device.\n *\n * If this is the first reference to a device, that device's driver will be\n * initialized. Otherwise, this function only updates the reference count.\n *\n * The device will remain running as long as the reference is held (that is,\n * until calling device_put()).\n *\n * If this function returns an error, do not call device_put().\n *\n * @param dev A device.\n *\n * @return Zero on success; an error code on failure.\n */\nint device_get(const struct device *dev);\n\n/**\n * Get a reference to a device.\n *\n * @return A reference to the device that was acquired, or a NULL pointer.\n */\nconst struct device *device_get_or_null(const struct device *dev);\n\n/**\n * Release a reference to a device.\n *\n * @param dev A reference to a device.\n */\nvoid device_put(const struct device *dev);\n\n/**\n * Implementation of the device probe function that does nothing.\n */\nint dummy_probe(const struct device *dev);\n\n/**\n * Implementation of the device release function that does nothing.\n */\nvoid dummy_release(const struct device *dev);\n\n#endif /* COMMON_DEVICE_H */\n"
  },
  {
    "path": "include/common/regulator_list.h",
    "content": "/*\n * Copyright © 2020-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef COMMON_REGULATOR_LIST_H\n#define COMMON_REGULATOR_LIST_H\n\n#include <regulator.h>\n\n/**\n * The regulator supplying VDD-CPUX.\n */\nextern const struct regulator_handle cpu_supply;\n\n/**\n * The regulator supplying VCC-DRAM.\n */\nextern const struct regulator_handle dram_supply;\n\n/**\n * The regulator supplying VCC-PLL.\n */\nextern const struct regulator_handle vcc_pll_supply;\n\n/**\n * The regulator supplying VDD-SYS.\n */\nextern const struct regulator_handle vdd_sys_supply;\n\n#endif /* COMMON_REGULATOR_LIST_H */\n"
  },
  {
    "path": "include/common/scpi.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef COMMON_SCPI_H\n#define COMMON_SCPI_H\n\n#include <scpi_protocol.h>\n#include <stdbool.h>\n#include <stdint.h>\n\n/**\n * The SCPI implementation has two clients: Linux and ATF. CPU/cluster and\n * system power state change requests are required to go through PSCI, so ATF\n * can coordinate with the secure OS (if present). These requests must only be\n * allowed if they arrive on the \"secure\" channel.\n */\nenum {\n\tSCPI_CLIENT_EL3 = 0, /**< Client 0: Secure EL3 (ATF). */\n\tSCPI_CLIENT_EL2 = 1, /**< Client 1: Nonsec EL2 (Linux). */\n\tSCPI_CLIENTS,\n};\n\n/**\n * Create and send an SCPI message. This is used for commands initiated by the\n * SCP.\n *\n * @param mailbox The mailbox used to send the message.\n * @param client  The client that should receive the message.\n * @param command The command number to include in the message.\n */\nvoid scpi_create_message(const struct device *mailbox, uint8_t client,\n                         uint8_t command);\n\n/**\n * Handle a received SCPI command. This function parses the message, performs\n * any requested actions, and possibly generates a reply message.\n *\n * @param  client The client from which the message was received.\n * @param  mem    The shared memory area containing the request and reply.\n * @return If the reply message is valid and should be sent to the client.\n */\nbool scpi_handle_cmd(uint8_t client, struct scpi_mem *mem);\n\n/**\n * Handle incoming SCPI commands and send replies as buffers become available.\n */\nvoid scpi_poll(const struct device *mailbox);\n\n#endif /* COMMON_SCPI_H */\n"
  },
  {
    "path": "include/common/simple_device.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef COMMON_SIMPLE_DEVICE_H\n#define COMMON_SIMPLE_DEVICE_H\n\n#include <clock.h>\n#include <device.h>\n#include <gpio.h>\n#include <intrusive.h>\n\n#define SIMPLE_DEVICE_PINS      2\n#define SIMPLE_DEVICE_PINS_INIT (const struct gpio_handle[SIMPLE_DEVICE_PINS])\n\nstruct simple_device {\n\tstruct device             dev;\n\tstruct clock_handle       clock;\n\tconst struct gpio_handle *pins;\n\tuintptr_t                 regs;\n};\n\n/**\n * Downcast a pointer to a simple device.\n */\nstatic inline const struct simple_device *\nto_simple_device(const struct device *dev)\n{\n\treturn container_of(dev, const struct simple_device, dev);\n}\n\n/**\n * Probe a simple device, which uses a clock and 0-2 GPIO pins.\n *\n * This function can be used to implement a device's .probe hook.\n */\nint simple_device_probe(const struct device *dev);\n\n/**\n * Release a simple device.\n *\n * This function can be used to implement a device's .release hook.\n */\nvoid simple_device_release(const struct device *dev);\n\n/**\n * Adjust the refcount of a device to match the state Linux left it in.\n *\n * If a device has no references, but its clock is running, acquire a\n * persistent reference to prevent the device and its resources from being\n * released.\n *\n * Similarly, if the only reference to a device is one previously acquired by\n * this function, and the device's clock is not running, release the reference.\n *\n * This function must not be called if other references to the device are held.\n */\nvoid simple_device_sync(const struct simple_device *sdev);\n\n#endif /* COMMON_SIMPLE_DEVICE_H */\n"
  },
  {
    "path": "include/common/steps.h",
    "content": "/*\n * Copyright © 2021-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef COMMON_STEPS_H\n#define COMMON_STEPS_H\n\n#include <stdint.h>\n#include <version.h>\n\n#define STEP_KIND(n) (VERSION_MAJOR << 12 | VERSION_MINOR << 8 | (n) << 4)\n\nenum {\n\tSTEP_NONE,\n\tSTEP_SUSPEND = STEP_KIND(0),\n\tSTEP_SUSPEND_CORE,\n\tSTEP_SUSPEND_CLUSTER,\n\tSTEP_SUSPEND_CSS,\n\tSTEP_SUSPEND_DEVICES,\n\tSTEP_SUSPEND_DRAM,\n\tSTEP_SUSPEND_CCU,\n\tSTEP_SUSPEND_PRCM,\n\tSTEP_SUSPEND_PMIC,\n\tSTEP_SUSPEND_REGULATORS,\n\tSTEP_SUSPEND_COMPLETE,\n\tSTEP_RESUME = STEP_KIND(1),\n\tSTEP_RESUME_PMIC,\n\tSTEP_RESUME_REGULATORS,\n\tSTEP_RESUME_PRCM,\n\tSTEP_RESUME_CCU,\n\tSTEP_RESUME_DRAM,\n\tSTEP_RESUME_DRAM_CHECKSUM,\n\tSTEP_RESUME_DEVICES,\n\tSTEP_RESUME_CSS,\n\tSTEP_RESUME_COMPLETE,\n};\n\n#if CONFIG(DEBUG_RECORD_STEPS)\n\nvoid record_exception(uint32_t exception, uint32_t pc);\nvoid record_step(uint32_t step);\nvoid report_last_step(void);\n\n#else\n\nstatic inline void\nrecord_exception(uint32_t exception UNUSED, uint32_t pc UNUSED)\n{\n}\n\nstatic inline void\nrecord_step(uint32_t step UNUSED)\n{\n}\n\nstatic inline void\nreport_last_step(void)\n{\n}\n\n#endif\n\n#endif /* COMMON_STEPS_H */\n"
  },
  {
    "path": "include/common/system.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef COMMON_SYSTEM_H\n#define COMMON_SYSTEM_H\n\n#include <stdint.h>\n\nenum {\n\tSD_NONE,    /**< Perform no extra suspend actions. */\n\tSD_OSC24M,  /**< Power down the high-speed oscillator and PLLs. */\n\tSD_AVCC,    /**< Gate the AVCC power domain. */\n\tSD_VDD_SYS, /**< Gate and reset the VDD_SYS power domain. */\n};\n\n/**\n * Perform system state management.\n *\n * This is the main loop of the firmware, which never returns.\n *\n * @param exception Exception information provided by startup assembly code.\n */\nnoreturn void system_state_machine(uint32_t exception);\n\n/**\n * Reboot the board, including the SoC and external peripherals.\n *\n * Must only be called while the system is awake.\n */\nvoid system_reboot(void);\n\n/**\n * Reset the SoC, including all CPUs and internal peripherals.\n *\n * Must only be called while the system is awake.\n */\nvoid system_reset(void);\n\n/**\n * Shut down the SoC, and turn off all possible power domains.\n *\n * Must only be called while the system is awake.\n */\nvoid system_shutdown(void);\n\n/**\n * Suspend the SoC, and turn off all non-wakeup power domains.\n *\n * Must only be called while the system is awake.\n */\nvoid system_suspend(void);\n\n/**\n * Wake the system.\n *\n * Transition to a state where the rich OS is awake and running, by resetting\n * the SoC or the entire board if necessary.\n *\n * May be called at any time.\n */\nvoid system_wake(void);\n\n#endif /* COMMON_SYSTEM_H */\n"
  },
  {
    "path": "include/common/timeout.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef COMMON_TIMEOUT_H\n#define COMMON_TIMEOUT_H\n\n#include <stdbool.h>\n#include <stdint.h>\n\n#define USEC_PER_MSEC 1000U\n#define USEC_PER_SEC  1000000U\n\n/**\n * Check if a timeout has expired.\n *\n * @param timeout The timeout.\n * @return        Whether or not the timeout has expired.\n */\nbool timeout_expired(uint32_t timeout);\n\n/**\n * Set a timeout for some point in the near future.\n *\n * Timeouts must not be set for greater than approximately one minute.\n *\n * @param useconds The delay in microseconds before the timeout expires.\n * @return         An opaque number that can be passed to timeout_expired().\n */\nuint32_t timeout_set(uint32_t useconds);\n\n#endif /* COMMON_TIMEOUT_H */\n"
  },
  {
    "path": "include/drivers/cec/dw-hdmi-cec.h",
    "content": "/*\n * Copyright © 2021-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef DRIVERS_CEC_DW_HDMI_CEC_H\n#define DRIVERS_CEC_DW_HDMI_CEC_H\n\n#include <clock.h>\n#include <device.h>\n#include <stdint.h>\n\nstruct dw_hdmi_cec {\n\tstruct device       dev;\n\tstruct clock_handle bus_clock;\n\tuintptr_t           regs;\n};\n\nextern const struct dw_hdmi_cec hdmi_cec;\n\nuint32_t dw_hdmi_cec_poll(const struct device *dev);\n\n#endif /* DRIVERS_CEC_DW_HDMI_CEC_H */\n"
  },
  {
    "path": "include/drivers/cec.h",
    "content": "/*\n * Copyright © 2021-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef DRIVERS_CEC_H\n#define DRIVERS_CEC_H\n\n#include <device.h>\n#include <stddef.h>\n#include <stdint.h>\n\n#if CONFIG(CEC)\n\n/**\n * Acquire a reference to the CEC receiver device suitable for polling.\n *\n * The reference must be released before resuming the rich OS.\n *\n * @return    A reference to the CEC receiver device.\n */\nconst struct device *cec_get(void);\n\n/**\n * Check the CEC receiver for a wakeup condition.\n *\n * @param dev A reference to the CEC receiver device.\n * @return    Nonzero if the system should wake up, else zero.\n */\nuint32_t cec_poll(const struct device *dev);\n\n#else\n\nstatic inline const struct device *\ncec_get(void)\n{\n\treturn NULL;\n}\n\nstatic inline uint32_t\ncec_poll(const struct device *dev UNUSED)\n{\n\treturn 0;\n}\n\n#endif\n\n#endif /* DRIVERS_CEC_H */\n"
  },
  {
    "path": "include/drivers/cir/sunxi-cir.h",
    "content": "/*\n * Copyright © 2020-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef DRIVERS_CIR_SUNXI_CIR_H\n#define DRIVERS_CIR_SUNXI_CIR_H\n\n#include <clock.h>\n#include <device.h>\n#include <gpio.h>\n#include <stdint.h>\n\nstruct sunxi_cir {\n\tstruct device       dev;\n\tstruct clock_handle bus_clock;\n\tstruct clock_handle mod_clock;\n\tstruct gpio_handle  pin;\n\tuintptr_t           regs;\n};\n\nextern const struct sunxi_cir r_cir_rx;\n\nuint32_t sunxi_cir_poll(const struct device *dev);\n\n#endif /* DRIVERS_CIR_SUNXI_CIR_H */\n"
  },
  {
    "path": "include/drivers/cir.h",
    "content": "/*\n * Copyright © 2020-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef DRIVERS_CIR_H\n#define DRIVERS_CIR_H\n\n#include <device.h>\n#include <stddef.h>\n#include <stdint.h>\n\n#if CONFIG(CIR)\n\n/**\n * Acquire a reference to the CIR receiver device suitable for polling.\n *\n * The reference must be released before resuming the rich OS.\n *\n * @return    A reference to the CIR receiver device.\n */\nconst struct device *cir_get(void);\n\n/**\n * Check the CIR receiver for a wakeup condition.\n *\n * @param dev A reference to the CIR receiver device.\n * @return    Nonzero if the system should wake up, else zero.\n */\nuint32_t cir_poll(const struct device *dev);\n\n#else\n\nstatic inline const struct device *\ncir_get(void)\n{\n\treturn NULL;\n}\n\nstatic inline uint32_t\ncir_poll(const struct device *dev UNUSED)\n{\n\treturn 0;\n}\n\n#endif\n\n#endif /* DRIVERS_CIR_H */\n"
  },
  {
    "path": "include/drivers/clock/ccu.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef DRIVERS_CLOCK_CCU_H\n#define DRIVERS_CLOCK_CCU_H\n\n#include <clock.h>\n#include <device.h>\n#if CONFIG(PLATFORM_A23)\n#include <clock/sun8i-a23-ccu.h>\n#include <clock/sun8i-r-ccu.h>\n#elif CONFIG(PLATFORM_A64)\n#include <clock/sun50i-a64-ccu.h>\n#include <clock/sun8i-r-ccu.h>\n#elif CONFIG(PLATFORM_A83T)\n#include <clock/sun8i-a83t-ccu.h>\n#include <clock/sun8i-r-ccu.h>\n#elif CONFIG(PLATFORM_H3)\n#include <clock/sun8i-h3-ccu.h>\n#include <clock/sun8i-r-ccu.h>\n#elif CONFIG(PLATFORM_H6)\n#include <clock/sun50i-h6-ccu.h>\n#include <clock/sun50i-h6-r-ccu.h>\n#endif\n\nstruct ccu {\n\tstruct device           dev;\n\tconst struct ccu_clock *clocks;\n\tuintptr_t               regs;\n};\n\nextern const struct ccu ccu;\nextern const struct ccu r_ccu;\n\nvoid ccu_suspend(void);\nvoid ccu_suspend_cluster(uint32_t cluster);\nvoid ccu_resume(void);\nvoid ccu_resume_cluster(uint32_t cluster);\nvoid ccu_init(void);\n\nvoid r_ccu_suspend(uint8_t depth);\nvoid r_ccu_resume(void);\nvoid r_ccu_init(void);\n\n#endif /* DRIVERS_CLOCK_CCU_H */\n"
  },
  {
    "path": "include/drivers/clock/sun50i-a64-ccu.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef DRIVERS_CLOCK_SUN50I_A64_CCU_H\n#define DRIVERS_CLOCK_SUN50I_A64_CCU_H\n\nenum {\n\tCLK_PLL_CPUX,\n\tCLK_PLL_DDR0,\n\tCLK_PLL_PERIPH0,\n#if CONFIG(SOC_A64)\n\tCLK_PLL_DDR1,\n#endif\n\tCLK_APB2,\n\tCLK_BUS_DRAM,\n\tCLK_BUS_MSGBOX,\n\tCLK_BUS_PIO,\n#if CONFIG(SERIAL_DEV_UART0)\n\tCLK_BUS_UART0,\n#elif CONFIG(SERIAL_DEV_UART1)\n\tCLK_BUS_UART1,\n#elif CONFIG(SERIAL_DEV_UART2)\n\tCLK_BUS_UART2,\n#elif CONFIG(SERIAL_DEV_UART3)\n\tCLK_BUS_UART3,\n#elif CONFIG(SERIAL_DEV_UART4) /* depends on SOC_A64 */\n\tCLK_BUS_UART4,\n#endif\n\tCLK_DRAM,\n\tCLK_MBUS,\n\tSUN50I_A64_CCU_CLOCKS\n};\n\n#endif /* DRIVERS_CLOCK_SUN50I_A64_CCU_H */\n"
  },
  {
    "path": "include/drivers/clock/sun50i-h6-ccu.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef DRIVERS_CLOCK_SUN50I_H6_CCU_H\n#define DRIVERS_CLOCK_SUN50I_H6_CCU_H\n\nenum {\n\tCLK_PLL_DDR0,\n\tCLK_PLL_PERIPH0,\n\tCLK_APB2,\n\tCLK_MBUS,\n\tCLK_BUS_MSGBOX,\n\tCLK_DRAM,\n\tCLK_BUS_DRAM,\n\tCLK_BUS_PIO,\n#if CONFIG(SERIAL_DEV_UART0)\n\tCLK_BUS_UART0,\n#elif CONFIG(SERIAL_DEV_UART1)\n\tCLK_BUS_UART1,\n#elif CONFIG(SERIAL_DEV_UART2)\n\tCLK_BUS_UART2,\n#elif CONFIG(SERIAL_DEV_UART3)\n\tCLK_BUS_UART3,\n#endif\n\tSUN50I_H6_CCU_CLOCKS\n};\n\n#endif /* DRIVERS_CLOCK_SUN50I_H6_CCU_H */\n"
  },
  {
    "path": "include/drivers/clock/sun50i-h6-r-ccu.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef DRIVERS_CLOCK_SUN50I_H6_R_CCU_H\n#define DRIVERS_CLOCK_SUN50I_H6_R_CCU_H\n\nenum {\n\tCLK_IOSC,\n\tCLK_OSC24M,\n\tCLK_OSC32K,\n\tCLK_AR100,\n\tCLK_R_AHB,\n\tCLK_R_APB1,\n\tCLK_R_APB2,\n\tCLK_BUS_R_PIO,\n\tCLK_BUS_R_TIMER,\n\tCLK_BUS_R_TWD,\n\tCLK_BUS_R_PWM,\n\tCLK_BUS_R_UART,\n\tCLK_BUS_R_I2C,\n\tCLK_BUS_R_RSB,\n\tCLK_BUS_R_CIR,\n\tCLK_BUS_R_W1,\n\tCLK_R_CIR,\n\tCLK_R_W1,\n\tSUN50I_H6_R_CCU_CLOCKS\n};\n\n#endif /* DRIVERS_CLOCK_SUN50I_H6_R_CCU_H */\n"
  },
  {
    "path": "include/drivers/clock/sun8i-a23-ccu.h",
    "content": "/*\n * Copyright © 2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef DRIVERS_CLOCK_SUN8I_A23_CCU_H\n#define DRIVERS_CLOCK_SUN8I_A23_CCU_H\n\nenum {\n\tCLK_PLL_CPUX,\n\tCLK_PLL_DDR0,\n\tCLK_PLL_PERIPH0,\n\tCLK_PLL_DDR1,\n\tCLK_APB2,\n\tCLK_BUS_DRAM,\n\tCLK_BUS_MSGBOX,\n\tCLK_BUS_PIO,\n#if CONFIG(SERIAL_DEV_UART0)\n\tCLK_BUS_UART0,\n#elif CONFIG(SERIAL_DEV_UART1)\n\tCLK_BUS_UART1,\n#elif CONFIG(SERIAL_DEV_UART2)\n\tCLK_BUS_UART2,\n#elif CONFIG(SERIAL_DEV_UART3)\n\tCLK_BUS_UART3,\n#elif CONFIG(SERIAL_DEV_UART4) /* depends on SOC_A23 */\n\tCLK_BUS_UART4,\n#endif\n\tCLK_DRAM,\n\tCLK_MBUS,\n\tSUN8I_A23_CCU_CLOCKS\n};\n\n#endif /* DRIVERS_CLOCK_SUN8I_A23_CCU_H */\n"
  },
  {
    "path": "include/drivers/clock/sun8i-a83t-ccu.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef DRIVERS_CLOCK_SUN8I_A83T_CCU_H\n#define DRIVERS_CLOCK_SUN8I_A83T_CCU_H\n\nenum {\n\tCLK_PLL_PERIPH0,\n\tCLK_APB2,\n\tCLK_BUS_MSGBOX,\n\tCLK_BUS_PIO,\n#if CONFIG(SERIAL_DEV_UART0)\n\tCLK_BUS_UART0,\n#elif CONFIG(SERIAL_DEV_UART1)\n\tCLK_BUS_UART1,\n#elif CONFIG(SERIAL_DEV_UART2)\n\tCLK_BUS_UART2,\n#elif CONFIG(SERIAL_DEV_UART3)\n\tCLK_BUS_UART3,\n#elif CONFIG(SERIAL_DEV_UART4)\n\tCLK_BUS_UART4,\n#endif\n\tSUN8I_A83T_CCU_CLOCKS\n};\n\n#endif /* DRIVERS_CLOCK_SUN8I_A83T_CCU_H */\n"
  },
  {
    "path": "include/drivers/clock/sun8i-h3-ccu.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef DRIVERS_CLOCK_SUN8I_H3_CCU_H\n#define DRIVERS_CLOCK_SUN8I_H3_CCU_H\n\nenum {\n\tCLK_PLL_CPUX,\n\tCLK_PLL_DDR0,\n\tCLK_PLL_PERIPH0,\n\tCLK_APB2,\n\tCLK_BUS_DRAM,\n\tCLK_BUS_MSGBOX,\n\tCLK_BUS_PIO,\n#if CONFIG(SERIAL_DEV_UART0)\n\tCLK_BUS_UART0,\n#elif CONFIG(SERIAL_DEV_UART1)\n\tCLK_BUS_UART1,\n#elif CONFIG(SERIAL_DEV_UART2)\n\tCLK_BUS_UART2,\n#elif CONFIG(SERIAL_DEV_UART3)\n\tCLK_BUS_UART3,\n#endif\n\tCLK_DRAM,\n\tCLK_MBUS,\n\tSUN8I_H3_CCU_CLOCKS\n};\n\n#endif /* DRIVERS_CLOCK_SUN8I_H3_CCU_H */\n"
  },
  {
    "path": "include/drivers/clock/sun8i-r-ccu.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef DRIVERS_CLOCK_SUN8I_R_CCU_H\n#define DRIVERS_CLOCK_SUN8I_R_CCU_H\n\nenum {\n\tCLK_IOSC,\n\tCLK_OSC24M,\n\tCLK_OSC32K,\n\tCLK_AR100,\n\tCLK_AHB0,\n\tCLK_APB0,\n\tCLK_BUS_R_PIO,\n#if CONFIG(HAVE_R_CIR)\n\tCLK_BUS_R_CIR,\n#endif\n\tCLK_BUS_R_TIMER,\n#if CONFIG(HAVE_R_RSB)\n\tCLK_BUS_R_RSB,\n#endif\n\tCLK_BUS_R_UART,\n\tCLK_BUS_R_I2C,\n#if CONFIG(HAVE_R_TWD)\n\tCLK_BUS_R_TWD,\n#endif\n\tCLK_R_CIR,\n\tSUN8I_R_CCU_CLOCKS\n};\n\n#endif /* DRIVERS_CLOCK_SUN8I_R_CCU_H */\n"
  },
  {
    "path": "include/drivers/clock.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef DRIVERS_CLOCK_H\n#define DRIVERS_CLOCK_H\n\n#include <device.h>\n#include <stdint.h>\n\nenum {\n\tCLOCK_STATE_DISABLED,\n\tCLOCK_STATE_GATED,\n\tCLOCK_STATE_ENABLED,\n};\n\nstruct clock_handle {\n\tconst struct device *dev; /**< The clock controller device. */\n\tuint8_t              id;  /**< The device-specific clock identifier. */\n};\n\n/**\n * Determine if a clock is active.\n *\n * A clock is active if it has any outstanding references. The state of the\n * hardware gate, if any, is not considered.\n *\n * @param clock A reference to a clock.\n * @return      The state of the clock.\n */\nbool clock_active(const struct clock_handle *clock);\n\n/**\n * Disable a clock.\n *\n * If the clock does not have a gate, this may have no effect on the hardware.\n * The clock's parent, if any, will be left as it is.\n *\n * @param clock A reference to a clock.\n */\nvoid clock_disable(const struct clock_handle *clock);\n\n/**\n * Enable a clock.\n *\n * If the clock does not have a gate, this may have no effect on the hardware.\n * The clock's parent, if any, will also be enabled.\n *\n * @param clock A reference to a clock.\n */\nvoid clock_enable(const struct clock_handle *clock);\n\n/**\n * Get a reference to a clock and its controller device, and enable the clock.\n *\n * If the clock does not have a gate, this may have no effect on the hardware.\n * The clock's parent, if any, will also be enabled.\n *\n * @param clock A handle specifying the clock.\n */\nvoid clock_get(const struct clock_handle *clock);\n\n/**\n * Get the current rate of a clock, as calculated from the hardware.\n *\n * This function returns the frequency the clock runs at when ungated,\n * regardless of if the clock is currently gated.\n *\n * @param clock A reference to a clock.\n * @return      The clock frequency in Hz.\n */\nuint32_t clock_get_rate(const struct clock_handle *clock);\n\n/**\n * Get the current state of a clock, as determined from the hardware.\n *\n * @param clock A reference to a clock.\n * @return      One of the enumerated clock states.\n */\nuint32_t clock_get_state(const struct clock_handle *clock);\n\n/**\n * Release a reference to a clock and its controller device.\n *\n * If this is the last reference to a clock, that clock (and its ancestors\n * recursively, if they have no other consumers) will be disabled.\n *\n * @param clock A reference to a clock.\n */\nvoid clock_put(const struct clock_handle *clock);\n\n#endif /* DRIVERS_CLOCK_H */\n"
  },
  {
    "path": "include/drivers/counter.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef DRIVERS_COUNTER_H\n#define DRIVERS_COUNTER_H\n\n#include <stdint.h>\n\n/**\n * Initialize the cycle counter.\n *\n * This function must be called once before attempting to read the cycle\n * counter. Note that the delay and timeout libraries use the cycle counter.\n */\nvoid cycle_counter_init(void);\n\n/**\n * Read the cycle counter.\n *\n * This counter is at least 32 bits wide and runs at the CPU clock frequency.\n */\nuint32_t cycle_counter_read(void);\n\n/**\n * Read the system counter.\n *\n * This counter is at least 32 bits wide and runs at the platform's reference\n * clock frequency (usually 24 MHz). Note that this clock may be unavailable\n * while the system is off or asleep.\n */\nuint32_t system_counter_read(void);\n\n#endif /* DRIVERS_COUNTER_H */\n"
  },
  {
    "path": "include/drivers/css.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef COMMON_CSS_H\n#define COMMON_CSS_H\n\n#include <stdint.h>\n\n/**\n * Get the number of clusters in the compute subsystem.\n *\n * The number returned cannot be greater than 8.\n */\nuint32_t css_get_cluster_count(void) ATTRIBUTE(const);\n\n/**\n * Get the state of a cluster and the cores it contains.\n *\n * The state of the cluster is returned in cluster_state.\n *\n * A bitmap representing the state of each core in the cluster is returned in\n * online_cores. A zero bit indicates that a core is completely off (it has no\n * execution context). Any other state is represented by a set bit.\n *\n * @param cluster       The index of the cluster.\n * @param cluster_state Where to store the cluster state.\n * @param online_cores  Where to store the bitmap of online cores.\n * @return              An SCPI success or error status.\n */\nint css_get_power_state(uint32_t cluster, uint32_t *cluster_state,\n                        uint32_t *online_cores);\n\n/**\n * Initialize the CSS driver, assuming the CSS is already running. Since the\n * firmware starts after the CSS, the driver may need to synchronize its state\n * with the actual state of the hardware.\n */\nvoid css_init(void);\n\n/**\n * Set the state of a CPU core and its ancestor power domains. There are no\n * restrictions on the requested power states; the best available power state\n * will be computed for each power domain.\n *\n * @param cluster       The index of the cluster.\n * @param core          The index of the core within the cluster.\n * @param core_state    The requested power state for the core.\n * @param cluster_state The requested power state for the core's cluster.\n * @param css_state     The requested power state for the CSS.\n * @return              An SCPI success or error status.\n */\nint css_set_power_state(uint32_t cluster, uint32_t core, uint32_t core_state,\n                        uint32_t cluster_state, uint32_t css_state);\n\n/**\n * Resume execution on the most recently active core in the CSS.\n */\nvoid css_resume(void);\n\n/**\n * Poll for CPUs that must wake up to handle pending IRQs.\n */\nvoid css_poll(void);\n\n#endif /* COMMON_CSS_H */\n"
  },
  {
    "path": "include/drivers/dram.h",
    "content": "/*\n * Copyright © 2020-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef DRIVERS_DRAM_H\n#define DRIVERS_DRAM_H\n\n/**\n * Initialize the DRAM controller driver.\n */\nvoid dram_init(void);\n\n/**\n * Resume the DRAM controller and exit self-refresh.\n */\nvoid dram_resume(void);\n\n/**\n * Enter self-refresh and suspend the DRAM controller.\n */\nvoid dram_suspend(void);\n\n#endif /* DRIVERS_DRAM_H */\n"
  },
  {
    "path": "include/drivers/gpio/sunxi-gpio.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef DRIVERS_GPIO_SUNXI_GPIO_H\n#define DRIVERS_GPIO_SUNXI_GPIO_H\n\n#include <gpio.h>\n#include <simple_device.h>\n\n#define SUNXI_GPIO_PIN(port, pin) (32 * (port) + (pin))\n\nenum {\n\tDRIVE_10mA = 0,\n\tDRIVE_20mA = 1,\n\tDRIVE_30mA = 2,\n\tDRIVE_40mA = 3,\n};\n\nenum {\n\tMODE_INPUT   = 0,\n\tMODE_OUTPUT  = 1,\n\tMODE_DISABLE = 7,\n};\n\nenum {\n\tPULL_NONE = 0,\n\tPULL_UP   = 1,\n\tPULL_DOWN = 2,\n};\n\nextern const struct simple_device pio;\nextern const struct simple_device r_pio;\n\n#endif /* DRIVERS_GPIO_SUNXI_GPIO_H */\n"
  },
  {
    "path": "include/drivers/gpio.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef DRIVERS_GPIO_H\n#define DRIVERS_GPIO_H\n\n#include <device.h>\n#include <stdbool.h>\n#include <stdint.h>\n\nstruct gpio_handle {\n\tconst struct device *dev;\n\tuint8_t              id;\n\tuint8_t              drive;\n\tuint8_t              mode;\n\tuint8_t              pull;\n};\n\n/**\n * Get a reference to a GPIO pin and its controller device, and set up the pin.\n *\n * The pin's mode, drive strength, and pull-up or pull-down will be set based\n * on the values in the handle.\n *\n * @param gpio A handle specifying the GPIO pin.\n * @return     Zero on success; an error code on failure.\n */\nint gpio_get(const struct gpio_handle *gpio);\n\n/**\n * Get the value of a GPIO pin.\n *\n * If the pin mode is not \"input\", this may not get the actual hardware state.\n *\n * @param gpio  A reference to a GPIO pin.\n * @param value The location to store the value read from the pin.\n * @return      Zero on success; an error code on failure.\n */\nint gpio_get_value(const struct gpio_handle *gpio, bool *value);\n\n/**\n * Release a reference to a GPIO pin and its controller device.\n *\n * If this is the last reference to a GPIO pin, that pin will be disabled.\n *\n * @param gpio A reference to a GPIO pin.\n */\nvoid gpio_put(const struct gpio_handle *gpio);\n\n/**\n * Set the value of a GPIO pin.\n *\n * If the pin mode is not \"output\", this may have no effect on the hardware.\n *\n * @param gpio  A reference to a GPIO pin.\n * @param value The value to set for the pin.\n * @return      Zero on success; an error code on failure.\n */\nint gpio_set_value(const struct gpio_handle *gpio, bool value);\n\n#endif /* DRIVERS_GPIO_H */\n"
  },
  {
    "path": "include/drivers/irq.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef DRIVERS_IRQ_H\n#define DRIVERS_IRQ_H\n\n#include <stdint.h>\n\n/**\n * Determine if any enabled IRQ requires AVCC in order to be received.\n *\n * @return Nonzero if some IRQ requires AVCC, else zero.\n */\nuint32_t irq_needs_avcc(void);\n\n/**\n * Determine if any enabled IRQ requires VDD_SYS in order to be received.\n *\n * @return Nonzero if some IRQ requires VDD_SYS, else zero.\n */\nuint32_t irq_needs_vdd_sys(void);\n\n/**\n * Get a bitmask of the IRQs that are both enabled and pending.\n *\n * @return Nonzero if some IRQ is enabled and pending, else zero.\n */\nuint32_t irq_poll(void);\n\n#endif /* DRIVERS_IRQ_H */\n"
  },
  {
    "path": "include/drivers/mfd/axp20x.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef DRIVERS_MFD_AXP20X_H\n#define DRIVERS_MFD_AXP20X_H\n\n#include <regmap.h>\n\nextern const struct regmap_device axp20x;\n\n#endif /* DRIVERS_MFD_AXP20X_H */\n"
  },
  {
    "path": "include/drivers/msgbox/sunxi-msgbox.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef DRIVERS_MSGBOX_SUNXI_MSGBOX_H\n#define DRIVERS_MSGBOX_SUNXI_MSGBOX_H\n\n#include <msgbox.h>\n#include <simple_device.h>\n\n/* The message box hardware provides 8 unidirectional channels. */\n#define SUNXI_MSGBOX_CHANS 8\n\nextern const struct simple_device msgbox;\n\n#endif /* DRIVERS_MSGBOX_SUNXI_MSGBOX_H */\n"
  },
  {
    "path": "include/drivers/msgbox.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef DRIVERS_MSGBOX_H\n#define DRIVERS_MSGBOX_H\n\n#include <device.h>\n#include <stdbool.h>\n#include <stdint.h>\n\n/**\n * Acknowledge a message received on a message box channel.\n *\n * @param dev  The message box device.\n * @param chan The message box channel.\n */\nvoid msgbox_ack_rx(const struct device *dev, uint8_t chan);\n\n/**\n * Check if the last transmission on a message box channel has completed, or if\n * it is still pending. A message is pending until the reception IRQ has been\n * cleared on the remote interface.\n *\n * @param dev  The message box device.\n * @param chan The message box channel.\n */\nbool msgbox_last_tx_done(const struct device *dev, uint8_t chan);\n\n/**\n * Receive a message via a message box channel.\n *\n * @param dev     The message box device.\n * @param chan    The channel to use within the message box.\n * @param message The message to receive.\n */\nint msgbox_receive(const struct device *dev, uint8_t chan, uint32_t *message);\n\n/**\n * Send a message via a message box channel.\n *\n * @param dev     The message box device.\n * @param chan    The channel to use within the message box.\n * @param message The message to send.\n */\nint msgbox_send(const struct device *dev, uint8_t chan, uint32_t message);\n\n#endif /* DRIVERS_MSGBOX_H */\n"
  },
  {
    "path": "include/drivers/pmic/axp20x.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef DRIVERS_PMIC_AXP20X_H\n#define DRIVERS_PMIC_AXP20X_H\n\n#include <device.h>\n#include <pmic.h>\n#include <regmap.h>\n\nstruct axp20x_pmic {\n\tstruct device        dev;\n\tconst struct regmap *map;\n};\n\n#endif /* DRIVERS_PMIC_AXP20X_H */\n"
  },
  {
    "path": "include/drivers/pmic/axp223.h",
    "content": "/*\n * Copyright © 2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef DRIVERS_PMIC_AXP223_H\n#define DRIVERS_PMIC_AXP223_H\n\n#include <pmic/axp20x.h>\n\nextern const struct axp20x_pmic axp223_pmic;\n\n#endif /* DRIVERS_PMIC_AXP223_H */\n"
  },
  {
    "path": "include/drivers/pmic/axp803.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef DRIVERS_PMIC_AXP803_H\n#define DRIVERS_PMIC_AXP803_H\n\n#include <pmic/axp20x.h>\n\nextern const struct axp20x_pmic axp803_pmic;\n\n#endif /* DRIVERS_PMIC_AXP803_H */\n"
  },
  {
    "path": "include/drivers/pmic/axp805.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef DRIVERS_PMIC_AXP805_H\n#define DRIVERS_PMIC_AXP805_H\n\n#include <pmic/axp20x.h>\n\nextern const struct axp20x_pmic axp805_pmic;\n\n#endif /* DRIVERS_PMIC_AXP805_H */\n"
  },
  {
    "path": "include/drivers/pmic.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef DRIVERS_PMIC_H\n#define DRIVERS_PMIC_H\n\n#include <device.h>\n\n/**\n * Get a reference to an available PMIC device.\n *\n * @return A reference to a PMIC device.\n */\nconst struct device *pmic_get(void);\n\n/**\n * Initiate the PMIC reset process.\n *\n * @param dev The device containing the PMIC functionality.\n */\nint pmic_reset(const struct device *dev);\n\n/**\n * Initiate the PMIC resume process.\n *\n * @param dev The device containing the PMIC functionality.\n */\nint pmic_resume(const struct device *dev);\n\n/**\n * Initiate the PMIC shutdown process.\n *\n * @param dev The device containing the PMIC functionality.\n */\nint pmic_shutdown(const struct device *dev);\n\n/**\n * Initiate the PMIC suspend process.\n *\n * @param dev The device containing the PMIC functionality.\n */\nint pmic_suspend(const struct device *dev);\n\n#endif /* DRIVERS_PMIC_H */\n"
  },
  {
    "path": "include/drivers/regmap/sun6i-i2c.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef DRIVERS_REGMAP_SUN6I_I2C_H\n#define DRIVERS_REGMAP_SUN6I_I2C_H\n\n#include <regmap.h>\n#include <simple_device.h>\n\nextern const struct simple_device r_i2c;\n\n#endif /* DRIVERS_REGMAP_SUN6I_I2C_H */\n"
  },
  {
    "path": "include/drivers/regmap/sunxi-rsb.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef DRIVERS_REGMAP_SUNXI_RSB_H\n#define DRIVERS_REGMAP_SUNXI_RSB_H\n\n#include <regmap.h>\n#include <simple_device.h>\n\nextern const struct simple_device r_rsb;\n\n#endif /* DRIVERS_REGMAP_SUNXI_RSB_H */\n"
  },
  {
    "path": "include/drivers/regmap.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef DRIVERS_REGMAP_H\n#define DRIVERS_REGMAP_H\n\n#include <device.h>\n#include <intrusive.h>\n#include <stdint.h>\n\nstruct regmap {\n\tconst struct device *dev;\n\tuint32_t             id;\n};\n\nstruct regmap_device {\n\tstruct device dev;\n\tstruct regmap map;\n};\n\n/**\n * Downcast a pointer to a regmap device.\n */\nstatic inline const struct regmap_device *\nto_regmap_device(const struct device *dev)\n{\n\treturn container_of(dev, const struct regmap_device, dev);\n}\n\n/**\n * Get a reference to a regmap and its provider bus/device.\n *\n * This function will verify the existence of the device containing the regmap.\n *\n * This function may fail with:\n *   EIO     There was a problem communicating with the hardware.\n *   ENODEV  The device was not found on its provider bus.\n *\n * @param map  A specifier for the bus/device providing the regmap.\n * @return     Zero on success; an error code on failure.\n */\nint regmap_get(const struct regmap *map);\n\n/**\n * Release a reference to a regmap.\n *\n * @param map  A reference to a regmap.\n */\nvoid regmap_put(const struct regmap *map);\n\n/**\n * Read a value from a regmap.\n *\n * This function may fail with:\n *   EIO     There was a problem communicating with the hardware.\n *\n * @param map  A reference to the regmap.\n * @param reg  The register to read.\n * @param val  The location to save the value read from the register.\n * @return     Zero on success; an error code on failure.\n */\nint regmap_read(const struct regmap *map, uint8_t reg, uint8_t *val);\n\n/**\n * Write a value to a regmap.\n *\n * This function may fail with:\n *   EIO     There was a problem communicating with the hardware.\n *\n * @param map  A reference to the regmap.\n * @param reg  The register to write.\n * @param val  The value to write to the register.\n * @return     Zero on success; an error code on failure.\n */\nint regmap_write(const struct regmap *map, uint8_t reg, uint8_t val);\n\n/**\n * Update a bitfield in a regmap register.\n *\n * This function may fail with:\n *   EIO     There was a problem communicating with the hardware.\n *\n * @param map  A reference to the regmap.\n * @param reg  The register to modify.\n * @param mask A mask of bits representing a bitfield.\n * @param val  The new value of the bitfield.\n * @return     Zero on success; an error code on failure.\n */\nint regmap_update_bits(const struct regmap *map, uint8_t reg, uint8_t mask,\n                       uint8_t val);\n\n/**\n * Clear bits in a regmap register.\n *\n * This function may fail with:\n *   EIO     There was a problem communicating with the hardware.\n *\n * @param map  A reference to the regmap.\n * @param reg  The register to modify.\n * @param clr  The mask of bits to clear in the register.\n * @return     Zero on success; an error code on failure.\n */\nstatic inline int\nregmap_clr_bits(const struct regmap *map, uint8_t reg, uint8_t clr)\n{\n\treturn regmap_update_bits(map, reg, clr, 0);\n}\n\n/**\n * Set bits in a regmap register.\n *\n * This function may fail with:\n *   EIO     There was a problem communicating with the hardware.\n *\n * @param map  A reference to the regmap.\n * @param reg  The register to modify.\n * @param set  The mask of bits to set in the register.\n * @return     Zero on success; an error code on failure.\n */\nstatic inline int\nregmap_set_bits(const struct regmap *map, uint8_t reg, uint8_t set)\n{\n\treturn regmap_update_bits(map, reg, set, set);\n}\n\n/**\n * Probe a device that owns a regmap.\n *\n * This function can be used to implement a device's .probe hook.\n */\nint regmap_device_probe(const struct device *dev);\n\n/**\n * Release a device that owns a regmap.\n *\n * This function can be used to implement a device's .release hook.\n */\nvoid regmap_device_release(const struct device *dev);\n\n/**\n * Probe a device that uses a regmap owned by another device.\n *\n * This function assumes that the regmap's owner is a regmap_device.\n *\n * This function can be used to implement a device's .probe hook.\n */\nint regmap_user_probe(const struct regmap *map);\n\n/**\n * Release a device that uses a regmap owned by another device.\n *\n * This function assumes that the regmap's owner is a regmap_device.\n *\n * This function can be used to implement a device's .release hook.\n */\nvoid regmap_user_release(const struct regmap *map);\n\n#endif /* DRIVERS_REGMAP_H */\n"
  },
  {
    "path": "include/drivers/regulator/axp20x.h",
    "content": "/*\n * Copyright © 2020-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef DRIVERS_REGULATOR_AXP20X_H\n#define DRIVERS_REGULATOR_AXP20X_H\n\n#include <device.h>\n#include <regmap.h>\n#include <regulator.h>\n\nstruct axp20x_regulator {\n\tstruct device                       dev;\n\tconst struct regmap                *map;\n\tconst struct axp20x_regulator_info *info;\n};\n\n#endif /* DRIVERS_REGULATOR_AXP20X_H */\n"
  },
  {
    "path": "include/drivers/regulator/axp221.h",
    "content": "/*\n * Copyright © 2023 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef DRIVERS_REGULATOR_AXP221_H\n#define DRIVERS_REGULATOR_AXP221_H\n\n#include <regulator/axp20x.h>\n\nenum {\n\tAXP221_REGL_DC5LDO,\n\tAXP221_REGL_DCDC1,\n\tAXP221_REGL_DCDC2,\n\tAXP221_REGL_DCDC3,\n\tAXP221_REGL_DCDC4,\n\tAXP221_REGL_DCDC5,\n\tAXP221_REGL_ALDO1,\n\tAXP221_REGL_ALDO2,\n\tAXP221_REGL_ALDO3,\n\tAXP221_REGL_DLDO1,\n\tAXP221_REGL_DLDO2,\n\tAXP221_REGL_DLDO3,\n\tAXP221_REGL_DLDO4,\n\tAXP221_REGL_ELDO1,\n\tAXP221_REGL_ELDO2,\n\tAXP221_REGL_ELDO3,\n\tAXP221_REGL_DC1SW,\n\tAXP221_REGL_COUNT,\n};\n\nextern const struct axp20x_regulator axp221_regulator;\n\n#endif /* DRIVERS_REGULATOR_AXP221_H */\n"
  },
  {
    "path": "include/drivers/regulator/axp803.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef DRIVERS_REGULATOR_AXP803_H\n#define DRIVERS_REGULATOR_AXP803_H\n\n#include <regulator/axp20x.h>\n\nenum {\n\tAXP803_REGL_DCDC1,\n\tAXP803_REGL_DCDC2,\n\tAXP803_REGL_DCDC3,\n\tAXP803_REGL_DCDC4,\n\tAXP803_REGL_DCDC5,\n\tAXP803_REGL_DCDC6,\n\tAXP803_REGL_DC1SW,\n\tAXP803_REGL_ALDO1,\n\tAXP803_REGL_ALDO2,\n\tAXP803_REGL_ALDO3,\n\tAXP803_REGL_DLDO1,\n\tAXP803_REGL_DLDO2,\n\tAXP803_REGL_DLDO3,\n\tAXP803_REGL_DLDO4,\n\tAXP803_REGL_ELDO1,\n\tAXP803_REGL_ELDO2,\n\tAXP803_REGL_ELDO3,\n\tAXP803_REGL_FLDO1,\n\tAXP803_REGL_FLDO2,\n\tAXP803_REGL_COUNT,\n};\n\nextern const struct axp20x_regulator axp803_regulator;\n\n#endif /* DRIVERS_REGULATOR_AXP803_H */\n"
  },
  {
    "path": "include/drivers/regulator/axp805.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef DRIVERS_REGULATOR_AXP805_H\n#define DRIVERS_REGULATOR_AXP805_H\n\n#include <regulator/axp20x.h>\n\nenum {\n\tAXP805_REGL_DCDCA,\n\tAXP805_REGL_DCDCB,\n\tAXP805_REGL_DCDCC,\n\tAXP805_REGL_DCDCD,\n\tAXP805_REGL_DCDCE,\n\tAXP805_REGL_ALDO1,\n\tAXP805_REGL_ALDO2,\n\tAXP805_REGL_ALDO3,\n\tAXP805_REGL_BLDO1,\n\tAXP805_REGL_BLDO2,\n\tAXP805_REGL_BLDO3,\n\tAXP805_REGL_BLDO4,\n\tAXP805_REGL_CLDO1,\n\tAXP805_REGL_CLDO2,\n\tAXP805_REGL_CLDO3,\n\tAXP805_REGL_DCSW,\n\tAXP805_REGL_COUNT,\n};\n\nextern const struct axp20x_regulator axp805_regulator;\n\n#endif /* DRIVERS_REGULATOR_AXP805_H */\n"
  },
  {
    "path": "include/drivers/regulator/gpio.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef DRIVERS_REGULATOR_GPIO_H\n#define DRIVERS_REGULATOR_GPIO_H\n\n#include <gpio.h>\n#include <regulator.h>\n\nstruct gpio_regulator {\n\tstruct device      dev;\n\tstruct gpio_handle pin;\n};\n\n#if CONFIG(REGULATOR_GPIO_CPU)\nextern const struct gpio_regulator gpio_cpu_regulator;\n#endif\n\n#if CONFIG(REGULATOR_GPIO_DRAM)\nextern const struct gpio_regulator gpio_dram_regulator;\n#endif\n\n#if CONFIG(REGULATOR_GPIO_VCC_PLL)\nextern const struct gpio_regulator gpio_vcc_pll_regulator;\n#endif\n\n#if CONFIG(REGULATOR_GPIO_VDD_SYS)\nextern const struct gpio_regulator gpio_vdd_sys_regulator;\n#endif\n\n#endif /* DRIVERS_REGULATOR_GPIO_H */\n"
  },
  {
    "path": "include/drivers/regulator/sy8106a.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef DRIVERS_REGULATOR_SY8106A_H\n#define DRIVERS_REGULATOR_SY8106A_H\n\n#include <regmap.h>\n#include <regulator.h>\n\n#define SY8106A_I2C_ADDRESS 0x65\n\nextern const struct regmap_device sy8106a;\n\n#endif /* DRIVERS_REGULATOR_SY8106A_H */\n"
  },
  {
    "path": "include/drivers/regulator.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef DRIVERS_REGULATOR_H\n#define DRIVERS_REGULATOR_H\n\n#include <device.h>\n#include <stdint.h>\n\nstruct regulator_handle {\n\tconst struct device *dev; /**< The regulator supplier device. */\n\tuint8_t              id;  /**< The device-specific identifier. */\n};\n\n/**\n * Disable the output of a regulator. If the regulator does not have\n * output on/off control, this function may have no effect on the hardware.\n *\n * This function will acquire and release a reference to the supplier device.\n *\n * This function may fail with:\n *   EIO    There was a problem communicating with the hardware.\n *\n * @param handle A reference to a regulator and its supplier.\n * @return       Zero on success; a defined error code on failure.\n */\nint regulator_disable(const struct regulator_handle *handle);\n\n/**\n * Enable the output of a regulator. If the regulator does not have\n * output on/off control, this function may have no effect on the hardware.\n *\n * This function will acquire and release a reference to the supplier device.\n *\n * This function may fail with:\n *   EIO    There was a problem communicating with the hardware.\n *\n * @param handle A reference to a regulator and its supplier.\n * @return       Zero on success; a defined error code on failure.\n */\nint regulator_enable(const struct regulator_handle *handle);\n\n/**\n * Get the current state of a regulator, as determined from the hardware.\n *\n * This function may fail with:\n *   EIO    There was a problem communicating with the hardware.\n *\n * @param handle  A reference to a regulator and its supplier.\n * @param enabled Pointer to where the state is stored.\n * @return        Zero on success; a defined error code on failure.\n */\nint regulator_get_state(const struct regulator_handle *handle, bool *enabled);\n\n#endif /* DRIVERS_REGULATOR_H */\n"
  },
  {
    "path": "include/drivers/serial.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef DRIVERS_SERIAL_H\n#define DRIVERS_SERIAL_H\n\n#include <stdbool.h>\n\n#if CONFIG(SERIAL)\n\n/**\n * Read a character from the UART.\n *\n * @return The character read, or 0 if no character is available.\n */\nchar serial_getc(void);\nvoid serial_putc(char c);\nvoid serial_puts(const char *s);\n\n/**\n * Initialize the UART.\n */\nvoid serial_init(void);\n\n/**\n * Verify that the UART is ready to use.\n *\n * This function must be called before performing any I/O. Other serial I/O\n * functions may only be called if this function returns true.\n */\nbool serial_ready(void);\n\n#else\n\nstatic inline char\nserial_getc(void)\n{\n\treturn 0;\n}\n\nstatic inline void\nserial_putc(char c UNUSED)\n{\n}\n\nstatic inline void\nserial_puts(const char *s UNUSED)\n{\n}\n\nstatic inline void\nserial_init(void)\n{\n}\n\nstatic inline bool\nserial_ready(void)\n{\n\treturn false;\n}\n\n#endif\n\n#endif /* DRIVERS_SERIAL_H */\n"
  },
  {
    "path": "include/drivers/watchdog/sun6i-a31-wdt.h",
    "content": "/*\n * Copyright © 2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef DRIVERS_WATCHDOG_SUN6I_A31_WDT_H\n#define DRIVERS_WATCHDOG_SUN6I_A31_WDT_H\n\n#include <device.h>\n#include <watchdog.h>\n\nstruct sun6i_a31_wdt {\n\tstruct device dev;\n\tuintptr_t     regs;\n};\n\nextern const struct sun6i_a31_wdt r_wdog;\n\n#endif /* DRIVERS_WATCHDOG_SUN6I_A31_WDT_H */\n"
  },
  {
    "path": "include/drivers/watchdog/sun9i-a80-twd.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef DRIVERS_WATCHDOG_SUN9I_A80_TWD_H\n#define DRIVERS_WATCHDOG_SUN9I_A80_TWD_H\n\n#include <simple_device.h>\n#include <watchdog.h>\n\nextern const struct simple_device r_twd;\n\n#endif /* DRIVERS_WATCHDOG_SUN9I_A80_TWD_H */\n"
  },
  {
    "path": "include/drivers/watchdog.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef DRIVERS_WATCHDOG_H\n#define DRIVERS_WATCHDOG_H\n\n#include <device.h>\n\n/**\n * Get a reference to an available watchdog device.\n *\n * @return A reference to a watchdog device.\n */\nconst struct device *watchdog_get(void);\n\n/**\n * Use the watchdog to reset the system as soon as possible.\n *\n * @param dev The watchdog device.\n */\nvoid watchdog_reset_system(const struct device *dev);\n\n/**\n * Restart the watchdog. This must be called before the watchdog times out.\n *\n * @param dev The watchdog device.\n */\nvoid watchdog_restart(const struct device *dev);\n\n#endif /* DRIVERS_WATCHDOG_H */\n"
  },
  {
    "path": "include/lib/bitfield.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef LIB_BITFIELD_H\n#define LIB_BITFIELD_H\n\n#include <stdint.h>\n\n/**\n * Get the value in a bitfield.\n *\n * @param word  A word containing a bitfield.\n * @param start The offset of the starting bit (LSB) of the bitfield.\n * @param width The width of the bitfield in bits.\n */\nuint32_t bitfield_get(uint32_t word, uint32_t start, uint32_t width);\n\n/**\n * Set the value in a bitfield.\n *\n * @param word  A word containing a bitfield.\n * @param start The offset of the starting bit (LSB) of the bitfield.\n * @param width The width of the bitfield in bits.\n * @param value The value to place in the bitfield.\n * @return      The original word, with the value of the bitfield replaced.\n */\nuint32_t bitfield_set(uint32_t word, uint32_t start, uint32_t width,\n                      uint32_t value);\n\n/**\n * Get the value in a bitfield accessed via MMIO.\n *\n * @param addr  The address of a word containing a bitfield.\n * @param start The offset of the starting bit (LSB) of the bitfield.\n * @param width The width of the bitfield in bits.\n */\nuint32_t mmio_get_bitfield_32(uintptr_t addr, uint32_t start, uint32_t width);\n\n/**\n * Set the value in a bitfield accessed via MMIO.\n *\n * @param addr  The address of a word containing a bitfield.\n * @param start The offset of the starting bit (LSB) of the bitfield.\n * @param width The width of the bitfield in bits.\n * @param value The value to place in the bitfield.\n */\nvoid mmio_set_bitfield_32(uintptr_t addr, uint32_t start, uint32_t width,\n                          uint32_t value);\n\n#endif /* LIB_BITFIELD_H */\n"
  },
  {
    "path": "include/lib/bitmap.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef LIB_BITMAP_H\n#define LIB_BITMAP_H\n\n#include <limits.h>\n#include <mmio.h>\n#include <stdbool.h>\n#include <stdint.h>\n#include <util.h>\n\n/**\n * Calculate a bit index from a word offset (in bytes) and a bit offset\n * within that word.\n *\n * @param word The offset of the word from the beginning of the bitmap.\n * @param bit  The offset (arithmetic shift) of the bit within the word.\n */\n#define BITMAP_INDEX(word, bit) (CHAR_BIT * (word) + (bit))\n\n/**\n * Extract the word offset (in bytes) from a bitmap index.\n *\n * @param index An index into a bitmap, in bits.\n */\n#define BITMAP_WORD(index)      ((index) / WORD_BIT * (WORD_BIT / CHAR_BIT))\n\n/**\n * Extract the bit offset (arithmetic shift) from a bitmap index.\n *\n * @param index An index into a bitmap, in bits.\n */\n#define BITMAP_BIT(index)       ((index) % WORD_BIT)\n\n/**\n * Clear a bit in a bitmap.\n *\n * @param base  The address of the start of the bitmap.\n * @param index The index into the bitmap (in bits) of the bit to clear.\n */\nstatic inline void\nbitmap_clear(uintptr_t base, uint32_t index)\n{\n\tmmio_clr_32(base + BITMAP_WORD(index), BIT(BITMAP_BIT(index)));\n}\n\n/**\n * Get a bit in a bitmap.\n *\n * @param base  The address of the start of the bitmap.\n * @param index The index into the bitmap (in bits) of the bit to get.\n */\nstatic inline bool\nbitmap_get(uintptr_t base, uint32_t index)\n{\n\treturn mmio_get_32(base + BITMAP_WORD(index), BIT(BITMAP_BIT(index)));\n}\n\n/**\n * Set a bit in a bitmap.\n *\n * @param base  The address of the start of the bitmap.\n * @param index The index into the bitmap (in bits) of the bit to set.\n */\nstatic inline void\nbitmap_set(uintptr_t base, uint32_t index)\n{\n\tmmio_set_32(base + BITMAP_WORD(index), BIT(BITMAP_BIT(index)));\n}\n\n#endif /* LIB_BITMAP_H */\n"
  },
  {
    "path": "include/lib/byteswap.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef LIB_BYTESWAP_H\n#define LIB_BYTESWAP_H\n\n#include <stdint.h>\n\nstatic inline uint16_t\nbswap16(uint16_t n)\n{\n\treturn ((n << 8) & 0xff00U) | \\\n\t       ((n >> 8) & 0xffU);\n}\n\nstatic inline uint32_t\nbswap32(uint32_t n)\n{\n\treturn ((n << 24) & 0xff000000U) | \\\n\t       ((n << 8) & 0xff0000U) | \\\n\t       ((n >> 8) & 0xff00U) | \\\n\t       ((n >> 24) & 0xffU);\n}\n\n#endif /* LIB_BYTESWAP_H */\n"
  },
  {
    "path": "include/lib/compiler.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef LIB_COMPILER_H\n#define LIB_COMPILER_H\n\n/* Attributes */\n#define ATTRIBUTE(...) __attribute__((__VA_ARGS__))\n#define UNUSED         __attribute__((unused))\n#define WEAK           __attribute__((weak))\n\n/* Barriers */\n#define barrier()      asm volatile (\"\" : : : \"memory\")\n\n/* Builtins */\n#define likely(e)      __builtin_expect(!!(e), 1)\n#define unlikely(e)    __builtin_expect(e, 0)\n#define unreachable()  __builtin_unreachable()\n\n/* Keywords */\n#define alignas        _Alignas\n#define alignof        _Alignof\n#define asm            __asm__\n#define fallthrough    __attribute__((__fallthrough__))\n#define noreturn       _Noreturn\n#define static_assert  _Static_assert\n\n/**\n * Calculate the size of a struct containing a flexible array member.\n *\n * @param type     The name of the structure type.\n * @param member   The name of the flexible array member.\n * @param elements The number of elements in the flexible array member.\n * @return         The total size of the type.\n */\n#define sizeof_struct(type, member, elements) \\\n\t(sizeof(type) + sizeof(*((type *)0)->member) * elements)\n\n#endif /* LIB_COMPILER_H */\n"
  },
  {
    "path": "include/lib/division.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef LIB_DIVISION_H\n#define LIB_DIVISION_H\n\n#include <stdint.h>\n\n#define UDIV_ROUND(dividend, divisor) \\\n\t(((dividend) + (divisor) / 2) / (divisor))\n\n/**\n * Perform correctly-rounded unsigned division.\n */\nstatic inline uint32_t\nudiv_round(uint32_t dividend, uint32_t divisor)\n{\n\treturn (dividend + divisor / 2) / divisor;\n}\n\n/**\n * Perform unsigned division.\n *\n * This function replaces the dividend with the quotient and returns the\n * remainder.\n */\nuint32_t udivmod(uint32_t *dividend, uint32_t divisor);\n\n#endif /* LIB_DIVISION_H */\n"
  },
  {
    "path": "include/lib/error.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef LIB_ERROR_H\n#define LIB_ERROR_H\n\n#define SUCCESS 0    /**< The operation succeeded. */\n#define EBUSY   (-1) /**< Try again later. */\n#define EEXIST  (-2) /**< The object already exists. */\n#define EINVAL  (-3) /**< The argument to the function was invalid. */\n#define EIO     (-4) /**< Communication with the hardware failed. */\n#define ENODEV  (-5) /**< The device does not exist. */\n#define ENOENT  (-6) /**< The entry does not exist. */\n#define ENOTSUP (-7) /**< The operation is not supported. */\n#define EPERM   (-8) /**< The operation is not permitted. */\n#define ERANGE  (-9) /**< The argument to the function was out of range. */\n\n#endif /* LIB_ERROR_H */\n"
  },
  {
    "path": "include/lib/intrusive.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef LIB_INTRUSIVE_H\n#define LIB_INTRUSIVE_H\n\n#include <stddef.h>\n#include <stdint.h>\n\n#define container_of(ptr, type, member) \\\n\t((type *)((char *)(ptr) - offsetof(type, member)))\n\n#endif /* LIB_INTRUSIVE_H */\n"
  },
  {
    "path": "include/lib/kconfig.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef LIB_KCONFIG_H\n#define LIB_KCONFIG_H\n\n/* These macros define the option values that will match (here just 1), as\n * well as the action that will be taken when a match is found. They work by\n * expanding a single argument into two arguments in the case of a match. */\n#define __kcm_self_1 \"this is junk\", __kca_self\n#define __kcm_init_1 \"this is junk\", __kca_init\n#define __kcm_true_1 \"this is junk\", __kca_true\n\n/* These macros define the result actions/expressions. Since __kc_indirect\n * consumes exactly two arguments, actions in the matching case have an extra\n * parameter (the one inserted by the match macros above). */\n#define __kca_null(...)\n#define __kca_self(junk, ...)      __VA_ARGS__\n#define __kca_init(junk, ...)      __VA_ARGS__,\n#define __kca_false(...)           0\n#define __kca_true(junk, ...)      1\n\n/* These macros split the comma-separated match expression (if present) into\n * two arguments, and then call the action named in the second argument. */\n#define __kc_concat(a, b)          a ## b\n#define __kc_do(junk, action, ...) action(__VA_ARGS__)\n#define __kc_expand(...)           __kc_do(__VA_ARGS__)\n#define __kc_tokenize(...)         __VA_ARGS__\n\n/**\n * Expands to the remainder of the argument list if the option is enabled;\n * otherwise expands to the empty string.\n */\n#define IF_ENABLED(option, ...) \\\n\t__kc_expand(__kc_concat(__kcm_self_, option), __kca_null, __VA_ARGS__)\n\n/**\n * Expands to the remainder of the argument list plus a comma if the option is\n * enabled; otherwise expands to the empty string. This is generally useful in\n * structure and array initializers.\n */\n#define IF_ENABLED_INIT(option, ...) \\\n\t__kc_expand(__kc_concat(__kcm_init_, option), __kca_null, __VA_ARGS__)\n\n/**\n * Expands to the token 1 if the option is enabled; otherwise expands to 0.\n */\n#define IS_ENABLED(option) \\\n\t__kc_expand(__kc_concat(__kcm_true_, option), __kca_false, junk)\n\n/**\n * Shorthand for IS_ENABLED(CONFIG_option).\n *\n * Expands to the token 1 if the option is enabled; otherwise expands to 0.\n */\n#define CONFIG(option) \\\n\tIS_ENABLED(__kc_tokenize(CONFIG_ ## option))\n\n#endif /* LIB_KCONFIG_H */\n"
  },
  {
    "path": "include/lib/macros.S",
    "content": "/*\n * Copyright © 2013-2017, ARM Limited and Contributors. All rights reserved.\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause\n */\n\n#ifndef MACROS_S\n#define MACROS_S\n\n\t/* This macro marks a global data declaration. */\n\t.macro data name\n\t.section .data.\\name, \"aw\", @progbits\n\t.global \\name\n\t.type \\name, %object\n\t.align 4\n\\name:\n\t.endm\n\n\t/* This macro marks the beginning of a function. */\n\t.macro func name\n\t.section .text.\\name, \"ax\", @progbits\n\t.global \\name\n\t.type \\name, %function\n\t.func \\name\n\t.cfi_sections .debug_frame\n\t.cfi_startproc\n\t.align 4\n\\name:\n\t.endm\n\n\t/* This macro marks the end of a function. */\n\t.macro endfunc name\n\t.cfi_endproc\n\t.endfunc\n\t.size \\name, . - \\name\n\t.endm\n\n#endif /* MACROS_S */\n"
  },
  {
    "path": "include/lib/mmio.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef LIB_MMIO_H\n#define LIB_MMIO_H\n\n#include <stdint.h>\n\n/**\n * Clear bits in a 32-bit MMIO register.\n *\n * @param addr The address of the register.\n * @param clr  The bits to clear.\n */\nstatic inline void\nmmio_clr_32(uintptr_t addr, uint32_t clr)\n{\n\tvolatile uint32_t *ptr = (void *)addr;\n\n\t*ptr &= ~clr;\n}\n\n/**\n * Clear and set bits in a 32-bit MMIO register.\n *\n * @param addr The address of the register.\n * @param clr  The bits to clear.\n * @param set  The bits to set.\n */\nstatic inline void\nmmio_clrset_32(uintptr_t addr, uint32_t clr, uint32_t set)\n{\n\tvolatile uint32_t *ptr = (void *)addr;\n\n\t*ptr = (*ptr & ~clr) | set;\n}\n\n/**\n * Get bits from a 32-bit MMIO register.\n *\n * @param addr The address of the register.\n * @param get  The bits to get.\n */\nstatic inline uint32_t\nmmio_get_32(uintptr_t addr, uint32_t get)\n{\n\tvolatile uint32_t *ptr = (void *)addr;\n\n\treturn *ptr & get;\n}\n\n/**\n * Spin until all bits in a mask are set in a 32-bit MMIO register.\n *\n * @param addr The address of the register.\n * @param mask The bits that must all be set.\n */\nstatic inline void\nmmio_poll_32(uintptr_t addr, uint32_t mask)\n{\n\tvolatile uint32_t *ptr = (void *)addr;\n\n\twhile ((*ptr & mask) != mask) {\n\t\t/* Do nothing. */\n\t}\n}\n\n/**\n * Spin until a value is present in a 32-bit MMIO register.\n *\n * @param addr The address of the register.\n * @param mask The bits to check.\n * @param val  The expected value for those bits.\n */\nstatic inline void\nmmio_polleq_32(uintptr_t addr, uint32_t mask, uint32_t val)\n{\n\tvolatile uint32_t *ptr = (void *)addr;\n\n\twhile ((*ptr & mask) != val) {\n\t\t/* Do nothing. */\n\t}\n}\n\n/**\n * Spin until all bits in a mask are cleared in a 32-bit MMIO register.\n *\n * @param addr The address of the register.\n * @param mask The bits that must all be cleared.\n */\nstatic inline void\nmmio_pollz_32(uintptr_t addr, uint32_t mask)\n{\n\tvolatile uint32_t *ptr = (void *)addr;\n\n\twhile ((*ptr & mask) != 0) {\n\t\t/* Do nothing. */\n\t}\n}\n\n/**\n * Read a 32-bit MMIO register.\n *\n * @param addr The address of the register.\n * @return     The value of the register.\n */\nstatic inline uint32_t\nmmio_read_32(uintptr_t addr)\n{\n\tvolatile uint32_t *ptr = (void *)addr;\n\n\treturn *ptr;\n}\n\n/**\n * Read a 8-bit MMIO register.\n *\n * @param addr The address of the register.\n * @return     The value of the register.\n */\nstatic inline uint8_t\nmmio_read_8(uintptr_t addr)\n{\n#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__\n\tvolatile uint8_t *ptr = (void *)(addr ^ 3);\n#else\n\tvolatile uint8_t *ptr = (void *)addr;\n#endif\n\n\treturn *ptr;\n}\n\n/**\n * Set bits in a 32-bit MMIO register.\n *\n * @param addr The address of the register.\n * @param set  The bits to set.\n */\nstatic inline void\nmmio_set_32(uintptr_t addr, uint32_t set)\n{\n\tvolatile uint32_t *ptr = (void *)addr;\n\n\t*ptr |= set;\n}\n\n/**\n * Write a 32-bit MMIO register.\n *\n * @param addr The address of the register.\n * @param val  The new value of the register.\n */\nstatic inline void\nmmio_write_32(uintptr_t addr, uint32_t val)\n{\n\tvolatile uint32_t *ptr = (void *)addr;\n\n\t*ptr = val;\n}\n\n/**\n * Write a 8-bit MMIO register.\n *\n * @param addr The address of the register.\n * @param val  The new value of the register.\n */\nstatic inline void\nmmio_write_8(uintptr_t addr, uint8_t val)\n{\n#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__\n\tvolatile uint8_t *ptr = (void *)(addr ^ 3);\n#else\n\tvolatile uint8_t *ptr = (void *)addr;\n#endif\n\n\t*ptr = val;\n}\n\n#endif /* LIB_MMIO_H */\n"
  },
  {
    "path": "include/lib/scpi_protocol.h",
    "content": "/*\n * Copyright © 2014-2017, ARM Limited and Contributors. All rights reserved.\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef COMMON_SCPI_PROTOCOL_H\n#define COMMON_SCPI_PROTOCOL_H\n\n#include <stdint.h>\n#include <util.h>\n\n/** The SCPI message header is specified to be 64 bits long. */\n#define SCPI_HEADER_SIZE     sizeof(uint64_t)\n\n/** The implementation-defined maximum size of an SCPI message. */\n#define SCPI_MESSAGE_SIZE    0x100\n\n/** The payload can use all but the 64 bits reserved for the header. */\n#define SCPI_PAYLOAD_SIZE    (SCPI_MESSAGE_SIZE - SCPI_HEADER_SIZE)\n\n/** The payload is represented as an array of 32-bit words. */\n#define SCPI_PAYLOAD_WORDS   (SCPI_PAYLOAD_SIZE / sizeof(uint32_t))\n\n/** The SCP must identify itself as sender 0 for messages it initiates. */\n#define SCPI_SENDER_SCP      0\n\n/**\n * The virtual channel number is defined by the SCPI specification.\n * Theoretically, this allows reusing the same shared memory area for different\n * types of messages, if a different virtual channel number is given. In this\n * implementation, the virtual channel number is the contents of the mailbox\n * message. Messages with any other virtual channel are ignored.\n */\n#define SCPI_VIRTUAL_CHANNEL BIT(0)\n\n/**\n * The set of standard SCPI commands, defined by the SCPI specification.\n */\nenum {\n\tSCPI_CMD_SCP_READY         = 0x01, /**< SCP ready. */\n\tSCPI_CMD_GET_SCP_CAP       = 0x02, /**< Get SCP capability. */\n\tSCPI_CMD_SET_CSS_POWER     = 0x03, /**< Set CSS power state. */\n\tSCPI_CMD_GET_CSS_POWER     = 0x04, /**< Get CSS power state. */\n\tSCPI_CMD_SET_SYS_POWER     = 0x05, /**< Set system power state. */\n\tSCPI_CMD_SET_CPU_TIMER     = 0x06, /**< Set CPU timer. */\n\tSCPI_CMD_CANCEL_CPU_TIMER  = 0x07, /**< Cancel CPU timer. */\n\tSCPI_CMD_GET_DVFS_CAP      = 0x08, /**< Get DVFS capability. */\n\tSCPI_CMD_GET_DVFS_INFO     = 0x09, /**< Get DVFS info. */\n\tSCPI_CMD_SET_DVFS          = 0x0a, /**< Set DVFS. */\n\tSCPI_CMD_GET_DVFS          = 0x0b, /**< Get DVFS. */\n\tSCPI_CMD_GET_DVFS_STATS    = 0x0c, /**< Get DVFS statistics. */\n\tSCPI_CMD_GET_CLOCK_CAP     = 0x0d, /**< Get clock capability. */\n\tSCPI_CMD_GET_CLOCK_INFO    = 0x0e, /**< Get clock info. */\n\tSCPI_CMD_SET_CLOCK         = 0x0f, /**< Set clock value. */\n\tSCPI_CMD_GET_CLOCK         = 0x10, /**< Get clock value. */\n\tSCPI_CMD_GET_PSU_CAP       = 0x11, /**< Get power supply capability. */\n\tSCPI_CMD_GET_PSU_INFO      = 0x12, /**< Get power supply info. */\n\tSCPI_CMD_SET_PSU           = 0x13, /**< Set power supply. */\n\tSCPI_CMD_GET_PSU           = 0x14, /**< Get power supply. */\n\tSCPI_CMD_GET_SENSOR_CAP    = 0x15, /**< Get sensor capability. */\n\tSCPI_CMD_GET_SENSOR_INFO   = 0x16, /**< Get sensor info. */\n\tSCPI_CMD_GET_SENSOR        = 0x17, /**< Get sensor value. */\n\tSCPI_CMD_CFG_SENSOR_PERIOD = 0x18, /**< Configure sensor period. */\n\tSCPI_CMD_CFG_SENSOR_BOUNDS = 0x19, /**< Configure sensor bounds. */\n\tSCPI_CMD_ASYNC_SENSOR      = 0x1a, /**< Asynchronous sensor value. */\n\tSCPI_CMD_SET_DEV_POWER     = 0x1b, /**< Set device power state. */\n\tSCPI_CMD_GET_DEV_POWER     = 0x1c, /**< Get device power state. */\n};\n\n/**\n * The set of possible status codes in an SCPI message, defined by the SCPI\n * specification.\n */\nenum {\n\tSCPI_OK         = 0,  /**< Success. */\n\tSCPI_E_PARAM    = 1,  /**< Invalid parameter(s). */\n\tSCPI_E_ALIGN    = 2,  /**< Invalid alignment. */\n\tSCPI_E_SIZE     = 3,  /**< Invalid size. */\n\tSCPI_E_HANDLER  = 4,  /**< Invalid handler or callback. */\n\tSCPI_E_ACCESS   = 5,  /**< Invalid access or permission denied. */\n\tSCPI_E_RANGE    = 6,  /**< Value out of range. */\n\tSCPI_E_TIMEOUT  = 7,  /**< Timeout has occurred. */\n\tSCPI_E_NOMEM    = 8,  /**< Invalid memory area or pointer. */\n\tSCPI_E_PWRSTATE = 9,  /**< Invalid power state. */\n\tSCPI_E_SUPPORT  = 10, /**< Feature not supported or disabled. */\n\tSCPI_E_DEVICE   = 11, /**< Device error. */\n\tSCPI_E_BUSY     = 12, /**< Device is busy. */\n\tSCPI_E_OS       = 13, /**< RTOS error occurred. */\n\tSCPI_E_DATA     = 14, /**< Unexpected or invalid data received. */\n\tSCPI_E_STATE    = 15, /**< Invalid or unattainable state requested. */\n};\n\n/**\n * Possible CSS power domain states, as used in existing SCPI implementations.\n */\nenum {\n\tSCPI_CSS_ON        = 0,\n\tSCPI_CSS_RETENTION = 1,\n\tSCPI_CSS_OFF       = 3,\n};\n\n/**\n * Possible system power states, defined by the SCPI protocol specification.\n */\nenum {\n\tSCPI_SYSTEM_SHUTDOWN = 0,\n\tSCPI_SYSTEM_REBOOT   = 1,\n\tSCPI_SYSTEM_RESET    = 2,\n};\n\n/**\n * The memory structure representing an SCPI message, defined by the SCPI\n * specification.\n *\n * The structure below does not exactly follow the specification. The set ID\n * bit has been merged into the command number, because it is semantically\n * meaningless. And the reserved bits have been merged into the payload size.\n * Any command with reserved bits set will be interpreted as being \"too large\"\n * and will be rejected.\n *\n * The fields in the first 32-bit word are reversed from their order in the\n * specification to account for hardware byte swapping. The payload is\n * represented as an array of 32-bit words to reduce the amount of byte\n * swapping needed in command implementations.\n */\nstruct scpi_msg {\n#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__\n\tuint16_t size;\n\tuint8_t  sender;\n\tuint8_t  command;\n#else\n\tuint8_t  command;\n\tuint8_t  sender;\n\tuint16_t size;\n#endif\n\tuint32_t status;\n#ifdef __or1k__\n\tuint32_t payload[SCPI_PAYLOAD_WORDS];\n#else\n\tuint8_t  payload[SCPI_PAYLOAD_SIZE];\n#endif\n};\n\n/**\n * The structure representing an SCPI shared memory area, defined by the SCPI\n * specification.\n */\nstruct scpi_mem {\n\tstruct scpi_msg tx_msg; /**< Server to client message. */\n\tstruct scpi_msg rx_msg; /**< Client to server message. */\n};\n\n#endif /* COMMON_SCPI_PROTOCOL_H */\n"
  },
  {
    "path": "include/lib/util.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef LIB_UTIL_H\n#define LIB_UTIL_H\n\n#ifdef __ASSEMBLER__\n#define U(n)          (n)\n#else\n#define U(n)          (n ## U)\n#endif\n\n#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))\n\n#define BIT(n)        (U(1) << (n))\n\n#define GENMASK(h, l) ((U(0xffffffff) << (l)) & (U(0xffffffff) >> (31 - (h))))\n\n#endif /* LIB_UTIL_H */\n"
  },
  {
    "path": "include/stdlib/ctype.h",
    "content": "/*\n * Copyright © 2005-2014 Rich Felker, et al.\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: MIT\n */\n\n#ifndef STDLIB_CTYPE_H\n#define STDLIB_CTYPE_H\n\n#include <stdbool.h>\n\n#define isalpha(a) (((unsigned)(a) | 32) - 'a' < 26)\n#define isascii(a) ((unsigned)(a) < 128)\n#define isdigit(a) ((unsigned)(a) - '0' < 10)\n#define isgraph(a) ((unsigned)(a) - 0x21 < 0x5e)\n#define islower(a) ((unsigned)(a) - 'a' < 26)\n#define isprint(a) ((unsigned)(a) - 0x20 < 0x5f)\n#define isupper(a) ((unsigned)(a) - 'A' < 26)\n#define tolower(a) ((a) | 0x20)\n#define toupper(a) ((a) & 0x5f)\n\nstatic inline bool\nisalnum(char c)\n{\n\treturn isalpha(c) || isdigit(c);\n}\n\nstatic inline bool\nisblank(char c)\n{\n\treturn c == ' ' || c == '\\t';\n}\n\nstatic inline bool\niscntrl(char c)\n{\n\treturn (unsigned)c < 0x20 || c == 0x7f;\n}\n\nstatic inline bool\nispunct(char c)\n{\n\treturn isgraph(c) && !isalnum(c);\n}\n\nstatic inline bool\nisspace(char c)\n{\n\treturn c == ' ' || (unsigned)c - '\\t' < 5;\n}\n\nstatic inline bool\nisxdigit(char c)\n{\n\treturn isdigit(c) || ((unsigned)c | 32) - 'a' < 6;\n}\n\n#endif /* STDLIB_CTYPE_H */\n"
  },
  {
    "path": "include/stdlib/limits.h",
    "content": "/*\n * Copyright © 2005-2014 Rich Felker, et al.\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef STDLIB_LIMITS_H\n#define STDLIB_LIMITS_H\n\n#define CHAR_BIT   8\n#define CHAR_MAX   0xff\n#define CHAR_MIN   0\n\n#define WORD_BIT   32\n#define INT_MAX    0x7fffffff\n#define INT_MIN    (-1 - 0x7fffffff)\n\n#define LONG_BIT   32\n#define LONG_MAX   0x7fffffffL\n#define LONG_MIN   (-0x7fffffffL - 1)\n#define LLONG_MAX  0x7fffffffffffffffLL\n#define LLONG_MIN  (-0x7fffffffffffffffLL - 1)\n\n#define SCHAR_MAX  0x7f\n#define SCHAR_MIN  (-1 - 0x7f)\n\n#define SHRT_MAX   0x7fff\n#define SHRT_MIN   (-1 - 0x7fff)\n\n#define UCHAR_MAX  0xff\n\n#define UINT_MAX   0xffffffffU\n\n#define ULONG_MAX  0xffffffffUL\n#define ULLONG_MAX 0xffffffffffffffffULL\n\n#define USHRT_MAX  0xffff\n\n#endif /* STDLIB_LIMITS_H */\n"
  },
  {
    "path": "include/stdlib/stdarg.h",
    "content": "/*\n * Copyright © 2005-2014 Rich Felker, et al.\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef STDLIB_STDARG_H\n#define STDLIB_STDARG_H\n\n#define va_arg(v, l)   __builtin_va_arg(v, l)\n#define va_copy(d, s)  __builtin_va_copy(d, s)\n#define va_end(v)      __builtin_va_end(v)\n#define va_start(v, l) __builtin_va_start(v, l)\n\ntypedef __builtin_va_list va_list;\n\n#endif /* STDLIB_STDARG_H */\n"
  },
  {
    "path": "include/stdlib/stdbool.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef STDLIB_STDBOOL_H\n#define STDLIB_STDBOOL_H\n\n#define bool  _Bool\n#define false 0\n#define true  1\n\n#endif /* STDLIB_STDBOOL_H */\n"
  },
  {
    "path": "include/stdlib/stddef.h",
    "content": "/*\n * Copyright © 2005-2014 Rich Felker, et al.\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef STDLIB_STDDEF_H\n#define STDLIB_STDDEF_H\n\n#define NULL                   ((void *)0)\n#define offsetof(type, member) __builtin_offsetof(type, member)\n\ntypedef int          ptrdiff_t;\ntypedef unsigned int size_t;\n\n#endif /* STDLIB_STDDEF_H */\n"
  },
  {
    "path": "include/stdlib/stdint.h",
    "content": "/*\n * Copyright © 2005-2014 Rich Felker, et al.\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef STDLIB_STDINT_H\n#define STDLIB_STDINT_H\n\n#define INT8_MAX    0x7f\n#define INT8_MIN    (-1 - 0x7f)\n#define INT16_MAX   0x7fff\n#define INT16_MIN   (-1 - 0x7fff)\n#define INT32_MAX   0x7fffffff\n#define INT32_MIN   (-1 - 0x7fffffff)\n#define INT64_MAX   0x7fffffffffffffff\n#define INT64_MIN   (-1 - 0x7fffffffffffffff)\n\n#define INTMAX_MAX  INT64_MAX\n#define INTMAX_MIN  INT64_MIN\n#define INTPTR_MAX  INT32_MAX\n#define INTPTR_MIN  INT32_MIN\n\n#define PTRDIFF_MAX INT32_MAX\n#define PTRDIFF_MIN INT32_MIN\n\n#define SIZE_MAX    UINT32_MAX\n\n#define UINT8_MAX   0xff\n#define UINT16_MAX  0xffff\n#define UINT32_MAX  0xffffffffU\n#define UINT64_MAX  0xffffffffffffffffU\n\n#define UINTMAX_MAX UINT64_MAX\n#define UINTPTR_MAX UINT32_MAX\n\ntypedef signed char        int8_t;\ntypedef short              int16_t;\ntypedef int                int32_t;\ntypedef long long          int64_t;\n\ntypedef long long          intmax_t;\ntypedef int                intptr_t;\n\ntypedef unsigned char      uint8_t;\ntypedef unsigned short     uint16_t;\ntypedef unsigned           uint32_t;\ntypedef unsigned long long uint64_t;\n\ntypedef unsigned long long uintmax_t;\ntypedef unsigned           uintptr_t;\n\n#endif /* STDLIB_STDINT_H */\n"
  },
  {
    "path": "lib/Makefile",
    "content": "#\n# Copyright © 2017-2022 The Crust Firmware Authors.\n# SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n#\n\nlib-y += bitfield.o\n"
  },
  {
    "path": "lib/bitfield.c",
    "content": "/*\n * Copyright © 2019-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <bitfield.h>\n#include <mmio.h>\n#include <stdint.h>\n#include <util.h>\n\nuint32_t\nbitfield_get(uint32_t word, uint32_t start, uint32_t width)\n{\n\treturn (word >> start) & (BIT(width) - 1);\n}\n\nuint32_t\nbitfield_set(uint32_t word, uint32_t start, uint32_t width, uint32_t value)\n{\n\treturn word ^ ((value << start ^ word) & ((BIT(width) - 1) << start));\n}\n\nuint32_t\nmmio_get_bitfield_32(uintptr_t addr, uint32_t start, uint32_t width)\n{\n\treturn bitfield_get(mmio_read_32(addr), start, width);\n}\n\nvoid\nmmio_set_bitfield_32(uintptr_t addr, uint32_t start, uint32_t width,\n                     uint32_t value)\n{\n\tuint32_t word = mmio_read_32(addr);\n\n\tmmio_write_32(addr, bitfield_set(word, start, width, value));\n}\n"
  },
  {
    "path": "platform/Kconfig",
    "content": "#\n# Copyright © 2017-2022 The Crust Firmware Authors.\n# SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n#\n\nconfig PLATFORM\n\tstring\n\tdefault \"a23\"  if PLATFORM_A23\n\tdefault \"a64\"  if PLATFORM_A64\n\tdefault \"a83t\" if PLATFORM_A83T\n\tdefault \"h3\"   if PLATFORM_H3\n\tdefault \"h6\"   if PLATFORM_H6\n\nchoice\n\tprompt \"Platform selection\"\n\nconfig PLATFORM_A23\n\tbool \"A23/A33\"\n\tdepends on ARCH_OR1K\n\tselect HAVE_R_RSB\n\nconfig PLATFORM_A64\n\tbool \"A64/H5\"\n\tdepends on ARCH_OR1K\n\tselect HAVE_DRAM_SUSPEND\n\tselect HAVE_HDMI\n\tselect HAVE_R_CIR\n\tselect HAVE_R_TWD\n\nconfig PLATFORM_A83T\n\tbool \"A83T\"\n\tdepends on ARCH_OR1K\n\tselect HAVE_HDMI\n\tselect HAVE_R_CIR\n\tselect HAVE_R_RSB\n\tselect HAVE_R_TWD\n\tselect HAVE_UART4\n\nconfig PLATFORM_H3\n\tbool \"H3\"\n\tdepends on ARCH_OR1K\n\tselect HAVE_DRAM_SUSPEND\n\tselect HAVE_HDMI\n\tselect HAVE_R_CIR\n\tselect HAVE_R_TWD\n\nconfig PLATFORM_H6\n\tbool \"H6\"\n\tdepends on ARCH_OR1K\n\tselect HAVE_DCXO\n\tselect HAVE_DRAM_SUSPEND\n\tselect HAVE_HDMI\n\tselect HAVE_R_CIR\n\tselect HAVE_R_RSB\n\tselect HAVE_R_TWD\n\nendchoice\n\nsource \"a23/Kconfig\"\nsource \"a64/Kconfig\"\n\nconfig HAVE_DCXO\n\tbool\n\thelp\n\t\tSelect this option on platforms with a DCXO in the RTC\n\t\tdomain in addition to X24M pads in the PLL domain.\n\nconfig HAVE_DRAM_SUSPEND\n\tbool\n\thelp\n\t\tSelect this option on platforms with the ability to\n\t\tsuspend the DRAM controller.\n\nconfig HAVE_HDMI\n\tbool\n\thelp\n\t\tSelect this option on platforms with an HDMI controller.\n\nconfig HAVE_R_CIR\n\tbool\n\thelp\n\t\tSelect this option on platforms with a consumer infrared\n\t\t(CIR) controller.\n\nconfig HAVE_R_I2C\n\tbool\n\tdefault y\n\thelp\n\t\tSelect this option on platforms with an R_I2C controller.\n\nconfig HAVE_R_RSB\n\tbool\n\thelp\n\t\tSelect this option on platforms with an RSB controller.\n\nconfig HAVE_R_TWD\n\tbool\n\thelp\n\t\tSelect this option on platforms with a trusted watchdog.\n\nconfig HAVE_UART4\n\tbool\n\thelp\n\t\tSelect this option on platforms with a UART4.\n"
  },
  {
    "path": "platform/a23/Kconfig",
    "content": "#\n# Copyright © 2022 The Crust Firmware Authors.\n# SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n#\n\nif PLATFORM_A23\n\nchoice\n\tbool \"SoC\"\n\nconfig SOC_A23\n\tbool \"A23\"\n\tselect HAVE_UART4\n\nconfig SOC_A33\n\tbool \"A33\"\n\nendchoice\n\nendif\n"
  },
  {
    "path": "platform/a23/include/platform/cpucfg.h",
    "content": "/*\n * Copyright © 2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef PLATFORM_CPUCFG_H\n#define PLATFORM_CPUCFG_H\n\n#include <util.h>\n#include <platform/devices.h>\n\n#define CPUS_RESET_REG                  (DEV_R_CPUCFG + 0x0000)\n#define CPUS_RESET                      BIT(0)\n\n/* Four of these ranges exist. */\n#define CPUS_BYTE_SWAP_EN_REG           (DEV_R_CPUCFG + 0x000c)\n#define CPUS_BYTE_SWAP_EN_REG_RANGEn(n) BIT(0 + (n))\n\n#define CPUS_BYTE_SWAP_LO_REG(n)        (DEV_R_CPUCFG + 0x0010 + 0x08 * (n))\n#define CPUS_BYTE_SWAP_HI_REG(n)        (DEV_R_CPUCFG + 0x0014 + 0x08 * (n))\n\n#define CPUn_RST_CTRL_REG(n)            (DEV_R_CPUCFG + 0x0040 + 0x40 * (n))\n#define CPUn_RST_CTRL_REG_nCORERESET    BIT(1)\n#define CPUn_RST_CTRL_REG_nCPUPORESET   BIT(0)\n\n#define CPUn_CTRL_REG(n)                (DEV_R_CPUCFG + 0x0044 + 0x40 * (n))\n#define CPUn_CTRL_REG_CP15SDISABLE      BIT(0)\n\n#define CPUn_STATUS_REG(n)              (DEV_R_CPUCFG + 0x0048 + 0x40 * (n))\n#define CPUn_STATUS_REG_STANDBYWFI      BIT(2)\n#define CPUn_STATUS_REG_STANDBYWFE      BIT(1)\n#define CPUn_STATUS_REG_SMPnAMP         BIT(0)\n\n#define CPU_SYS_RESET_REG               (DEV_R_CPUCFG + 0x0140)\n#define CPU_SYS_RESET                   BIT(0)\n\n#define GEN_CTRL_REG                    (DEV_R_CPUCFG + 0x0184)\n#define GEN_CTRL_REG_CFGSDISABLE        BIT(8)\n#define GEN_CTRL_REG_ACINACTM           BIT(6)\n#define GEN_CTRL_REG_nL2RESET           BIT(5)\n#define GEN_CTRL_REG_L2RSTDISABLE       BIT(4)\n#define GEN_CTRL_REG_L1RSTDISABLE(n)    BIT(0 + (n))\n#define GEN_CTRL_REG_L1RSTDISABLE_MASK  (0xf << 0)\n\n#define EVENT_IN_REG                    (DEV_R_CPUCFG + 0x0190)\n#define EVENT_IN                        BIT(0)\n\n#define DBG_CTRL_REG0                   (DEV_R_CPUCFG + 0x01e0)\n\n#define DBG_CTRL_REG1                   (DEV_R_CPUCFG + 0x01e4)\n#define DBG_CTRL_REG1_DBGPWRDUP(n)      BIT(0 + (n))\n#define DBG_CTRL_REG1_DBGPWRDUP_MASK    (0xf << 0)\n\n#define CNT64_CTRL_REG                  (DEV_R_CPUCFG + 0x0280)\n#define CNT64_RL_EN                     BIT(1)\n#define CNT64_CLR_EN                    BIT(0)\n\n#define CNT64_LO_REG                    (DEV_R_CPUCFG + 0x0284)\n#define CNT64_HI_REG                    (DEV_R_CPUCFG + 0x0288)\n\n#endif /* PLATFORM_CPUCFG_H */\n"
  },
  {
    "path": "platform/a23/include/platform/css.h",
    "content": "/*\n * Copyright © 2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef PLATFORM_CSS_H\n#define PLATFORM_CSS_H\n\n#define MAX_CLUSTERS          1\n#if CONFIG(SOC_A23)\n#define MAX_CORES_PER_CLUSTER 2\n#else\n#define MAX_CORES_PER_CLUSTER 4\n#endif\n\n#endif /* PLATFORM_CSS_H */\n"
  },
  {
    "path": "platform/a23/include/platform/devices.h",
    "content": "/*\n * Copyright © 2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef PLATFORM_DEVICES_H\n#define PLATFORM_DEVICES_H\n\n#define DEV_SYSCON    0x01c00000\n#define DEV_DMA       0x01c02000\n#define DEV_NAND      0x01c03000\n#define DEV_TCON0     0x01c0c000\n#define DEV_VE        0x01c0e000\n#define DEV_MMC0      0x01c0f000\n#define DEV_MMC1      0x01c10000\n#define DEV_MMC2      0x01c11000\n#define DEV_CE        0x01c15000\n#define DEV_MSGBOX    0x01c17000\n#define DEV_SPINLOCK  0x01c18000\n#define DEV_USBOTG    0x01c19000\n#define DEV_USB0      0x01c1a000\n#define DEV_CCU       0x01c20000\n#define DEV_PIO       0x01c20800\n#define DEV_TIMER     0x01c20c00\n#define DEV_PWM       0x01c21400\n#define DEV_I2S0      0x01c22000\n#define DEV_I2S1      0x01c22400\n#define DEV_LRADC     0x01c22800\n#define DEV_CODEC     0x01c22c00\n#define DEV_THS       0x01c25000\n#define DEV_UART0     0x01c28000\n#define DEV_UART1     0x01c28400\n#define DEV_UART2     0x01c28800\n#define DEV_UART3     0x01c28c00\n#define DEV_UART4     0x01c29000\n#define DEV_I2C0      0x01c2ac00\n#define DEV_I2C1      0x01c2b000\n#define DEV_I2C2      0x01c2b400\n#define DEV_GPU       0x01c40000\n#define DEV_HSTIMER   0x01c60000\n#define DEV_DRAMCOM   0x01c62000\n#define DEV_DRAMCTL   0x01c63000\n#define DEV_DRAMPHY   0x01c65000\n#define DEV_SPI0      0x01c68000\n#define DEV_SPI1      0x01c69000\n#define DEV_SCU       0x01c80000\n#define DEV_GICD      0x01c81000\n#define DEV_GICC      0x01c82000\n#define DEV_MIPI_DSI  0x01ca0000\n#define DEV_MIPI_DPHY 0x01ca1000\n#define DEV_CSI       0x01cb0000\n#define DEV_DEFE      0x01e00000\n#define DEV_DEBE      0x01e60000\n#define DEV_DRC       0x01e70000\n#define DEV_SAT       0x01e80000\n#define DEV_RTC       0x01f00000\n#define DEV_R_TIMER   0x01f00800\n#define DEV_R_INTC    0x01f00c00\n#define DEV_R_WDOG    0x01f01000\n#define DEV_R_PRCM    0x01f01400\n#define DEV_R_CPUCFG  0x01f01c00\n#define DEV_R_I2C     0x01f02400\n#define DEV_R_UART    0x01f02800\n#define DEV_R_PIO     0x01f02c00\n#define DEV_R_RSB     0x01f03400\n#define DEV_R_PWM     0x01f03800\n\n#endif /* PLATFORM_DEVICES_H */\n"
  },
  {
    "path": "platform/a23/include/platform/irq.h",
    "content": "/*\n * Copyright © 2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef PLATFORM_IRQ_H\n#define PLATFORM_IRQ_H\n\n#define IRQ_NMI      0x00\n#define IRQ_R_TIMER0 0x01\n#define IRQ_R_TIMER1 0x02\n\n#define IRQ_R_WDOG   0x04\n\n#define IRQ_R_UART   0x06\n#define IRQ_R_RSB    0x07\n#define IRQ_R_ALARM0 0x08\n#define IRQ_R_ALARM1 0x09\n\n#define IRQ_R_I2C    0x0c\n#define IRQ_R_PIO_PL 0x0d\n\n#define IRQ_MSGBOX   0x11\n\n#endif /* PLATFORM_IRQ_H */\n"
  },
  {
    "path": "platform/a23/include/platform/memory.h",
    "content": "/*\n * Copyright © 2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef PLATFORM_MEMORY_H\n#define PLATFORM_MEMORY_H\n\n#define FIRMWARE_BASE  0x00010000\n#define FIRMWARE_LIMIT SCPI_MEM_BASE\n#define FIRMWARE_SIZE  (FIRMWARE_LIMIT - FIRMWARE_BASE)\n\n#define SCPI_MEM_BASE  (SRAM_A2_LIMIT - 0x400)\n#define SCPI_MEM_LIMIT SRAM_A2_LIMIT\n#define SCPI_MEM_SIZE  (SCPI_MEM_LIMIT - SCPI_MEM_BASE)\n\n#define SRAM_A2_BASE   0x00000000\n#define SRAM_A2_LIMIT  0x00014000\n#define SRAM_A2_SIZE   (SRAM_A2_LIMIT - SRAM_A2_BASE)\n\n/* Difference between SRAM_A2_BASE in the AR100 and ARM address spaces. */\n#define SRAM_A2_OFFSET 0x00040000\n\n#define STACK_SIZE     0x00000400\n\n#endif /* PLATFORM_MEMORY_H */\n"
  },
  {
    "path": "platform/a23/include/platform/prcm.h",
    "content": "/*\n * Copyright © 2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef PLATFORM_PRCM_H\n#define PLATFORM_PRCM_H\n\n#include <util.h>\n#include <platform/devices.h>\n\n#define CPUS_CLK_REG                      (DEV_R_PRCM + 0x0000)\n#define CPUS_CLK_REG_CLK_SRC(x)           ((x) << 16)\n#define CPUS_CLK_REG_CLK_SRC_MASK         (0x3 << 16)\n#define CPUS_CLK_REG_PRE_DIV(x)           ((x) << 8)\n#define CPUS_CLK_REG_PRE_DIV_MASK         (0x1f << 8)\n#define CPUS_CLK_REG_DIV_P(x)             ((x) << 4)\n#define CPUS_CLK_REG_DIV_P_MASK           (0x3 << 4)\n\n#define APB0_CLK_REG                      (DEV_R_PRCM + 0x000c)\n#define APB0_CLK_REG_DIV_M(x)             ((x) << 0)\n#define APB0_CLK_REG_DIV_M_MASK           (0x3 << 0)\n\n/* See r_ccu driver for bit definitions */\n#define APB0_GATE_REG                     (DEV_R_PRCM + 0x0028)\n#define RTC_GATE_REG                      (DEV_R_PRCM + 0x002c)\n\n#define PLL_CTRL_REG0                     (DEV_R_PRCM + 0x0040)\n#define PLL_CTRL_REG0_TEST_CLK_SEL        BIT(24)\n#define PLL_CTRL_REG0_OSC24M_CLK_SEL(x)   ((x) << 20)\n#define PLL_CTRL_REG0_OSC24M_CLK_SEL_MASK (0x3 << 20)\n#define PLL_CTRL_REG0_PLL_INPUT_SEL(x)    ((x) << 12)\n#define PLL_CTRL_REG0_PLL_INPUT_SEL_MASK  (0x3 << 12)\n#define PLL_CTRL_REG0_USB24M_CLK_SEL(x)   ((x) << 4)\n#define PLL_CTRL_REG0_USB24M_CLK_SEL_MASK (0x3 << 4)\n#define PLL_CTRL_REG0_OSC24M_GAIN_ENHANCE BIT(1)\n#define PLL_CTRL_REG0_PLL_BIAS_EN         BIT(0)\n\n#define PLL_CTRL_REG1                     (DEV_R_PRCM + 0x0044)\n#define PLL_CTRL_REG1_KEY                 (0xa7 << 24)\n#define PLL_CTRL_REG1_KEY_FIELD           (0xff << 24)\n#define PLL_CTRL_REG1_PLL_LDO_OUT(x)      ((x) << 16)\n#define PLL_CTRL_REG1_PLL_LDO_OUT_MASK    (0x7 << 16)\n#define PLL_CTRL_REG1_PLL_IN_PWR_SEL      BIT(15)\n#define PLL_CTRL_REG1_CLKTEST_EN          BIT(3)\n#define PLL_CTRL_REG1_CRYSTAL_EN          BIT(2)\n#define PLL_CTRL_REG1_LDO_EN              (0x3 << 0)\n\n/* See r_ccu driver for bit definitions */\n#define APB0_RESET_REG                    (DEV_R_PRCM + 0x00b0)\n\n/* CPU0 does not have its own gating */\n#define C0_PWROFF_GATING_REG              (DEV_R_PRCM + 0x0100)\n#define C0_CPUn_PWROFF_GATING(n)          BIT(0 + (n))\n#define C0_PWROFF_GATING                  BIT(0)\n\n#define VDD_SYS_PWROFF_GATING_REG         (DEV_R_PRCM + 0x0110)\n#define VDD_CPUS_GATING                   BIT(3)\n#define AVCC_GATING                       BIT(2)\n#define DRAM_PAD_HOLD                     (0x3 << 0)\n\n#define GPU_PWROFF_GATING_REG             (DEV_R_PRCM + 0x0118)\n#define GPU_PWROFF_GATING                 BIT(0)\n\n#define VDD_SYS_RESET_REG                 (DEV_R_PRCM + 0x0120)\n#define VDD_SYS_RESET                     BIT(0)\n\n/* CPU0 does not have its own power switch */\n#define C0_CPUn_PWR_SWITCH_REG(n)         (DEV_R_PRCM + 0x0140 + 0x04 * (n))\n\n#define ADDA_PR_CFG_REG                   (DEV_R_PRCM + 0x01c0)\n#define ADDA_PR_CFG_REG_RESET             BIT(28)\n#define ADDA_PR_CFG_REG_RW                BIT(24)\n#define ADDA_PR_CFG_REG_ADDR(x)           ((x) << 16)\n#define ADDA_PR_CFG_REG_ADDR_MASK         (0x1f << 16)\n#define ADDA_PR_CFG_REG_WDAT(x)           ((x) << 8)\n#define ADDA_PR_CFG_REG_WDAT_MASK         (0xff << 8)\n#define ADDA_PR_CFG_REG_RDAT(x)           ((x) << 0)\n#define ADDA_PR_CFG_REG_RDAT_MASK         (0xff << 0)\n\n#define PRCM_SEC_SWITCH_REG               (DEV_R_PRCM + 0x01d0)\n#define PRCM_SEC_SWITCH_REG_POWER_SEC     BIT(2)\n#define PRCM_SEC_SWITCH_REG_PLL_SEC       BIT(1)\n#define PRCM_SEC_SWITCH_REG_CPUS_CLK_SEC  BIT(0)\n\n#endif /* PLATFORM_PRCM_H */\n"
  },
  {
    "path": "platform/a23/include/platform/time.h",
    "content": "/*\n * Copyright © 2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef PLATFORM_TIME_H\n#define PLATFORM_TIME_H\n\n/* Actually around 600 kHz, but this is close enough for timeouts. */\n#define CPUCLK_MHz 1\n#define CPUCLK_kHz (CPUCLK_MHz * 1000)\n#define CPUCLK_Hz  (CPUCLK_MHz * 1000000)\n\n#define REFCLK_MHZ 24\n#define REFCLK_KHZ (REFCLK_MHZ * 1000)\n#define REFCLK_HZ  (REFCLK_MHZ * 1000000)\n\n#endif /* PLATFORM_TIME_H */\n"
  },
  {
    "path": "platform/a64/Kconfig",
    "content": "#\n# Copyright © 2017-2022 The Crust Firmware Authors.\n# SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n#\n\nif PLATFORM_A64\n\nchoice\n\tbool \"SoC\"\n\nconfig SOC_A64\n\tbool \"A64\"\n\tselect HAVE_R_RSB\n\tselect HAVE_UART4\n\nconfig SOC_H5\n\tbool \"H5\"\n\nendchoice\n\nendif\n"
  },
  {
    "path": "platform/a64/include/platform/cpucfg.h",
    "content": "/*\n * Copyright © 2020-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef PLATFORM_CPUCFG_H\n#define PLATFORM_CPUCFG_H\n\n#include <util.h>\n#include <platform/devices.h>\n\n#define C0_CTRL_REG0                      (DEV_CPUCFG + 0x0000)\n#define C0_CTRL_REG0_SYSBARDISABLE        BIT(31)\n#define C0_CTRL_REG0_BROADCASTINNER       BIT(30)\n#define C0_CTRL_REG0_BROADCASTOUTER       BIT(29)\n#define C0_CTRL_REG0_BROADCASTCACHEMAINT  BIT(28)\n#define C0_CTRL_REG0_AA64nAA32(n)         BIT(24 + (n))\n#define C0_CTRL_REG0_AA64nAA32_MASK       (0xf << 24)\n#define C0_CTRL_REG0_CP15SDISABLE(n)      BIT(8 + (n))\n#define C0_CTRL_REG0_L2RSTDISABLE         BIT(4)\n\n#define C0_CTRL_REG1                      (DEV_CPUCFG + 0x0004)\n#define C0_CTRL_REG1_ACINACTM             BIT(0)\n\n#define CACHE_CFG_REG0                    (DEV_CPUCFG + 0x0008)\n#define CACHE_CFG_REG0_L1SDT_DELAY        (0x7 << 28)\n#define CACHE_CFG_REG0_L1TLB_DELAY        (0x7 << 24)\n#define CACHE_CFG_REG0_BTAC_DELAY         (0x7 << 20)\n#define CACHE_CFG_REG0_L1DY_DELAY         (0x7 << 16)\n#define CACHE_CFG_REG0_L1DT_DELAY         (0x7 << 12)\n#define CACHE_CFG_REG0_L1DD_DELAY         (0x7 << 8)\n#define CACHE_CFG_REG0_L1IT_DELAY         (0x7 << 4)\n#define CACHE_CFG_REG0_L1ID_DELAY         (0x7 << 0)\n\n#define CACHE_CFG_REG1                    (DEV_CPUCFG + 0x000c)\n#define CACHE_CFG_REG1_EMAW               (0x7 << 24)\n#define CACHE_CFG_REG1_EMA                (0x7 << 16)\n#define CACHE_CFG_REG1_L2V_DELAY          (0x7 << 12)\n#define CACHE_CFG_REG1_L2T_DELAY          (0x7 << 4)\n\n#define DBG_REG0                          (DEV_CPUCFG + 0x0020)\n/* This bit is present; its meaning is guessed from the H6 manual */\n#define DBG_REG0_DBGL1RSTDISABLE          BIT(16)\n#define DBG_REG0_DBGPWRDUP(n)             BIT(0 + (n))\n#define DBG_REG0_DBGPWRDUP_MASK           (0xf << 0)\n\n/* Name taken from H6 manual. */\n#define C0_CTRL_REG2                      (DEV_CPUCFG + 0x0028)\n#define C0_CTRL_REG2_EVENTI               BIT(24)\n#define C0_CTRL_REG2_EXM_CLR(n)           BIT(20 + (n))\n#define C0_CTRL_REG2_CLREXMONREQ          BIT(16)\n#define C0_CTRL_REG2_CRYPTODISABLE(n)     BIT(12 + (n))\n#define C0_CTRL_REG2_L2FLUSHREQ           BIT(8)\n#define C0_CTRL_REG2_GICCDISABLE          BIT(4)\n\n#define C0_CPU_STATUS_REG                 (DEV_CPUCFG + 0x0030)\n#define C0_CPU_STATUS_REG_SMPnAMP(n)      BIT(24 + (n))\n#define C0_CPU_STATUS_REG_STANDBYWFI(n)   BIT(16 + (n))\n#define C0_CPU_STATUS_REG_STANDBYWFI_MASK (0xf << 16)\n#define C0_CPU_STATUS_REG_STANDBYWFE(n)   BIT(8 + (n))\n#define C0_CPU_STATUS_REG_STANDBYWFE_MASK (0xf << 8)\n#define C0_CPU_STATUS_REG_STANDBYWFIL2    BIT(0)\n\n#define L2_STATUS_REG                     (DEV_CPUCFG + 0x003c)\n#define L2_STATUS_REG_L2FLUSHDONE         BIT(10)\n#define L2_STATUS_REG_EVENTO              BIT(9)\n#define L2_STATUS_REG_CLREXMONACK         BIT(8)\n\n#define C0_RST_CTRL_REG                   (DEV_CPUCFG + 0x0080)\n#define C0_RST_CTRL_REG_nDDR_RST          BIT(28)\n#define C0_RST_CTRL_REG_nSOC_DBG_RST      BIT(24)\n#define C0_RST_CTRL_REG_nMBISTRESET       BIT(20)\n#define C0_RST_CTRL_REG_nH_RST            BIT(12)\n#define C0_RST_CTRL_REG_nL2RESET          BIT(8)\n#define C0_RST_CTRL_REG_nCORERESET(n)     BIT(0 + (n))\n#define C0_RST_CTRL_REG_MASK              (C0_RST_CTRL_REG_nDDR_RST | \\\n\t                                   C0_RST_CTRL_REG_nSOC_DBG_RST | \\\n\t                                   C0_RST_CTRL_REG_nMBISTRESET | \\\n\t                                   C0_RST_CTRL_REG_nH_RST | \\\n\t                                   C0_RST_CTRL_REG_nL2RESET)\n\n#define RVBA_LO_REG(n)                    (DEV_CPUCFG + 0x00a0 + 0x08 * (n))\n#define RVBA_HI_REG(n)                    (DEV_CPUCFG + 0x00a4 + 0x08 * (n))\n\n#define CPUS_RESET_REG                    (DEV_R_CPUCFG + 0x0000)\n#define CPUS_RESET                        BIT(0)\n\n/* Four of these ranges exist. */\n#define CPUS_BYTE_SWAP_EN_REG             (DEV_R_CPUCFG + 0x000c)\n#define CPUS_BYTE_SWAP_EN_REG_RANGEn(n)   BIT(0 + (n))\n\n#define CPUS_BYTE_SWAP_LO_REG(n)          (DEV_R_CPUCFG + 0x0010 + 0x08 * (n))\n#define CPUS_BYTE_SWAP_HI_REG(n)          (DEV_R_CPUCFG + 0x0014 + 0x08 * (n))\n\n#define C0_PWRON_RESET_REG                (DEV_R_CPUCFG + 0x0030)\n#define C0_PWRON_RESET_REG_nCPUPORESET(n) BIT(0 + (n))\n\n#define CPU_SYS_RESET_REG                 (DEV_R_CPUCFG + 0x0140)\n#define CPU_SYS_RESET                     BIT(0)\n\n#define IRQ_FIQ_STATUS_REG                (DEV_R_CPUCFG + 0x014c)\n#define C0_IRQ_OUT(n)                     BIT(0 + (n))\n#define C0_IRQ_OUT_MASK                   (0xf << 0)\n\n#define CNT64_CTRL_REG                    (DEV_R_CPUCFG + 0x0280)\n#define CNT64_RL_EN                       BIT(1)\n#define CNT64_CLR_EN                      BIT(0)\n\n#define CNT64_LO_REG                      (DEV_R_CPUCFG + 0x0284)\n#define CNT64_HI_REG                      (DEV_R_CPUCFG + 0x0288)\n\n#endif /* PLATFORM_CPUCFG_H */\n"
  },
  {
    "path": "platform/a64/include/platform/css.h",
    "content": "/*\n * Copyright © 2020-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef PLATFORM_CSS_H\n#define PLATFORM_CSS_H\n\n#define MAX_CLUSTERS          1\n#define MAX_CORES_PER_CLUSTER 4\n\n#endif /* PLATFORM_CSS_H */\n"
  },
  {
    "path": "platform/a64/include/platform/devices.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef PLATFORM_DEVICES_H\n#define PLATFORM_DEVICES_H\n\n#define DEV_DE          0x01000000\n#define DEV_DEBUG       0x01400000\n#define DEV_CPU_BIST    0x01502000\n#define DEV_CPUCFG      0x01700000\n#define DEV_SYSCON      0x01c00000\n#define DEV_DMA         0x01c02000\n#define DEV_NAND        0x01c03000\n#define DEV_TSC         0x01c06000\n#define DEV_KEYMEM      0x01c0b000\n#define DEV_TCON0       0x01c0c000\n#define DEV_TCON1       0x01c0d000\n#define DEV_VE          0x01c0e000\n#define DEV_MMC0        0x01c0f000\n#define DEV_MMC1        0x01c10000\n#define DEV_MMC2        0x01c11000\n#define DEV_SID         0x01c14000\n#define DEV_CE          0x01c15000\n#define DEV_MSGBOX      0x01c17000\n#define DEV_SPINLOCK    0x01c18000\n#define DEV_USBOTG      0x01c19000\n#define DEV_USB0        0x01c1a000\n#define DEV_USB1        0x01c1b000\n#if CONFIG(SOC_H5)\n#define DEV_USB2        0x01c1c000\n#define DEV_USB3        0x01c1d000\n#endif\n#define DEV_TZASC       0x01c1e000\n#define DEV_CCU         0x01c20000\n#define DEV_PIO         0x01c20800\n#define DEV_TIMER       0x01c20c00\n#define DEV_SPDIF       0x01c21000\n#define DEV_PWM         0x01c21400\n#define DEV_KEYADC      0x01c21800\n#define DEV_I2S0        0x01c22000\n#define DEV_I2S1        0x01c22400\n#define DEV_I2S2        0x01c22800\n#define DEV_CODEC       0x01c22c00\n#define DEV_SPC         0x01c23400\n#define DEV_THS         0x01c25000\n#define DEV_UART0       0x01c28000\n#define DEV_UART1       0x01c28400\n#define DEV_UART2       0x01c28800\n#define DEV_UART3       0x01c28c00\n#if CONFIG(SOC_A64)\n#define DEV_UART4       0x01c29000\n#endif\n#define DEV_I2C0        0x01c2ac00\n#define DEV_I2C1        0x01c2b000\n#define DEV_I2C2        0x01c2b400\n#define DEV_SCR0        0x01c2c400\n#if CONFIG(SOC_H5)\n#define DEV_SCR1        0x01c2c800\n#endif\n#define DEV_EMAC        0x01c30000\n#if CONFIG(SOC_A64)\n#define DEV_GPU         0x01c40000\n#endif\n#define DEV_HSTIMER     0x01c60000\n#define DEV_DRAMCOM     0x01c62000\n#define DEV_DRAMCTL     0x01c63000\n#define DEV_DRAMPHY     0x01c65000\n#define DEV_SPI0        0x01c68000\n#define DEV_SPI1        0x01c69000\n#define DEV_SCU         0x01c80000\n#define DEV_GICD        0x01c81000\n#define DEV_GICC        0x01c82000\n#if CONFIG(SOC_A64)\n#define DEV_MIPI_DSI    0x01ca0000\n#define DEV_MIPI_DPHY   0x01ca1000\n#endif\n#define DEV_CSI         0x01cb0000\n#define DEV_DEINTERLACE 0x01e00000\n#if CONFIG(SOC_H5)\n#define DEV_TVE         0x01e40000\n#define DEV_GPU         0x01e80000\n#endif\n#define DEV_HDMI        0x01ee0000\n#define DEV_HDMI_PHY    0x01ef0000\n#define DEV_RTC         0x01f00000\n#define DEV_R_TIMER     0x01f00800\n#define DEV_R_INTC      0x01f00c00\n#define DEV_R_WDOG      0x01f01000\n#define DEV_R_PRCM      0x01f01400\n#define DEV_R_TWD       0x01f01800\n#define DEV_R_CPUCFG    0x01f01c00\n#define DEV_R_CIR_RX    0x01f02000\n#define DEV_R_I2C       0x01f02400\n#define DEV_R_UART      0x01f02800\n#define DEV_R_PIO       0x01f02c00\n#if CONFIG(SOC_A64)\n#define DEV_R_RSB       0x01f03400\n#endif\n#define DEV_R_PWM       0x01f03800\n\n#endif /* PLATFORM_DEVICES_H */\n"
  },
  {
    "path": "platform/a64/include/platform/irq.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef PLATFORM_IRQ_H\n#define PLATFORM_IRQ_H\n\n#define IRQ_NMI      0x00\n#define IRQ_R_TIMER0 0x01\n#define IRQ_R_TIMER1 0x02\n\n#define IRQ_R_WDOG   0x04\n#define IRQ_R_CIR_RX 0x05\n#define IRQ_R_UART   0x06\n#if CONFIG(SOC_A64)\n#define IRQ_R_RSB    0x07\n#endif\n#define IRQ_R_ALARM0 0x08\n#define IRQ_R_ALARM1 0x09\n#define IRQ_R_TIMER2 0x0a\n#define IRQ_R_TIMER3 0x0b\n#define IRQ_R_I2C    0x0c\n#define IRQ_R_PIO_PL 0x0d\n#define IRQ_R_TWD    0x0e\n\n#define IRQ_MSGBOX   0x11\n\n#endif /* PLATFORM_IRQ_H */\n"
  },
  {
    "path": "platform/a64/include/platform/memory.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef PLATFORM_MEMORY_H\n#define PLATFORM_MEMORY_H\n\n#define FIRMWARE_BASE  0x00010000\n#define FIRMWARE_LIMIT SCPI_MEM_BASE\n#define FIRMWARE_SIZE  (FIRMWARE_LIMIT - FIRMWARE_BASE)\n\n#define SCPI_MEM_BASE  (SRAM_A2_LIMIT - 0x400)\n#define SCPI_MEM_LIMIT SRAM_A2_LIMIT\n#define SCPI_MEM_SIZE  (SCPI_MEM_LIMIT - SCPI_MEM_BASE)\n\n#define SRAM_A2_BASE   0x00000000\n#define SRAM_A2_LIMIT  0x00014000\n#define SRAM_A2_SIZE   (SRAM_A2_LIMIT - SRAM_A2_BASE)\n\n/* Difference between SRAM_A2_BASE in the AR100 and ARM address spaces. */\n#define SRAM_A2_OFFSET 0x00040000\n\n#define STACK_SIZE     0x00000400\n\n#endif /* PLATFORM_MEMORY_H */\n"
  },
  {
    "path": "platform/a64/include/platform/prcm.h",
    "content": "/*\n * Copyright © 2020-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef PLATFORM_PRCM_H\n#define PLATFORM_PRCM_H\n\n#include <util.h>\n#include <platform/devices.h>\n\n#define CPUS_CLK_REG                      (DEV_R_PRCM + 0x0000)\n#define CPUS_CLK_REG_CLK_SRC(x)           ((x) << 16)\n#define CPUS_CLK_REG_CLK_SRC_MASK         (0x3 << 16)\n#define CPUS_CLK_REG_PRE_DIV(x)           ((x) << 8)\n#define CPUS_CLK_REG_PRE_DIV_MASK         (0x1f << 8)\n#define CPUS_CLK_REG_DIV_P(x)             ((x) << 4)\n#define CPUS_CLK_REG_DIV_P_MASK           (0x3 << 4)\n\n#define APB0_CLK_REG                      (DEV_R_PRCM + 0x000c)\n#define APB0_CLK_REG_DIV_M(x)             ((x) << 0)\n#define APB0_CLK_REG_DIV_M_MASK           (0x3 << 0)\n\n/* See r_ccu driver for bit definitions */\n#define APB0_GATE_REG                     (DEV_R_PRCM + 0x0028)\n#define RTC_GATE_REG                      (DEV_R_PRCM + 0x002c)\n\n/* Documented in A23/A31s manual; all bits are present on A64 */\n#define PLL_CTRL_REG0                     (DEV_R_PRCM + 0x0040)\n#define PLL_CTRL_REG0_TEST_CLK_SEL        BIT(24)\n#define PLL_CTRL_REG0_OSC24M_CLK_SEL(x)   ((x) << 20)\n#define PLL_CTRL_REG0_OSC24M_CLK_SEL_MASK (0x3 << 20)\n#define PLL_CTRL_REG0_PLL_INPUT_SEL(x)    ((x) << 12)\n#define PLL_CTRL_REG0_PLL_INPUT_SEL_MASK  (0x3 << 12)\n#define PLL_CTRL_REG0_USB24M_CLK_SEL(x)   ((x) << 4)\n#define PLL_CTRL_REG0_USB24M_CLK_SEL_MASK (0x3 << 4)\n#define PLL_CTRL_REG0_OSC24M_GAIN_ENHANCE BIT(1)\n#define PLL_CTRL_REG0_PLL_BIAS_EN         BIT(0)\n\n/* Documented in A23/A31s manual; bits 3 and 15 are not verified on A64 */\n#define PLL_CTRL_REG1                     (DEV_R_PRCM + 0x0044)\n#define PLL_CTRL_REG1_KEY                 (0xa7 << 24)\n#define PLL_CTRL_REG1_KEY_FIELD           (0xff << 24)\n#define PLL_CTRL_REG1_PLL_LDO_OUT(x)      ((x) << 16)\n#define PLL_CTRL_REG1_PLL_LDO_OUT_MASK    (0x7 << 16)\n#define PLL_CTRL_REG1_PLL_IN_PWR_SEL      BIT(15)\n#define PLL_CTRL_REG1_CLKTEST_EN          BIT(3)\n#define PLL_CTRL_REG1_CRYSTAL_EN          BIT(2)\n#define PLL_CTRL_REG1_LDO_EN              (0x3 << 0)\n\n/* See r_ccu driver for bit definitions */\n#define R_CIR_RX_CLK_REG                  (DEV_R_PRCM + 0x0054)\n#define APB0_RESET_REG                    (DEV_R_PRCM + 0x00b0)\n\n/* CPU0 does not have its own gating */\n#define C0_PWROFF_GATING_REG              (DEV_R_PRCM + 0x0100)\n#define C0_CPUn_PWROFF_GATING(n)          BIT(0 + (n))\n#define C0_PWROFF_GATING                  BIT(0)\n\n#define VDD_SYS_PWROFF_GATING_REG         (DEV_R_PRCM + 0x0110)\n#define VDD_CPUS_GATING                   BIT(3)\n#define AVCC_GATING                       BIT(2)\n#define DRAM_PAD_HOLD                     (0x3 << 0)\n\n#define GPU_PWROFF_GATING_REG             (DEV_R_PRCM + 0x0118)\n#define GPU_PWROFF_GATING                 BIT(0)\n\n#define VDD_SYS_RESET_REG                 (DEV_R_PRCM + 0x0120)\n#define VDD_SYS_RESET                     BIT(0)\n\n/* CPU0 does not have its own power switch */\n#define C0_CPUn_PWR_SWITCH_REG(n)         (DEV_R_PRCM + 0x0140 + 0x04 * (n))\n\n#define ADDA_PR_CFG_REG                   (DEV_R_PRCM + 0x01c0)\n#define ADDA_PR_CFG_REG_RESET             BIT(28)\n#define ADDA_PR_CFG_REG_RW                BIT(24)\n#define ADDA_PR_CFG_REG_ADDR(x)           ((x) << 16)\n#define ADDA_PR_CFG_REG_ADDR_MASK         (0x1f << 16)\n#define ADDA_PR_CFG_REG_WDAT(x)           ((x) << 8)\n#define ADDA_PR_CFG_REG_WDAT_MASK         (0xff << 8)\n#define ADDA_PR_CFG_REG_RDAT(x)           ((x) << 0)\n#define ADDA_PR_CFG_REG_RDAT_MASK         (0xff << 0)\n\n#define PRCM_SEC_SWITCH_REG               (DEV_R_PRCM + 0x01d0)\n#define PRCM_SEC_SWITCH_REG_POWER_SEC     BIT(2)\n#define PRCM_SEC_SWITCH_REG_PLL_SEC       BIT(1)\n#define PRCM_SEC_SWITCH_REG_CPUS_CLK_SEC  BIT(0)\n\n#endif /* PLATFORM_PRCM_H */\n"
  },
  {
    "path": "platform/a64/include/platform/time.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef PLATFORM_TIME_H\n#define PLATFORM_TIME_H\n\n#define CPUCLK_MHz 16\n#define CPUCLK_kHz (CPUCLK_MHz * 1000)\n#define CPUCLK_Hz  (CPUCLK_MHz * 1000000)\n\n#define REFCLK_MHZ 24\n#define REFCLK_KHZ (REFCLK_MHZ * 1000)\n#define REFCLK_HZ  (REFCLK_MHZ * 1000000)\n\n#endif /* PLATFORM_TIME_H */\n"
  },
  {
    "path": "platform/a83t/include/platform/css.h",
    "content": "/*\n * Copyright © 2020-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef PLATFORM_CSS_H\n#define PLATFORM_CSS_H\n\n#define MAX_CLUSTERS          2\n#define MAX_CORES_PER_CLUSTER 4\n\n#endif /* PLATFORM_CSS_H */\n"
  },
  {
    "path": "platform/a83t/include/platform/devices.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef PLATFORM_DEVICES_H\n#define PLATFORM_DEVICES_H\n\n#define DEV_DE               0x01000000\n#define DEV_DEBUG            0x01400000\n#define DEV_CPU_BIST_C0      0x01502000\n#define DEV_CPU_BIST_C1      0x01602000\n#define DEV_CPUCFG           0x01700000\n#define DEV_TIMESTAMP_STATUS 0x01710000\n#define DEV_TIMESTAMP_CTRL   0x01720000\n#define DEV_CCI              0x01790000\n#define DEV_SYSCON           0x01c00000\n#define DEV_DMA              0x01c02000\n#define DEV_NAND             0x01c03000\n#define DEV_KEYMEM           0x01c0b000\n#define DEV_TCON0            0x01c0c000\n#define DEV_TCON1            0x01c0d000\n#define DEV_VE               0x01c0e000\n#define DEV_MMC0             0x01c0f000\n#define DEV_MMC1             0x01c10000\n#define DEV_MMC2             0x01c11000\n#define DEV_SID              0x01c14000\n#define DEV_SS               0x01c15000\n#define DEV_MSGBOX           0x01c17000\n#define DEV_SPINLOCK         0x01c18000\n#define DEV_USBOTG           0x01c19000\n#define DEV_USB0             0x01c1a000\n#define DEV_USB1             0x01c1b000\n#define DEV_TZASC            0x01c1e000\n#define DEV_CCU              0x01c20000\n#define DEV_PIO              0x01c20800\n#define DEV_TIMER            0x01c20c00\n#define DEV_SPDIF            0x01c21000\n#define DEV_PWM              0x01c21400\n#define DEV_I2S0             0x01c22000\n#define DEV_I2S1             0x01c22400\n#define DEV_I2S2             0x01c22800\n#define DEV_TDM              0x01c23000\n#define DEV_SPC              0x01c23400\n#define DEV_DSI              0x01c26000\n#define DEV_UART0            0x01c28000\n#define DEV_UART1            0x01c28400\n#define DEV_UART2            0x01c28800\n#define DEV_UART3            0x01c28c00\n#define DEV_UART4            0x01c29000\n#define DEV_I2C0             0x01c2ac00\n#define DEV_I2C1             0x01c2b000\n#define DEV_I2C2             0x01c2b400\n#define DEV_EMAC             0x01c30000\n#define DEV_GPU              0x01c40000\n#define DEV_HSTIMER          0x01c60000\n#define DEV_DRAMCOM          0x01c62000\n#define DEV_DRAMCTL          0x01c63000\n#define DEV_DRAMPHY          0x01c65000\n#define DEV_SPI0             0x01c68000\n#define DEV_SPI1             0x01c69000\n#define DEV_GIC              0x01c80000\n#define DEV_GICD             0x01c81000\n#define DEV_GICC             0x01c82000\n#define DEV_CSI              0x01cb0000\n#define DEV_HDMI             0x01ee0000\n#define DEV_R_TIMER          0x01f00800\n#define DEV_R_INTC           0x01f00c00\n#define DEV_R_WDOG           0x01f01000\n#define DEV_R_PRCM           0x01f01400\n#define DEV_R_TWD            0x01f01800\n#define DEV_R_CPUCFG         0x01f01c00\n#define DEV_R_CIR_RX         0x01f02000\n#define DEV_R_I2C            0x01f02400\n#define DEV_R_UART           0x01f02800\n#define DEV_R_PIO            0x01f02c00\n#define DEV_R_RSB            0x01f03400\n#define DEV_R_PWM            0x01f03800\n#define DEV_R_LRADC          0x01f03c00\n#define DEV_R_THS            0x01f04000\n\n#endif /* PLATFORM_DEVICES_H */\n"
  },
  {
    "path": "platform/a83t/include/platform/irq.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef PLATFORM_IRQ_H\n#define PLATFORM_IRQ_H\n\n#define IRQ_NMI      0x00\n#define IRQ_R_TIMER0 0x01\n#define IRQ_R_TIMER1 0x02\n#define IRQ_R_WDOG   0x04\n#define IRQ_R_CIR_RX 0x05\n#define IRQ_R_UART   0x06\n#define IRQ_R_RSB    0x07\n#define IRQ_R_THS    0x09\n#define IRQ_R_LRADC  0x0a\n#define IRQ_R_I2C    0x0c\n#define IRQ_R_PIO_PL 0x0d\n#define IRQ_R_TWD    0x0e\n\n#define IRQ_MSGBOX   0x11\n\n#endif /* PLATFORM_IRQ_H */\n"
  },
  {
    "path": "platform/a83t/include/platform/memory.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef PLATFORM_MEMORY_H\n#define PLATFORM_MEMORY_H\n\n#define FIRMWARE_BASE  0x00010000\n#define FIRMWARE_LIMIT SCPI_MEM_BASE\n#define FIRMWARE_SIZE  (FIRMWARE_LIMIT - FIRMWARE_BASE)\n\n#define SCPI_MEM_BASE  (SRAM_A2_LIMIT - 0x400)\n#define SCPI_MEM_LIMIT SRAM_A2_LIMIT\n#define SCPI_MEM_SIZE  (SCPI_MEM_LIMIT - SCPI_MEM_BASE)\n\n#define SRAM_A2_BASE   0x00000000\n#define SRAM_A2_LIMIT  0x00014000\n#define SRAM_A2_SIZE   (SRAM_A2_LIMIT - SRAM_A2_BASE)\n\n/* Difference between SRAM_A2_BASE in the AR100 and ARM address spaces. */\n#define SRAM_A2_OFFSET 0x00040000\n\n#define STACK_SIZE     0x00000400\n\n#endif /* PLATFORM_MEMORY_H */\n"
  },
  {
    "path": "platform/a83t/include/platform/prcm.h",
    "content": "/*\n * Copyright © 2020-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef PLATFORM_PRCM_H\n#define PLATFORM_PRCM_H\n\n#include <util.h>\n#include <platform/devices.h>\n\n#define CPUS_CLK_REG                      (DEV_R_PRCM + 0x0000)\n#define CPUS_CLK_REG_CLK_SRC(x)           ((x) << 16)\n#define CPUS_CLK_REG_CLK_SRC_MASK         (0x3 << 16)\n#define CPUS_CLK_REG_PRE_DIV(x)           ((x) << 8)\n#define CPUS_CLK_REG_PRE_DIV_MASK         (0x1f << 8)\n#define CPUS_CLK_REG_DIV_P(x)             ((x) << 4)\n#define CPUS_CLK_REG_DIV_P_MASK           (0x3 << 4)\n\n#define APB0_CLK_REG                      (DEV_R_PRCM + 0x000c)\n#define APB0_CLK_REG_DIV_M(x)             ((x) << 0)\n#define APB0_CLK_REG_DIV_M_MASK           (0x3 << 0)\n\n/* See r_ccu driver for bit definitions */\n#define APB0_GATE_REG                     (DEV_R_PRCM + 0x0028)\n\n/* Documented in A23/A31s manual */\n#define PLL_CTRL_REG0                     (DEV_R_PRCM + 0x0040)\n#define PLL_CTRL_REG0_TEST_CLK_SEL        BIT(24)\n#define PLL_CTRL_REG0_OSC24M_CLK_SEL(x)   ((x) << 20)\n#define PLL_CTRL_REG0_OSC24M_CLK_SEL_MASK (0x3 << 20)\n#define PLL_CTRL_REG0_PLL_INPUT_SEL(x)    ((x) << 12)\n#define PLL_CTRL_REG0_PLL_INPUT_SEL_MASK  (0x3 << 12)\n#define PLL_CTRL_REG0_USB24M_CLK_SEL(x)   ((x) << 4)\n#define PLL_CTRL_REG0_USB24M_CLK_SEL_MASK (0x3 << 4)\n#define PLL_CTRL_REG0_OSC24M_GAIN_ENHANCE BIT(1)\n#define PLL_CTRL_REG0_PLL_BIAS_EN         BIT(0)\n\n/* Documented in A23/A31s manual; bits 3 and 15 are not verified on A83T */\n#define PLL_CTRL_REG1                     (DEV_R_PRCM + 0x0044)\n#define PLL_CTRL_REG1_KEY                 (0xa7 << 24)\n#define PLL_CTRL_REG1_KEY_FIELD           (0xff << 24)\n#define PLL_CTRL_REG1_PLL_LDO_OUT(x)      ((x) << 16)\n#define PLL_CTRL_REG1_PLL_LDO_OUT_MASK    (0x7 << 16)\n#define PLL_CTRL_REG1_PLL_IN_PWR_SEL      BIT(15)\n#define PLL_CTRL_REG1_CLKTEST_EN          BIT(3)\n#define PLL_CTRL_REG1_CRYSTAL_EN          BIT(2)\n#define PLL_CTRL_REG1_LDO_EN              (0x3 << 0)\n\n/* See r_ccu driver for bit definitions */\n#define R_CIR_RX_CLK_REG                  (DEV_R_PRCM + 0x0054)\n#define APB0_RESET_REG                    (DEV_R_PRCM + 0x00b0)\n\n#define Cm_PWROFF_GATING_REG(m)           (DEV_R_PRCM + 0x0100 + 0x04 * (m))\n#define Cm_CPUn_PWROFF_GATING(n)          BIT((n) ? 0 + (n) : 4)\n#define Cm_PWROFF_GATING                  BIT(0)\n\n#define VDD_SYS_PWROFF_GATING_REG         (DEV_R_PRCM + 0x0110)\n#define VCC_GPIO_GATING                   BIT(12)\n#define VCC_PLL_GATING                    BIT(8)\n#define VCC_PLL_LOW_VOLTAGE_GATING        BIT(4)\n#define VDD_CPUS_GATING                   BIT(3)\n#define AVCC_GATING                       0 /* Not applicable */\n#define DRAM_PAD_HOLD                     (0x3 << 0)\n\n#define GPU_PWROFF_GATING_REG             (DEV_R_PRCM + 0x0118)\n#define GPU_PWROFF_GATING                 BIT(0)\n\n#define VDD_SYS_RESET_REG                 (DEV_R_PRCM + 0x0120)\n#define VDD_SYS_RESET                     BIT(0)\n\n#define Cm_CPUn_PWR_SWITCH_REG(m, n)      (DEV_R_PRCM + 0x0140 + \\\n\t                                   0x10 * (m) + 0x04 * (n))\n\n#define R_PIO_HOLD_REG                    (DEV_R_PRCM + 0x01f0)\n#define R_PIO_HOLD_REG_WRITE_PULSE        BIT(31)\n#define R_PIO_HOLD_REG_PIO_REG_ADDR(x)    ((x) << 16)\n#define R_PIO_HOLD_REG_PIO_REG_ADDR_MASK  (0x3 << 16)\n#define R_PIO_HOLD_REG_DATA_WRITE(x)      ((x) << 8)\n#define R_PIO_HOLD_REG_DATA_WRITE_MASK    (0xff << 8)\n#define R_PIO_HOLD_REG_DATA_READ_MASK     (0xff << 0)\n\n#define OSC24M_CTRL_REG                   (DEV_R_PRCM + 0x01f4)\n#define OSC24M_CTRL_REG_OSC24M_SRC_SELECT BIT(1)\n#define OSC24M_CTRL_REG_OSC16M_ENABLE     BIT(0)\n\n#endif /* PLATFORM_PRCM_H */\n"
  },
  {
    "path": "platform/a83t/include/platform/time.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef PLATFORM_TIME_H\n#define PLATFORM_TIME_H\n\n#define CPUCLK_MHz 16\n#define CPUCLK_kHz (CPUCLK_MHz * 1000)\n#define CPUCLK_Hz  (CPUCLK_MHz * 1000000)\n\n#define REFCLK_MHZ 24\n#define REFCLK_KHZ (REFCLK_MHZ * 1000)\n#define REFCLK_HZ  (REFCLK_MHZ * 1000000)\n\n#endif /* PLATFORM_TIME_H */\n"
  },
  {
    "path": "platform/h3/include/platform/cpucfg.h",
    "content": "/*\n * Copyright © 2020-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef PLATFORM_CPUCFG_H\n#define PLATFORM_CPUCFG_H\n\n#include <util.h>\n#include <platform/devices.h>\n\n#define CPUS_RESET_REG                   (DEV_R_CPUCFG + 0x0000)\n#define CPUS_RESET                       BIT(0)\n\n/* Four of these ranges exist. */\n#define CPUS_BYTE_SWAP_EN_REG            (DEV_R_CPUCFG + 0x000c)\n#define CPUS_BYTE_SWAP_EN_REG_RANGEn(n)  BIT(0 + (n))\n\n#define CPUS_BYTE_SWAP_LO_REG(n)         (DEV_R_CPUCFG + 0x0010 + 0x08 * (n))\n#define CPUS_BYTE_SWAP_HI_REG(n)         (DEV_R_CPUCFG + 0x0014 + 0x08 * (n))\n\n#define CPUn_RST_CTRL_REG(n)             (DEV_R_CPUCFG + 0x0040 + 0x40 * (n))\n#define CPUn_RST_CTRL_REG_nCORERESET     BIT(1)\n#define CPUn_RST_CTRL_REG_nCPUPORESET    BIT(0)\n\n#define CPUn_CTRL_REG(n)                 (DEV_R_CPUCFG + 0x0044 + 0x40 * (n))\n#define CPUn_CTRL_REG_CP15SDISABLE       BIT(0)\n\n#define CPUn_STATUS_REG(n)               (DEV_R_CPUCFG + 0x0048 + 0x40 * (n))\n#define CPUn_STATUS_REG_STANDBYWFI       BIT(2)\n#define CPUn_STATUS_REG_STANDBYWFE       BIT(1)\n#define CPUn_STATUS_REG_SMPnAMP          BIT(0)\n\n#define CPU_SYS_RESET_REG                (DEV_R_CPUCFG + 0x0140)\n#define CPU_SYS_RESET                    BIT(0)\n\n#define CPU_CLK_GATING_REG               (DEV_R_CPUCFG + 0x0144)\n#define CPU_CLK_GATING_REG_L2_GATING     BIT(8)\n#define CPU_CLK_GATING_REG_CPU_GATING(n) BIT(0 + (n))\n\n#define IRQ_FIQ_STATUS_REG               (DEV_R_CPUCFG + 0x014c)\n#define C0_IRQ_OUT(n)                    BIT(0 + (n))\n#define C0_IRQ_OUT_MASK                  (0xf << 0)\n#define C0_FIQ_OUT(n)                    BIT(8 + (n))\n#define C0_FIQ_OUT_MASK                  (0xf << 8)\n\n#define GEN_CTRL_REG                     (DEV_R_CPUCFG + 0x0184)\n#define GEN_CTRL_REG_CFGSDISABLE         BIT(8)\n#define GEN_CTRL_REG_ACINACTM            BIT(6)\n#define GEN_CTRL_REG_nL2RESET            BIT(5)\n#define GEN_CTRL_REG_L2RSTDISABLE        BIT(4)\n#define GEN_CTRL_REG_L1RSTDISABLE(n)     BIT(0 + (n))\n#define GEN_CTRL_REG_L1RSTDISABLE_MASK   (0xf << 0)\n\n#define EVENT_IN_REG                     (DEV_R_CPUCFG + 0x0190)\n#define EVENT_IN                         BIT(0)\n\n#define DBG_CTRL_REG0                    (DEV_R_CPUCFG + 0x01e0)\n\n#define DBG_CTRL_REG1                    (DEV_R_CPUCFG + 0x01e4)\n#define DBG_CTRL_REG1_DBGPWRDUP(n)       BIT(0 + (n))\n#define DBG_CTRL_REG1_DBGPWRDUP_MASK     (0xf << 0)\n\n#define CNT64_CTRL_REG                   (DEV_R_CPUCFG + 0x0280)\n#define CNT64_RL_EN                      BIT(1)\n#define CNT64_CLR_EN                     BIT(0)\n\n#define CNT64_LO_REG                     (DEV_R_CPUCFG + 0x0284)\n#define CNT64_HI_REG                     (DEV_R_CPUCFG + 0x0288)\n\n#endif /* PLATFORM_CPUCFG_H */\n"
  },
  {
    "path": "platform/h3/include/platform/css.h",
    "content": "/*\n * Copyright © 2020-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef PLATFORM_CSS_H\n#define PLATFORM_CSS_H\n\n#define MAX_CLUSTERS          1\n#define MAX_CORES_PER_CLUSTER 4\n\n#endif /* PLATFORM_CSS_H */\n"
  },
  {
    "path": "platform/h3/include/platform/devices.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef PLATFORM_DEVICES_H\n#define PLATFORM_DEVICES_H\n\n#define DEV_DE          0x01000000\n#define DEV_DEINTERLACE 0x01400000\n#define DEV_SYSCON      0x01c00000\n#define DEV_DMA         0x01c02000\n#define DEV_NAND        0x01c03000\n#define DEV_TSC         0x01c06000\n#define DEV_KEYMEM      0x01c0b000\n#define DEV_TCON0       0x01c0c000\n#define DEV_TCON1       0x01c0d000\n#define DEV_VE          0x01c0e000\n#define DEV_MMC0        0x01c0f000\n#define DEV_MMC1        0x01c10000\n#define DEV_MMC2        0x01c11000\n#define DEV_SID         0x01c14000\n#define DEV_CE          0x01c15000\n#define DEV_MSGBOX      0x01c17000\n#define DEV_SPINLOCK    0x01c18000\n#define DEV_USBOTG      0x01c19000\n#define DEV_USB0        0x01c1a000\n#define DEV_USB1        0x01c1b000\n#define DEV_USB2        0x01c1c000\n#define DEV_USB3        0x01c1d000\n#define DEV_TZASC       0x01c1e000\n#define DEV_CCU         0x01c20000\n#define DEV_PIO         0x01c20800\n#define DEV_TIMER       0x01c20c00\n#define DEV_SPDIF       0x01c21000\n#define DEV_PWM         0x01c21400\n#define DEV_KEYADC      0x01c21800\n#define DEV_I2S0        0x01c22000\n#define DEV_I2S1        0x01c22400\n#define DEV_I2S2        0x01c22800\n#define DEV_CODEC       0x01c22c00\n#define DEV_SPC         0x01c23400\n#define DEV_THS         0x01c25000\n#define DEV_UART0       0x01c28000\n#define DEV_UART1       0x01c28400\n#define DEV_UART2       0x01c28800\n#define DEV_UART3       0x01c28c00\n#define DEV_I2C0        0x01c2ac00\n#define DEV_I2C1        0x01c2b000\n#define DEV_I2C2        0x01c2b400\n#define DEV_SCR         0x01c2c400\n#define DEV_EMAC        0x01c30000\n#define DEV_GPU         0x01c40000\n#define DEV_HSTIMER     0x01c60000\n#define DEV_DRAMCOM     0x01c62000\n#define DEV_DRAMCTL     0x01c63000\n#define DEV_DRAMPHY     0x01c65000\n#define DEV_SPI0        0x01c68000\n#define DEV_SPI1        0x01c69000\n#define DEV_SCU         0x01c80000\n#define DEV_GICD        0x01c81000\n#define DEV_GICC        0x01c82000\n#define DEV_CSI         0x01cb0000\n#define DEV_TVE         0x01e00000\n#define DEV_HDMI        0x01ee0000\n#define DEV_RTC         0x01f00000\n#define DEV_R_TIMER     0x01f00800\n#define DEV_R_INTC      0x01f00c00\n#define DEV_R_WDOG      0x01f01000\n#define DEV_R_PRCM      0x01f01400\n#define DEV_R_TWD       0x01f01800\n#define DEV_R_CPUCFG    0x01f01c00\n#define DEV_R_CIR_RX    0x01f02000\n#define DEV_R_I2C       0x01f02400\n#define DEV_R_UART      0x01f02800\n#define DEV_R_PIO       0x01f02c00\n#define DEV_R_PWM       0x01f03800\n\n#endif /* PLATFORM_DEVICES_H */\n"
  },
  {
    "path": "platform/h3/include/platform/irq.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef PLATFORM_IRQ_H\n#define PLATFORM_IRQ_H\n\n#define IRQ_NMI      0x00\n#define IRQ_R_TIMER0 0x01\n#define IRQ_R_TIMER1 0x02\n\n#define IRQ_R_WDOG   0x04\n#define IRQ_R_CIR_RX 0x05\n#define IRQ_R_UART   0x06\n\n#define IRQ_R_ALARM0 0x08\n#define IRQ_R_ALARM1 0x09\n#define IRQ_R_TIMER2 0x0a\n#define IRQ_R_TIMER3 0x0b\n#define IRQ_R_I2C    0x0c\n#define IRQ_R_PIO_PL 0x0d\n#define IRQ_R_TWD    0x0e\n\n#define IRQ_MSGBOX   0x11\n\n#endif /* PLATFORM_IRQ_H */\n"
  },
  {
    "path": "platform/h3/include/platform/memory.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef PLATFORM_MEMORY_H\n#define PLATFORM_MEMORY_H\n\n#define FIRMWARE_BASE  0x00008000\n#define FIRMWARE_LIMIT SCPI_MEM_BASE\n#define FIRMWARE_SIZE  (FIRMWARE_LIMIT - FIRMWARE_BASE)\n\n#define SCPI_MEM_BASE  (SRAM_A2_LIMIT - 0x400)\n#define SCPI_MEM_LIMIT SRAM_A2_LIMIT\n#define SCPI_MEM_SIZE  (SCPI_MEM_LIMIT - SCPI_MEM_BASE)\n\n#define SRAM_A2_BASE   0x00000000\n#define SRAM_A2_LIMIT  0x0000c000\n#define SRAM_A2_SIZE   (SRAM_A2_LIMIT - SRAM_A2_BASE)\n\n/* Difference between SRAM_A2_BASE in the AR100 and ARM address spaces. */\n#define SRAM_A2_OFFSET 0x00040000\n\n#define STACK_SIZE     0x00000400\n\n#endif /* PLATFORM_MEMORY_H */\n"
  },
  {
    "path": "platform/h3/include/platform/prcm.h",
    "content": "/*\n * Copyright © 2020-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef PLATFORM_PRCM_H\n#define PLATFORM_PRCM_H\n\n#include <util.h>\n#include <platform/devices.h>\n\n#define CPUS_CLK_REG                      (DEV_R_PRCM + 0x0000)\n#define CPUS_CLK_REG_CLK_SRC(x)           ((x) << 16)\n#define CPUS_CLK_REG_CLK_SRC_MASK         (0x3 << 16)\n#define CPUS_CLK_REG_PRE_DIV(x)           ((x) << 8)\n#define CPUS_CLK_REG_PRE_DIV_MASK         (0x1f << 8)\n#define CPUS_CLK_REG_DIV_P(x)             ((x) << 4)\n#define CPUS_CLK_REG_DIV_P_MASK           (0x3 << 4)\n\n#define APB0_CLK_REG                      (DEV_R_PRCM + 0x000c)\n#define APB0_CLK_REG_DIV_M(x)             ((x) << 0)\n#define APB0_CLK_REG_DIV_M_MASK           (0x3 << 0)\n\n/* See r_ccu driver for bit definitions */\n#define APB0_GATE_REG                     (DEV_R_PRCM + 0x0028)\n#define RTC_GATE_REG                      (DEV_R_PRCM + 0x002c)\n\n/* Documented in A23/A31s manual; all bits are present on H3 */\n#define PLL_CTRL_REG0                     (DEV_R_PRCM + 0x0040)\n#define PLL_CTRL_REG0_TEST_CLK_SEL        BIT(24)\n#define PLL_CTRL_REG0_OSC24M_CLK_SEL(x)   ((x) << 20)\n#define PLL_CTRL_REG0_OSC24M_CLK_SEL_MASK (0x3 << 20)\n#define PLL_CTRL_REG0_PLL_INPUT_SEL(x)    ((x) << 12)\n#define PLL_CTRL_REG0_PLL_INPUT_SEL_MASK  (0x3 << 12)\n#define PLL_CTRL_REG0_USB24M_CLK_SEL(x)   ((x) << 4)\n#define PLL_CTRL_REG0_USB24M_CLK_SEL_MASK (0x3 << 4)\n#define PLL_CTRL_REG0_OSC24M_GAIN_ENHANCE BIT(1)\n#define PLL_CTRL_REG0_PLL_BIAS_EN         BIT(0)\n\n/* Documented in A23/A31s manual; bits 3 and 15 are not verified on H3 */\n#define PLL_CTRL_REG1                     (DEV_R_PRCM + 0x0044)\n#define PLL_CTRL_REG1_KEY                 (0xa7 << 24)\n#define PLL_CTRL_REG1_KEY_FIELD           (0xff << 24)\n#define PLL_CTRL_REG1_PLL_LDO_OUT(x)      ((x) << 16)\n#define PLL_CTRL_REG1_PLL_LDO_OUT_MASK    (0x7 << 16)\n#define PLL_CTRL_REG1_PLL_IN_PWR_SEL      BIT(15)\n#define PLL_CTRL_REG1_CLKTEST_EN          BIT(3)\n#define PLL_CTRL_REG1_CRYSTAL_EN          BIT(2)\n#define PLL_CTRL_REG1_LDO_EN              (0x3 << 0)\n\n/* See r_ccu driver for bit definitions */\n#define R_CIR_RX_CLK_REG                  (DEV_R_PRCM + 0x0054)\n#define APB0_RESET_REG                    (DEV_R_PRCM + 0x00b0)\n\n#define C0_PWROFF_GATING_REG              (DEV_R_PRCM + 0x0100)\n#define C0_CPUn_PWROFF_GATING(n)          BIT(0 + (n))\n\n#define VDD_SYS_PWROFF_GATING_REG         (DEV_R_PRCM + 0x0110)\n#define VDD_CPUS_GATING                   BIT(3)\n#define AVCC_GATING                       BIT(2)\n#define DRAM_PAD_HOLD                     (0x3 << 0)\n\n#define GPU_PWROFF_GATING_REG             (DEV_R_PRCM + 0x0118)\n#define GPU_PWROFF_GATING                 BIT(0)\n\n#define VDD_SYS_RESET_REG                 (DEV_R_PRCM + 0x0120)\n#define VDD_SYS_RESET                     BIT(0)\n\n#define C0_CPUn_PWR_SWITCH_REG(n)         (DEV_R_PRCM + 0x0140 + 0x04 * (n))\n\n#define ADDA_PR_CFG_REG                   (DEV_R_PRCM + 0x01c0)\n#define ADDA_PR_CFG_REG_RESET             BIT(28)\n#define ADDA_PR_CFG_REG_RW                BIT(24)\n#define ADDA_PR_CFG_REG_ADDR(x)           ((x) << 16)\n#define ADDA_PR_CFG_REG_ADDR_MASK         (0x1f << 16)\n#define ADDA_PR_CFG_REG_WDAT(x)           ((x) << 8)\n#define ADDA_PR_CFG_REG_WDAT_MASK         (0xff << 8)\n#define ADDA_PR_CFG_REG_RDAT(x)           ((x) << 0)\n#define ADDA_PR_CFG_REG_RDAT_MASK         (0xff << 0)\n\n#define PRCM_SEC_SWITCH_REG               (DEV_R_PRCM + 0x01d0)\n#define PRCM_SEC_SWITCH_REG_POWER_SEC     BIT(2)\n#define PRCM_SEC_SWITCH_REG_PLL_SEC       BIT(1)\n#define PRCM_SEC_SWITCH_REG_CPUS_CLK_SEC  BIT(0)\n\n#endif /* PLATFORM_PRCM_H */\n"
  },
  {
    "path": "platform/h3/include/platform/time.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef PLATFORM_TIME_H\n#define PLATFORM_TIME_H\n\n#define CPUCLK_MHz 16\n#define CPUCLK_kHz (CPUCLK_MHz * 1000)\n#define CPUCLK_Hz  (CPUCLK_MHz * 1000000)\n\n#define REFCLK_MHZ 24\n#define REFCLK_KHZ (REFCLK_MHZ * 1000)\n#define REFCLK_HZ  (REFCLK_MHZ * 1000000)\n\n#endif /* PLATFORM_TIME_H */\n"
  },
  {
    "path": "platform/h6/include/platform/cpucfg.h",
    "content": "/*\n * Copyright © 2020-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef PLATFORM_CPUCFG_H\n#define PLATFORM_CPUCFG_H\n\n#include <util.h>\n#include <platform/devices.h>\n\n#define C0_RST_CTRL_REG                   (DEV_CPUCFG + 0x0000)\n#define C0_RST_CTRL_REG_nDDR_RST          BIT(28)\n#define C0_RST_CTRL_REG_nMBISTRESET       BIT(25)\n#define C0_RST_CTRL_REG_nSOC_DBG_RST      BIT(24)\n#define C0_RST_CTRL_REG_nETM_RST_MASK     (0xf << 20)\n#define C0_RST_CTRL_REG_nDBG_RST_MASK     (0xf << 16)\n#define C0_RST_CTRL_REG_nL2RESET          BIT(8)\n#define C0_RST_CTRL_REG_nCORERESET(n)     BIT(0 + (n))\n#define C0_RST_CTRL_REG_MASK              (C0_RST_CTRL_REG_nDDR_RST | \\\n\t                                   C0_RST_CTRL_REG_nMBISTRESET | \\\n\t                                   C0_RST_CTRL_REG_nSOC_DBG_RST | \\\n\t                                   C0_RST_CTRL_REG_nETM_RST_MASK | \\\n\t                                   C0_RST_CTRL_REG_nDBG_RST_MASK | \\\n\t                                   C0_RST_CTRL_REG_nL2RESET)\n\n#define C0_CTRL_REG0                      (DEV_CPUCFG + 0x0010)\n#define C0_CTRL_REG0_SYSBARDISABLE        BIT(31)\n#define C0_CTRL_REG0_BROADCASTINNER       BIT(30)\n#define C0_CTRL_REG0_BROADCASTOUTER       BIT(29)\n#define C0_CTRL_REG0_BROADCASTCACHEMAINT  BIT(28)\n#define C0_CTRL_REG0_AA64nAA32(n)         BIT(24 + (n))\n#define C0_CTRL_REG0_AA64nAA32_MASK       (0xf << 24)\n#define C0_CTRL_REG0_CP15SDISABLE(n)      BIT(8 + (n))\n#define C0_CTRL_REG0_L2RSTDISABLE         BIT(4)\n\n#define C0_CTRL_REG1                      (DEV_CPUCFG + 0x0014)\n#define C0_CTRL_REG1_ACINACTM             BIT(0)\n\n#define C0_CTRL_REG2                      (DEV_CPUCFG + 0x0018)\n#define C0_CTRL_REG2_EVENTI               BIT(24)\n#define C0_CTRL_REG2_EXM_CLR(n)           BIT(20 + (n))\n#define C0_CTRL_REG2_CLREXMONREQ          BIT(16)\n#define C0_CTRL_REG2_CRYPTODISABLE(n)     BIT(12 + (n))\n#define C0_CTRL_REG2_L2FLUSHREQ           BIT(8)\n#define C0_CTRL_REG2_GICCDISABLE          BIT(4)\n\n/* Not documented for H6, but probably matches A64 */\n#define CACHE_CFG_REG0                    (DEV_CPUCFG + 0x0020)\n\n#define CACHE_CFG_REG1                    (DEV_CPUCFG + 0x0024)\n/* L2D fields are documented for A50/H616 and present on H6 */\n#define CACHE_CFG_REG1_EMA_L2D            (0x7 << 19)\n#define CACHE_CFG_REG1_EMAW_L2D           (0x3 << 17)\n#define CACHE_CFG_REG1_EMAS_L2D           BIT(16)\n#define CACHE_CFG_REG1_EMA                (0x7 << 3)\n#define CACHE_CFG_REG1_EMAW               (0x3 << 1)\n#define CACHE_CFG_REG1_EMAS               BIT(0)\n\n#define RVBA_LO_REG(n)                    (DEV_CPUCFG + 0x0040 + 0x08 * (n))\n#define RVBA_HI_REG(n)                    (DEV_CPUCFG + 0x0044 + 0x08 * (n))\n\n#define C0_CPU_STATUS_REG                 (DEV_CPUCFG + 0x0080)\n#define C0_CPU_STATUS_REG_SMPnAMP(n)      BIT(24 + (n))\n#define C0_CPU_STATUS_REG_STANDBYWFI(n)   BIT(16 + (n))\n#define C0_CPU_STATUS_REG_STANDBYWFI_MASK (0xf << 16)\n#define C0_CPU_STATUS_REG_STANDBYWFE(n)   BIT(8 + (n))\n#define C0_CPU_STATUS_REG_STANDBYWFE_MASK (0xf << 8)\n#define C0_CPU_STATUS_REG_STANDBYWFIL2    BIT(0)\n\n#define L2_STATUS_REG                     (DEV_CPUCFG + 0x0084)\n#define L2_STATUS_REG_L2FLUSHDONE         BIT(10)\n#define L2_STATUS_REG_EVENTO              BIT(9)\n#define L2_STATUS_REG_CLREXMONACK         BIT(8)\n\n#define DBG_REG0                          (DEV_CPUCFG + 0x00c0)\n#define DBG_REG0_DBGL1RSTDISABLE          BIT(16)\n#define DBG_REG0_DBGRESTART(n)            BIT(8 + (n))\n#define DBG_REG0_DBGPWRDUP(n)             BIT(0 + (n))\n#define DBG_REG0_DBGPWRDUP_MASK           (0xf << 0)\n\n#define DBG_REG1                          (DEV_CPUCFG + 0x00c4)\n#define DBG_REG1_DBGRESTARTED(n)          BIT(12 + (n))\n#define DBG_REG1_DBGRSTREQ(n)             BIT(8 + (n))\n#define DBG_REG1_DBGNOPWRDWN(n)           BIT(4 + (n))\n#define DBG_REG1_DBGPWRUPREQ(n)           BIT(0 + (n))\n\n#define CPUS_RESET_REG                    (DEV_R_CPUCFG + 0x0000)\n#define CPUS_RESET                        BIT(0)\n\n/* Four of these ranges exist. */\n#define CPUS_BYTE_SWAP_EN_REG             (DEV_R_CPUCFG + 0x000c)\n#define CPUS_BYTE_SWAP_EN_REG_RANGEn(n)   BIT(0 + (n))\n\n#define CPUS_BYTE_SWAP_LO_REG(n)          (DEV_R_CPUCFG + 0x0010 + 0x08 * (n))\n#define CPUS_BYTE_SWAP_HI_REG(n)          (DEV_R_CPUCFG + 0x0014 + 0x08 * (n))\n\n#define C0_PWRON_RESET_REG                (DEV_R_CPUCFG + 0x0040)\n#define C0_PWRON_RESET_REG_nH_RST         BIT(16)\n#define C0_PWRON_RESET_REG_nCPUPORESET(n) BIT(0 + (n))\n\n#define C0_PWROFF_GATING_REG              (DEV_R_CPUCFG + 0x0044)\n#define C0_PWROFF_GATING                  BIT(4)\n#define C0_CPUn_PWROFF_GATING(n)          BIT(0 + (n))\n\n#define C0_CPUn_PWR_SWITCH_REG(n)         (DEV_R_CPUCFG + 0x0050 + 0x04 * (n))\n\n#define CPU_SYS_RESET_REG                 (DEV_R_CPUCFG + 0x00a0)\n#define CPU_SYS_RESET                     BIT(0)\n\n#define CPUIDLE_EN_REG                    (DEV_R_CPUCFG + 0x0100)\n#define CPUIDLE_EN_REG_KEY0               (0x16aa << 16)\n#define CPUIDLE_EN_REG_KEY1               (0xaa16 << 16)\n#define CPUIDLE_EN_REG_KEY_FIELD          (0xffff << 16)\n#define CPUIDLE_EN_REG_CPUIDLE_EN         BIT(0)\n\n#define CLOSE_FLAG_REG                    (DEV_R_CPUCFG + 0x0104)\n#define CLOSE_FLAG_REG_CPUn_AND_C0(n)     BIT(16 + (n))\n#define CLOSE_FLAG_REG_CPUn_AND_C0_MASK   (0xf << 16)\n#define CLOSE_FLAG_REG_CPUn(n)            BIT(0 + (n))\n#define CLOSE_FLAG_REG_CPUn_MASK          (0xf << 0)\n\n#define CPUIDLE_PEND_REG                  (DEV_R_CPUCFG + 0x0108)\n#define CPUIDLE_PEND_REG_CPUn_IRQ(n)      BIT(0 + (n))\n#define CPUIDLE_PEND_REG_CPUn_IRQ_MASK    (0xf << 0)\n\n#define CPUIDLE_WAKE_REG                  (DEV_R_CPUCFG + 0x010c)\n#define CPUIDLE_WAKE_REG_CPUn_IRQ(n)      BIT(0 + (n))\n#define CPUIDLE_WAKE_REG_CPUn_IRQ_MASK    (0xf << 0)\n\n#define CPUIDLE_STAT_REG                  (DEV_R_CPUCFG + 0x0110)\n#define CPUIDLE_STAT_REG_C0_IDLE          BIT(13)\n#define CPUIDLE_STAT_REG_C0_OFF           BIT(12)\n#define CPUIDLE_STAT_REG_CPUn_VOTE(n)     BIT(8 + (n))\n#define CPUIDLE_STAT_REG_CPUn_VOTE_MASK   (0xf << 8)\n#define CPUIDLE_STAT_REG_CPUn_OFF(n)      BIT(4 + (n))\n#define CPUIDLE_STAT_REG_CPUn_OFF_MASK    (0xf << 4)\n#define CPUIDLE_STAT_REG_CPUn_IDLE(n)     BIT(0 + (n))\n#define CPUIDLE_STAT_REG_CPUn_IDLE_MASK   (0xf << 0)\n\n#define PWR_SW_DELAY_REG                  (DEV_R_CPUCFG + 0x0140)\n#define CONFIG_DELAY_REG                  (DEV_R_CPUCFG + 0x0144)\n#define PWR_DOWN_CFG_REG                  (DEV_R_CPUCFG + 0x0148)\n/* Six of these registers exist. */\n#define PWR_UP_CFG_REG(n)                 (DEV_R_CPUCFG + 0x0150 + 0x04 * (n))\n\n#endif /* PLATFORM_CPUCFG_H */\n"
  },
  {
    "path": "platform/h6/include/platform/css.h",
    "content": "/*\n * Copyright © 2020-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef PLATFORM_CSS_H\n#define PLATFORM_CSS_H\n\n#define MAX_CLUSTERS          1\n#define MAX_CORES_PER_CLUSTER 4\n\n#endif /* PLATFORM_CSS_H */\n"
  },
  {
    "path": "platform/h6/include/platform/devices.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef PLATFORM_DEVICES_H\n#define PLATFORM_DEVICES_H\n\n#define DEV_DE               0x01000000\n#define DEV_DEBUG            0x01420000\n#define DEV_GPU              0x01800000\n#define DEV_CE_NS            0x01904000\n#define DEV_CE_S             0x01904800\n#define DEV_EMCE             0x01905000\n#define DEV_KEYMEM           0x01908000\n#define DEV_VP9              0x01c00000\n#define DEV_VE               0x01c0e000\n#define DEV_SYSCON           0x03000000\n#define DEV_CCU              0x03001000\n#define DEV_DMA              0x03002000\n#define DEV_MSGBOX           0x03003000\n#define DEV_SPINLOCK         0x03004000\n#define DEV_HSTIMER          0x03005000\n#define DEV_SID              0x03006000\n#define DEV_TZASC            0x03007000\n#define DEV_SPC              0x03008000\n#define DEV_TIMER            0x03009000\n#define DEV_PWM              0x0300a000\n#define DEV_PIO              0x0300b000\n#define DEV_PSI              0x0300c000\n#define DEV_DCU              0x03010000\n#define DEV_SCU              0x03020000\n#define DEV_GICD             0x03021000\n#define DEV_GICC             0x03022000\n#define DEV_IOMMU            0x030f0000\n#define DEV_DRAMCOM          0x04002000\n#define DEV_DRAMCTL          0x04003000\n#define DEV_DRAMPHY          0x04005000\n#define DEV_NAND             0x04011000\n#define DEV_MMC0             0x04020000\n#define DEV_MMC1             0x04021000\n#define DEV_MMC2             0x04022000\n#define DEV_UART0            0x05000000\n#define DEV_UART1            0x05000400\n#define DEV_UART2            0x05000800\n#define DEV_UART3            0x05000c00\n#define DEV_I2C0             0x05002000\n#define DEV_I2C1             0x05002400\n#define DEV_I2C2             0x05002800\n#define DEV_I2C3             0x05002c00\n#define DEV_SCR0             0x05005000\n#define DEV_SCR1             0x05005400\n#define DEV_SPI0             0x05010000\n#define DEV_SPI1             0x05011000\n#define DEV_EMAC             0x05020000\n#define DEV_TS0              0x05060000\n#define DEV_THS              0x05070400\n#define DEV_CIR_TX           0x05061000\n#define DEV_I2S3             0x0508f000\n#define DEV_I2S0             0x05090000\n#define DEV_I2S1             0x05091000\n#define DEV_I2S2             0x05092000\n#define DEV_SPDIF            0x05093000\n#define DEV_DMIC             0x05095000\n#define DEV_AHUB             0x05097000\n#define DEV_USB0             0x05100000\n#define DEV_USB1             0x05200000\n#define DEV_USB3             0x05311000\n#define DEV_PCIE             0x05400000\n#define DEV_HDMI             0x06000000\n#define DEV_TCON_TOP         0x06510000\n#define DEV_TCON0            0x06511000\n#define DEV_TCON1            0x06515000\n#define DEV_CSI              0x06620000\n#define DEV_RTC              0x07000000\n#define DEV_R_CPUCFG         0x07000400\n#define DEV_R_PRCM           0x07010000\n#define DEV_R_TIMER          0x07020000\n#define DEV_R_WDOG           0x07020400\n#define DEV_R_TWD            0x07020800\n#define DEV_R_PWM            0x07020c00\n#define DEV_R_INTC           0x07021000\n#define DEV_R_PIO            0x07022000\n#define DEV_R_CIR_RX         0x07040000\n#define DEV_R_W1             0x07040400\n#define DEV_R_UART           0x07080000\n#define DEV_R_I2C            0x07081400\n#define DEV_R_RSB            0x07083000\n#define DEV_CPUSYSCFG        0x08100000\n#define DEV_TIMESTAMP_STATUS 0x08110000\n#define DEV_TIMESTAMP_CTRL   0x08120000\n#define DEV_CPUCFG           0x09010000\n#define DEV_CPU_BIST         0x09020000\n\n#endif /* PLATFORM_DEVICES_H */\n"
  },
  {
    "path": "platform/h6/include/platform/irq.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef PLATFORM_IRQ_H\n#define PLATFORM_IRQ_H\n\n#define IRQ_NMI      0x00\n#define IRQ_R_TIMER0 0x01\n#define IRQ_R_TIMER1 0x02\n#define IRQ_R_TIMER2 0x03\n#define IRQ_R_TIMER3 0x04\n#define IRQ_R_ALARM0 0x05\n#define IRQ_R_ALARM1 0x06\n#define IRQ_R_WDOG   0x07\n#define IRQ_R_TWD    0x08\n#define IRQ_R_PIO_PL 0x09\n#define IRQ_R_UART   0x0a\n#define IRQ_R_I2C    0x0b\n#define IRQ_R_RSB    0x0c\n#define IRQ_R_CIR_RX 0x0d\n#define IRQ_R_OWC    0x0e\n#define IRQ_R_PIO_PM 0x0f\n\n#define IRQ_MSGBOX   0x13\n\n#endif /* PLATFORM_IRQ_H */\n"
  },
  {
    "path": "platform/h6/include/platform/memory.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef PLATFORM_MEMORY_H\n#define PLATFORM_MEMORY_H\n\n#define FIRMWARE_BASE  0x00014000\n#define FIRMWARE_LIMIT SCPI_MEM_BASE\n#define FIRMWARE_SIZE  (FIRMWARE_LIMIT - FIRMWARE_BASE)\n\n#define SCPI_MEM_BASE  (SRAM_A2_LIMIT - 0x400)\n#define SCPI_MEM_LIMIT SRAM_A2_LIMIT\n#define SCPI_MEM_SIZE  (SCPI_MEM_LIMIT - SCPI_MEM_BASE)\n\n#define SRAM_A2_BASE   0x00000000\n#define SRAM_A2_LIMIT  0x00018000\n#define SRAM_A2_SIZE   (SRAM_A2_LIMIT - SRAM_A2_BASE)\n\n/* Difference between SRAM_A2_BASE in the AR100 and ARM address spaces. */\n#define SRAM_A2_OFFSET 0x00100000\n\n#define STACK_SIZE     0x00000400\n\n#endif /* PLATFORM_MEMORY_H */\n"
  },
  {
    "path": "platform/h6/include/platform/prcm.h",
    "content": "/*\n * Copyright © 2020-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef PLATFORM_PRCM_H\n#define PLATFORM_PRCM_H\n\n#include <util.h>\n#include <platform/devices.h>\n\n#define CPUS_CLK_REG                     (DEV_R_PRCM + 0x0000)\n#define CPUS_CLK_REG_CLK_SRC(x)          ((x) << 24)\n#define CPUS_CLK_REG_CLK_SRC_MASK        (0x3 << 24)\n#define CPUS_CLK_REG_DIV_P(x)            ((x) << 8)\n#define CPUS_CLK_REG_DIV_P_MASK          (0x3 << 8)\n#define CPUS_CLK_REG_PRE_DIV(x)          ((x) << 0)\n#define CPUS_CLK_REG_PRE_DIV_MASK        (0x1f << 0)\n\n#define R_APB1_CLK_REG                   (DEV_R_PRCM + 0x000c)\n#define R_APB1_CLK_REG_DIV_M(x)          ((x) << 0)\n#define R_APB1_CLK_REG_DIV_M_MASK        (0x3 << 0)\n\n#define R_APB2_CLK_REG                   (DEV_R_PRCM + 0x0010)\n#define R_APB2_CLK_REG_CLK_SRC(x)        ((x) << 24)\n#define R_APB2_CLK_REG_CLK_SRC_MASK      (0x3 << 24)\n#define R_APB2_CLK_REG_DIV_P(x)          ((x) << 8)\n#define R_APB2_CLK_REG_DIV_P_MASK        (0x3 << 8)\n#define R_APB2_CLK_REG_PRE_DIV(x)        ((x) << 0)\n#define R_APB2_CLK_REG_PRE_DIV_MASK      (0x1f << 0)\n\n/* See r_ccu driver for bit definitions */\n#define R_TIMER_GATE_REG                 (DEV_R_PRCM + 0x011c)\n#define R_TWDOG_GATE_REG                 (DEV_R_PRCM + 0x012c)\n#define R_PWM_GATE_REG                   (DEV_R_PRCM + 0x013c)\n#define R_UART_GATE_REG                  (DEV_R_PRCM + 0x018c)\n#define R_I2C_GATE_REG                   (DEV_R_PRCM + 0x019c)\n#define R_RSB_GATE_REG                   (DEV_R_PRCM + 0x01bc)\n#define R_CIR_RX_CLK_REG                 (DEV_R_PRCM + 0x01c0)\n#define R_CIR_RX_GATE_REG                (DEV_R_PRCM + 0x01cc)\n#define R_OWC_CLK_REG                    (DEV_R_PRCM + 0x01e0)\n#define R_OWC_GATE_REG                   (DEV_R_PRCM + 0x01ec)\n#define R_RTC_GATE_REG                   (DEV_R_PRCM + 0x020c)\n\n/* Differs from earlier generations; only the bits below are valid */\n#define PLL_CTRL_REG0                    (DEV_R_PRCM + 0x0240)\n#define PLL_CTRL_REG0_UNK_BIT_24         BIT(24)\n#define PLL_CTRL_REG0_UNK_BIT_02         BIT(2)\n#define PLL_CTRL_REG0_UNK_BIT_01         BIT(1)\n#define PLL_CTRL_REG0_UNK_BIT_00         BIT(0)\n\n/* Documented in A23/A31s manual; bits 3 and 15 are not verified on H6 */\n#define PLL_CTRL_REG1                    (DEV_R_PRCM + 0x0244)\n#define PLL_CTRL_REG1_KEY                (0xa7 << 24)\n#define PLL_CTRL_REG1_KEY_FIELD          (0xff << 24)\n#define PLL_CTRL_REG1_PLL_LDO_OUT(x)     ((x) << 16)\n#define PLL_CTRL_REG1_PLL_LDO_OUT_MASK   (0x7 << 16)\n#define PLL_CTRL_REG1_PLL_IN_PWR_SEL     BIT(15)\n#define PLL_CTRL_REG1_CLKTEST_EN         BIT(3)\n#define PLL_CTRL_REG1_CRYSTAL_EN         BIT(2)\n#define PLL_CTRL_REG1_LDO_EN             BIT(0)\n\n#define VDD_SYS_PWROFF_GATING_REG        (DEV_R_PRCM + 0x0250)\n#define VDD_CPUS_GATING                  BIT(3)\n#define AVCC_GATING                      BIT(2)\n#define DRAM_PAD_HOLD                    (0x3 << 0)\n\n#define GPU_PWROFF_GATING_REG            (DEV_R_PRCM + 0x0254)\n#define GPU_PWROFF_GATING                BIT(0)\n\n#define VDD_SYS_RESET_REG                (DEV_R_PRCM + 0x0260)\n#define VDD_SYS_RESET                    BIT(0)\n\n/* Bits are documented for A64 and assumed to match here */\n#define PRCM_SEC_SWITCH_REG              (DEV_R_PRCM + 0x0290)\n#define PRCM_SEC_SWITCH_REG_POWER_SEC    BIT(2)\n#define PRCM_SEC_SWITCH_REG_PLL_SEC      BIT(1)\n#define PRCM_SEC_SWITCH_REG_CPUS_CLK_SEC BIT(0)\n\n#define RES_CAL_CTRL_REG                 (DEV_R_PRCM + 0x0310)\n/* set in dram_power_up_process() */\n#define RES_CAL_CTRL_REG_UNK_BIT_08      BIT(8)\n/* \"calibration circuits analog enable\" */\n#define RES_CAL_CTRL_REG_CAL_ANA_EN      BIT(1)\n#define RES_CAL_CTRL_REG_CAL_EN          BIT(0)\n\n#define UNK_REG_0318                     (DEV_R_PRCM + 0x0318)\n/* cleared in dram_power_up_process() */\n#define UNK_REG_0318_UNK_BIT_00_05       (0x3f << 0)\n\n#endif /* PLATFORM_PRCM_H */\n"
  },
  {
    "path": "platform/h6/include/platform/time.h",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#ifndef PLATFORM_TIME_H\n#define PLATFORM_TIME_H\n\n#define CPUCLK_MHz 16\n#define CPUCLK_kHz (CPUCLK_MHz * 1000)\n#define CPUCLK_Hz  (CPUCLK_MHz * 1000000)\n\n#define REFCLK_MHZ 24\n#define REFCLK_KHZ (REFCLK_MHZ * 1000)\n#define REFCLK_HZ  (REFCLK_MHZ * 1000000)\n\n#endif /* PLATFORM_TIME_H */\n"
  },
  {
    "path": "scripts/Makefile.format",
    "content": "#\n# Copyright © 2017-2022 The Crust Firmware Authors.\n# SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n#\n\nfind_files\t = $(sort $(wildcard $(foreach X,$2,$(1:%=$(SRC)/%/$X))))\n\nformat_dirs\t:= arch/* common drivers/* include/* lib platform/* tools\nformat_globs\t:= *.c */*.c *.h */*.h */*/*.h\nformat_files\t:= $(call find_files,$(format_dirs),$(format_globs))\n\ncheck-format: $(format_files)\n\t$(Q) uncrustify -c $(SRC)/.uncrustify -l C -q --check $^\n\nformat: $(format_files)\n\t$(Q) uncrustify -c $(SRC)/.uncrustify -l C -q --no-backup --replace $^\n\n.PHONY: check-format format\n"
  },
  {
    "path": "scripts/Makefile.kbuild",
    "content": "#\n# Copyright © 2017-2022 The Crust Firmware Authors.\n# SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n#\n\n#\n# Variables for use in included Makefiles\n#\nsrc\t\t = $(SRC)/$(subdir)\nobj\t\t = $(OBJ)/$(subdir)\ntgt\t\t = $(TGT)/$(subdir)\n\n#\n# Variables for use in the main Makefile\n#\nbuildprogs-all\t:=\nhostprogs-all\t:=\nlib-all\t\t:=\nobj-all\t\t:=\ntest-all\t:=\ntools-all\t:=\n\n#\n# Internal variables\n#\ndir_AFLAGS\t = $(asflags-y)\ndir_CFLAGS\t = $(ccflags-y)\ndir_CPPFLAGS\t = $(cppflags-y)\ndir_LDFLAGS\t = $(ldflags-y)\ndir_BUILDAFLAGS\t = $(asflags-y)\ndir_BUILDCFLAGS\t = $(ccflags-y)\ndir_BUILDCPPFLAGS= $(cppflags-y)\ndir_BUILDLDFLAGS = $(ldflags-y)\ndir_HOSTAFLAGS\t = $(asflags-y)\ndir_HOSTCFLAGS\t = $(ccflags-y)\ndir_HOSTCPPFLAGS = $(cppflags-y)\ndir_HOSTLDFLAGS\t = $(ldflags-y)\n\nflags\t\t = AFLAGS CFLAGS CPPFLAGS LDFLAGS LDLIBS\nflags_object\t:= $(filter-out LD%,$(flags))\nflags_program\t:= $(filter CFLAGS LD%,$(flags))\n\nvars\t\t = buildprogs hostprogs lib obj test tools\n\n#\n# Defined functions and procedures (those starting with '_' are internal)\n#\n\n#\n# Adds compiler/linker flags to the target-specific variables for this file.\n#\n# $1: File name (no path)\n# $2: List of flags, e.g. $(flags_object) or $(flags_program)\n#\nbuild_file_flags  = $(foreach f,$(2:%=BUILD%),$(call _file_flag,$(obj),$1,$f))\nhost_file_flags   = $(foreach f,$(2:%=HOST%),$(call _file_flag,$(obj),$1,$f))\ntarget_file_flags = $(foreach f,$2,$(call _file_flag,$(tgt),$1,$f))\n\n#\n# Internal helper to add target-specific variables. $(eval) provides the\n# necessary eager binding. Also avoids adding blank/whitespace variables.\n#\n# $1: Directory\n# $2: File name\n# $3: Flag name\n#\n_file_flag = $(if $(strip $(dir_$3)$($3_$2)), \\\n                  $(eval $1/$2: $3 += $(dir_$3) $($3_$2)))\n\n#\n# Overrides compiler/linker paths and flags to the correct variable for the\n# type of object (build vs host).\n#\n# $1: File name (no path)\n# $2: List of flags, e.g. $(flags_object) or $(flags_program)\n#\nbuild_overrides  = $(foreach f,AR CC $2,$(eval $(obj)/$1: HOST$f = $$(BUILD$f)))\n\n#\n# Adds the necessary dependencies and flags for a list of build object files.\n#\n# $1: List of object file names (no path)\n#\nbuild_objects = $(foreach object,$1,$(eval $(value _build_object)))\ndefine _build_object\n  $(call build_file_flags,$(object),$(flags_object))\n  $(call build_overrides,$(object),$(flags_object))\n  $(obj)/$(object): | $(obj)/. $(OBJ_DEPS)\n  -include $(obj)/$(object:.o=.d)\nendef\n\n#\n# Adds the necessary dependencies and flags for a list of build programs.\n#\n# $1: List of program names (no path)\n#\nbuild_programs = $(foreach program,$1,$(eval $(value _build_program)))\ndefine _build_program\n  $(call build_file_flags,$(program),$(flags_program))\n  $(call build_overrides,$(program),$(flags_program))\n  ifeq ($($(program)-objs),)\n    $(program)-objs := $(program).o\n  endif\n  $(obj)/$(program): $($(program)-objs:%=$(obj)/%) | $(obj)/.\n  $(call build_objects,$($(program)-objs))\nendef\n\n#\n# Adds the necessary dependencies and flags for a list of host object files.\n#\n# $1: List of object file names (no path)\n#\nhost_objects = $(foreach object,$1,$(eval $(value _host_object)))\ndefine _host_object\n  $(call host_file_flags,$(object),$(flags_object))\n  $(obj)/$(object): | $(obj)/. $(OBJ_DEPS)\n  -include $(obj)/$(object:.o=.d)\nendef\n\n#\n# Adds the necessary dependencies and flags for a list of host programs.\n#\n# $1: List of program names (no path)\n#\nhost_programs = $(foreach program,$1,$(eval $(value _host_program)))\ndefine _host_program\n  $(call host_file_flags,$(program),$(flags_program))\n  ifeq ($($(program)-objs),)\n    $(program)-objs := $(program).o\n  endif\n  $(obj)/$(program): $($(program)-objs:%=$(obj)/%) | $(obj)/.\n  $(call host_objects,$($(program)-objs))\nendef\n\n#\n# Includes a list of object files in the main static library (both host and\n# target versions). Also adds the necessary dependencies and flags for each\n# object file.\n#\n# $1: List of object file names (no path)\n#\nlibrary_objects = $(foreach object,$1,$(eval $(value _library_object)))\ndefine _library_object\n  # Add the host version of this library object\n  $(OBJ)/lib.a: $(obj)/$(object)\n  $(call host_objects,$(object))\n  # Add the target version of this library object\n  $(TGT)/lib.a: $(tgt)/$(object)\n  $(call target_objects,$(object))\nendef\n\n#\n# Adds the necessary dependencies and flags for a list of target object files.\n#\n# $1: List of object file names (no path)\n#\ntarget_objects = $(foreach object,$1,$(eval $(value _target_object)))\ndefine _target_object\n  $(call target_file_flags,$(object),$(flags_object))\n  $(tgt)/$(object): | $(tgt)/. $(OBJ_DEPS)\n  -include $(tgt)/$(object:.o=.d)\nendef\n\n#\n# Descend into each of a list of directories. For every directory entered,\n# recursively read and evaluate rules from its Makefile.\n#\n# $1: List of directories (relative to the root of the source tree)\n#\ndescend = $(foreach subdir,$1,$(eval $(value _descend)))\ndefine _descend\n  # Clear all per-directory variables\n  $(foreach var,$(filter %-objs %-y,$(.VARIABLES)),$(eval $(var) :=))\n\n  # Read the Makefile in this directory\n  $(src)/Makefile:;\n  include $(src)/Makefile\n\n  # Filter out directory dependencies\n  dirs-y\t:= $(filter %/,$(foreach var,$(vars),$($(var)-y)))\n  buildprogs-y\t:= $(filter-out %/,$(buildprogs-y))\n  hostprogs-y\t:= $(filter-out %/,$(hostprogs-y))\n  lib-y\t\t:= $(filter-out %/,$(lib-y))\n  obj-y\t\t:= $(filter-out %/,$(obj-y))\n  test-y\t:= $(filter-out %/,$(test-y))\n  tools-y\t:= $(filter-out %/,$(tools-y))\n\n  # Combine all sources of flags\n  asflags-y\t+= $(parent-asflags) $(subdir-asflags-y)\n  ccflags-y\t+= $(parent-ccflags) $(subdir-ccflags-y)\n  cppflags-y\t+= $(parent-cppflags) $(subdir-cppflags-y)\n  ldflags-y\t+= $(parent-ldflags) $(subdir-ldflags-y)\n\n  # Handle file rules\n  $(call build_programs, $(buildprogs-y))\n  $(call host_programs,  $(hostprogs-y))\n  $(call library_objects,$(lib-y))\n  $(call target_objects, $(obj-y))\n  $(call host_programs,  $(test-y))\n  $(call host_programs,  $(tools-y))\n\n  # Accumulate file names (library objects are handled above)\n  buildprogs-all+= $(buildprogs-y:%=$(obj)/%)\n  hostprogs-all\t+= $(hostprogs-y:%=$(obj)/%)\n  obj-all\t+= $(obj-y:%=$(tgt)/%)\n  test-all\t+= $(test-y:%=$(obj)/%)\n  tools-all\t+= $(tools-y:%=$(obj)/%)\n\n  # Push recursive flags\n  $(subdir)-asflags\t:= $(parent-asflags)\n  $(subdir)-ccflags\t:= $(parent-ccflags)\n  $(subdir)-cppflags\t:= $(parent-cppflags)\n  $(subdir)-ldflags\t:= $(parent-ldflags)\n  parent-asflags\t+= $(subdir-asflags-y)\n  parent-ccflags\t+= $(subdir-ccflags-y)\n  parent-cppflags\t+= $(subdir-cppflags-y)\n  parent-ldflags\t+= $(subdir-ldflags-y)\n\n  # Recursively descend into sub-directories\n  $(call descend,$(dirs-y:%/=$(subdir)/%))\n\n  # Pop recursive flags\n  parent-asflags\t:= $($(subdir)-asflags)\n  parent-ccflags\t:= $($(subdir)-ccflags)\n  parent-cppflags\t:= $($(subdir)-cppflags)\n  parent-ldflags\t:= $($(subdir)-ldflags)\n\n  # Clear this directory's flags\n  ifneq ($(filter undefine,$(.FEATURES)),)\n    undefine $(subdir)-asflags\n    undefine $(subdir)-ccflags\n    undefine $(subdir)-cppflags\n    undefine $(subdir)-ldflags\n  else\n    $(subdir)-asflags\t:=\n    $(subdir)-ccflags\t:=\n    $(subdir)-cppflags\t:=\n    $(subdir)-ldflags\t:=\n  endif\nendef\n"
  },
  {
    "path": "scripts/test.sh",
    "content": "#!/bin/sh -eu\n#\n# Copyright © 2017-2022 The Crust Firmware Authors.\n# SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n#\n\nbinary=$1\noutput=$2\n\nif \"$binary\" > \"${output}.tmp\"; then\n  mv -f \"${output}.tmp\" \"$output\"\nelse\n  error=$?\n  cat \"${output}.tmp\"\n  rm -f \"${output}.tmp\"\n  exit \"$error\"\nfi\n"
  },
  {
    "path": "scripts/version.sh",
    "content": "#!/bin/sh -eu\n#\n# Copyright © 2020-2022 The Crust Firmware Authors.\n# SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n#\n\nmajor=0\nminor=6\npatch=10000\n\nsrcdir=$1\noutput=$2\n\nif test \"$srcdir\" = \"$(git -C \"$srcdir\" rev-parse --show-toplevel 2>/dev/null)\"; then\n  set -- $(git -C \"$srcdir\" describe --dirty --long --match 'v[0-9]*' | tr '.-' '  ')\n\n  if test \"$#\" -ge 4; then\n    major=${1#v}\n    minor=$2\n    patch=$3\n  fi\n\n  if test \"$#\" -ge 5 && test \"$5\" = \"dirty\"; then\n    patch=$((patch+10000))\n  fi\nfi\n\ntrap 'rm -f \"$output.tmp\"' EXIT\n\ncat > \"$output.tmp\" << EOF\n#define VERSION_MAJOR $major\n#define VERSION_MINOR $minor\n#define VERSION_PATCH $patch\n#define VERSION_STRING \"v${major}.${minor}.${patch}\"\nEOF\n\nif ! test -f \"$output\" ||\n   ! test \"$(cat \"$output.tmp\")\" = \"$(cat \"$output\")\"; then\n  mv -f \"$output.tmp\" \"$output\"\nfi\n"
  },
  {
    "path": "tools/Makefile",
    "content": "#\n# Copyright © 2017-2022 The Crust Firmware Authors.\n# SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n#\n\ntools-y += load\ntools-y += test\n"
  },
  {
    "path": "tools/load.c",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <fcntl.h>\n#include <limits.h>\n#include <stdint.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <unistd.h>\n#include <sys/mman.h>\n#include <sys/stat.h>\n\n#include <config.h>\n#include <kconfig.h>\n#include <mmio.h>\n#include <util.h>\n#include <asm/exception.h>\n#include <platform/devices.h>\n#include <platform/memory.h>\n\n#ifndef PAGESIZE\n#define PAGESIZE          0x1000\n#endif\n#define PAGE_BASE(addr)   ((addr) & ~(PAGESIZE - 1))\n#define PAGE_OFFSET(addr) ((addr) & (PAGESIZE - 1))\n\nint\nmain(int argc, char *argv[])\n{\n\tstruct stat st;\n\tchar *file;\n\tchar *sram;\n\tuintptr_t r_cpucfg;\n\tvoid *r_cpucfg_map;\n\tint fd;\n\n\tif (argc < 2 || strcmp(\"--help\", argv[1]) == 0) {\n\t\tputs(\"ARISC firmware loader for \" CONFIG_PLATFORM);\n\t\tprintf(\"usage: %s [--help] --reset | <filename>\\n\", argv[0]);\n\t\treturn argc < 2 ? EXIT_FAILURE : EXIT_SUCCESS;\n\t}\n\n\tfd = open(\"/dev/mem\", O_RDWR | O_SYNC);\n\tif (fd < 0) {\n\t\tperror(\"Failed to open /dev/mem\");\n\t\treturn EXIT_FAILURE;\n\t}\n\tr_cpucfg_map = mmap(NULL, PAGESIZE, PROT_READ | PROT_WRITE, MAP_SHARED,\n\t                    fd, PAGE_BASE(DEV_R_CPUCFG));\n\tif (r_cpucfg_map == MAP_FAILED) {\n\t\tperror(\"Failed to mmap R_CPUCFG\");\n\t\treturn EXIT_FAILURE;\n\t}\n\tsram = mmap(NULL, SRAM_A2_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED,\n\t            fd, PAGE_BASE(SRAM_A2_OFFSET + SRAM_A2_BASE));\n\tif (sram == MAP_FAILED) {\n\t\tperror(\"Failed to mmap SRAM A2\");\n\t\treturn EXIT_FAILURE;\n\t}\n\tclose(fd);\n\n\tr_cpucfg = (uintptr_t)r_cpucfg_map + PAGE_OFFSET(DEV_R_CPUCFG);\n\n\tif (strcmp(\"--reset\", argv[1]) == 0) {\n\t\tif (!mmio_get_32(r_cpucfg, BIT(0))) {\n\t\t\tputs(\"ARISC is already in reset\");\n\t\t\treturn EXIT_SUCCESS;\n\t\t}\n\t\tputs(\"Asserting ARISC reset\");\n\t\tmmio_clr_32(r_cpucfg, BIT(0));\n\t\tif (mmio_get_32(r_cpucfg, BIT(0))) {\n\t\t\tputs(\"Failed to assert ARISC reset\");\n\t\t\treturn EXIT_FAILURE;\n\t\t}\n\t\treturn EXIT_SUCCESS;\n\t}\n\n\tfd = open(argv[1], O_RDONLY);\n\tif (fd < 0) {\n\t\tperror(\"Failed to open firmware file\");\n\t\treturn EXIT_FAILURE;\n\t}\n\tif (fstat(fd, &st)) {\n\t\tperror(\"Failed to stat firmware file\");\n\t\treturn EXIT_FAILURE;\n\t}\n\tif (st.st_size > FIRMWARE_SIZE) {\n\t\tputs(\"Firmware will not fit in available SRAM\");\n\t\treturn EXIT_FAILURE;\n\t}\n\tfile = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);\n\tif (file == MAP_FAILED) {\n\t\tperror(\"Failed to mmap firmware file\");\n\t\treturn EXIT_FAILURE;\n\t}\n\tclose(fd);\n\n\tputs(\"Asserting ARISC reset\");\n\tmmio_clr_32(r_cpucfg, BIT(0));\n\tif (mmio_get_32(r_cpucfg, BIT(0))) {\n\t\tputs(\"Failed to assert ARISC reset\");\n\t\treturn EXIT_FAILURE;\n\t}\n\tputs(\"Writing exception vectors\");\n\tfor (int i = RESET_EXCEPTION; i <= TRAP_EXCEPTION; ++i) {\n\t\tuint32_t jump   = EXCEPTION_VECTOR_ADDRESS(i);\n\t\tuint32_t offset = FIRMWARE_BASE - jump;\n\n\t\tmmio_write_32((uintptr_t)(sram + jump), offset >> 2);\n\t}\n\tprintf(\"Writing firmware (%jd/%d bytes used)\\n\",\n\t       (intmax_t)st.st_size, FIRMWARE_SIZE);\n\tmemcpy(sram + FIRMWARE_BASE, file, st.st_size);\n\tmsync(sram + FIRMWARE_BASE, st.st_size, MS_SYNC);\n\tputs(\"Deasserting ARISC reset\");\n\tmmio_set_32(r_cpucfg, BIT(0));\n\tif (!mmio_get_32(r_cpucfg, BIT(0))) {\n\t\tputs(\"Failed to deassert ARISC reset\");\n\t\treturn EXIT_FAILURE;\n\t}\n\n\tmunmap(file, st.st_size);\n\tmunmap(r_cpucfg_map, PAGESIZE);\n\tmunmap(sram, SRAM_A2_SIZE);\n\n\treturn EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "tools/test.c",
    "content": "/*\n * Copyright © 2017-2022 The Crust Firmware Authors.\n * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only\n */\n\n#include <assert.h>\n#include <fcntl.h>\n#include <limits.h>\n#include <setjmp.h>\n#include <stdarg.h>\n#include <stdbool.h>\n#include <stdint.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <stdnoreturn.h>\n#include <string.h>\n#include <time.h>\n#include <unistd.h>\n#include <sys/mman.h>\n\n#include <compiler.h>\n#include <config.h>\n#include <kconfig.h>\n#include <mmio.h>\n#include <scpi_protocol.h>\n#include <util.h>\n#include <platform/devices.h>\n#include <platform/memory.h>\n\n/* SCPI device (clock/power supply) flags. */\n#define FLAG_READABLE               BIT(0)\n#define FLAG_WRITABLE               BIT(1)\n\n/* Simplified version of the message box register definitions. This tool only\n * uses virtual channel 0 (hardware channels 0/1). */\n#define MSGBOX_LOCAL_IRQ_STATUS_REG 0x0070\n#define MSGBOX_LOCAL_RX_IRQ         BIT(2)\n\n#define MSGBOX_ARISC_IRQ_STATUS_REG 0x0050\n#define MSGBOX_ARISC_RX_IRQ         BIT(0)\n\n#define MSGBOX_RX_MSG_STATUS_REG    0x0144\n#define MSGBOX_TX_MSG_STATUS_REG    0x0140\n#define MSGBOX_MSG_STATUS_MASK      GENMASK(2, 0)\n\n#define MSGBOX_RX_MSG_DATA_REG      0x0184\n#define MSGBOX_TX_MSG_DATA_REG      0x0180\n\n#define SENSOR_CLASS_TEMPERATURE    0\n#define SENSOR_CLASS_COUNT          5\n\n/* PAGESIZE is not defined on architectures with variable-sized pages. Assume\n * 4k pages if the size is unknown. */\n#ifndef PAGESIZE\n#define PAGESIZE          0x1000\n#endif\n#define PAGE_BASE(addr)   ((addr) & ~(PAGESIZE - 1))\n#define PAGE_OFFSET(addr) ((addr) & (PAGESIZE - 1))\n\n/** Shorthand for the virtual mmapped address of the shared memory area. */\n#define SCPI_SHMEM        (&((struct scpi_mem *)sram)[1])\n\n/** Arbitrary value to identify messages sent by the test program. */\n#define SCPI_SENDER_TEST  0xaa\n\n/** Arbitrary value to ensure the firmware correctly handles status codes. */\n#define SCPI_STATUS_TEST  0xcafef00d\n\n/** Convert a symbol to a string. */\n#define STRINGIFY(token)  #token\n\n/** Fail the current test if some condition is false. */\n#define test_assert(x)    ((void)((x) || (test_assert_fail(#x, __LINE__), 0)))\n\n/** Begin a test. */\n#define test_begin(id) \\\n\tdo { \\\n\t\ttests_attempted |= BIT(id); \\\n\t\tif (sigsetjmp(test_buf, 0)) { \\\n\t\t\ttest_fail(id); \\\n\t\t\treturn; \\\n\t\t} \\\n\t} while (0)\n\n/** Severities for log levels. */\nenum {\n\tLOG_INFO,  /**< An informational message. */\n\tLOG_WARN,  /**< A warning. The current test will continue. */\n\tLOG_ERR,   /**< An error. The current test cannot continue. */\n\tLOG_FATAL, /**< A fatal error. Testing the firmware cannot continue. */\n};\n\n/** Identifiers for the various tests. */\nenum {\n\tTEST_BOOT,\n\tTEST_INTERRUPT,\n\tTEST_SCP_CAP,\n\tTEST_CLOCK_CAP,\n\tTEST_CLOCK_CMDS,\n\tTEST_CLOCK_INFO,\n\tTEST_CLOCK_CTRL,\n\tTEST_CSS_INFO,\n\tTEST_DVFS_CAP,\n\tTEST_DVFS_CMDS,\n\tTEST_DVFS_INFO,\n\tTEST_DVFS_CTRL,\n\tTEST_PSU_CAP,\n\tTEST_PSU_CMDS,\n\tTEST_PSU_INFO,\n\tTEST_PSU_CTRL,\n\tTEST_SENSOR_CAP,\n\tTEST_SENSOR_CMDS,\n\tTEST_SENSOR_INFO,\n\tTEST_SENSOR_READ,\n\tTEST_SYS_POWER,\n\tTEST_COUNT,\n};\n\n/** A structure containing the timing data needed to analyze an SCPI call. */\nstruct scpi_call_times {\n\tstruct timespec start;       /**< Before doing any processing. */\n\tstruct timespec send;        /**< Before the call to msgbox_send. */\n\tstruct timespec send_ack;    /**< After return from msgbox_send. */\n\tstruct timespec receive;     /**< After return from msgbox_receive. */\n\tstruct timespec receive_ack; /**< After return from msgbox_ack. */\n\tstruct timespec finish;      /**< After all processing is complete. */\n};\n\n/** Context for returning to the main program on failure. */\nstatic sigjmp_buf main_buf;\n/** Context for continuing with the next test on failure. */\nstatic sigjmp_buf test_buf;\n\n/** Prefixes for the various log levels. */\nstatic const char *const log_prefixes[] = {\n\t\"\",\n\t\"warning: \",\n\t\"error: \",\n\t\"fatal: \"\n};\n\n/** Virtual address of the mmapped msgbox registers. */\nstatic uintptr_t mbox;\n/** Virtual address of the mmapped SCPI shared memory in SRAM A2. */\nstatic uintptr_t sram;\n\n/** SCPI command names printed with timing information. */\nstatic const char *const scpi_command_names[] = {\n\t\"INVALID SCPI COMMAND\",\n\tSTRINGIFY(SCPI_CMD_SCP_READY),\n\tSTRINGIFY(SCPI_CMD_GET_SCP_CAP),\n\tSTRINGIFY(SCPI_CMD_SET_CSS_POWER),\n\tSTRINGIFY(SCPI_CMD_GET_CSS_POWER),\n\tSTRINGIFY(SCPI_CMD_SET_SYS_POWER),\n\tSTRINGIFY(SCPI_CMD_SET_CPU_TIMER),\n\tSTRINGIFY(SCPI_CMD_CANCEL_CPU_TIMER),\n\tSTRINGIFY(SCPI_CMD_GET_DVFS_CAP),\n\tSTRINGIFY(SCPI_CMD_GET_DVFS_INFO),\n\tSTRINGIFY(SCPI_CMD_SET_DVFS),\n\tSTRINGIFY(SCPI_CMD_GET_DVFS),\n\tSTRINGIFY(SCPI_CMD_GET_DVFS_STATS),\n\tSTRINGIFY(SCPI_CMD_GET_CLOCK_CAP),\n\tSTRINGIFY(SCPI_CMD_GET_CLOCK_INFO),\n\tSTRINGIFY(SCPI_CMD_SET_CLOCK),\n\tSTRINGIFY(SCPI_CMD_GET_CLOCK),\n\tSTRINGIFY(SCPI_CMD_GET_PSU_CAP),\n\tSTRINGIFY(SCPI_CMD_GET_PSU_INFO),\n\tSTRINGIFY(SCPI_CMD_SET_PSU),\n\tSTRINGIFY(SCPI_CMD_GET_PSU),\n\tSTRINGIFY(SCPI_CMD_GET_SENSOR_CAP),\n\tSTRINGIFY(SCPI_CMD_GET_SENSOR_INFO),\n\tSTRINGIFY(SCPI_CMD_GET_SENSOR),\n\tSTRINGIFY(SCPI_CMD_CFG_SENSOR_PERIOD),\n\tSTRINGIFY(SCPI_CMD_CFG_SENSOR_BOUNDS),\n\tSTRINGIFY(SCPI_CMD_ASYNC_SENSOR),\n\tSTRINGIFY(SCPI_CMD_SET_DEV_POWER),\n\tSTRINGIFY(SCPI_CMD_GET_DEV_POWER),\n};\n\n/** A bitmap of the available SCPI commands, from SCPI_CMD_GET_SCP_CAP. */\nstatic uint32_t scpi_commands_available;\n\n/** Human-readable names for the various tests. */\nstatic const char *const test_names[TEST_COUNT] = {\n\t\"Boot\",\n\t\"Interrupt\",\n\t\"SCP capability\",\n\t\"Clock capability\",\n\t\"Clock commands\",\n\t\"Clock info\",\n\t\"Clock control\",\n\t\"CSS info\",\n\t\"DVFS capability\",\n\t\"DVFS commands\",\n\t\"DVFS info\",\n\t\"DVFS control\",\n\t\"PSU capability\",\n\t\"PSU commands\",\n\t\"PSU info\",\n\t\"PSU control\",\n\t\"Sensor capability\",\n\t\"Sensor commands\",\n\t\"Sensor info\",\n\t\"Sensor read\",\n\t\"System power\",\n};\n\n/** A bitmap of attempted tests. */\nstatic unsigned long tests_attempted;\n/** A bitmap of failed tests. */\nstatic unsigned long tests_failed;\n/** A bitmap of passed tests. */\nstatic unsigned long tests_passed;\n\n/**\n * Get the number of set bits in a bitmap.\n */\nstatic unsigned\nbitmap_weight(unsigned long bits)\n{\n\treturn __builtin_popcount(bits);\n}\n\n/**\n * Clean and invalidate lines in the data cache associated with a range of\n * virtual addresses.\n */\nstatic void\ndata_cache_clean(void *start, size_t length)\n{\n#ifdef __aarch64__\n\tuintptr_t addr = (uintptr_t)start;\n\tuintptr_t end = (uintptr_t)start + length;\n\tuintptr_t order, stride;\n\n\t/* Ensure the compiler doesn't move stores past the cache cleaning. */\n\tbarrier();\n\t/* Extract the order of the size of the smallest cache line. */\n\tasm (\"mrs  %0, CTR_EL0\\n\\t\"\n             \"ubfx %0, %0, #16, #4\" : \"=r\" (order));\n\t/* Get the actual stride length from its order. */\n\tstride = BIT(order);\n\t/* Align the address to the stride, and clean the cache by VA. */\n\tfor (addr &= ~(stride - 1); addr < end; addr += stride)\n\t\tasm volatile (\"dc civac, %0\" : : \"r\" (addr));\n\tasm volatile (\"dsb sy\");\n#else\n#error \"No cache cleaning implementation available for this architecture\"\n#endif\n}\n\n/**\n * Get the difference between two timespecs in nanoseconds.\n */\nstatic long\ndifftimespec(const struct timespec *x, const struct timespec *y)\n{\n\treturn 1000000000L * (x->tv_sec - y->tv_sec) + x->tv_nsec - y->tv_nsec;\n}\n\n/**\n * Log a message to standard error, and possibly abort testing.\n */\nstatic void\nlog(unsigned level, const char *fmt, ...)\n{\n\tva_list ap;\n\n\tva_start(ap, fmt);\n\tfflush(NULL);\n\tfputs(log_prefixes[level], stderr);\n\tvfprintf(stderr, fmt, ap);\n\tfputc('\\n', stderr);\n\tva_end(ap);\n\n\tif (level >= LOG_FATAL) {\n\t\t/* Fatal error: print summary and exit. */\n\t\tsiglongjmp(main_buf, 1);\n\t} else if (level >= LOG_ERR) {\n\t\t/* Non-fatal error: fail the test and resume with the next. */\n\t\tsiglongjmp(test_buf, 1);\n\t}\n}\n\n/**\n * Acknowledge that message has been received and its associated shared memory\n * is again available for use.\n */\nstatic void\nmsgbox_ack(void)\n{\n\t/* Clear the local message reception IRQ. */\n\tmmio_write_32(mbox + MSGBOX_LOCAL_IRQ_STATUS_REG, MSGBOX_LOCAL_RX_IRQ);\n}\n\n/**\n * Wait for a message, and ensure that it is an SCPI message.\n */\nstatic void\nmsgbox_receive(void)\n{\n\tuint32_t msgs, reg;\n\n\t/* Wait for a message reception IRQ. */\n\tmmio_poll_32(mbox + MSGBOX_LOCAL_IRQ_STATUS_REG, MSGBOX_LOCAL_RX_IRQ);\n\t/* Read the number of available messages. */\n\treg = mmio_read_32(mbox + MSGBOX_RX_MSG_STATUS_REG);\n\tif (unlikely((msgs = reg & MSGBOX_MSG_STATUS_MASK) > 1))\n\t\tlog(LOG_WARN, \"Expected one message, received %u\", msgs);\n\telse if (unlikely(msgs == 0))\n\t\tlog(LOG_FATAL, \"Received an IRQ, but no messages\");\n\treg = mmio_read_32(mbox + MSGBOX_RX_MSG_DATA_REG);\n\tif (unlikely(reg != SCPI_VIRTUAL_CHANNEL))\n\t\tlog(LOG_FATAL, \"Expected SCPI, received protocol 0x%08x\", reg);\n}\n\n/**\n * Send a message, and wait for it to be acknowledged.\n */\nstatic void\nmsgbox_send(void)\n{\n\t/* Send the message. */\n\tmmio_write_32(mbox + MSGBOX_TX_MSG_DATA_REG, SCPI_VIRTUAL_CHANNEL);\n\t/* Wait for the firmware to acknowledge the message. */\n\tmmio_pollz_32(mbox + MSGBOX_ARISC_IRQ_STATUS_REG,\n\t              MSGBOX_ARISC_RX_IRQ);\n}\n\n/**\n * Get the actual size of an SCPI message in bytes.\n */\nstatic size_t\nscpi_msg_size(struct scpi_msg *msg)\n{\n\treturn SCPI_HEADER_SIZE + msg->size;\n}\n\n/**\n * Copy an SCPI message, ensuring cache coherency.\n */\nstatic void\nscpi_copy_msg(struct scpi_msg *dest, struct scpi_msg *src)\n{\n\tsize_t length = scpi_msg_size(src);\n\n\t/* Only copy the necessary number of bytes from the message. */\n\tmemcpy(dest, src, length);\n\n\t/* Ensure that there is no stale cache of the shared memory area. */\n\tif (dest == &SCPI_SHMEM->rx_msg)\n\t\tdata_cache_clean(dest, length);\n\telse if (src == &SCPI_SHMEM->tx_msg)\n\t\tdata_cache_clean(src, length);\n}\n\n/**\n * Check if a command is in the set of available SCPI commands.\n */\nstatic bool\nscpi_has_command(uint8_t id)\n{\n\tif (id >= CHAR_BIT * sizeof(scpi_commands_available))\n\t\treturn false;\n\n\treturn (scpi_commands_available & BIT(id)) == BIT(id);\n}\n\n/**\n * Initialize the header of an SCPI message.\n */\nstatic void\nscpi_prepare_msg(struct scpi_msg *msg, uint8_t command)\n{\n\tmsg->command = command;\n\tmsg->sender  = SCPI_SENDER_TEST;\n\tmsg->size    = 0;\n\tmsg->status  = SCPI_STATUS_TEST;\n}\n\n/**\n * Send an SCPI request and verify its success.\n */\nstatic bool\nscpi_send_request(struct scpi_msg *msg, struct scpi_call_times *times)\n{\n\t/* Save the original command and sender to compare with the reply. */\n\tuint8_t  sender  = msg->sender;\n\tuint32_t command = msg->command;\n\n\tclock_gettime(CLOCK_MONOTONIC, &times->start);\n\t/* Copy the message to shared memory. */\n\tscpi_copy_msg(&SCPI_SHMEM->rx_msg, msg);\n\t/* Send the message. */\n\tclock_gettime(CLOCK_MONOTONIC, &times->send);\n\tmsgbox_send();\n\tclock_gettime(CLOCK_MONOTONIC, &times->send_ack);\n\t/* Wait for a response message. */\n\tmsgbox_receive();\n\tclock_gettime(CLOCK_MONOTONIC, &times->receive);\n\t/* Copy the message from shared memory to DRAM. */\n\tscpi_copy_msg(msg, &SCPI_SHMEM->tx_msg);\n\t/* Acknowledge the response, now that it's safely stored in DRAM. */\n\tmsgbox_ack();\n\tclock_gettime(CLOCK_MONOTONIC, &times->receive_ack);\n\t/* Stop the timer. */\n\tclock_gettime(CLOCK_MONOTONIC, &times->finish);\n\n\t/* Verify that the received message is an appropriate response. */\n\tif (unlikely(msg->command != command)) {\n\t\tlog(LOG_ERR, \"Expected reply for command %u, received %u\",\n\t\t    command, msg->command);\n\t\treturn false;\n\t}\n\tif (unlikely(msg->sender != sender)) {\n\t\tlog(LOG_ERR, \"Expected reply to sender %u, received %u\",\n\t\t    sender, msg->sender);\n\t\treturn false;\n\t}\n\n\treturn true;\n}\n\n/**\n * Wait for an SCPI request and send a reply.\n */\nstatic bool\nscpi_serve_reply(struct scpi_msg *msg, struct scpi_call_times *times,\n                 uint32_t command)\n{\n\tclock_gettime(CLOCK_MONOTONIC, &times->start);\n\t/* Wait for a message to arrive. */\n\tmsgbox_receive();\n\tclock_gettime(CLOCK_MONOTONIC, &times->receive);\n\t/* Copy the message from shared memory to DRAM. */\n\tscpi_copy_msg(msg, &SCPI_SHMEM->tx_msg);\n\t/* Acknowledge that the message was received. */\n\tmsgbox_ack();\n\tclock_gettime(CLOCK_MONOTONIC, &times->receive_ack);\n\t/* Prepare the reply message (a copy of the received message). */\n\tif (likely(msg->command == command && msg->sender == SCPI_SENDER_SCP))\n\t\tmsg->status = SCPI_OK;\n\telse\n\t\tmsg->status = SCPI_E_PARAM;\n\tscpi_copy_msg(&SCPI_SHMEM->rx_msg, msg);\n\t/* Send the reply message. */\n\tclock_gettime(CLOCK_MONOTONIC, &times->send);\n\tmsgbox_send();\n\tclock_gettime(CLOCK_MONOTONIC, &times->send_ack);\n\n\t/* Verify that the received message is as expected. */\n\tif (unlikely(msg->command != command)) {\n\t\tlog(LOG_ERR, \"Expected command %u, received %u\",\n\t\t    command, msg->command);\n\t\treturn false;\n\t}\n\tif (unlikely(msg->sender != SCPI_SENDER_SCP)) {\n\t\tlog(LOG_ERR, \"Expected sender %u, got sender %u\",\n\t\t    SCPI_SENDER_SCP, msg->sender);\n\t\treturn false;\n\t}\n\n\treturn true;\n}\n\n/**\n * Handle failure of a test.\n */\nstatic noreturn void\ntest_assert_fail(const char *expr, unsigned line)\n{\n\tlog(LOG_ERR, \"Assertion failed: %d: '%s'\", line, expr);\n\n\tsiglongjmp(test_buf, -1);\n}\n\n/**\n * Mark a test as completed (passed).\n */\nstatic void\ntest_complete(uint8_t id)\n{\n\tif (tests_passed & BIT(id))\n\t\treturn;\n\n\ttests_passed |= BIT(id);\n\tprintf(\"PASS: %s\\n\", test_names[id]);\n}\n\n/**\n * Mark a test as failed.\n */\nstatic void\ntest_fail(uint8_t id)\n{\n\tif (tests_failed & BIT(id))\n\t\treturn;\n\n\ttests_failed |= BIT(id);\n\tprintf(\"FAIL: %s\\n\", test_names[id]);\n}\n\n/**\n * Send an SCPI request as part of a test.\n */\nstatic void\ntest_send_request(struct scpi_msg *msg)\n{\n\tstruct scpi_call_times times;\n\n\ttest_assert(scpi_send_request(msg, &times));\n\tprintf(\"TIME: %-25s │ send: %10ldns │ receive: %10ldns │ busy: %10ldns\"\n\t       \" │ total: %10ldns\\n\",\n\t       scpi_command_names[msg->command],\n\t       difftimespec(&times.send_ack, &times.send),\n\t       difftimespec(&times.receive_ack, &times.receive),\n\t       difftimespec(&times.receive_ack, &times.send),\n\t       difftimespec(&times.finish, &times.start));\n}\n\n/**\n * Wait for an SCPI request as part of a test.\n */\nstatic void\ntest_serve_reply(struct scpi_msg *msg, long *wait_time)\n{\n\tstruct scpi_call_times times;\n\n\ttest_assert(scpi_serve_reply(msg, &times, msg->command));\n\t*wait_time = difftimespec(&times.receive, &times.start);\n}\n\n/**\n * Print a summary of tests run.\n */\nstatic void\ntest_summary(void)\n{\n\tprintf(\"DONE: %u tests, %u passed, %u failed, %u skipped\\n\",\n\t       TEST_COUNT,\n\t       bitmap_weight(tests_passed),\n\t       bitmap_weight(tests_failed),\n\t       TEST_COUNT - bitmap_weight(tests_attempted));\n}\n\n/*\n * Test: Basic commands (SCP capability).\n */\nstatic void\ntry_basic(void)\n{\n\tstruct scpi_msg msg;\n\n\t/* Send an invalid command to test basic message processing. */\n\ttest_begin(TEST_INTERRUPT);\n\tscpi_prepare_msg(&msg, 0);\n\ttest_send_request(&msg);\n\ttest_assert(msg.status == SCPI_E_SUPPORT);\n\ttest_assert(msg.size == 0);\n\n\t/* Send a valid command with the wrong payload size. */\n\tscpi_prepare_msg(&msg, SCPI_CMD_GET_SCP_CAP);\n\tmsg.size = 4;\n\ttest_send_request(&msg);\n\ttest_assert(msg.status == SCPI_E_SIZE);\n\ttest_assert(msg.size == 0);\n\ttest_complete(TEST_INTERRUPT);\n\n\t/* Query the firmware's capabilities. Save the resulting set of\n\t * supported commands in a global variable for later use. */\n\ttest_begin(TEST_SCP_CAP);\n\tscpi_prepare_msg(&msg, SCPI_CMD_GET_SCP_CAP);\n\ttest_send_request(&msg);\n\ttest_assert(msg.status == SCPI_OK);\n\ttest_assert(msg.size == 28);\n\t/* The supported SCPI standard must be revision 1.2. */\n\ttest_assert(((uint16_t *)msg.payload)[0] == 2);\n\ttest_assert(((uint16_t *)msg.payload)[1] == 1);\n\t/* The supported payload size must match the header definitions. */\n\ttest_assert(((uint16_t *)msg.payload)[2] == SCPI_PAYLOAD_SIZE);\n\ttest_assert(((uint16_t *)msg.payload)[3] == SCPI_PAYLOAD_SIZE);\n\tscpi_commands_available = ((uint32_t *)msg.payload)[3];\n\t/* Ensure the supported commands word is sane (that the firmware claims\n\t * to support the commands we just sent). */\n\ttest_assert(scpi_has_command(SCPI_CMD_SCP_READY));\n\ttest_assert(scpi_has_command(SCPI_CMD_GET_SCP_CAP));\n\ttest_complete(TEST_SCP_CAP);\n}\n\n/*\n * Test: Boot (SCP ready).\n */\nstatic void\ntry_boot(void)\n{\n\tstruct scpi_msg msg;\n\tlong boot_time;\n\n\t/* Seeing \"SCP ready\" means the firmware booted successfully. */\n\tlog(LOG_INFO, \"Waiting for firmware...\");\n\ttest_begin(TEST_BOOT);\n\tscpi_prepare_msg(&msg, SCPI_CMD_SCP_READY);\n\ttest_serve_reply(&msg, &boot_time);\n\tlog(LOG_INFO, \"Firmware booted in %ld ns\", boot_time);\n\ttest_complete(TEST_BOOT);\n}\n\n/*\n * Test: Clocks.\n */\nstatic void\ntry_clocks(void)\n{\n\tstruct scpi_msg msg;\n\tuint16_t clocks = 0;\n\n\t/* Skip this test if the required commands are not available. */\n\tif (!scpi_has_command(SCPI_CMD_GET_CLOCK_CAP))\n\t\treturn;\n\n\t/* Get the number of clocks. */\n\ttest_begin(TEST_CLOCK_CAP);\n\tscpi_prepare_msg(&msg, SCPI_CMD_GET_CLOCK_CAP);\n\ttest_send_request(&msg);\n\ttest_assert(msg.status == SCPI_OK);\n\ttest_assert(msg.size == 2);\n\tclocks = ((uint16_t *)msg.payload)[0];\n\ttest_complete(TEST_CLOCK_CAP);\n\n\t/* If the firmware has clocks, it must fully support clock control. */\n\tif (clocks > 0) {\n\t\ttest_begin(TEST_CLOCK_CMDS);\n\t\ttest_assert(scpi_has_command(SCPI_CMD_GET_CLOCK_INFO));\n\t\ttest_assert(scpi_has_command(SCPI_CMD_SET_CLOCK));\n\t\ttest_assert(scpi_has_command(SCPI_CMD_GET_CLOCK));\n\t\ttest_complete(TEST_CLOCK_CMDS);\n\t}\n\n\tfor (volatile uint16_t i = 0; i < clocks; ++i) {\n\t\tuint8_t  flags;\n\t\tuint32_t max_rate, min_rate;\n\n\t\ttest_begin(TEST_CLOCK_INFO);\n\t\tscpi_prepare_msg(&msg, SCPI_CMD_GET_CLOCK_INFO);\n\t\t/* Send the clock ID. */\n\t\tmsg.size = 2;\n\t\t((uint16_t *)msg.payload)[0] = i;\n\t\ttest_send_request(&msg);\n\t\ttest_assert(msg.status == SCPI_OK);\n\t\ttest_assert(msg.size >= 12);\n\t\t/* Assert that we got the same ID back. */\n\t\ttest_assert(((uint16_t *)msg.payload)[0] == i);\n\t\t/* Assert that there are no reserved flags. */\n\t\tflags = ((uint16_t *)msg.payload)[1];\n\t\ttest_assert((flags & ~(FLAG_READABLE | FLAG_WRITABLE)) == 0);\n\t\t/* Assert that the minimum and maximum rates make sense. */\n\t\tmin_rate = ((uint32_t *)msg.payload)[1];\n\t\tmax_rate = ((uint32_t *)msg.payload)[2];\n\t\ttest_assert(max_rate >= min_rate);\n\t\ttest_complete(TEST_CLOCK_INFO);\n\n\t\t/* Try setting both the minimum and maximum rates. */\n\t\ttest_begin(TEST_CLOCK_CTRL);\n\t\tscpi_prepare_msg(&msg, SCPI_CMD_SET_CLOCK);\n\t\tmsg.size = 8;\n\t\t((uint32_t *)msg.payload)[0] = i;\n\t\t((uint32_t *)msg.payload)[1] = min_rate;\n\t\ttest_send_request(&msg);\n\t\t/* Assert that the firmware respects its permission flags. */\n\t\tif (!(flags & FLAG_WRITABLE)) {\n\t\t\ttest_assert(msg.status == SCPI_E_ACCESS);\n\t\t} else {\n\t\t\t/* Set the clock may still fail if it is in use. */\n\t\t\ttest_assert(msg.status == SCPI_OK ||\n\t\t\t            msg.status == SCPI_E_ACCESS);\n\t\t}\n\t\ttest_assert(msg.size == 0);\n\n\t\tscpi_prepare_msg(&msg, SCPI_CMD_SET_CLOCK);\n\t\tmsg.size = 8;\n\t\t((uint32_t *)msg.payload)[0] = i;\n\t\t((uint32_t *)msg.payload)[1] = max_rate;\n\t\ttest_send_request(&msg);\n\t\t/* Assert that the firmware respects its permission flags. */\n\t\tif (!(flags & FLAG_WRITABLE)) {\n\t\t\ttest_assert(msg.status == SCPI_E_ACCESS);\n\t\t} else {\n\t\t\t/* Set the clock may still fail if it is in use. */\n\t\t\ttest_assert(msg.status == SCPI_OK ||\n\t\t\t            msg.status == SCPI_E_ACCESS);\n\t\t}\n\t\ttest_assert(msg.size == 0);\n\n\t\t/* Read back clock rate and ensure it is in range. */\n\t\tscpi_prepare_msg(&msg, SCPI_CMD_GET_CLOCK);\n\t\tmsg.size = 2;\n\t\t((uint16_t *)msg.payload)[0] = i;\n\t\ttest_send_request(&msg);\n\t\t/* Assert that the firmware respects its permission flags. */\n\t\tif (!(flags & FLAG_READABLE)) {\n\t\t\ttest_assert(msg.status == SCPI_E_ACCESS);\n\t\t\ttest_complete(TEST_CLOCK_CTRL);\n\t\t\tcontinue;\n\t\t}\n\t\ttest_assert(msg.status == SCPI_OK);\n\t\ttest_assert(msg.size == 4);\n\t\ttest_assert(((uint32_t *)msg.payload)[0] >= min_rate);\n\t\ttest_assert(((uint32_t *)msg.payload)[0] <= max_rate);\n\t\ttest_complete(TEST_CLOCK_CTRL);\n\t}\n\n\t/* Test the failure case of sending an invalid clock ID. */\n\ttest_begin(TEST_CLOCK_INFO);\n\tscpi_prepare_msg(&msg, SCPI_CMD_GET_CLOCK_INFO);\n\tmsg.size = 2;\n\t((uint16_t *)msg.payload)[0] = clocks;\n\ttest_send_request(&msg);\n\ttest_assert(msg.status == SCPI_E_PARAM);\n\ttest_complete(TEST_CLOCK_INFO);\n}\n\n/*\n * Test: CSS power.\n */\nstatic void\ntry_css_power(void)\n{\n\tstruct scpi_msg msg;\n\n\t/* Skip this test if the required commands are not available. */\n\tif (!scpi_has_command(SCPI_CMD_GET_CSS_POWER))\n\t\treturn;\n\n\ttest_begin(TEST_CSS_INFO);\n\tscpi_prepare_msg(&msg, SCPI_CMD_GET_CSS_POWER);\n\ttest_send_request(&msg);\n\ttest_assert(msg.status == SCPI_OK);\n\t/* Assert that there is at least one cluster. */\n\ttest_assert(msg.size >= 2);\n\t/* Each descriptor is 2 bytes long. */\n\ttest_assert(msg.size % 2 == 0);\n\t/* Assert that all clusters are on. */\n\tfor (size_t i = 0; i < msg.size / 2; ++i)\n\t\ttest_assert((((uint16_t *)msg.payload)[i] & 0x0f) == 0);\n\ttest_complete(TEST_CSS_INFO);\n}\n\n/*\n * Test: DVFS.\n */\nstatic void\ntry_dvfs(void)\n{\n\tstruct scpi_msg msg;\n\tuint8_t domains = 0, opps;\n\n\t/* Skip this test if the required commands are not available. */\n\tif (!scpi_has_command(SCPI_CMD_GET_DVFS_CAP))\n\t\treturn;\n\n\t/* Get the number of DVFS domains. */\n\ttest_begin(TEST_DVFS_CAP);\n\tscpi_prepare_msg(&msg, SCPI_CMD_GET_DVFS_CAP);\n\ttest_send_request(&msg);\n\ttest_assert(msg.status == SCPI_OK);\n\ttest_assert(msg.size == 1);\n\tdomains = ((uint8_t *)msg.payload)[0];\n\ttest_complete(TEST_DVFS_CAP);\n\n\t/* If the firmware has DVFS domains, it must fully support DVFS. */\n\tif (domains > 0) {\n\t\ttest_begin(TEST_DVFS_CMDS);\n\t\ttest_assert(scpi_has_command(SCPI_CMD_GET_DVFS_INFO));\n\t\ttest_assert(scpi_has_command(SCPI_CMD_SET_DVFS));\n\t\ttest_assert(scpi_has_command(SCPI_CMD_GET_DVFS));\n\t\ttest_complete(TEST_DVFS_CMDS);\n\t}\n\n\tfor (volatile uint8_t i = 0; i < domains; ++i) {\n\t\ttest_begin(TEST_DVFS_INFO);\n\t\tscpi_prepare_msg(&msg, SCPI_CMD_GET_DVFS_INFO);\n\t\t/* Send the domain ID. */\n\t\tmsg.size = 1;\n\t\t((uint8_t *)msg.payload)[0] = i;\n\t\ttest_send_request(&msg);\n\t\ttest_assert(msg.status == SCPI_OK);\n\t\ttest_assert(msg.size >= 4);\n\t\t/* Assert that we got the same ID back. */\n\t\ttest_assert(((uint8_t *)msg.payload)[0] == i);\n\t\t/* Get the number of operating performance points. */\n\t\topps = ((uint8_t *)msg.payload)[1];\n\t\t/* Ensure the number of OPPs matches the message size. */\n\t\ttest_assert(opps > 0);\n\t\ttest_assert(msg.size == 8 * opps + 4);\n\t\ttest_complete(TEST_DVFS_INFO);\n\n\t\t/* Cycle through all of the OPPs. */\n\t\ttest_begin(TEST_DVFS_CTRL);\n\t\tfor (uint8_t j = 0; j < opps; ++j) {\n\t\t\t/* Set DVFS domain i to OPP j. */\n\t\t\tscpi_prepare_msg(&msg, SCPI_CMD_SET_DVFS);\n\t\t\tmsg.size = 2;\n\t\t\t((uint8_t *)msg.payload)[0] = i;\n\t\t\t((uint8_t *)msg.payload)[1] = j;\n\t\t\ttest_send_request(&msg);\n\t\t\ttest_assert(msg.status == SCPI_OK);\n\t\t\ttest_assert(msg.size == 0);\n\n\t\t\t/* Read back the OPP index and ensure it matches. */\n\t\t\tscpi_prepare_msg(&msg, SCPI_CMD_GET_DVFS);\n\t\t\tmsg.size = 1;\n\t\t\t((uint8_t *)msg.payload)[0] = i;\n\t\t\ttest_send_request(&msg);\n\t\t\ttest_assert(msg.status == SCPI_OK);\n\t\t\ttest_assert(msg.size == 1);\n\t\t\ttest_assert(((uint8_t *)msg.payload)[0] == j);\n\t\t}\n\t\ttest_complete(TEST_DVFS_CTRL);\n\t}\n\n\t/* Test the failure case of sending an invalid domain ID. */\n\ttest_begin(TEST_DVFS_INFO);\n\tscpi_prepare_msg(&msg, SCPI_CMD_GET_DVFS_INFO);\n\tmsg.size = 1;\n\t((uint8_t *)msg.payload)[0] = domains;\n\ttest_send_request(&msg);\n\ttest_assert(msg.status == SCPI_E_PARAM);\n\ttest_complete(TEST_DVFS_INFO);\n}\n\n/*\n * Test: Power supplies.\n */\nstatic void\ntry_psus(void)\n{\n\tstruct scpi_msg msg;\n\tuint16_t psus = 0;\n\n\t/* Skip this test if the required commands are not available. */\n\tif (!scpi_has_command(SCPI_CMD_GET_PSU_CAP))\n\t\treturn;\n\n\t/* Get the number of clocks. */\n\ttest_begin(TEST_PSU_CAP);\n\tscpi_prepare_msg(&msg, SCPI_CMD_GET_PSU_CAP);\n\ttest_send_request(&msg);\n\ttest_assert(msg.status == SCPI_OK);\n\ttest_assert(msg.size == 2);\n\tpsus = ((uint16_t *)msg.payload)[0];\n\ttest_complete(TEST_PSU_CAP);\n\n\t/* If the firmware has clocks, it must fully support clock control. */\n\tif (psus > 0) {\n\t\ttest_begin(TEST_PSU_CMDS);\n\t\ttest_assert(scpi_has_command(SCPI_CMD_GET_PSU_INFO));\n\t\ttest_assert(scpi_has_command(SCPI_CMD_SET_PSU));\n\t\ttest_assert(scpi_has_command(SCPI_CMD_GET_PSU));\n\t\ttest_complete(TEST_PSU_CMDS);\n\t}\n\n\tfor (volatile uint16_t i = 0; i < psus; ++i) {\n\t\tuint8_t  flags;\n\t\tuint32_t min_voltage, max_voltage, voltage;\n\n\t\ttest_begin(TEST_PSU_INFO);\n\t\tscpi_prepare_msg(&msg, SCPI_CMD_GET_PSU_INFO);\n\t\t/* Send the PSU ID. */\n\t\tmsg.size = 2;\n\t\t((uint16_t *)msg.payload)[0] = i;\n\t\ttest_send_request(&msg);\n\t\ttest_assert(msg.status == SCPI_OK);\n\t\ttest_assert(msg.size >= 12);\n\t\t/* Assert that we got the same ID back. */\n\t\ttest_assert(((uint16_t *)msg.payload)[0] == i);\n\t\t/* Assert that there are no reserved flags. */\n\t\tflags = ((uint16_t *)msg.payload)[1];\n\t\ttest_assert((flags & ~(FLAG_READABLE | FLAG_WRITABLE)) == 0);\n\t\t/* Assert that the minimum and maximum voltages make sense. */\n\t\tmin_voltage = ((uint32_t *)msg.payload)[1];\n\t\tmax_voltage = ((uint32_t *)msg.payload)[2];\n\t\ttest_assert(max_voltage >= min_voltage);\n\t\ttest_complete(TEST_PSU_INFO);\n\n\t\t/* Set an invalid value (over the maximum). */\n\t\tscpi_prepare_msg(&msg, SCPI_CMD_SET_PSU);\n\t\tmsg.size = 8;\n\t\t((uint32_t *)msg.payload)[0] = i;\n\t\t((uint32_t *)msg.payload)[1] = max_voltage + 1000;\n\t\ttest_send_request(&msg);\n\t\t/* Assert that the firmware respects its permission flags. */\n\t\tif (flags & FLAG_WRITABLE)\n\t\t\ttest_assert(msg.status == SCPI_E_RANGE);\n\t\telse\n\t\t\ttest_assert(msg.status == SCPI_E_ACCESS);\n\t\ttest_assert(msg.size == 0);\n\n\t\t/* Get the current value, for setting below. */\n\t\ttest_begin(TEST_PSU_CTRL);\n\t\tscpi_prepare_msg(&msg, SCPI_CMD_GET_PSU);\n\t\tmsg.size = 2;\n\t\t((uint16_t *)msg.payload)[0] = i;\n\t\ttest_send_request(&msg);\n\t\t/* Assert that the firmware respects its permission flags. */\n\t\tif (!(flags & FLAG_READABLE)) {\n\t\t\ttest_assert(msg.status == SCPI_E_ACCESS);\n\t\t\ttest_complete(TEST_PSU_CTRL);\n\t\t\tcontinue;\n\t\t}\n\t\ttest_assert(msg.status == SCPI_OK);\n\t\ttest_assert(msg.size == 4);\n\t\tvoltage = ((uint32_t *)msg.payload)[0];\n\t\ttest_assert(voltage >= min_voltage);\n\t\ttest_assert(voltage <= max_voltage);\n\n\t\t/* Setting arbitrary values is unsafe; set what was read. */\n\t\tscpi_prepare_msg(&msg, SCPI_CMD_SET_PSU);\n\t\tmsg.size = 8;\n\t\t((uint32_t *)msg.payload)[0] = i;\n\t\t((uint32_t *)msg.payload)[1] = voltage;\n\t\ttest_send_request(&msg);\n\t\t/* Assert that the firmware respects its permission flags. */\n\t\tif (flags & FLAG_WRITABLE)\n\t\t\ttest_assert(msg.status == SCPI_OK);\n\t\telse\n\t\t\ttest_assert(msg.status == SCPI_E_ACCESS);\n\t\ttest_assert(msg.size == 0);\n\t\ttest_complete(TEST_PSU_CTRL);\n\t}\n\n\t/* Test the failure case of sending an invalid PSU ID. */\n\ttest_begin(TEST_PSU_INFO);\n\tscpi_prepare_msg(&msg, SCPI_CMD_GET_PSU_INFO);\n\tmsg.size = 2;\n\t((uint16_t *)msg.payload)[0] = psus;\n\ttest_send_request(&msg);\n\ttest_assert(msg.status == SCPI_E_PARAM);\n\ttest_complete(TEST_PSU_INFO);\n}\n\n/*\n * Test: Sensors.\n */\nstatic void\ntry_sensors(void)\n{\n\tstruct scpi_msg msg;\n\tuint16_t sensors = 0;\n\n\t/* Skip this test if the required commands are not available. */\n\tif (!scpi_has_command(SCPI_CMD_GET_SENSOR_CAP))\n\t\treturn;\n\n\t/* Get the number of sensors. */\n\ttest_begin(TEST_SENSOR_CAP);\n\tscpi_prepare_msg(&msg, SCPI_CMD_GET_SENSOR_CAP);\n\ttest_send_request(&msg);\n\ttest_assert(msg.status == SCPI_OK);\n\ttest_assert(msg.size == 2);\n\tsensors = ((uint16_t *)msg.payload)[0];\n\ttest_complete(TEST_SENSOR_CAP);\n\n\t/* If the firmware has clocks, it must fully support clock control. */\n\tif (sensors > 0) {\n\t\ttest_begin(TEST_SENSOR_CMDS);\n\t\ttest_assert(scpi_has_command(SCPI_CMD_GET_SENSOR_INFO));\n\t\ttest_assert(scpi_has_command(SCPI_CMD_GET_SENSOR));\n\t\ttest_complete(TEST_SENSOR_CMDS);\n\t}\n\n\tfor (volatile uint16_t i = 0; i < sensors; ++i) {\n\t\tuint8_t  class;\n\t\tuint32_t value;\n\n\t\ttest_begin(TEST_SENSOR_INFO);\n\t\tscpi_prepare_msg(&msg, SCPI_CMD_GET_SENSOR_INFO);\n\t\t/* Send the sensor ID. */\n\t\tmsg.size = 2;\n\t\t((uint16_t *)msg.payload)[0] = i;\n\t\ttest_send_request(&msg);\n\t\ttest_assert(msg.status == SCPI_OK);\n\t\ttest_assert(msg.size >= 4);\n\t\t/* Assert that we got the same ID back. */\n\t\ttest_assert(((uint16_t *)msg.payload)[0] == i);\n\t\t/* Assert that the class is valid. */\n\t\tclass = ((uint8_t *)msg.payload)[2];\n\t\ttest_assert(class < SENSOR_CLASS_COUNT);\n\t\t/* Assert that the triggers are valid. */\n\t\ttest_assert((msg.payload[3] & ~(BIT(0) | BIT(1))) == 0);\n\t\ttest_complete(TEST_SENSOR_INFO);\n\n\t\t/* Check the current value for sanity. */\n\t\ttest_begin(TEST_SENSOR_READ);\n\t\tscpi_prepare_msg(&msg, SCPI_CMD_GET_SENSOR);\n\t\tmsg.size = 2;\n\t\t((uint16_t *)msg.payload)[0] = i;\n\t\ttest_send_request(&msg);\n\t\ttest_assert(msg.status == SCPI_OK);\n\t\ttest_assert(msg.size == 8);\n\t\tvalue = ((uint32_t *)msg.payload)[0];\n\t\t/* Ensure temperature readings are below 100°C. */\n\t\tif (class == SENSOR_CLASS_TEMPERATURE)\n\t\t\ttest_assert(value < 100000);\n\t\t/* The firmware does not support more than 32-bit output. */\n\t\ttest_assert(((uint32_t *)msg.payload)[1] == 0);\n\t\ttest_complete(TEST_SENSOR_READ);\n\t}\n}\n\n/*\n * Test: System power.\n */\nstatic void\ntry_sys_power(void)\n{\n\tstruct scpi_msg msg;\n\n\t/* Positive tests would reset the machine; only test failure cases. */\n\ttest_begin(TEST_SYS_POWER);\n\tscpi_prepare_msg(&msg, SCPI_CMD_SET_SYS_POWER);\n\tmsg.size = 1;\n\t/* 4 is not a valid system power state. */\n\t((uint8_t *)msg.payload)[0] = 4;\n\ttest_send_request(&msg);\n\ttest_assert(msg.status == SCPI_E_PARAM);\n\n\tscpi_prepare_msg(&msg, SCPI_CMD_SET_SYS_POWER);\n\tmsg.size = 1;\n\t/* 20 is not a valid system power state. */\n\t((uint8_t *)msg.payload)[0] = 20;\n\ttest_send_request(&msg);\n\ttest_assert(msg.status == SCPI_E_PARAM);\n\ttest_complete(TEST_SYS_POWER);\n}\n\nint\nmain(int argc, char *argv[])\n{\n\tvoid *mbox_map, *sram_map;\n\tint fd;\n\n\tstatic_assert(sizeof(struct scpi_msg) == SCPI_MESSAGE_SIZE,\n\t              \"struct scpi_msg does not have the correct size\");\n\n\tif (argc >= 2) {\n\t\tputs(\"ARISC firmware tester for \" CONFIG_PLATFORM);\n\t\tprintf(\"usage: %s [--help]\\n\", argv[0]);\n\t\treturn strcmp(\"--help\", argv[1]) ? EXIT_FAILURE : EXIT_SUCCESS;\n\t}\n\n\t/* Map the SCPI shared memory and the message box. */\n\tfd = open(\"/dev/mem\", O_RDWR | O_SYNC);\n\tif (fd < 0) {\n\t\tperror(\"Failed to open /dev/mem\");\n\t\treturn EXIT_FAILURE;\n\t}\n\tmbox_map = mmap(NULL, PAGESIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd,\n\t                PAGE_BASE(DEV_MSGBOX));\n\tif (mbox_map == MAP_FAILED) {\n\t\tperror(\"Failed to mmap MSGBOX\");\n\t\treturn EXIT_FAILURE;\n\t}\n\tsram_map = mmap(NULL, PAGESIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd,\n\t                PAGE_BASE(SRAM_A2_OFFSET + SCPI_MEM_BASE));\n\tif (sram_map == MAP_FAILED) {\n\t\tperror(\"Failed to mmap SRAM A2\");\n\t\treturn EXIT_FAILURE;\n\t}\n\tclose(fd);\n\n\t/* Correct the addresses for mmap requiring page alignment. */\n\tmbox = (uintptr_t)mbox_map + PAGE_OFFSET(DEV_MSGBOX);\n\tsram = (uintptr_t)sram_map + PAGE_OFFSET(SRAM_A2_OFFSET +\n\t                                         SCPI_MEM_BASE);\n\n\t/* Set up the fatal error handler. */\n\tif (sigsetjmp(main_buf, 0)) {\n\t\ttest_summary();\n\t\treturn EXIT_FAILURE;\n\t}\n\n\t/* Run all tests. */\n\ttry_boot();\n\ttry_basic();\n\ttry_clocks();\n\ttry_css_power();\n\ttry_dvfs();\n\ttry_psus();\n\ttry_sensors();\n\ttry_sys_power();\n\n\t/* Display a summary of the tests. */\n\ttest_summary();\n\n\t/* Clean up. */\n\tmunmap(mbox_map, PAGESIZE);\n\tmunmap(sram_map, PAGESIZE);\n\n\treturn EXIT_SUCCESS;\n}\n"
  }
]