diff --git a/.clang-format b/.clang-format index fa959436bcfd0fdc41d69e15496289bc998a07e6..9b87ea1fc16e9ca86cd0cfed7c8015f40e16f93f 100644 --- a/.clang-format +++ b/.clang-format @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 # -# clang-format configuration file. Intended for clang-format >= 4. +# clang-format configuration file. Intended for clang-format >= 11. # # For more information, see: # @@ -13,7 +13,7 @@ AccessModifierOffset: -4 AlignAfterOpenBracket: Align AlignConsecutiveAssignments: false AlignConsecutiveDeclarations: false -#AlignEscapedNewlines: Left # Unknown to clang-format-4.0 +AlignEscapedNewlines: Left AlignOperands: true AlignTrailingComments: false AllowAllParametersOfDeclarationOnNextLine: false @@ -37,24 +37,24 @@ BraceWrapping: AfterObjCDeclaration: false AfterStruct: false AfterUnion: false - #AfterExternBlock: false # Unknown to clang-format-5.0 + AfterExternBlock: false BeforeCatch: false BeforeElse: false IndentBraces: false - #SplitEmptyFunction: true # Unknown to clang-format-4.0 - #SplitEmptyRecord: true # Unknown to clang-format-4.0 - #SplitEmptyNamespace: true # Unknown to clang-format-4.0 + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true BreakBeforeBinaryOperators: None BreakBeforeBraces: Custom -#BreakBeforeInheritanceComma: false # Unknown to clang-format-4.0 +BreakBeforeInheritanceComma: false BreakBeforeTernaryOperators: false BreakConstructorInitializersBeforeComma: false -#BreakConstructorInitializers: BeforeComma # Unknown to clang-format-4.0 +BreakConstructorInitializers: BeforeComma BreakAfterJavaFieldAnnotations: false BreakStringLiterals: false ColumnLimit: 80 CommentPragmas: '^ IWYU pragma:' -#CompactNamespaces: false # Unknown to clang-format-4.0 +CompactNamespaces: false ConstructorInitializerAllOnOneLineOrOnePerLine: false ConstructorInitializerIndentWidth: 8 ContinuationIndentWidth: 8 @@ -62,39 +62,56 @@ Cpp11BracedListStyle: false DerivePointerAlignment: false DisableFormat: false ExperimentalAutoDetectBinPacking: false -#FixNamespaceComments: false # Unknown to clang-format-4.0 +FixNamespaceComments: false # Taken from: -# git grep -h '^#define [^[:space:]]*for_each[^[:space:]]*(' include/ \ +# git grep -h '^#define [^[:space:]]*for_each[^[:space:]]*(' include/ tools/ \ # | sed "s,^#define \([^[:space:]]*for_each[^[:space:]]*\)(.*$, - '\1'," \ -# | sort | uniq +# | LC_ALL=C sort -u ForEachMacros: + - '__ata_qc_for_each' + - '__bio_for_each_bvec' + - '__bio_for_each_segment' + - '__evlist__for_each_entry' + - '__evlist__for_each_entry_continue' + - '__evlist__for_each_entry_from' + - '__evlist__for_each_entry_reverse' + - '__evlist__for_each_entry_safe' + - '__for_each_mem_range' + - '__for_each_mem_range_rev' + - '__for_each_thread' + - '__hlist_for_each_rcu' + - '__map__for_each_symbol_by_name' + - '__perf_evlist__for_each_entry' + - '__perf_evlist__for_each_entry_reverse' + - '__perf_evlist__for_each_entry_safe' + - '__rq_for_each_bio' + - '__shost_for_each_device' - 'apei_estatus_for_each_section' - 'ata_for_each_dev' - 'ata_for_each_link' - - '__ata_qc_for_each' - 'ata_qc_for_each' - 'ata_qc_for_each_raw' - 'ata_qc_for_each_with_internal' - 'ax25_for_each' - 'ax25_uid_for_each' - - '__bio_for_each_bvec' - 'bio_for_each_bvec' - 'bio_for_each_bvec_all' + - 'bio_for_each_folio_all' - 'bio_for_each_integrity_vec' - - '__bio_for_each_segment' - 'bio_for_each_segment' - 'bio_for_each_segment_all' - 'bio_list_for_each' - 'bip_for_each_vec' - - 'bitmap_for_each_clear_region' - - 'bitmap_for_each_set_region' - - 'blkg_for_each_descendant_post' - - 'blkg_for_each_descendant_pre' - - 'blk_queue_for_each_rl' - 'bond_for_each_slave' - 'bond_for_each_slave_rcu' + - 'bpf__perf_for_each_map' + - 'bpf__perf_for_each_map_named' - 'bpf_for_each_spilled_reg' + - 'bpf_object__for_each_map' + - 'bpf_object__for_each_program' + - 'bpf_object__for_each_safe' + - 'bpf_perf_object__for_each' - 'btree_for_each_safe128' - 'btree_for_each_safe32' - 'btree_for_each_safe64' @@ -102,6 +119,7 @@ ForEachMacros: - 'card_for_each_dev' - 'cgroup_taskset_for_each' - 'cgroup_taskset_for_each_leader' + - 'cpufreq_for_each_efficient_entry_idx' - 'cpufreq_for_each_entry' - 'cpufreq_for_each_entry_idx' - 'cpufreq_for_each_valid_entry' @@ -109,9 +127,22 @@ ForEachMacros: - 'css_for_each_child' - 'css_for_each_descendant_post' - 'css_for_each_descendant_pre' + - 'damon_for_each_region' + - 'damon_for_each_region_safe' + - 'damon_for_each_scheme' + - 'damon_for_each_scheme_safe' + - 'damon_for_each_target' + - 'damon_for_each_target_safe' + - 'data__for_each_file' + - 'data__for_each_file_new' + - 'data__for_each_file_start' - 'device_for_each_child_node' - 'displayid_iter_for_each' + - 'dma_fence_array_for_each' - 'dma_fence_chain_for_each' + - 'dma_fence_unwrap_for_each' + - 'dma_resv_for_each_fence' + - 'dma_resv_for_each_fence_unlocked' - 'do_for_each_ftrace_op' - 'drm_atomic_crtc_for_each_plane' - 'drm_atomic_crtc_state_for_each_plane' @@ -135,6 +166,25 @@ ForEachMacros: - 'drm_mm_for_each_node' - 'drm_mm_for_each_node_in_range' - 'drm_mm_for_each_node_safe' + - 'dsa_switch_for_each_available_port' + - 'dsa_switch_for_each_cpu_port' + - 'dsa_switch_for_each_port' + - 'dsa_switch_for_each_port_continue_reverse' + - 'dsa_switch_for_each_port_safe' + - 'dsa_switch_for_each_user_port' + - 'dsa_tree_for_each_user_port' + - 'dso__for_each_symbol' + - 'dsos__for_each_with_build_id' + - 'elf_hash_for_each_possible' + - 'elf_section__for_each_rel' + - 'elf_section__for_each_rela' + - 'elf_symtab__for_each_symbol' + - 'evlist__for_each_cpu' + - 'evlist__for_each_entry' + - 'evlist__for_each_entry_continue' + - 'evlist__for_each_entry_from' + - 'evlist__for_each_entry_reverse' + - 'evlist__for_each_entry_safe' - 'flow_action_for_each' - 'for_each_acpi_dev_match' - 'for_each_active_dev_scope' @@ -142,8 +192,11 @@ ForEachMacros: - 'for_each_active_iommu' - 'for_each_aggr_pgid' - 'for_each_available_child_of_node' + - 'for_each_bench' - 'for_each_bio' - 'for_each_board_func_rsrc' + - 'for_each_btf_ext_rec' + - 'for_each_btf_ext_sec' - 'for_each_bvec' - 'for_each_card_auxs' - 'for_each_card_auxs_safe' @@ -159,17 +212,22 @@ ForEachMacros: - 'for_each_child_of_node' - 'for_each_clear_bit' - 'for_each_clear_bit_from' + - 'for_each_clear_bitrange' + - 'for_each_clear_bitrange_from' + - 'for_each_cmd' - 'for_each_cmsghdr' + - 'for_each_collection' + - 'for_each_comp_order' - 'for_each_compatible_node' - 'for_each_component_dais' - 'for_each_component_dais_safe' - - 'for_each_comp_order' - 'for_each_console' - 'for_each_cpu' - 'for_each_cpu_and' - 'for_each_cpu_not' - 'for_each_cpu_wrap' - 'for_each_dapm_widgets' + - 'for_each_dedup_cand' - 'for_each_dev_addr' - 'for_each_dev_scope' - 'for_each_dma_cap_mask' @@ -179,13 +237,14 @@ ForEachMacros: - 'for_each_dpcm_fe' - 'for_each_drhd_unit' - 'for_each_dss_dev' - - 'for_each_dtpm_table' - 'for_each_efi_memory_desc' - 'for_each_efi_memory_desc_in_map' - 'for_each_element' - 'for_each_element_extid' - 'for_each_element_id' - 'for_each_endpoint_of_node' + - 'for_each_event' + - 'for_each_event_tps' - 'for_each_evictable_lru' - 'for_each_fib6_node_rt_rcu' - 'for_each_fib6_walker_rt' @@ -194,30 +253,35 @@ ForEachMacros: - 'for_each_free_mem_range' - 'for_each_free_mem_range_reverse' - 'for_each_func_rsrc' + - 'for_each_group_evsel' + - 'for_each_group_member' - 'for_each_hstate' - 'for_each_if' + - 'for_each_inject_fn' + - 'for_each_insn' + - 'for_each_insn_prefix' + - 'for_each_intid' - 'for_each_iommu' - 'for_each_ip_tunnel_rcu' - 'for_each_irq_nr' + - 'for_each_lang' - 'for_each_link_codecs' - 'for_each_link_cpus' - 'for_each_link_platforms' - 'for_each_lru' - 'for_each_matching_node' - 'for_each_matching_node_and_match' - - 'for_each_member' - - 'for_each_memcg_cache_index' - 'for_each_mem_pfn_range' - - '__for_each_mem_range' - 'for_each_mem_range' - - '__for_each_mem_range_rev' - 'for_each_mem_range_rev' - 'for_each_mem_region' + - 'for_each_member' + - 'for_each_memory' - 'for_each_migratetype_order' - - 'for_each_msi_entry' - - 'for_each_msi_entry_safe' + - 'for_each_missing_reg' - 'for_each_net' - 'for_each_net_continue_reverse' + - 'for_each_net_rcu' - 'for_each_netdev' - 'for_each_netdev_continue' - 'for_each_netdev_continue_rcu' @@ -227,12 +291,13 @@ ForEachMacros: - 'for_each_netdev_rcu' - 'for_each_netdev_reverse' - 'for_each_netdev_safe' - - 'for_each_net_rcu' - 'for_each_new_connector_in_state' - 'for_each_new_crtc_in_state' - 'for_each_new_mst_mgr_in_state' - 'for_each_new_plane_in_state' + - 'for_each_new_plane_in_state_reverse' - 'for_each_new_private_obj_in_state' + - 'for_each_new_reg' - 'for_each_node' - 'for_each_node_by_name' - 'for_each_node_by_type' @@ -248,20 +313,20 @@ ForEachMacros: - 'for_each_old_connector_in_state' - 'for_each_old_crtc_in_state' - 'for_each_old_mst_mgr_in_state' + - 'for_each_old_plane_in_state' + - 'for_each_old_private_obj_in_state' - 'for_each_oldnew_connector_in_state' - 'for_each_oldnew_crtc_in_state' - 'for_each_oldnew_mst_mgr_in_state' - 'for_each_oldnew_plane_in_state' - 'for_each_oldnew_plane_in_state_reverse' - 'for_each_oldnew_private_obj_in_state' - - 'for_each_old_plane_in_state' - - 'for_each_old_private_obj_in_state' - 'for_each_online_cpu' - 'for_each_online_node' - 'for_each_online_pgdat' + - 'for_each_path' - 'for_each_pci_bridge' - 'for_each_pci_dev' - - 'for_each_pci_msi_entry' - 'for_each_pcm_streams' - 'for_each_physmem_range' - 'for_each_populated_zone' @@ -269,6 +334,7 @@ ForEachMacros: - 'for_each_present_cpu' - 'for_each_prime_number' - 'for_each_prime_number_from' + - 'for_each_probe_cache_entry' - 'for_each_process' - 'for_each_process_thread' - 'for_each_prop_codec_conf' @@ -278,6 +344,8 @@ ForEachMacros: - 'for_each_prop_dlc_cpus' - 'for_each_prop_dlc_platforms' - 'for_each_property_of_node' + - 'for_each_reg' + - 'for_each_reg_filtered' - 'for_each_registered_fb' - 'for_each_requested_gpio' - 'for_each_requested_gpio_in_range' @@ -287,8 +355,12 @@ ForEachMacros: - 'for_each_rtd_components' - 'for_each_rtd_cpu_dais' - 'for_each_rtd_dais' + - 'for_each_script' + - 'for_each_sec' - 'for_each_set_bit' - 'for_each_set_bit_from' + - 'for_each_set_bitrange' + - 'for_each_set_bitrange_from' - 'for_each_set_clump8' - 'for_each_sg' - 'for_each_sg_dma_page' @@ -297,18 +369,25 @@ ForEachMacros: - 'for_each_sgtable_dma_sg' - 'for_each_sgtable_page' - 'for_each_sgtable_sg' + - 'for_each_shell_test' - 'for_each_sibling_event' - 'for_each_subelement' - 'for_each_subelement_extid' - 'for_each_subelement_id' - - '__for_each_thread' + - 'for_each_sublist' + - 'for_each_subsystem' + - 'for_each_supported_activate_fn' + - 'for_each_supported_inject_fn' + - 'for_each_test' - 'for_each_thread' + - 'for_each_token' - 'for_each_unicast_dest_pgid' - 'for_each_vsi' - 'for_each_wakeup_source' - 'for_each_zone' - 'for_each_zone_zonelist' - 'for_each_zone_zonelist_nodemask' + - 'func_for_each_insn' - 'fwnode_for_each_available_child_node' - 'fwnode_for_each_child_node' - 'fwnode_graph_for_each_endpoint' @@ -322,7 +401,13 @@ ForEachMacros: - 'hash_for_each_possible_safe' - 'hash_for_each_rcu' - 'hash_for_each_safe' + - 'hashmap__for_each_entry' + - 'hashmap__for_each_entry_safe' + - 'hashmap__for_each_key_entry' + - 'hashmap__for_each_key_entry_safe' - 'hctx_for_each_ctx' + - 'hists__for_each_format' + - 'hists__for_each_sort_list' - 'hlist_bl_for_each_entry' - 'hlist_bl_for_each_entry_rcu' - 'hlist_bl_for_each_entry_safe' @@ -338,7 +423,6 @@ ForEachMacros: - 'hlist_for_each_entry_rcu_notrace' - 'hlist_for_each_entry_safe' - 'hlist_for_each_entry_srcu' - - '__hlist_for_each_rcu' - 'hlist_for_each_safe' - 'hlist_nulls_for_each_entry' - 'hlist_nulls_for_each_entry_from' @@ -346,9 +430,6 @@ ForEachMacros: - 'hlist_nulls_for_each_entry_safe' - 'i3c_bus_for_each_i2cdev' - 'i3c_bus_for_each_i3cdev' - - 'ide_host_for_each_port' - - 'ide_port_for_each_dev' - - 'ide_port_for_each_present_dev' - 'idr_for_each_entry' - 'idr_for_each_entry_continue' - 'idr_for_each_entry_continue_ul' @@ -356,7 +437,12 @@ ForEachMacros: - 'in_dev_for_each_ifa_rcu' - 'in_dev_for_each_ifa_rtnl' - 'inet_bind_bucket_for_each' + - 'inet_lhash2_for_each_icsk' + - 'inet_lhash2_for_each_icsk_continue' - 'inet_lhash2_for_each_icsk_rcu' + - 'intlist__for_each_entry' + - 'intlist__for_each_entry_safe' + - 'kcore_copy__for_each_phdr' - 'key_for_each' - 'key_for_each_safe' - 'klp_for_each_func' @@ -367,7 +453,9 @@ ForEachMacros: - 'klp_for_each_object_static' - 'kunit_suite_for_each_test_case' - 'kvm_for_each_memslot' + - 'kvm_for_each_memslot_in_gfn_range' - 'kvm_for_each_vcpu' + - 'libbpf_nla_for_each_attr' - 'list_for_each' - 'list_for_each_codec' - 'list_for_each_codec_safe' @@ -387,6 +475,7 @@ ForEachMacros: - 'list_for_each_entry_safe_from' - 'list_for_each_entry_safe_reverse' - 'list_for_each_entry_srcu' + - 'list_for_each_from' - 'list_for_each_prev' - 'list_for_each_prev_safe' - 'list_for_each_safe' @@ -394,11 +483,18 @@ ForEachMacros: - 'llist_for_each_entry' - 'llist_for_each_entry_safe' - 'llist_for_each_safe' + - 'map__for_each_symbol' + - 'map__for_each_symbol_by_name' + - 'map_for_each_event' + - 'map_for_each_metric' + - 'maps__for_each_entry' + - 'maps__for_each_entry_safe' - 'mci_for_each_dimm' - 'media_device_for_each_entity' - 'media_device_for_each_intf' - 'media_device_for_each_link' - 'media_device_for_each_pad' + - 'msi_for_each_desc' - 'nanddev_io_for_each_page' - 'netdev_for_each_lower_dev' - 'netdev_for_each_lower_private' @@ -423,6 +519,20 @@ ForEachMacros: - 'pcl_for_each_chunk' - 'pcl_for_each_segment' - 'pcm_for_each_format' + - 'perf_config_items__for_each_entry' + - 'perf_config_sections__for_each_entry' + - 'perf_config_set__for_each_entry' + - 'perf_cpu_map__for_each_cpu' + - 'perf_evlist__for_each_entry' + - 'perf_evlist__for_each_entry_reverse' + - 'perf_evlist__for_each_entry_safe' + - 'perf_evlist__for_each_evsel' + - 'perf_evlist__for_each_mmap' + - 'perf_hpp_list__for_each_format' + - 'perf_hpp_list__for_each_format_safe' + - 'perf_hpp_list__for_each_sort_list' + - 'perf_hpp_list__for_each_sort_list_safe' + - 'perf_pmu__for_each_hybrid_pmu' - 'ping_portaddr_for_each_entry' - 'plist_for_each' - 'plist_for_each_continue' @@ -442,6 +552,7 @@ ForEachMacros: - 'rdma_for_each_block' - 'rdma_for_each_port' - 'rdma_umem_for_each_dma_block' + - 'resort_rb__for_each_entry' - 'resource_list_for_each_entry' - 'resource_list_for_each_entry_safe' - 'rhl_for_each_entry_rcu' @@ -455,15 +566,18 @@ ForEachMacros: - 'rht_for_each_from' - 'rht_for_each_rcu' - 'rht_for_each_rcu_from' - - '__rq_for_each_bio' - 'rq_for_each_bvec' - 'rq_for_each_segment' + - 'rq_list_for_each' + - 'rq_list_for_each_safe' - 'scsi_for_each_prot_sg' - 'scsi_for_each_sg' - 'sctp_for_each_hentry' - 'sctp_skb_for_each' + - 'sec_for_each_insn' + - 'sec_for_each_insn_continue' + - 'sec_for_each_insn_from' - 'shdma_for_each_chan' - - '__shost_for_each_device' - 'shost_for_each_device' - 'sk_for_each' - 'sk_for_each_bound' @@ -480,7 +594,13 @@ ForEachMacros: - 'snd_soc_dapm_widget_for_each_path_safe' - 'snd_soc_dapm_widget_for_each_sink_path' - 'snd_soc_dapm_widget_for_each_source_path' + - 'strlist__for_each_entry' + - 'strlist__for_each_entry_safe' + - 'sym_for_each_insn' + - 'sym_for_each_insn_continue_reverse' + - 'symbols__for_each_entry' - 'tb_property_for_each' + - 'tcf_act_for_each_action' - 'tcf_exts_for_each_action' - 'udp_portaddr_for_each_entry' - 'udp_portaddr_for_each_entry_rcu' @@ -504,15 +624,17 @@ ForEachMacros: - 'xbc_node_for_each_array_value' - 'xbc_node_for_each_child' - 'xbc_node_for_each_key_value' + - 'xbc_node_for_each_subkey' - 'zorro_for_each_dev' -#IncludeBlocks: Preserve # Unknown to clang-format-5.0 +IncludeBlocks: Preserve IncludeCategories: - Regex: '.*' Priority: 1 IncludeIsMainRegex: '(Test)?$' IndentCaseLabels: false -#IndentPPDirectives: None # Unknown to clang-format-5.0 +IndentGotoLabels: false +IndentPPDirectives: None IndentWidth: 8 IndentWrappedFunctionNames: false JavaScriptQuotes: Leave @@ -522,13 +644,13 @@ MacroBlockBegin: '' MacroBlockEnd: '' MaxEmptyLinesToKeep: 1 NamespaceIndentation: None -#ObjCBinPackProtocolList: Auto # Unknown to clang-format-5.0 +ObjCBinPackProtocolList: Auto ObjCBlockIndentWidth: 8 ObjCSpaceAfterProperty: true ObjCSpaceBeforeProtocolList: true # Taken from git's rules -#PenaltyBreakAssignment: 10 # Unknown to clang-format-4.0 +PenaltyBreakAssignment: 10 PenaltyBreakBeforeFirstCallParameter: 30 PenaltyBreakComment: 10 PenaltyBreakFirstLessLess: 0 @@ -539,14 +661,14 @@ PenaltyReturnTypeOnItsOwnLine: 60 PointerAlignment: Right ReflowComments: false SortIncludes: false -#SortUsingDeclarations: false # Unknown to clang-format-4.0 +SortUsingDeclarations: false SpaceAfterCStyleCast: false SpaceAfterTemplateKeyword: true SpaceBeforeAssignmentOperators: true -#SpaceBeforeCtorInitializerColon: true # Unknown to clang-format-5.0 -#SpaceBeforeInheritanceColon: true # Unknown to clang-format-5.0 -SpaceBeforeParens: ControlStatements -#SpaceBeforeRangeBasedForLoopColon: true # Unknown to clang-format-5.0 +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatementsExceptForEachMacros +SpaceBeforeRangeBasedForLoopColon: true SpaceInEmptyParentheses: false SpacesBeforeTrailingComments: 1 SpacesInAngles: false diff --git a/Documentation/ABI/testing/debugfs-hisi-hpre b/Documentation/ABI/testing/debugfs-hisi-hpre index 396de7bc735d0f6878788ef33d1a2ef29e56388c..82abf92df429fdafa8001f44cca91fa17d51519c 100644 --- a/Documentation/ABI/testing/debugfs-hisi-hpre +++ b/Documentation/ABI/testing/debugfs-hisi-hpre @@ -104,6 +104,20 @@ Description: Dump the status of the QM. Four states: initiated, started, stopped and closed. Available for both PF and VF, and take no other effect on HPRE. +What: /sys/kernel/debug/hisi_hpre//qm/diff_regs +Date: Mar 2022 +Contact: linux-crypto@vger.kernel.org +Description: QM debug registers(regs) read hardware register value. This + node is used to show the change of the qm register values. This + node can be help users to check the change of register values. + +What: /sys/kernel/debug/hisi_hpre//hpre_dfx/diff_regs +Date: Mar 2022 +Contact: linux-crypto@vger.kernel.org +Description: HPRE debug registers(regs) read hardware register value. This + node is used to show the change of the register values. This + node can be help users to check the change of register values. + What: /sys/kernel/debug/hisi_hpre//hpre_dfx/send_cnt Date: Apr 2020 Contact: linux-crypto@vger.kernel.org diff --git a/Documentation/ABI/testing/debugfs-hisi-sec b/Documentation/ABI/testing/debugfs-hisi-sec index 2bf84ced484b755a9a343534bb992af7b19f3ef8..93c530d1bf0fcb096f1620df5e73dc40689f5cc5 100644 --- a/Documentation/ABI/testing/debugfs-hisi-sec +++ b/Documentation/ABI/testing/debugfs-hisi-sec @@ -84,6 +84,20 @@ Description: Dump the status of the QM. Four states: initiated, started, stopped and closed. Available for both PF and VF, and take no other effect on SEC. +What: /sys/kernel/debug/hisi_sec2//qm/diff_regs +Date: Mar 2022 +Contact: linux-crypto@vger.kernel.org +Description: QM debug registers(regs) read hardware register value. This + node is used to show the change of the qm register values. This + node can be help users to check the change of register values. + +What: /sys/kernel/debug/hisi_sec2//sec_dfx/diff_regs +Date: Mar 2022 +Contact: linux-crypto@vger.kernel.org +Description: SEC debug registers(regs) read hardware register value. This + node is used to show the change of the register values. This + node can be help users to check the change of register values. + What: /sys/kernel/debug/hisi_sec2//sec_dfx/send_cnt Date: Apr 2020 Contact: linux-crypto@vger.kernel.org diff --git a/Documentation/ABI/testing/debugfs-hisi-zip b/Documentation/ABI/testing/debugfs-hisi-zip index bf1258bc64959a9b9cfa212fef04f7d85c5cdd13..fd3f314cf8d1c73f4a84c590db7fc978362aa654 100644 --- a/Documentation/ABI/testing/debugfs-hisi-zip +++ b/Documentation/ABI/testing/debugfs-hisi-zip @@ -97,6 +97,20 @@ Description: Dump the status of the QM. Four states: initiated, started, stopped and closed. Available for both PF and VF, and take no other effect on ZIP. +What: /sys/kernel/debug/hisi_zip//qm/diff_regs +Date: Mar 2022 +Contact: linux-crypto@vger.kernel.org +Description: QM debug registers(regs) read hardware register value. This + node is used to show the change of the qm registers value. This + node can be help users to check the change of register values. + +What: /sys/kernel/debug/hisi_zip//zip_dfx/diff_regs +Date: Mar 2022 +Contact: linux-crypto@vger.kernel.org +Description: ZIP debug registers(regs) read hardware register value. This + node is used to show the change of the registers value. this + node can be help users to check the change of register values. + What: /sys/kernel/debug/hisi_zip//zip_dfx/send_cnt Date: Apr 2020 Contact: linux-crypto@vger.kernel.org diff --git a/Documentation/ABI/testing/sysfs-class-cxl b/Documentation/ABI/testing/sysfs-class-cxl index 3c77677e0ca74d4091102aeaaec5b9af45fd7159..594fda2541306a9b4514f87dfae641f310cec399 100644 --- a/Documentation/ABI/testing/sysfs-class-cxl +++ b/Documentation/ABI/testing/sysfs-class-cxl @@ -103,8 +103,8 @@ What: /sys/class/cxl//api_version_compatible Date: September 2014 Contact: linuxppc-dev@lists.ozlabs.org Description: read only - Decimal value of the the lowest version of the userspace API - this this kernel supports. + Decimal value of the lowest version of the userspace API + this kernel supports. Users: https://github.com/ibm-capi/libcxl diff --git a/Documentation/ABI/testing/sysfs-driver-ccp b/Documentation/ABI/testing/sysfs-driver-ccp new file mode 100644 index 0000000000000000000000000000000000000000..7aded9b7555350297cd29bd9d10d57f35810676d --- /dev/null +++ b/Documentation/ABI/testing/sysfs-driver-ccp @@ -0,0 +1,87 @@ +What: /sys/bus/pci/devices//fused_part +Date: June 2022 +KernelVersion: 5.19 +Contact: mario.limonciello@amd.com +Description: + The /sys/bus/pci/devices//fused_part file reports + whether the CPU or APU has been fused to prevent tampering. + 0: Not fused + 1: Fused + +What: /sys/bus/pci/devices//debug_lock_on +Date: June 2022 +KernelVersion: 5.19 +Contact: mario.limonciello@amd.com +Description: + The /sys/bus/pci/devices//debug_lock_on reports + whether the AMD CPU or APU has been unlocked for debugging. + Possible values: + 0: Not locked + 1: Locked + +What: /sys/bus/pci/devices//tsme_status +Date: June 2022 +KernelVersion: 5.19 +Contact: mario.limonciello@amd.com +Description: + The /sys/bus/pci/devices//tsme_status file reports + the status of transparent secure memory encryption on AMD systems. + Possible values: + 0: Not active + 1: Active + +What: /sys/bus/pci/devices//anti_rollback_status +Date: June 2022 +KernelVersion: 5.19 +Contact: mario.limonciello@amd.com +Description: + The /sys/bus/pci/devices//anti_rollback_status file reports + whether the PSP is enforcing rollback protection. + Possible values: + 0: Not enforcing + 1: Enforcing + +What: /sys/bus/pci/devices//rpmc_production_enabled +Date: June 2022 +KernelVersion: 5.19 +Contact: mario.limonciello@amd.com +Description: + The /sys/bus/pci/devices//rpmc_production_enabled file reports + whether Replay Protected Monotonic Counter support has been enabled. + Possible values: + 0: Not enabled + 1: Enabled + +What: /sys/bus/pci/devices//rpmc_spirom_available +Date: June 2022 +KernelVersion: 5.19 +Contact: mario.limonciello@amd.com +Description: + The /sys/bus/pci/devices//rpmc_spirom_available file reports + whether an Replay Protected Monotonic Counter supported SPI is installed + on the system. + Possible values: + 0: Not present + 1: Present + +What: /sys/bus/pci/devices//hsp_tpm_available +Date: June 2022 +KernelVersion: 5.19 +Contact: mario.limonciello@amd.com +Description: + The /sys/bus/pci/devices//hsp_tpm_available file reports + whether the HSP TPM has been activated. + Possible values: + 0: Not activated or present + 1: Activated + +What: /sys/bus/pci/devices//rom_armor_enforced +Date: June 2022 +KernelVersion: 5.19 +Contact: mario.limonciello@amd.com +Description: + The /sys/bus/pci/devices//rom_armor_enforced file reports + whether RomArmor SPI protection is enforced. + Possible values: + 0: Not enforced + 1: Enforced diff --git a/Documentation/admin-guide/bootconfig.rst b/Documentation/admin-guide/bootconfig.rst index a1860fc0ca88ad0152464e8e96fc3a89acb5d59f..d99994345d41d7a95f19269ce7626b0c18970f27 100644 --- a/Documentation/admin-guide/bootconfig.rst +++ b/Documentation/admin-guide/bootconfig.rst @@ -158,9 +158,15 @@ Each key-value pair is shown in each line with following style:: Boot Kernel With a Boot Config ============================== -Since the boot configuration file is loaded with initrd, it will be added -to the end of the initrd (initramfs) image file with padding, size, -checksum and 12-byte magic word as below. +There are two options to boot the kernel with bootconfig: attaching the +bootconfig to the initrd image or embedding it in the kernel itself. + +Attaching a Boot Config to Initrd +--------------------------------- + +Since the boot configuration file is loaded with initrd by default, +it will be added to the end of the initrd (initramfs) image file with +padding, size, checksum and 12-byte magic word as below. [initrd][bootconfig][padding][size(le32)][checksum(le32)][#BOOTCONFIG\n] @@ -196,6 +202,25 @@ To remove the config from the image, you can use -d option as below:: Then add "bootconfig" on the normal kernel command line to tell the kernel to look for the bootconfig at the end of the initrd file. +Embedding a Boot Config into Kernel +----------------------------------- + +If you can not use initrd, you can also embed the bootconfig file in the +kernel by Kconfig options. In this case, you need to recompile the kernel +with the following configs:: + + CONFIG_BOOT_CONFIG_EMBED=y + CONFIG_BOOT_CONFIG_EMBED_FILE="/PATH/TO/BOOTCONFIG/FILE" + +``CONFIG_BOOT_CONFIG_EMBED_FILE`` requires an absolute path or a relative +path to the bootconfig file from source tree or object tree. +The kernel will embed it as the default bootconfig. + +Just as when attaching the bootconfig to the initrd, you need ``bootconfig`` +option on the kernel command line to enable the embedded bootconfig. + +Note that even if you set this option, you can override the embedded +bootconfig by another bootconfig which attached to the initrd. Kernel parameters via Boot Config ================================= diff --git a/Documentation/admin-guide/pm/intel-speed-select.rst b/Documentation/admin-guide/pm/intel-speed-select.rst index 0a1fbdb54bfe9fe8fb09396a175d71a46d752bab..a2bfb971654f84745d78f8d3bdfa95e45037b209 100644 --- a/Documentation/admin-guide/pm/intel-speed-select.rst +++ b/Documentation/admin-guide/pm/intel-speed-select.rst @@ -262,6 +262,28 @@ Which shows that the base frequency now increased from 2600 MHz at performance level 0 to 2800 MHz at performance level 4. As a result, any workload, which can use fewer CPUs, can see a boost of 200 MHz compared to performance level 0. +Changing performance level via BMC Interface +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +It is possible to change SST-PP level using out of band (OOB) agent (Via some +remote management console, through BMC "Baseboard Management Controller" +interface). This mode is supported from the Sapphire Rapids processor +generation. The kernel and tool change to support this mode is added to Linux +kernel version 5.18. To enable this feature, kernel config +"CONFIG_INTEL_HFI_THERMAL" is required. The minimum version of the tool +is "v1.12" to support this feature, which is part of Linux kernel version 5.18. + +To support such configuration, this tool can be used as a daemon. Add +a command line option --oob:: + + # intel-speed-select --oob + Intel(R) Speed Select Technology + Executing on CPU model:143[0x8f] + OOB mode is enabled and will run as daemon + +In this mode the tool will online/offline CPUs based on the new performance +level. + Check presence of other Intel(R) SST features --------------------------------------------- diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,mt8186-clock.yaml b/Documentation/devicetree/bindings/arm/mediatek/mediatek,mt8186-clock.yaml new file mode 100644 index 0000000000000000000000000000000000000000..cf1002c3efa6fbfc260ec3a1b6633686e0340bce --- /dev/null +++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,mt8186-clock.yaml @@ -0,0 +1,56 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: "http://devicetree.org/schemas/arm/mediatek/mediatek,mt8186-clock.yaml#" +$schema: "http://devicetree.org/meta-schemas/core.yaml#" + +title: MediaTek Functional Clock Controller for MT8186 + +maintainers: + - Chun-Jie Chen + +description: | + The clock architecture in MediaTek like below + PLLs --> + dividers --> + muxes + --> + clock gate + + The devices provide clock gate control in different IP blocks. + +properties: + compatible: + items: + - enum: + - mediatek,mt8186-imp_iic_wrap + - mediatek,mt8186-mfgsys + - mediatek,mt8186-wpesys + - mediatek,mt8186-imgsys1 + - mediatek,mt8186-imgsys2 + - mediatek,mt8186-vdecsys + - mediatek,mt8186-vencsys + - mediatek,mt8186-camsys + - mediatek,mt8186-camsys_rawa + - mediatek,mt8186-camsys_rawb + - mediatek,mt8186-mdpsys + - mediatek,mt8186-ipesys + reg: + maxItems: 1 + + '#clock-cells': + const: 1 + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + imp_iic_wrap: clock-controller@11017000 { + compatible = "mediatek,mt8186-imp_iic_wrap"; + reg = <0x11017000 0x1000>; + #clock-cells = <1>; + }; diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,mt8186-sys-clock.yaml b/Documentation/devicetree/bindings/arm/mediatek/mediatek,mt8186-sys-clock.yaml new file mode 100644 index 0000000000000000000000000000000000000000..0886e2e335bb1b97e6dab9f1e1de39f755b58345 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,mt8186-sys-clock.yaml @@ -0,0 +1,54 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: "http://devicetree.org/schemas/arm/mediatek/mediatek,mt8186-sys-clock.yaml#" +$schema: "http://devicetree.org/meta-schemas/core.yaml#" + +title: MediaTek System Clock Controller for MT8186 + +maintainers: + - Chun-Jie Chen + +description: | + The clock architecture in MediaTek like below + PLLs --> + dividers --> + muxes + --> + clock gate + + The apmixedsys provides most of PLLs which generated from SoC 26m. + The topckgen provides dividers and muxes which provide the clock source to other IP blocks. + The infracfg_ao provides clock gate in peripheral and infrastructure IP blocks. + The mcusys provides mux control to select the clock source in AP MCU. + The device nodes also provide the system control capacity for configuration. + +properties: + compatible: + items: + - enum: + - mediatek,mt8186-mcusys + - mediatek,mt8186-topckgen + - mediatek,mt8186-infracfg_ao + - mediatek,mt8186-apmixedsys + - const: syscon + + reg: + maxItems: 1 + + '#clock-cells': + const: 1 + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + topckgen: syscon@10000000 { + compatible = "mediatek,mt8186-topckgen", "syscon"; + reg = <0x10000000 0x1000>; + #clock-cells = <1>; + }; diff --git a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra-ccplex-cluster.yaml b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra-ccplex-cluster.yaml new file mode 100644 index 0000000000000000000000000000000000000000..8c6543b5c0dc276f9b3f7a93f00040adf7f6b775 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra-ccplex-cluster.yaml @@ -0,0 +1,52 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: "http://devicetree.org/schemas/arm/tegra/nvidia,tegra-ccplex-cluster.yaml#" +$schema: "http://devicetree.org/meta-schemas/core.yaml#" + +title: NVIDIA Tegra CPU COMPLEX CLUSTER area device tree bindings + +maintainers: + - Sumit Gupta + - Mikko Perttunen + - Jon Hunter + - Thierry Reding + +description: |+ + The Tegra CPU COMPLEX CLUSTER area contains memory-mapped + registers that initiate CPU frequency/voltage transitions. + +properties: + $nodename: + pattern: "ccplex@([0-9a-f]+)$" + + compatible: + enum: + - nvidia,tegra186-ccplex-cluster + - nvidia,tegra234-ccplex-cluster + + reg: + maxItems: 1 + + nvidia,bpmp: + $ref: '/schemas/types.yaml#/definitions/phandle' + description: | + Specifies the BPMP node that needs to be queried to get + operating point data for all CPUs. + +additionalProperties: false + +required: + - compatible + - reg + - nvidia,bpmp + - status + +examples: + - | + ccplex@e000000 { + compatible = "nvidia,tegra234-ccplex-cluster"; + reg = <0x0e000000 0x5ffff>; + nvidia,bpmp = <&bpmp>; + status = "okay"; + }; diff --git a/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml b/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml new file mode 100644 index 0000000000000000000000000000000000000000..d60e746548097cf29de7d9d70b2956e02b6aad42 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml @@ -0,0 +1,58 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/airoha,en7523-scu.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: EN7523 Clock Device Tree Bindings + +maintainers: + - Felix Fietkau + - John Crispin + +description: | + This node defines the System Control Unit of the EN7523 SoC, + a collection of registers configuring many different aspects of the SoC. + + The clock driver uses it to read and configure settings of the + PLL controller, which provides clocks for the CPU, the bus and + other SoC internal peripherals. + + Each clock is assigned an identifier and client nodes use this identifier + to specify which clock they consume. + + All these identifiers can be found in: + [1]: . + + The clocks are provided inside a system controller node. + +properties: + compatible: + items: + - const: airoha,en7523-scu + + reg: + maxItems: 2 + + "#clock-cells": + description: + The first cell indicates the clock number, see [1] for available + clocks. + const: 1 + +required: + - compatible + - reg + - '#clock-cells' + +additionalProperties: false + +examples: + - | + #include + scu: system-controller@1fa20000 { + compatible = "airoha,en7523-scu"; + reg = <0x1fa20000 0x400>, + <0x1fb00000 0x1000>; + #clock-cells = <1>; + }; diff --git a/Documentation/devicetree/bindings/clock/clock-bindings.txt b/Documentation/devicetree/bindings/clock/clock-bindings.txt index f2ea53832ac63eac9f34b5db49ff3995d23e6522..6fe541368889ec530c1a8a5a73ddecc44d18031e 100644 --- a/Documentation/devicetree/bindings/clock/clock-bindings.txt +++ b/Documentation/devicetree/bindings/clock/clock-bindings.txt @@ -1,186 +1,2 @@ -This binding is a work-in-progress, and are based on some experimental -work by benh[1]. - -Sources of clock signal can be represented by any node in the device -tree. Those nodes are designated as clock providers. Clock consumer -nodes use a phandle and clock specifier pair to connect clock provider -outputs to clock inputs. Similar to the gpio specifiers, a clock -specifier is an array of zero, one or more cells identifying the clock -output on a device. The length of a clock specifier is defined by the -value of a #clock-cells property in the clock provider node. - -[1] https://patchwork.ozlabs.org/patch/31551/ - -==Clock providers== - -Required properties: -#clock-cells: Number of cells in a clock specifier; Typically 0 for nodes - with a single clock output and 1 for nodes with multiple - clock outputs. - -Optional properties: -clock-output-names: Recommended to be a list of strings of clock output signal - names indexed by the first cell in the clock specifier. - However, the meaning of clock-output-names is domain - specific to the clock provider, and is only provided to - encourage using the same meaning for the majority of clock - providers. This format may not work for clock providers - using a complex clock specifier format. In those cases it - is recommended to omit this property and create a binding - specific names property. - - Clock consumer nodes must never directly reference - the provider's clock-output-names property. - -For example: - - oscillator { - #clock-cells = <1>; - clock-output-names = "ckil", "ckih"; - }; - -- this node defines a device with two clock outputs, the first named - "ckil" and the second named "ckih". Consumer nodes always reference - clocks by index. The names should reflect the clock output signal - names for the device. - -clock-indices: If the identifying number for the clocks in the node - is not linear from zero, then this allows the mapping of - identifiers into the clock-output-names array. - -For example, if we have two clocks <&oscillator 1> and <&oscillator 3>: - - oscillator { - compatible = "myclocktype"; - #clock-cells = <1>; - clock-indices = <1>, <3>; - clock-output-names = "clka", "clkb"; - } - - This ensures we do not have any empty strings in clock-output-names - - -==Clock consumers== - -Required properties: -clocks: List of phandle and clock specifier pairs, one pair - for each clock input to the device. Note: if the - clock provider specifies '0' for #clock-cells, then - only the phandle portion of the pair will appear. - -Optional properties: -clock-names: List of clock input name strings sorted in the same - order as the clocks property. Consumers drivers - will use clock-names to match clock input names - with clocks specifiers. -clock-ranges: Empty property indicating that child nodes can inherit named - clocks from this node. Useful for bus nodes to provide a - clock to their children. - -For example: - - device { - clocks = <&osc 1>, <&ref 0>; - clock-names = "baud", "register"; - }; - - -This represents a device with two clock inputs, named "baud" and "register". -The baud clock is connected to output 1 of the &osc device, and the register -clock is connected to output 0 of the &ref. - -==Example== - - /* external oscillator */ - osc: oscillator { - compatible = "fixed-clock"; - #clock-cells = <0>; - clock-frequency = <32678>; - clock-output-names = "osc"; - }; - - /* phase-locked-loop device, generates a higher frequency clock - * from the external oscillator reference */ - pll: pll@4c000 { - compatible = "vendor,some-pll-interface" - #clock-cells = <1>; - clocks = <&osc 0>; - clock-names = "ref"; - reg = <0x4c000 0x1000>; - clock-output-names = "pll", "pll-switched"; - }; - - /* UART, using the low frequency oscillator for the baud clock, - * and the high frequency switched PLL output for register - * clocking */ - uart@a000 { - compatible = "fsl,imx-uart"; - reg = <0xa000 0x1000>; - interrupts = <33>; - clocks = <&osc 0>, <&pll 1>; - clock-names = "baud", "register"; - }; - -This DT fragment defines three devices: an external oscillator to provide a -low-frequency reference clock, a PLL device to generate a higher frequency -clock signal, and a UART. - -* The oscillator is fixed-frequency, and provides one clock output, named "osc". -* The PLL is both a clock provider and a clock consumer. It uses the clock - signal generated by the external oscillator, and provides two output signals - ("pll" and "pll-switched"). -* The UART has its baud clock connected the external oscillator and its - register clock connected to the PLL clock (the "pll-switched" signal) - -==Assigned clock parents and rates== - -Some platforms may require initial configuration of default parent clocks -and clock frequencies. Such a configuration can be specified in a device tree -node through assigned-clocks, assigned-clock-parents and assigned-clock-rates -properties. The assigned-clock-parents property should contain a list of parent -clocks in the form of a phandle and clock specifier pair and the -assigned-clock-rates property should contain a list of frequencies in Hz. Both -these properties should correspond to the clocks listed in the assigned-clocks -property. - -To skip setting parent or rate of a clock its corresponding entry should be -set to 0, or can be omitted if it is not followed by any non-zero entry. - - uart@a000 { - compatible = "fsl,imx-uart"; - reg = <0xa000 0x1000>; - ... - clocks = <&osc 0>, <&pll 1>; - clock-names = "baud", "register"; - - assigned-clocks = <&clkcon 0>, <&pll 2>; - assigned-clock-parents = <&pll 2>; - assigned-clock-rates = <0>, <460800>; - }; - -In this example the <&pll 2> clock is set as parent of clock <&clkcon 0> and -the <&pll 2> clock is assigned a frequency value of 460800 Hz. - -Configuring a clock's parent and rate through the device node that consumes -the clock can be done only for clocks that have a single user. Specifying -conflicting parent or rate configuration in multiple consumer nodes for -a shared clock is forbidden. - -Configuration of common clocks, which affect multiple consumer devices can -be similarly specified in the clock provider node. - -==Protected clocks== - -Some platforms or firmwares may not fully expose all the clocks to the OS, such -as in situations where those clks are used by drivers running in ARM secure -execution levels. Such a configuration can be specified in device tree with the -protected-clocks property in the form of a clock specifier list. This property should -only be specified in the node that is providing the clocks being protected: - - clock-controller@a000f000 { - compatible = "vendor,clk95; - reg = <0xa000f000 0x1000> - #clocks-cells = <1>; - ... - protected-clocks = , ; - }; +This file has moved to the clock binding schema: +https://github.com/devicetree-org/dt-schema/blob/main/dtschema/schemas/clock/clock.yaml diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-apq8064.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-apq8064.yaml index 97936411b6b4b55762c37d34756bf6ae417ce982..9fafcb0800691b918395673a7996d1c547c216e7 100644 --- a/Documentation/devicetree/bindings/clock/qcom,gcc-apq8064.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,gcc-apq8064.yaml @@ -20,12 +20,10 @@ description: | See also: - dt-bindings/clock/qcom,gcc-msm8960.h - dt-bindings/reset/qcom,gcc-msm8960.h - - dt-bindings/clock/qcom,gcc-apq8084.h - - dt-bindings/reset/qcom,gcc-apq8084.h properties: compatible: - const: qcom,gcc-apq8084 + const: qcom,gcc-apq8064 nvmem-cells: minItems: 1 diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-apq8084.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-apq8084.yaml new file mode 100644 index 0000000000000000000000000000000000000000..397fb918e0324183eb65af6030faa6a44d687578 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/qcom,gcc-apq8084.yaml @@ -0,0 +1,42 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/qcom,gcc-apq8084.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Global Clock & Reset Controller Binding for APQ8084 + +maintainers: + - Stephen Boyd + - Taniya Das + +description: | + Qualcomm global clock control module which supports the clocks, resets and + power domains on APQ8084. + + See also:: + - dt-bindings/clock/qcom,gcc-apq8084.h + - dt-bindings/reset/qcom,gcc-apq8084.h + +allOf: + - $ref: qcom,gcc.yaml# + +properties: + compatible: + const: qcom,gcc-apq8084 + +required: + - compatible + +unevaluatedProperties: false + +examples: + - | + clock-controller@fc400000 { + compatible = "qcom,gcc-apq8084"; + reg = <0xfc400000 0x4000>; + #clock-cells = <1>; + #reset-cells = <1>; + #power-domain-cells = <1>; + }; +... diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-sc8280xp.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-sc8280xp.yaml new file mode 100644 index 0000000000000000000000000000000000000000..0bcdc69c6f8964811206b90d1727fcfc32ef7306 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/qcom,gcc-sc8280xp.yaml @@ -0,0 +1,128 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/qcom,gcc-sc8280xp.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Global Clock & Reset Controller Binding for SC8280xp + +maintainers: + - Bjorn Andersson + +description: | + Qualcomm global clock control module which supports the clocks, resets and + power domains on SC8280xp. + + See also: + - include/dt-bindings/clock/qcom,gcc-sc8280xp.h + +properties: + compatible: + const: qcom,gcc-sc8280xp + + clocks: + items: + - description: XO reference clock + - description: Sleep clock + - description: UFS memory first RX symbol clock + - description: UFS memory second RX symbol clock + - description: UFS memory first TX symbol clock + - description: UFS card first RX symbol clock + - description: UFS card second RX symbol clock + - description: UFS card first TX symbol clock + - description: Primary USB SuperSpeed pipe clock + - description: USB4 PHY pipegmux clock source + - description: USB4 PHY DP gmux clock source + - description: USB4 PHY sys piegmux clock source + - description: USB4 PHY PCIe pipe clock + - description: USB4 PHY router max pipe clock + - description: Primary USB4 RX0 clock + - description: Primary USB4 RX1 clock + - description: Secondary USB SuperSpeed pipe clock + - description: Second USB4 PHY pipegmux clock source + - description: Second USB4 PHY DP gmux clock source + - description: Second USB4 PHY sys pipegmux clock source + - description: Second USB4 PHY PCIe pipe clock + - description: Second USB4 PHY router max pipe clock + - description: Secondary USB4 RX0 clock + - description: Secondary USB4 RX1 clock + - description: Multiport USB first SupserSpeed pipe clock + - description: Multiport USB second SuperSpeed pipe clock + - description: PCIe 2a pipe clock + - description: PCIe 2b pipe clock + - description: PCIe 3a pipe clock + - description: PCIe 3b pipe clock + - description: PCIe 4 pipe clock + - description: First EMAC controller reference clock + - description: Second EMAC controller reference clock + + '#clock-cells': + const: 1 + + '#reset-cells': + const: 1 + + '#power-domain-cells': + const: 1 + + reg: + maxItems: 1 + + protected-clocks: + maxItems: 389 + +required: + - compatible + - clocks + - reg + - '#clock-cells' + - '#reset-cells' + - '#power-domain-cells' + +additionalProperties: false + +examples: + - | + #include + clock-controller@100000 { + compatible = "qcom,gcc-sc8280xp"; + reg = <0x00100000 0x1f0000>; + clocks = <&rpmhcc RPMH_CXO_CLK>, + <&sleep_clk>, + <&ufs_phy_rx_symbol_0_clk>, + <&ufs_phy_rx_symbol_1_clk>, + <&ufs_phy_tx_symbol_0_clk>, + <&ufs_card_rx_symbol_0_clk>, + <&ufs_card_rx_symbol_1_clk>, + <&ufs_card_tx_symbol_0_clk>, + <&usb_0_ssphy>, + <&gcc_usb4_phy_pipegmux_clk_src>, + <&gcc_usb4_phy_dp_gmux_clk_src>, + <&gcc_usb4_phy_sys_pipegmux_clk_src>, + <&usb4_phy_gcc_usb4_pcie_pipe_clk>, + <&usb4_phy_gcc_usb4rtr_max_pipe_clk>, + <&qusb4phy_gcc_usb4_rx0_clk>, + <&qusb4phy_gcc_usb4_rx1_clk>, + <&usb_1_ssphy>, + <&gcc_usb4_1_phy_pipegmux_clk_src>, + <&gcc_usb4_1_phy_dp_gmux_clk_src>, + <&gcc_usb4_1_phy_sys_pipegmux_clk_src>, + <&usb4_1_phy_gcc_usb4_pcie_pipe_clk>, + <&usb4_1_phy_gcc_usb4rtr_max_pipe_clk>, + <&qusb4phy_1_gcc_usb4_rx0_clk>, + <&qusb4phy_1_gcc_usb4_rx1_clk>, + <&usb_2_ssphy>, + <&usb_3_ssphy>, + <&pcie2a_lane>, + <&pcie2b_lane>, + <&pcie3a_lane>, + <&pcie3b_lane>, + <&pcie4_lane>, + <&rxc0_ref_clk>, + <&rxc1_ref_clk>; + + #clock-cells = <1>; + #reset-cells = <1>; + #power-domain-cells = <1>; + }; +... diff --git a/Documentation/devicetree/bindings/clock/qcom,rpmcc.txt b/Documentation/devicetree/bindings/clock/qcom,rpmcc.txt deleted file mode 100644 index da295c3c004bec763c94732a9ef8bbd1a9d2e597..0000000000000000000000000000000000000000 --- a/Documentation/devicetree/bindings/clock/qcom,rpmcc.txt +++ /dev/null @@ -1,63 +0,0 @@ -Qualcomm RPM Clock Controller Binding ------------------------------------------------- -The RPM is a dedicated hardware engine for managing the shared -SoC resources in order to keep the lowest power profile. It -communicates with other hardware subsystems via shared memory -and accepts clock requests, aggregates the requests and turns -the clocks on/off or scales them on demand. - -Required properties : -- compatible : shall contain only one of the following. The generic - compatible "qcom,rpmcc" should be also included. - - "qcom,rpmcc-mdm9607", "qcom,rpmcc" - "qcom,rpmcc-msm8660", "qcom,rpmcc" - "qcom,rpmcc-apq8060", "qcom,rpmcc" - "qcom,rpmcc-msm8226", "qcom,rpmcc" - "qcom,rpmcc-msm8916", "qcom,rpmcc" - "qcom,rpmcc-msm8936", "qcom,rpmcc" - "qcom,rpmcc-msm8953", "qcom,rpmcc" - "qcom,rpmcc-msm8974", "qcom,rpmcc" - "qcom,rpmcc-msm8976", "qcom,rpmcc" - "qcom,rpmcc-apq8064", "qcom,rpmcc" - "qcom,rpmcc-ipq806x", "qcom,rpmcc" - "qcom,rpmcc-msm8992",·"qcom,rpmcc" - "qcom,rpmcc-msm8994",·"qcom,rpmcc" - "qcom,rpmcc-msm8996", "qcom,rpmcc" - "qcom,rpmcc-msm8998", "qcom,rpmcc" - "qcom,rpmcc-qcm2290", "qcom,rpmcc" - "qcom,rpmcc-qcs404", "qcom,rpmcc" - "qcom,rpmcc-sdm660", "qcom,rpmcc" - "qcom,rpmcc-sm6115", "qcom,rpmcc" - "qcom,rpmcc-sm6125", "qcom,rpmcc" - -- #clock-cells : shall contain 1 - -The clock enumerators are defined in -and come in pairs: FOO_CLK followed by FOO_A_CLK. The latter clock -is an "active" clock, which means that the consumer only care that the -clock is available when the apps CPU subsystem is active, i.e. not -suspended or in deep idle. If it is important that the clock keeps running -during system suspend, you need to specify the non-active clock, the one -not containing *_A_* in the enumerator name. - -Example: - smd { - compatible = "qcom,smd"; - - rpm { - interrupts = <0 168 1>; - qcom,ipc = <&apcs 8 0>; - qcom,smd-edge = <15>; - - rpm_requests { - compatible = "qcom,rpm-msm8916"; - qcom,smd-channels = "rpm_requests"; - - rpmcc: clock-controller { - compatible = "qcom,rpmcc-msm8916", "qcom,rpmcc"; - #clock-cells = <1>; - }; - }; - }; - }; diff --git a/Documentation/devicetree/bindings/clock/qcom,rpmcc.yaml b/Documentation/devicetree/bindings/clock/qcom,rpmcc.yaml new file mode 100644 index 0000000000000000000000000000000000000000..9d296b89a8d0bc2f31cbd1334be80e3ebc49c83a --- /dev/null +++ b/Documentation/devicetree/bindings/clock/qcom,rpmcc.yaml @@ -0,0 +1,75 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/qcom,rpmcc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm RPM Clock Controller + +maintainers: + - Bjorn Andersson + - Krzysztof Kozlowski + +description: | + The clock enumerators are defined in and + come in pairs:: FOO_CLK followed by FOO_A_CLK. The latter clock is + an "active" clock, which means that the consumer only care that the clock is + available when the apps CPU subsystem is active, i.e. not suspended or in + deep idle. If it is important that the clock keeps running during system + suspend, you need to specify the non-active clock, the one not containing + *_A_* in the enumerator name. + +properties: + compatible: + items: + - enum: + - qcom,rpmcc-apq8060 + - qcom,rpmcc-apq8064 + - qcom,rpmcc-ipq806x + - qcom,rpmcc-mdm9607 + - qcom,rpmcc-msm8226 + - qcom,rpmcc-msm8660 + - qcom,rpmcc-msm8916 + - qcom,rpmcc-msm8936 + - qcom,rpmcc-msm8953 + - qcom,rpmcc-msm8974 + - qcom,rpmcc-msm8976 + - qcom,rpmcc-msm8992 + - qcom,rpmcc-msm8994 + - qcom,rpmcc-msm8996 + - qcom,rpmcc-msm8998 + - qcom,rpmcc-qcm2290 + - qcom,rpmcc-qcs404 + - qcom,rpmcc-sdm660 + - qcom,rpmcc-sm6115 + - qcom,rpmcc-sm6125 + - const: qcom,rpmcc + + '#clock-cells': + const: 1 + + clocks: + maxItems: 1 + + clock-names: + const: xo + +required: + - compatible + - '#clock-cells' + +additionalProperties: false + +examples: + - | + rpm { + rpm-requests { + compatible = "qcom,rpm-msm8916"; + qcom,smd-channels = "rpm_requests"; + + clock-controller { + compatible = "qcom,rpmcc-msm8916", "qcom,rpmcc"; + #clock-cells = <1>; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/clock/renesas,cpg-mssr.yaml b/Documentation/devicetree/bindings/clock/renesas,cpg-mssr.yaml index e0b86214f0f547b13b8b5470045401d414dd0fc4..e57bc40d307a2c1e88ca2e69fef24e02ad6bca4e 100644 --- a/Documentation/devicetree/bindings/clock/renesas,cpg-mssr.yaml +++ b/Documentation/devicetree/bindings/clock/renesas,cpg-mssr.yaml @@ -49,6 +49,7 @@ properties: - renesas,r8a77995-cpg-mssr # R-Car D3 - renesas,r8a779a0-cpg-mssr # R-Car V3U - renesas,r8a779f0-cpg-mssr # R-Car S4-8 + - renesas,r8a779g0-cpg-mssr # R-Car V4H reg: maxItems: 1 diff --git a/Documentation/devicetree/bindings/clock/renesas,r9a06g032-sysctrl.yaml b/Documentation/devicetree/bindings/clock/renesas,r9a06g032-sysctrl.yaml index 25dbb0fac0656460eeda590792abe9e7227ebfe9..95bf485c6cec3ea566939e2da91eefe3eb5dd257 100644 --- a/Documentation/devicetree/bindings/clock/renesas,r9a06g032-sysctrl.yaml +++ b/Documentation/devicetree/bindings/clock/renesas,r9a06g032-sysctrl.yaml @@ -39,6 +39,17 @@ properties: '#power-domain-cells': const: 0 + '#address-cells': + const: 1 + + '#size-cells': + const: 1 + +patternProperties: + "^dma-router@[a-f0-9]+$": + type: object + $ref: "../dma/renesas,rzn1-dmamux.yaml#" + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/clock/renesas,rzg2l-cpg.yaml b/Documentation/devicetree/bindings/clock/renesas,rzg2l-cpg.yaml index bd3af8fc616b7815b1314f8467af313da5e56e5f..8880b834f264cd9fe90905779612ae5fd33d5d3b 100644 --- a/Documentation/devicetree/bindings/clock/renesas,rzg2l-cpg.yaml +++ b/Documentation/devicetree/bindings/clock/renesas,rzg2l-cpg.yaml @@ -4,14 +4,15 @@ $id: "http://devicetree.org/schemas/clock/renesas,rzg2l-cpg.yaml#" $schema: "http://devicetree.org/meta-schemas/core.yaml#" -title: Renesas RZ/{G2L,V2L} Clock Pulse Generator / Module Standby Mode +title: Renesas RZ/{G2L,V2L,V2M} Clock Pulse Generator / Module Standby Mode maintainers: - Geert Uytterhoeven description: | - On Renesas RZ/{G2L,V2L} SoC, the CPG (Clock Pulse Generator) and Module - Standby Mode share the same register block. + On Renesas RZ/{G2L,V2L}-alike SoC's, the CPG (Clock Pulse Generator) and Module + Standby Mode share the same register block. On RZ/V2M, the functionality is + similar, but does not have Clock Monitor Registers. They provide the following functionalities: - The CPG block generates various core clocks, @@ -23,8 +24,10 @@ description: | properties: compatible: enum: - - renesas,r9a07g044-cpg # RZ/G2{L,LC} - - renesas,r9a07g054-cpg # RZ/V2L + - renesas,r9a07g043-cpg # RZ/G2UL{Type-1,Type-2} + - renesas,r9a07g044-cpg # RZ/G2{L,LC} + - renesas,r9a07g054-cpg # RZ/V2L + - renesas,r9a09g011-cpg # RZ/V2M reg: maxItems: 1 @@ -42,9 +45,10 @@ properties: description: | - For CPG core clocks, the two clock specifier cells must be "CPG_CORE" and a core clock reference, as defined in - + - For module clocks, the two clock specifier cells must be "CPG_MOD" and - a module number, as defined in the . + a module number, as defined in the or + . const: 2 '#power-domain-cells': @@ -58,7 +62,7 @@ properties: '#reset-cells': description: The single reset specifier cell must be the module number, as defined in - the . + the or . const: 1 required: diff --git a/Documentation/devicetree/bindings/clock/rockchip,px30-cru.txt b/Documentation/devicetree/bindings/clock/rockchip,px30-cru.txt deleted file mode 100644 index 55e78cddec8c272af21dec71616fa5744b8447c4..0000000000000000000000000000000000000000 --- a/Documentation/devicetree/bindings/clock/rockchip,px30-cru.txt +++ /dev/null @@ -1,70 +0,0 @@ -* Rockchip PX30 Clock and Reset Unit - -The PX30 clock controller generates and supplies clock to various -controllers within the SoC and also implements a reset controller for SoC -peripherals. - -Required Properties: - -- compatible: PMU for CRU should be "rockchip,px30-pmu-cru" -- compatible: CRU should be "rockchip,px30-cru" -- reg: physical base address of the controller and length of memory mapped - region. -- clocks: A list of phandle + clock-specifier pairs for the clocks listed - in clock-names -- clock-names: Should contain the following: - - "xin24m" for both PMUCRU and CRU - - "gpll" for CRU (sourced from PMUCRU) -- #clock-cells: should be 1. -- #reset-cells: should be 1. - -Optional Properties: - -- rockchip,grf: phandle to the syscon managing the "general register files" - If missing, pll rates are not changeable, due to the missing pll lock status. - -Each clock is assigned an identifier and client nodes can use this identifier -to specify the clock which they consume. All available clocks are defined as -preprocessor macros in the dt-bindings/clock/px30-cru.h headers and can be -used in device tree sources. Similar macros exist for the reset sources in -these files. - -External clocks: - -There are several clocks that are generated outside the SoC. It is expected -that they are defined using standard clock bindings with following -clock-output-names: - - "xin24m" - crystal input - required, - - "xin32k" - rtc clock - optional, - - "i2sx_clkin" - external I2S clock - optional, - - "gmac_clkin" - external GMAC clock - optional - -Example: Clock controller node: - - pmucru: clock-controller@ff2bc000 { - compatible = "rockchip,px30-pmucru"; - reg = <0x0 0xff2bc000 0x0 0x1000>; - #clock-cells = <1>; - #reset-cells = <1>; - }; - - cru: clock-controller@ff2b0000 { - compatible = "rockchip,px30-cru"; - reg = <0x0 0xff2b0000 0x0 0x1000>; - rockchip,grf = <&grf>; - #clock-cells = <1>; - #reset-cells = <1>; - }; - -Example: UART controller node that consumes the clock generated by the clock - controller: - - uart0: serial@ff030000 { - compatible = "rockchip,px30-uart", "snps,dw-apb-uart"; - reg = <0x0 0xff030000 0x0 0x100>; - interrupts = ; - clocks = <&pmucru SCLK_UART0_PMU>, <&pmucru PCLK_UART0_PMU>; - clock-names = "baudclk", "apb_pclk"; - reg-shift = <2>; - reg-io-width = <4>; - }; diff --git a/Documentation/devicetree/bindings/clock/rockchip,px30-cru.yaml b/Documentation/devicetree/bindings/clock/rockchip,px30-cru.yaml new file mode 100644 index 0000000000000000000000000000000000000000..3eec381c7cf54c45065238548793747fdbc967be --- /dev/null +++ b/Documentation/devicetree/bindings/clock/rockchip,px30-cru.yaml @@ -0,0 +1,119 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/rockchip,px30-cru.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Rockchip PX30 Clock and Reset Unit (CRU) + +maintainers: + - Elaine Zhang + - Heiko Stuebner + +description: | + The PX30 clock controller generates and supplies clocks to various + controllers within the SoC and also implements a reset controller for SoC + peripherals. + Each clock is assigned an identifier and client nodes can use this identifier + to specify the clock which they consume. All available clocks are defined as + preprocessor macros in the dt-bindings/clock/px30-cru.h headers and can be + used in device tree sources. Similar macros exist for the reset sources in + these files. + There are several clocks that are generated outside the SoC. It is expected + that they are defined using standard clock bindings with following + clock-output-names: + - "xin24m" - crystal input - required + - "xin32k" - rtc clock - optional + - "i2sx_clkin" - external I2S clock - optional + - "gmac_clkin" - external GMAC clock - optional + +properties: + compatible: + enum: + - rockchip,px30-cru + - rockchip,px30-pmucru + + reg: + maxItems: 1 + + "#clock-cells": + const: 1 + + "#reset-cells": + const: 1 + + clocks: + minItems: 1 + items: + - description: Clock for both PMUCRU and CRU + - description: Clock for CRU (sourced from PMUCRU) + + clock-names: + minItems: 1 + items: + - const: xin24m + - const: gpll + + rockchip,grf: + $ref: /schemas/types.yaml#/definitions/phandle + description: + Phandle to the syscon managing the "general register files" (GRF), + if missing pll rates are not changeable, due to the missing pll + lock status. + +required: + - compatible + - reg + - clocks + - clock-names + - "#clock-cells" + - "#reset-cells" + +allOf: + - if: + properties: + compatible: + contains: + const: rockchip,px30-cru + + then: + properties: + clocks: + minItems: 2 + + clock-names: + minItems: 2 + + else: + properties: + clocks: + maxItems: 1 + + clock-names: + maxItems: 1 + +additionalProperties: false + +examples: + - | + #include + + pmucru: clock-controller@ff2bc000 { + compatible = "rockchip,px30-pmucru"; + reg = <0xff2bc000 0x1000>; + clocks = <&xin24m>; + clock-names = "xin24m"; + rockchip,grf = <&grf>; + #clock-cells = <1>; + #reset-cells = <1>; + }; + + cru: clock-controller@ff2b0000 { + compatible = "rockchip,px30-cru"; + reg = <0xff2b0000 0x1000>; + clocks = <&xin24m>, <&pmucru PLL_GPLL>; + clock-names = "xin24m", "gpll"; + rockchip,grf = <&grf>; + #clock-cells = <1>; + #reset-cells = <1>; + }; diff --git a/Documentation/devicetree/bindings/clock/rockchip,rk3036-cru.txt b/Documentation/devicetree/bindings/clock/rockchip,rk3036-cru.txt deleted file mode 100644 index 20df350b9ef3d491b3e2e714f8877d74477afcd8..0000000000000000000000000000000000000000 --- a/Documentation/devicetree/bindings/clock/rockchip,rk3036-cru.txt +++ /dev/null @@ -1,56 +0,0 @@ -* Rockchip RK3036 Clock and Reset Unit - -The RK3036 clock controller generates and supplies clock to various -controllers within the SoC and also implements a reset controller for SoC -peripherals. - -Required Properties: - -- compatible: should be "rockchip,rk3036-cru" -- reg: physical base address of the controller and length of memory mapped - region. -- #clock-cells: should be 1. -- #reset-cells: should be 1. - -Optional Properties: - -- rockchip,grf: phandle to the syscon managing the "general register files" - If missing pll rates are not changeable, due to the missing pll lock status. - -Each clock is assigned an identifier and client nodes can use this identifier -to specify the clock which they consume. All available clocks are defined as -preprocessor macros in the dt-bindings/clock/rk3036-cru.h headers and can be -used in device tree sources. Similar macros exist for the reset sources in -these files. - -External clocks: - -There are several clocks that are generated outside the SoC. It is expected -that they are defined using standard clock bindings with following -clock-output-names: - - "xin24m" - crystal input - required, - - "ext_i2s" - external I2S clock - optional, - - "rmii_clkin" - external EMAC clock - optional - -Example: Clock controller node: - - cru: cru@20000000 { - compatible = "rockchip,rk3036-cru"; - reg = <0x20000000 0x1000>; - rockchip,grf = <&grf>; - - #clock-cells = <1>; - #reset-cells = <1>; - }; - -Example: UART controller node that consumes the clock generated by the clock - controller: - - uart0: serial@20060000 { - compatible = "snps,dw-apb-uart"; - reg = <0x20060000 0x100>; - interrupts = ; - reg-shift = <2>; - reg-io-width = <4>; - clocks = <&cru SCLK_UART0>; - }; diff --git a/Documentation/devicetree/bindings/clock/rockchip,rk3036-cru.yaml b/Documentation/devicetree/bindings/clock/rockchip,rk3036-cru.yaml new file mode 100644 index 0000000000000000000000000000000000000000..1376230fede60f83bc1ce61b03694e9c9fcd735e --- /dev/null +++ b/Documentation/devicetree/bindings/clock/rockchip,rk3036-cru.yaml @@ -0,0 +1,72 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/rockchip,rk3036-cru.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Rockchip RK3036 Clock and Reset Unit (CRU) + +maintainers: + - Elaine Zhang + - Heiko Stuebner + +description: | + The RK3036 clock controller generates and supplies clocks to various + controllers within the SoC and also implements a reset controller for SoC + peripherals. + Each clock is assigned an identifier and client nodes can use this identifier + to specify the clock which they consume. All available clocks are defined as + preprocessor macros in the dt-bindings/clock/rk3036-cru.h headers and can be + used in device tree sources. Similar macros exist for the reset sources in + these files. + There are several clocks that are generated outside the SoC. It is expected + that they are defined using standard clock bindings with following + clock-output-names: + - "xin24m" - crystal input - required + - "ext_i2s" - external I2S clock - optional + - "rmii_clkin" - external EMAC clock - optional + +properties: + compatible: + enum: + - rockchip,rk3036-cru + + reg: + maxItems: 1 + + "#clock-cells": + const: 1 + + "#reset-cells": + const: 1 + + clocks: + maxItems: 1 + + clock-names: + const: xin24m + + rockchip,grf: + $ref: /schemas/types.yaml#/definitions/phandle + description: + Phandle to the syscon managing the "general register files" (GRF), + if missing pll rates are not changeable, due to the missing pll + lock status. + +required: + - compatible + - reg + - "#clock-cells" + - "#reset-cells" + +additionalProperties: false + +examples: + - | + cru: clock-controller@20000000 { + compatible = "rockchip,rk3036-cru"; + reg = <0x20000000 0x1000>; + rockchip,grf = <&grf>; + #clock-cells = <1>; + #reset-cells = <1>; + }; diff --git a/Documentation/devicetree/bindings/clock/rockchip,rk3188-cru.txt b/Documentation/devicetree/bindings/clock/rockchip,rk3188-cru.txt deleted file mode 100644 index 7f368530a2e4397653f1bc5069b0ed0587d507bb..0000000000000000000000000000000000000000 --- a/Documentation/devicetree/bindings/clock/rockchip,rk3188-cru.txt +++ /dev/null @@ -1,61 +0,0 @@ -* Rockchip RK3188/RK3066 Clock and Reset Unit - -The RK3188/RK3066 clock controller generates and supplies clock to various -controllers within the SoC and also implements a reset controller for SoC -peripherals. - -Required Properties: - -- compatible: should be "rockchip,rk3188-cru", "rockchip,rk3188a-cru" or - "rockchip,rk3066a-cru" -- reg: physical base address of the controller and length of memory mapped - region. -- #clock-cells: should be 1. -- #reset-cells: should be 1. - -Optional Properties: - -- rockchip,grf: phandle to the syscon managing the "general register files" - If missing pll rates are not changeable, due to the missing pll lock status. - -Each clock is assigned an identifier and client nodes can use this identifier -to specify the clock which they consume. All available clocks are defined as -preprocessor macros in the dt-bindings/clock/rk3188-cru.h and -dt-bindings/clock/rk3066-cru.h headers and can be used in device tree sources. -Similar macros exist for the reset sources in these files. - -External clocks: - -There are several clocks that are generated outside the SoC. It is expected -that they are defined using standard clock bindings with following -clock-output-names: - - "xin24m" - crystal input - required, - - "xin32k" - rtc clock - optional, - - "xin27m" - 27mhz crystal input on rk3066 - optional, - - "ext_hsadc" - external HSADC clock - optional, - - "ext_cif0" - external camera clock - optional, - - "ext_rmii" - external RMII clock - optional, - - "ext_jtag" - externalJTAG clock - optional - -Example: Clock controller node: - - cru: cru@20000000 { - compatible = "rockchip,rk3188-cru"; - reg = <0x20000000 0x1000>; - rockchip,grf = <&grf>; - - #clock-cells = <1>; - #reset-cells = <1>; - }; - -Example: UART controller node that consumes the clock generated by the clock - controller: - - uart0: serial@10124000 { - compatible = "snps,dw-apb-uart"; - reg = <0x10124000 0x400>; - interrupts = ; - reg-shift = <2>; - reg-io-width = <1>; - clocks = <&cru SCLK_UART0>; - }; diff --git a/Documentation/devicetree/bindings/clock/rockchip,rk3188-cru.yaml b/Documentation/devicetree/bindings/clock/rockchip,rk3188-cru.yaml new file mode 100644 index 0000000000000000000000000000000000000000..ddd7e46af0f24f3878b4a787de2b041a16f20faa --- /dev/null +++ b/Documentation/devicetree/bindings/clock/rockchip,rk3188-cru.yaml @@ -0,0 +1,78 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/rockchip,rk3188-cru.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Rockchip RK3188/RK3066 Clock and Reset Unit (CRU) + +maintainers: + - Elaine Zhang + - Heiko Stuebner + +description: | + The RK3188/RK3066 clock controller generates and supplies clocks to various + controllers within the SoC and also implements a reset controller for SoC + peripherals. + Each clock is assigned an identifier and client nodes can use this identifier + to specify the clock which they consume. All available clocks are defined as + preprocessor macros in the dt-bindings/clock/rk3188-cru.h and + dt-bindings/clock/rk3066-cru.h headers and can be used in device tree sources. + Similar macros exist for the reset sources in these files. + There are several clocks that are generated outside the SoC. It is expected + that they are defined using standard clock bindings with following + clock-output-names: + - "xin24m" - crystal input - required + - "xin32k" - RTC clock - optional + - "xin27m" - 27mhz crystal input on RK3066 - optional + - "ext_hsadc" - external HSADC clock - optional + - "ext_cif0" - external camera clock - optional + - "ext_rmii" - external RMII clock - optional + - "ext_jtag" - external JTAG clock - optional + +properties: + compatible: + enum: + - rockchip,rk3066a-cru + - rockchip,rk3188-cru + - rockchip,rk3188a-cru + + reg: + maxItems: 1 + + "#clock-cells": + const: 1 + + "#reset-cells": + const: 1 + + clocks: + maxItems: 1 + + clock-names: + const: xin24m + + rockchip,grf: + $ref: /schemas/types.yaml#/definitions/phandle + description: + Phandle to the syscon managing the "general register files" (GRF), + if missing pll rates are not changeable, due to the missing pll + lock status. + +required: + - compatible + - reg + - "#clock-cells" + - "#reset-cells" + +additionalProperties: false + +examples: + - | + cru: clock-controller@20000000 { + compatible = "rockchip,rk3188-cru"; + reg = <0x20000000 0x1000>; + rockchip,grf = <&grf>; + #clock-cells = <1>; + #reset-cells = <1>; + }; diff --git a/Documentation/devicetree/bindings/clock/rockchip,rk3228-cru.txt b/Documentation/devicetree/bindings/clock/rockchip,rk3228-cru.txt deleted file mode 100644 index f323048127eb0d8aa3adf72605792cc92c4dc7b1..0000000000000000000000000000000000000000 --- a/Documentation/devicetree/bindings/clock/rockchip,rk3228-cru.txt +++ /dev/null @@ -1,58 +0,0 @@ -* Rockchip RK3228 Clock and Reset Unit - -The RK3228 clock controller generates and supplies clock to various -controllers within the SoC and also implements a reset controller for SoC -peripherals. - -Required Properties: - -- compatible: should be "rockchip,rk3228-cru" -- reg: physical base address of the controller and length of memory mapped - region. -- #clock-cells: should be 1. -- #reset-cells: should be 1. - -Optional Properties: - -- rockchip,grf: phandle to the syscon managing the "general register files" - If missing pll rates are not changeable, due to the missing pll lock status. - -Each clock is assigned an identifier and client nodes can use this identifier -to specify the clock which they consume. All available clocks are defined as -preprocessor macros in the dt-bindings/clock/rk3228-cru.h headers and can be -used in device tree sources. Similar macros exist for the reset sources in -these files. - -External clocks: - -There are several clocks that are generated outside the SoC. It is expected -that they are defined using standard clock bindings with following -clock-output-names: - - "xin24m" - crystal input - required, - - "ext_i2s" - external I2S clock - optional, - - "ext_gmac" - external GMAC clock - optional - - "ext_hsadc" - external HSADC clock - optional - - "phy_50m_out" - output clock of the pll in the mac phy - -Example: Clock controller node: - - cru: cru@20000000 { - compatible = "rockchip,rk3228-cru"; - reg = <0x20000000 0x1000>; - rockchip,grf = <&grf>; - - #clock-cells = <1>; - #reset-cells = <1>; - }; - -Example: UART controller node that consumes the clock generated by the clock - controller: - - uart0: serial@10110000 { - compatible = "snps,dw-apb-uart"; - reg = <0x10110000 0x100>; - interrupts = ; - reg-shift = <2>; - reg-io-width = <4>; - clocks = <&cru SCLK_UART0>; - }; diff --git a/Documentation/devicetree/bindings/clock/rockchip,rk3228-cru.yaml b/Documentation/devicetree/bindings/clock/rockchip,rk3228-cru.yaml new file mode 100644 index 0000000000000000000000000000000000000000..cf7dc01d9478500a8355131e6be30897a1673b87 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/rockchip,rk3228-cru.yaml @@ -0,0 +1,74 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/rockchip,rk3228-cru.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Rockchip RK3228 Clock and Reset Unit (CRU) + +maintainers: + - Elaine Zhang + - Heiko Stuebner + +description: | + The RK3228 clock controller generates and supplies clocks to various + controllers within the SoC and also implements a reset controller for SoC + peripherals. + Each clock is assigned an identifier and client nodes can use this identifier + to specify the clock which they consume. All available clocks are defined as + preprocessor macros in the dt-bindings/clock/rk3228-cru.h headers and can be + used in device tree sources. Similar macros exist for the reset sources in + these files. + There are several clocks that are generated outside the SoC. It is expected + that they are defined using standard clock bindings with following + clock-output-names: + - "xin24m" - crystal input - required + - "ext_i2s" - external I2S clock - optional + - "ext_gmac" - external GMAC clock - optional + - "ext_hsadc" - external HSADC clock - optional + - "phy_50m_out" - output clock of the pll in the mac phy + +properties: + compatible: + enum: + - rockchip,rk3228-cru + + reg: + maxItems: 1 + + "#clock-cells": + const: 1 + + "#reset-cells": + const: 1 + + clocks: + maxItems: 1 + + clock-names: + const: xin24m + + rockchip,grf: + $ref: /schemas/types.yaml#/definitions/phandle + description: + Phandle to the syscon managing the "general register files" (GRF), + if missing pll rates are not changeable, due to the missing pll + lock status. + +required: + - compatible + - reg + - "#clock-cells" + - "#reset-cells" + +additionalProperties: false + +examples: + - | + cru: clock-controller@20000000 { + compatible = "rockchip,rk3228-cru"; + reg = <0x20000000 0x1000>; + rockchip,grf = <&grf>; + #clock-cells = <1>; + #reset-cells = <1>; + }; diff --git a/Documentation/devicetree/bindings/clock/rockchip,rk3288-cru.txt b/Documentation/devicetree/bindings/clock/rockchip,rk3288-cru.txt deleted file mode 100644 index bf3a9ec1924168a8a569e4d26b31cff5d8917903..0000000000000000000000000000000000000000 --- a/Documentation/devicetree/bindings/clock/rockchip,rk3288-cru.txt +++ /dev/null @@ -1,67 +0,0 @@ -* Rockchip RK3288 Clock and Reset Unit - -The RK3288 clock controller generates and supplies clock to various -controllers within the SoC and also implements a reset controller for SoC -peripherals. - -A revision of this SoC is available: rk3288w. The clock tree is a bit -different so another dt-compatible is available. Noticed that it is only -setting the difference but there is no automatic revision detection. This -should be performed by bootloaders. - -Required Properties: - -- compatible: should be "rockchip,rk3288-cru" or "rockchip,rk3288w-cru" in - case of this revision of Rockchip rk3288. -- reg: physical base address of the controller and length of memory mapped - region. -- #clock-cells: should be 1. -- #reset-cells: should be 1. - -Optional Properties: - -- rockchip,grf: phandle to the syscon managing the "general register files" - If missing pll rates are not changeable, due to the missing pll lock status. - -Each clock is assigned an identifier and client nodes can use this identifier -to specify the clock which they consume. All available clocks are defined as -preprocessor macros in the dt-bindings/clock/rk3288-cru.h headers and can be -used in device tree sources. Similar macros exist for the reset sources in -these files. - -External clocks: - -There are several clocks that are generated outside the SoC. It is expected -that they are defined using standard clock bindings with following -clock-output-names: - - "xin24m" - crystal input - required, - - "xin32k" - rtc clock - optional, - - "ext_i2s" - external I2S clock - optional, - - "ext_hsadc" - external HSADC clock - optional, - - "ext_edp_24m" - external display port clock - optional, - - "ext_vip" - external VIP clock - optional, - - "ext_isp" - external ISP clock - optional, - - "ext_jtag" - external JTAG clock - optional - -Example: Clock controller node: - - cru: cru@20000000 { - compatible = "rockchip,rk3188-cru"; - reg = <0x20000000 0x1000>; - rockchip,grf = <&grf>; - - #clock-cells = <1>; - #reset-cells = <1>; - }; - -Example: UART controller node that consumes the clock generated by the clock - controller: - - uart0: serial@10124000 { - compatible = "snps,dw-apb-uart"; - reg = <0x10124000 0x400>; - interrupts = ; - reg-shift = <2>; - reg-io-width = <1>; - clocks = <&cru SCLK_UART0>; - }; diff --git a/Documentation/devicetree/bindings/clock/rockchip,rk3288-cru.yaml b/Documentation/devicetree/bindings/clock/rockchip,rk3288-cru.yaml new file mode 100644 index 0000000000000000000000000000000000000000..96bc05749e1a4f46ce39272d1a014a26c389f53d --- /dev/null +++ b/Documentation/devicetree/bindings/clock/rockchip,rk3288-cru.yaml @@ -0,0 +1,85 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/rockchip,rk3288-cru.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Rockchip RK3288 Clock and Reset Unit (CRU) + +maintainers: + - Elaine Zhang + - Heiko Stuebner + +description: | + The RK3288 clock controller generates and supplies clocks to various + controllers within the SoC and also implements a reset controller for SoC + peripherals. + + A revision of this SoC is available: rk3288w. The clock tree is a bit + different so another dt-compatible is available. Noticed that it is only + setting the difference but there is no automatic revision detection. This + should be performed by boot loaders. + + Each clock is assigned an identifier and client nodes can use this identifier + to specify the clock which they consume. All available clocks are defined as + preprocessor macros in the dt-bindings/clock/rk3288-cru.h headers and can be + used in device tree sources. Similar macros exist for the reset sources in + these files. + + There are several clocks that are generated outside the SoC. It is expected + that they are defined using standard clock bindings with following + clock-output-names: + - "xin24m" - crystal input - required, + - "xin32k" - rtc clock - optional, + - "ext_i2s" - external I2S clock - optional, + - "ext_hsadc" - external HSADC clock - optional, + - "ext_edp_24m" - external display port clock - optional, + - "ext_vip" - external VIP clock - optional, + - "ext_isp" - external ISP clock - optional, + - "ext_jtag" - external JTAG clock - optional + +properties: + compatible: + enum: + - rockchip,rk3288-cru + - rockchip,rk3288w-cru + + reg: + maxItems: 1 + + "#clock-cells": + const: 1 + + "#reset-cells": + const: 1 + + clocks: + maxItems: 1 + + clock-names: + const: xin24m + + rockchip,grf: + $ref: /schemas/types.yaml#/definitions/phandle + description: + Phandle to the syscon managing the "general register files" (GRF), + if missing pll rates are not changeable, due to the missing pll + lock status. + +required: + - compatible + - reg + - "#clock-cells" + - "#reset-cells" + +additionalProperties: false + +examples: + - | + cru: clock-controller@ff760000 { + compatible = "rockchip,rk3288-cru"; + reg = <0xff760000 0x1000>; + rockchip,grf = <&grf>; + #clock-cells = <1>; + #reset-cells = <1>; + }; diff --git a/Documentation/devicetree/bindings/clock/rockchip,rk3308-cru.txt b/Documentation/devicetree/bindings/clock/rockchip,rk3308-cru.txt deleted file mode 100644 index 9b151c5b0c905a544a98e74d608441a9b68411a7..0000000000000000000000000000000000000000 --- a/Documentation/devicetree/bindings/clock/rockchip,rk3308-cru.txt +++ /dev/null @@ -1,60 +0,0 @@ -* Rockchip RK3308 Clock and Reset Unit - -The RK3308 clock controller generates and supplies clock to various -controllers within the SoC and also implements a reset controller for SoC -peripherals. - -Required Properties: - -- compatible: CRU should be "rockchip,rk3308-cru" -- reg: physical base address of the controller and length of memory mapped - region. -- #clock-cells: should be 1. -- #reset-cells: should be 1. - -Optional Properties: - -- rockchip,grf: phandle to the syscon managing the "general register files" - If missing, pll rates are not changeable, due to the missing pll lock status. - -Each clock is assigned an identifier and client nodes can use this identifier -to specify the clock which they consume. All available clocks are defined as -preprocessor macros in the dt-bindings/clock/rk3308-cru.h headers and can be -used in device tree sources. Similar macros exist for the reset sources in -these files. - -External clocks: - -There are several clocks that are generated outside the SoC. It is expected -that they are defined using standard clock bindings with following -clock-output-names: - - "xin24m" - crystal input - required, - - "xin32k" - rtc clock - optional, - - "mclk_i2s0_8ch_in", "mclk_i2s1_8ch_in", "mclk_i2s2_8ch_in", - "mclk_i2s3_8ch_in", "mclk_i2s0_2ch_in", - "mclk_i2s1_2ch_in" - external I2S or SPDIF clock - optional, - - "mac_clkin" - external MAC clock - optional - -Example: Clock controller node: - - cru: clock-controller@ff500000 { - compatible = "rockchip,rk3308-cru"; - reg = <0x0 0xff500000 0x0 0x1000>; - rockchip,grf = <&grf>; - #clock-cells = <1>; - #reset-cells = <1>; - }; - -Example: UART controller node that consumes the clock generated by the clock - controller: - - uart0: serial@ff0a0000 { - compatible = "rockchip,rk3308-uart", "snps,dw-apb-uart"; - reg = <0x0 0xff0a0000 0x0 0x100>; - interrupts = ; - clocks = <&cru SCLK_UART0>, <&cru PCLK_UART0>; - clock-names = "baudclk", "apb_pclk"; - reg-shift = <2>; - reg-io-width = <4>; - status = "disabled"; - }; diff --git a/Documentation/devicetree/bindings/clock/rockchip,rk3308-cru.yaml b/Documentation/devicetree/bindings/clock/rockchip,rk3308-cru.yaml new file mode 100644 index 0000000000000000000000000000000000000000..523ee578a586a955ca3a66d901ce3aedef82a35e --- /dev/null +++ b/Documentation/devicetree/bindings/clock/rockchip,rk3308-cru.yaml @@ -0,0 +1,76 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/rockchip,rk3308-cru.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Rockchip RK3308 Clock and Reset Unit (CRU) + +maintainers: + - Elaine Zhang + - Heiko Stuebner + +description: | + The RK3308 clock controller generates and supplies clocks to various + controllers within the SoC and also implements a reset controller for SoC + peripherals. + Each clock is assigned an identifier and client nodes can use this identifier + to specify the clock which they consume. All available clocks are defined as + preprocessor macros in the dt-bindings/clock/rk3308-cru.h headers and can be + used in device tree sources. Similar macros exist for the reset sources in + these files. + There are several clocks that are generated outside the SoC. It is expected + that they are defined using standard clock bindings with following + clock-output-names: + - "xin24m" - crystal input - required + - "xin32k" - rtc clock - optional + - "mclk_i2s0_8ch_in", "mclk_i2s1_8ch_in", + "mclk_i2s2_8ch_in", "mclk_i2s3_8ch_in", + "mclk_i2s0_2ch_in", "mclk_i2s1_2ch_in" - external I2S or + SPDIF clock - optional + - "mac_clkin" - external MAC clock - optional + +properties: + compatible: + enum: + - rockchip,rk3308-cru + + reg: + maxItems: 1 + + "#clock-cells": + const: 1 + + "#reset-cells": + const: 1 + + clocks: + maxItems: 1 + + clock-names: + const: xin24m + + rockchip,grf: + $ref: /schemas/types.yaml#/definitions/phandle + description: + Phandle to the syscon managing the "general register files" (GRF), + if missing pll rates are not changeable, due to the missing pll + lock status. + +required: + - compatible + - reg + - "#clock-cells" + - "#reset-cells" + +additionalProperties: false + +examples: + - | + cru: clock-controller@ff500000 { + compatible = "rockchip,rk3308-cru"; + reg = <0xff500000 0x1000>; + rockchip,grf = <&grf>; + #clock-cells = <1>; + #reset-cells = <1>; + }; diff --git a/Documentation/devicetree/bindings/clock/rockchip,rk3368-cru.txt b/Documentation/devicetree/bindings/clock/rockchip,rk3368-cru.txt deleted file mode 100644 index 7c8bbcfed8d22f04a2690a72afdc643f177c318f..0000000000000000000000000000000000000000 --- a/Documentation/devicetree/bindings/clock/rockchip,rk3368-cru.txt +++ /dev/null @@ -1,61 +0,0 @@ -* Rockchip RK3368 Clock and Reset Unit - -The RK3368 clock controller generates and supplies clock to various -controllers within the SoC and also implements a reset controller for SoC -peripherals. - -Required Properties: - -- compatible: should be "rockchip,rk3368-cru" -- reg: physical base address of the controller and length of memory mapped - region. -- #clock-cells: should be 1. -- #reset-cells: should be 1. - -Optional Properties: - -- rockchip,grf: phandle to the syscon managing the "general register files" - If missing, pll rates are not changeable, due to the missing pll lock status. - -Each clock is assigned an identifier and client nodes can use this identifier -to specify the clock which they consume. All available clocks are defined as -preprocessor macros in the dt-bindings/clock/rk3368-cru.h headers and can be -used in device tree sources. Similar macros exist for the reset sources in -these files. - -External clocks: - -There are several clocks that are generated outside the SoC. It is expected -that they are defined using standard clock bindings with following -clock-output-names: - - "xin24m" - crystal input - required, - - "xin32k" - rtc clock - optional, - - "ext_i2s" - external I2S clock - optional, - - "ext_gmac" - external GMAC clock - optional - - "ext_hsadc" - external HSADC clock - optional, - - "ext_isp" - external ISP clock - optional, - - "ext_jtag" - external JTAG clock - optional - - "ext_vip" - external VIP clock - optional, - - "usbotg_out" - output clock of the pll in the otg phy - -Example: Clock controller node: - - cru: clock-controller@ff760000 { - compatible = "rockchip,rk3368-cru"; - reg = <0x0 0xff760000 0x0 0x1000>; - rockchip,grf = <&grf>; - #clock-cells = <1>; - #reset-cells = <1>; - }; - -Example: UART controller node that consumes the clock generated by the clock - controller: - - uart0: serial@10124000 { - compatible = "snps,dw-apb-uart"; - reg = <0x10124000 0x400>; - interrupts = ; - reg-shift = <2>; - reg-io-width = <1>; - clocks = <&cru SCLK_UART0>; - }; diff --git a/Documentation/devicetree/bindings/clock/rockchip,rk3368-cru.yaml b/Documentation/devicetree/bindings/clock/rockchip,rk3368-cru.yaml new file mode 100644 index 0000000000000000000000000000000000000000..adb67877720da46ae1f8c84dbc75d26368194c0d --- /dev/null +++ b/Documentation/devicetree/bindings/clock/rockchip,rk3368-cru.yaml @@ -0,0 +1,78 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/rockchip,rk3368-cru.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Rockchip RK3368 Clock and Reset Unit (CRU) + +maintainers: + - Elaine Zhang + - Heiko Stuebner + +description: | + The RK3368 clock controller generates and supplies clocks to various + controllers within the SoC and also implements a reset controller for SoC + peripherals. + Each clock is assigned an identifier and client nodes can use this identifier + to specify the clock which they consume. All available clocks are defined as + preprocessor macros in the dt-bindings/clock/rk3368-cru.h headers and can be + used in device tree sources. Similar macros exist for the reset sources in + these files. + There are several clocks that are generated outside the SoC. It is expected + that they are defined using standard clock bindings with following + clock-output-names: + - "xin24m" - crystal input - required + - "xin32k" - rtc clock - optional + - "ext_i2s" - external I2S clock - optional + - "ext_gmac" - external GMAC clock - optional + - "ext_hsadc" - external HSADC clock - optional + - "ext_isp" - external ISP clock - optional + - "ext_jtag" - external JTAG clock - optional + - "ext_vip" - external VIP clock - optional + - "usbotg_out" - output clock of the pll in the otg phy + +properties: + compatible: + enum: + - rockchip,rk3368-cru + + reg: + maxItems: 1 + + "#clock-cells": + const: 1 + + "#reset-cells": + const: 1 + + clocks: + maxItems: 1 + + clock-names: + const: xin24m + + rockchip,grf: + $ref: /schemas/types.yaml#/definitions/phandle + description: + Phandle to the syscon managing the "general register files" (GRF), + if missing pll rates are not changeable, due to the missing pll + lock status. + +required: + - compatible + - reg + - "#clock-cells" + - "#reset-cells" + +additionalProperties: false + +examples: + - | + cru: clock-controller@ff760000 { + compatible = "rockchip,rk3368-cru"; + reg = <0xff760000 0x1000>; + rockchip,grf = <&grf>; + #clock-cells = <1>; + #reset-cells = <1>; + }; diff --git a/Documentation/devicetree/bindings/clock/rockchip,rk3399-cru.yaml b/Documentation/devicetree/bindings/clock/rockchip,rk3399-cru.yaml index 72b286a1beba2f24a0182472c74aff67d06f594f..54da1e31ea7386081fc599e811308efff9569aa9 100644 --- a/Documentation/devicetree/bindings/clock/rockchip,rk3399-cru.yaml +++ b/Documentation/devicetree/bindings/clock/rockchip,rk3399-cru.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Rockchip RK3399 Clock and Reset Unit maintainers: - - Xing Zheng + - Elaine Zhang - Heiko Stuebner description: | @@ -22,11 +22,11 @@ description: | There are several clocks that are generated outside the SoC. It is expected that they are defined using standard clock bindings with following clock-output-names: - - "xin24m" - crystal input - required, - - "xin32k" - rtc clock - optional, - - "clkin_gmac" - external GMAC clock - optional, - - "clkin_i2s" - external I2S clock - optional, - - "pclkin_cif" - external ISP clock - optional, + - "xin24m" - crystal input - required, + - "xin32k" - rtc clock - optional, + - "clkin_gmac" - external GMAC clock - optional, + - "clkin_i2s" - external I2S clock - optional, + - "pclkin_cif" - external ISP clock - optional, - "clk_usbphy0_480m" - output clock of the pll in the usbphy0 - "clk_usbphy1_480m" - output clock of the pll in the usbphy1 @@ -46,24 +46,15 @@ properties: const: 1 clocks: - minItems: 1 - - assigned-clocks: - minItems: 1 - maxItems: 64 - - assigned-clock-parents: - minItems: 1 - maxItems: 64 + maxItems: 1 - assigned-clock-rates: - minItems: 1 - maxItems: 64 + clock-names: + const: xin24m rockchip,grf: $ref: /schemas/types.yaml#/definitions/phandle - description: > - phandle to the syscon managing the "general register files". It is used + description: + Phandle to the syscon managing the "general register files". It is used for GRF muxes, if missing any muxes present in the GRF will not be available. @@ -77,7 +68,7 @@ additionalProperties: false examples: - | - pmucru: pmu-clock-controller@ff750000 { + pmucru: clock-controller@ff750000 { compatible = "rockchip,rk3399-pmucru"; reg = <0xff750000 0x1000>; #clock-cells = <1>; diff --git a/Documentation/devicetree/bindings/clock/rockchip,rk3568-cru.yaml b/Documentation/devicetree/bindings/clock/rockchip,rk3568-cru.yaml index b2c26097827f65cfae2035ca52bc2d43bccbf486..fc7546f521c55f2189690b19b187c276c90ac3cc 100644 --- a/Documentation/devicetree/bindings/clock/rockchip,rk3568-cru.yaml +++ b/Documentation/devicetree/bindings/clock/rockchip,rk3568-cru.yaml @@ -34,6 +34,19 @@ properties: "#reset-cells": const: 1 + clocks: + maxItems: 1 + + clock-names: + const: xin24m + + rockchip,grf: + $ref: /schemas/types.yaml#/definitions/phandle + description: + Phandle to the syscon managing the "general register files" (GRF), + if missing pll rates are not changeable, due to the missing pll + lock status. + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/clock/rockchip,rv1108-cru.txt b/Documentation/devicetree/bindings/clock/rockchip,rv1108-cru.txt deleted file mode 100644 index 161326a4f9c1feebe41d0ee38e8089c769043dd1..0000000000000000000000000000000000000000 --- a/Documentation/devicetree/bindings/clock/rockchip,rv1108-cru.txt +++ /dev/null @@ -1,59 +0,0 @@ -* Rockchip RV1108 Clock and Reset Unit - -The RV1108 clock controller generates and supplies clock to various -controllers within the SoC and also implements a reset controller for SoC -peripherals. - -Required Properties: - -- compatible: should be "rockchip,rv1108-cru" -- reg: physical base address of the controller and length of memory mapped - region. -- #clock-cells: should be 1. -- #reset-cells: should be 1. - -Optional Properties: - -- rockchip,grf: phandle to the syscon managing the "general register files" - If missing pll rates are not changeable, due to the missing pll lock status. - -Each clock is assigned an identifier and client nodes can use this identifier -to specify the clock which they consume. All available clocks are defined as -preprocessor macros in the dt-bindings/clock/rv1108-cru.h headers and can be -used in device tree sources. Similar macros exist for the reset sources in -these files. - -External clocks: - -There are several clocks that are generated outside the SoC. It is expected -that they are defined using standard clock bindings with following -clock-output-names: - - "xin24m" - crystal input - required, - - "ext_vip" - external VIP clock - optional - - "ext_i2s" - external I2S clock - optional - - "ext_gmac" - external GMAC clock - optional - - "hdmiphy" - external clock input derived from HDMI PHY - optional - - "usbphy" - external clock input derived from USB PHY - optional - -Example: Clock controller node: - - cru: cru@20200000 { - compatible = "rockchip,rv1108-cru"; - reg = <0x20200000 0x1000>; - rockchip,grf = <&grf>; - - #clock-cells = <1>; - #reset-cells = <1>; - }; - -Example: UART controller node that consumes the clock generated by the clock - controller: - - uart0: serial@10230000 { - compatible = "rockchip,rv1108-uart", "snps,dw-apb-uart"; - reg = <0x10230000 0x100>; - interrupts = ; - reg-shift = <2>; - reg-io-width = <4>; - clocks = <&cru SCLK_UART0>; - }; diff --git a/Documentation/devicetree/bindings/clock/rockchip,rv1108-cru.yaml b/Documentation/devicetree/bindings/clock/rockchip,rv1108-cru.yaml new file mode 100644 index 0000000000000000000000000000000000000000..20421c22f1846dd8868d6189d7b15dc86fa998a4 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/rockchip,rv1108-cru.yaml @@ -0,0 +1,75 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/rockchip,rv1108-cru.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Rockchip RV1108 Clock and Reset Unit (CRU) + +maintainers: + - Elaine Zhang + - Heiko Stuebner + +description: | + The RV1108 clock controller generates and supplies clocks to various + controllers within the SoC and also implements a reset controller for SoC + peripherals. + Each clock is assigned an identifier and client nodes can use this identifier + to specify the clock which they consume. All available clocks are defined as + preprocessor macros in the dt-bindings/clock/rv1108-cru.h headers and can be + used in device tree sources. Similar macros exist for the reset sources in + these files. + There are several clocks that are generated outside the SoC. It is expected + that they are defined using standard clock bindings with following + clock-output-names: + - "xin24m" - crystal input - required + - "ext_vip" - external VIP clock - optional + - "ext_i2s" - external I2S clock - optional + - "ext_gmac" - external GMAC clock - optional + - "hdmiphy" - external clock input derived from HDMI PHY - optional + - "usbphy" - external clock input derived from USB PHY - optional + +properties: + compatible: + enum: + - rockchip,rv1108-cru + + reg: + maxItems: 1 + + "#clock-cells": + const: 1 + + "#reset-cells": + const: 1 + + clocks: + maxItems: 1 + + clock-names: + const: xin24m + + rockchip,grf: + $ref: /schemas/types.yaml#/definitions/phandle + description: + Phandle to the syscon managing the "general register files" (GRF), + if missing pll rates are not changeable, due to the missing pll + lock status. + +required: + - compatible + - reg + - "#clock-cells" + - "#reset-cells" + +additionalProperties: false + +examples: + - | + cru: clock-controller@20200000 { + compatible = "rockchip,rv1108-cru"; + reg = <0x20200000 0x1000>; + rockchip,grf = <&grf>; + #clock-cells = <1>; + #reset-cells = <1>; + }; diff --git a/Documentation/devicetree/bindings/clock/st,stm32mp1-rcc.yaml b/Documentation/devicetree/bindings/clock/st,stm32mp1-rcc.yaml index 45b94124366c76c76d3b3e15eae31a9366def7d6..f8c4742278073f6245cda9e5481cb10c06d8ac16 100644 --- a/Documentation/devicetree/bindings/clock/st,stm32mp1-rcc.yaml +++ b/Documentation/devicetree/bindings/clock/st,stm32mp1-rcc.yaml @@ -41,6 +41,7 @@ description: | The list of valid indices for STM32MP1 is available in: include/dt-bindings/reset-controller/stm32mp1-resets.h + include/dt-bindings/reset-controller/stm32mp13-resets.h This file implements defines like: #define LTDC_R 3072 @@ -57,6 +58,7 @@ properties: - enum: - st,stm32mp1-rcc-secure - st,stm32mp1-rcc + - st,stm32mp13-rcc - const: syscon clocks: true clock-names: true diff --git a/Documentation/devicetree/bindings/clock/stericsson,u8500-clks.yaml b/Documentation/devicetree/bindings/clock/stericsson,u8500-clks.yaml index 9bc95a308477dd0a99e1267800aaa5ad9602e574..2150307219a0c18c15ee0044dc9c6740410cb3da 100644 --- a/Documentation/devicetree/bindings/clock/stericsson,u8500-clks.yaml +++ b/Documentation/devicetree/bindings/clock/stericsson,u8500-clks.yaml @@ -109,6 +109,25 @@ properties: additionalProperties: false + clkout-clock: + description: A subnode with three clock cells for externally routed clocks, + output clocks. These are two PRCMU-internal clocks that can be divided and + muxed out on the pads of the DB8500 SoC. + type: object + + properties: + '#clock-cells': + description: + The first cell indicates which output clock we are using, + possible values are 0 (CLKOUT1) and 1 (CLKOUT2). + The second cell indicates which clock we want to use as source, + possible values are 0 thru 7, see the defines for the different + source clocks. + The third cell is a divider, legal values are 1 thru 63. + const: 3 + + additionalProperties: false + required: - compatible - reg @@ -119,3 +138,41 @@ required: - smp-twd-clock additionalProperties: false + +examples: + - | + #include + clocks@8012 { + compatible = "stericsson,u8500-clks"; + reg = <0x8012f000 0x1000>, <0x8011f000 0x1000>, + <0x8000f000 0x1000>, <0xa03ff000 0x1000>, + <0xa03cf000 0x1000>; + + prcmu_clk: prcmu-clock { + #clock-cells = <1>; + }; + + prcc_pclk: prcc-periph-clock { + #clock-cells = <2>; + }; + + prcc_kclk: prcc-kernel-clock { + #clock-cells = <2>; + }; + + prcc_reset: prcc-reset-controller { + #reset-cells = <2>; + }; + + rtc_clk: rtc32k-clock { + #clock-cells = <0>; + }; + + smp_twd_clk: smp-twd-clock { + #clock-cells = <0>; + }; + + clkout_clk: clkout-clock { + #clock-cells = <3>; + }; + }; diff --git a/Documentation/devicetree/bindings/clock/ti,am654-ehrpwm-tbclk.yaml b/Documentation/devicetree/bindings/clock/ti,am654-ehrpwm-tbclk.yaml index 9b537bc876b5c8a2f824e438a1c9ffe61fcd4a3f..66765116aff5d847f07ebc0e8106ef466a8a29c2 100644 --- a/Documentation/devicetree/bindings/clock/ti,am654-ehrpwm-tbclk.yaml +++ b/Documentation/devicetree/bindings/clock/ti,am654-ehrpwm-tbclk.yaml @@ -15,6 +15,7 @@ properties: - enum: - ti,am654-ehrpwm-tbclk - ti,am64-epwm-tbclk + - ti,am62-epwm-tbclk - const: syscon "#clock-cells": diff --git a/Documentation/devicetree/bindings/cpufreq/cpufreq-mediatek.txt b/Documentation/devicetree/bindings/cpufreq/cpufreq-mediatek.txt index b8233ec91d3d4fc6a4de9beb9af68d2d43f164ca..e0a4ba599abcd074e388ffa8957bafb98f71d10a 100644 --- a/Documentation/devicetree/bindings/cpufreq/cpufreq-mediatek.txt +++ b/Documentation/devicetree/bindings/cpufreq/cpufreq-mediatek.txt @@ -20,6 +20,13 @@ Optional properties: Vsram to fit SoC specific needs. When absent, the voltage scaling flow is handled by hardware, hence no software "voltage tracking" is needed. +- mediatek,cci: + Used to confirm the link status between cpufreq and mediatek cci. Because + cpufreq and mediatek cci could share the same regulator in some MediaTek SoCs. + To prevent the issue of high frequency and low voltage, we need to use this + property to make sure mediatek cci is ready. + For details of mediatek cci, please refer to + Documentation/devicetree/bindings/interconnect/mediatek,cci.yaml - #cooling-cells: For details, please refer to Documentation/devicetree/bindings/thermal/thermal-cooling-devices.yaml diff --git a/Documentation/devicetree/bindings/crypto/ti,sa2ul.yaml b/Documentation/devicetree/bindings/crypto/ti,sa2ul.yaml index a410d2cedde6317216fa6aa188af8730fc9c66e2..02f47c2e79987f1975580c34a5f1f3f2235d96bb 100644 --- a/Documentation/devicetree/bindings/crypto/ti,sa2ul.yaml +++ b/Documentation/devicetree/bindings/crypto/ti,sa2ul.yaml @@ -15,6 +15,7 @@ properties: - ti,j721e-sa2ul - ti,am654-sa2ul - ti,am64-sa2ul + - ti,am62-sa3ul reg: maxItems: 1 diff --git a/Documentation/devicetree/bindings/dma/allwinner,sun50i-a64-dma.yaml b/Documentation/devicetree/bindings/dma/allwinner,sun50i-a64-dma.yaml index b6e1ebfaf3666941646efeae2f9a5942668627f6..ff0a5c58d78ccd6537d98dc20a9d07effc3636aa 100644 --- a/Documentation/devicetree/bindings/dma/allwinner,sun50i-a64-dma.yaml +++ b/Documentation/devicetree/bindings/dma/allwinner,sun50i-a64-dma.yaml @@ -20,9 +20,11 @@ properties: compatible: oneOf: - - const: allwinner,sun50i-a64-dma - - const: allwinner,sun50i-a100-dma - - const: allwinner,sun50i-h6-dma + - enum: + - allwinner,sun20i-d1-dma + - allwinner,sun50i-a64-dma + - allwinner,sun50i-a100-dma + - allwinner,sun50i-h6-dma - items: - const: allwinner,sun8i-r40-dma - const: allwinner,sun50i-a64-dma @@ -58,6 +60,7 @@ if: properties: compatible: enum: + - allwinner,sun20i-d1-dma - allwinner,sun50i-a100-dma - allwinner,sun50i-h6-dma diff --git a/Documentation/devicetree/bindings/dma/altr,msgdma.yaml b/Documentation/devicetree/bindings/dma/altr,msgdma.yaml index b193ee2db4a7d6b1516ee4ebf1dc83768cf8f2f1..b53ac7631a76539afaa0067356bd9c4236d373f6 100644 --- a/Documentation/devicetree/bindings/dma/altr,msgdma.yaml +++ b/Documentation/devicetree/bindings/dma/altr,msgdma.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Altera mSGDMA IP core maintainers: - - Olivier Dautricourt + - Olivier Dautricourt description: | Altera / Intel modular Scatter-Gather Direct Memory Access (mSGDMA) diff --git a/Documentation/devicetree/bindings/dma/arm,pl330.yaml b/Documentation/devicetree/bindings/dma/arm,pl330.yaml index decab185cf4d323ce7552dd05a8c3d9f8d28343e..2bec69b308f8665d64d86af4d9a28557022cfda0 100644 --- a/Documentation/devicetree/bindings/dma/arm,pl330.yaml +++ b/Documentation/devicetree/bindings/dma/arm,pl330.yaml @@ -55,6 +55,9 @@ properties: dma-coherent: true + power-domains: + maxItems: 1 + resets: minItems: 1 maxItems: 2 diff --git a/Documentation/devicetree/bindings/dma/mmp-dma.txt b/Documentation/devicetree/bindings/dma/mmp-dma.txt index 8f7364a7b349edc76bdad6737234dd97907c75d4..ec18bf0a802a7948fbe70a2ff4aca6f5449fd79e 100644 --- a/Documentation/devicetree/bindings/dma/mmp-dma.txt +++ b/Documentation/devicetree/bindings/dma/mmp-dma.txt @@ -10,10 +10,12 @@ Required properties: or one irq for pdma device Optional properties: -- #dma-channels: Number of DMA channels supported by the controller (defaults +- dma-channels: Number of DMA channels supported by the controller (defaults to 32 when not specified) -- #dma-requests: Number of DMA requestor lines supported by the controller +- #dma-channels: deprecated +- dma-requests: Number of DMA requestor lines supported by the controller (defaults to 32 when not specified) +- #dma-requests: deprecated "marvell,pdma-1.0" Used platforms: pxa25x, pxa27x, pxa3xx, pxa93x, pxa168, pxa910, pxa688. @@ -33,7 +35,7 @@ pdma: dma-controller@d4000000 { reg = <0xd4000000 0x10000>; interrupts = <0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15>; interrupt-parent = <&intcmux32>; - #dma-channels = <16>; + dma-channels = <16>; }; /* @@ -45,7 +47,7 @@ pdma: dma-controller@d4000000 { compatible = "marvell,pdma-1.0"; reg = <0xd4000000 0x10000>; interrupts = <47>; - #dma-channels = <16>; + dma-channels = <16>; }; diff --git a/Documentation/devicetree/bindings/dma/nvidia,tegra186-gpc-dma.yaml b/Documentation/devicetree/bindings/dma/nvidia,tegra186-gpc-dma.yaml new file mode 100644 index 0000000000000000000000000000000000000000..9dd1476d1849ad5f5b250ad4712b7a69103de249 --- /dev/null +++ b/Documentation/devicetree/bindings/dma/nvidia,tegra186-gpc-dma.yaml @@ -0,0 +1,110 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/dma/nvidia,tegra186-gpc-dma.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: NVIDIA Tegra GPC DMA Controller Device Tree Bindings + +description: | + The Tegra General Purpose Central (GPC) DMA controller is used for faster + data transfers between memory to memory, memory to device and device to + memory. + +maintainers: + - Jon Hunter + - Rajesh Gumasta + +allOf: + - $ref: "dma-controller.yaml#" + +properties: + compatible: + oneOf: + - const: nvidia,tegra186-gpcdma + - items: + - const: nvidia,tegra194-gpcdma + - const: nvidia,tegra186-gpcdma + + "#dma-cells": + const: 1 + + reg: + maxItems: 1 + + interrupts: + description: + Should contain all of the per-channel DMA interrupts in + ascending order with respect to the DMA channel index. + minItems: 1 + maxItems: 31 + + resets: + maxItems: 1 + + reset-names: + const: gpcdma + + iommus: + maxItems: 1 + + dma-coherent: true + +required: + - compatible + - reg + - interrupts + - resets + - reset-names + - "#dma-cells" + - iommus + +additionalProperties: false + +examples: + - | + #include + #include + #include + + dma-controller@2600000 { + compatible = "nvidia,tegra186-gpcdma"; + reg = <0x2600000 0x210000>; + resets = <&bpmp TEGRA186_RESET_GPCDMA>; + reset-names = "gpcdma"; + interrupts = , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + #dma-cells = <1>; + iommus = <&smmu TEGRA186_SID_GPCDMA_0>; + dma-coherent; + }; +... diff --git a/Documentation/devicetree/bindings/dma/qcom,gpi.yaml b/Documentation/devicetree/bindings/dma/qcom,gpi.yaml index d09d79d7406a3aa8378591c37c763f85683e197f..7d2fc4eb55305eb683008f342f7dbb6e4cd01f35 100644 --- a/Documentation/devicetree/bindings/dma/qcom,gpi.yaml +++ b/Documentation/devicetree/bindings/dma/qcom,gpi.yaml @@ -19,9 +19,12 @@ allOf: properties: compatible: enum: + - qcom,sc7280-gpi-dma - qcom,sdm845-gpi-dma - qcom,sm8150-gpi-dma - qcom,sm8250-gpi-dma + - qcom,sm8350-gpi-dma + - qcom,sm8450-gpi-dma reg: maxItems: 1 diff --git a/Documentation/devicetree/bindings/dma/renesas,rcar-dmac.yaml b/Documentation/devicetree/bindings/dma/renesas,rcar-dmac.yaml index 7c6badf39921b6602f6c3708b0b9cc19669c4d4b..7202cd68e7597dc23fffdafdf5537963e0b3fbba 100644 --- a/Documentation/devicetree/bindings/dma/renesas,rcar-dmac.yaml +++ b/Documentation/devicetree/bindings/dma/renesas,rcar-dmac.yaml @@ -42,11 +42,10 @@ properties: - const: renesas,rcar-dmac - items: - - const: renesas,dmac-r8a779a0 # R-Car V3U - - - items: - - const: renesas,dmac-r8a779f0 # R-Car S4-8 - - const: renesas,rcar-gen4-dmac + - enum: + - renesas,dmac-r8a779a0 # R-Car V3U + - renesas,dmac-r8a779f0 # R-Car S4-8 + - const: renesas,rcar-gen4-dmac # R-Car Gen4 reg: true @@ -121,7 +120,6 @@ if: compatible: contains: enum: - - renesas,dmac-r8a779a0 - renesas,rcar-gen4-dmac then: properties: diff --git a/Documentation/devicetree/bindings/dma/renesas,rzn1-dmamux.yaml b/Documentation/devicetree/bindings/dma/renesas,rzn1-dmamux.yaml new file mode 100644 index 0000000000000000000000000000000000000000..d83013b0dd74c0f55d912ffc3c4ffd26cd2975cb --- /dev/null +++ b/Documentation/devicetree/bindings/dma/renesas,rzn1-dmamux.yaml @@ -0,0 +1,51 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/dma/renesas,rzn1-dmamux.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Renesas RZ/N1 DMA mux + +maintainers: + - Miquel Raynal + +allOf: + - $ref: "dma-router.yaml#" + +properties: + compatible: + const: renesas,rzn1-dmamux + + reg: + maxItems: 1 + description: DMA mux first register offset within the system control parent. + + '#dma-cells': + const: 6 + description: + The first four cells are dedicated to the master DMA controller. The fifth + cell gives the DMA mux bit index that must be set starting from 0. The + sixth cell gives the binary value that must be written there, ie. 0 or 1. + + dma-masters: + minItems: 1 + maxItems: 2 + + dma-requests: + const: 32 + +required: + - reg + - dma-requests + +additionalProperties: false + +examples: + - | + dma-router@a0 { + compatible = "renesas,rzn1-dmamux"; + reg = <0xa0 4>; + #dma-cells = <6>; + dma-masters = <&dma0 &dma1>; + dma-requests = <32>; + }; diff --git a/Documentation/devicetree/bindings/dma/sifive,fu540-c000-pdma.yaml b/Documentation/devicetree/bindings/dma/sifive,fu540-c000-pdma.yaml index 47c46af255368e7866a35428a1db6d8649341ddb..3271755787b413b5be31c357711d0144f5f24836 100644 --- a/Documentation/devicetree/bindings/dma/sifive,fu540-c000-pdma.yaml +++ b/Documentation/devicetree/bindings/dma/sifive,fu540-c000-pdma.yaml @@ -28,7 +28,15 @@ allOf: properties: compatible: items: - - const: sifive,fu540-c000-pdma + - enum: + - sifive,fu540-c000-pdma + - const: sifive,pdma0 + description: + Should be "sifive,-pdma" and "sifive,pdma". + Supported compatible strings are - + "sifive,fu540-c000-pdma" for the SiFive PDMA v0 as integrated onto the + SiFive FU540 chip resp and "sifive,pdma0" for the SiFive PDMA v0 IP block + with no chip integration tweaks. reg: maxItems: 1 @@ -37,6 +45,12 @@ properties: minItems: 1 maxItems: 8 + dma-channels: + description: For backwards-compatibility, the default value is 4 + minimum: 1 + maximum: 4 + default: 4 + '#dma-cells': const: 1 @@ -50,8 +64,9 @@ unevaluatedProperties: false examples: - | dma-controller@3000000 { - compatible = "sifive,fu540-c000-pdma"; + compatible = "sifive,fu540-c000-pdma", "sifive,pdma0"; reg = <0x3000000 0x8000>; + dma-channels = <4>; interrupts = <23>, <24>, <25>, <26>, <27>, <28>, <29>, <30>; #dma-cells = <1>; }; diff --git a/Documentation/devicetree/bindings/dma/snps,dma-spear1340.yaml b/Documentation/devicetree/bindings/dma/snps,dma-spear1340.yaml index 6b35089ac0172a123e68c3fb013894ce518e08be..c13649bf7f19e6c166d38a78829b5a15607bf9c3 100644 --- a/Documentation/devicetree/bindings/dma/snps,dma-spear1340.yaml +++ b/Documentation/devicetree/bindings/dma/snps,dma-spear1340.yaml @@ -15,7 +15,13 @@ allOf: properties: compatible: - const: snps,dma-spear1340 + oneOf: + - const: snps,dma-spear1340 + - items: + - enum: + - renesas,r9a06g032-dma + - const: renesas,rzn1-dma + "#dma-cells": minimum: 3 diff --git a/Documentation/devicetree/bindings/dma/sprd-dma.txt b/Documentation/devicetree/bindings/dma/sprd-dma.txt index adccea9941f1bc493c382e9ef146e2b38bfb2934..c7e9b5fd50e74d0e0ce0bfe403cb5158a37717e9 100644 --- a/Documentation/devicetree/bindings/dma/sprd-dma.txt +++ b/Documentation/devicetree/bindings/dma/sprd-dma.txt @@ -8,10 +8,13 @@ Required properties: - interrupts: Should contain one interrupt shared by all channel. - #dma-cells: must be <1>. Used to represent the number of integer cells in the dmas property of client device. -- #dma-channels : Number of DMA channels supported. Should be 32. +- dma-channels : Number of DMA channels supported. Should be 32. - clock-names: Should contain the clock of the DMA controller. - clocks: Should contain a clock specifier for each entry in clock-names. +Deprecated properties: +- #dma-channels : Number of DMA channels supported. Should be 32. + Example: Controller: @@ -20,7 +23,7 @@ apdma: dma-controller@20100000 { reg = <0x20100000 0x4000>; interrupts = ; #dma-cells = <1>; - #dma-channels = <32>; + dma-channels = <32>; clock-names = "enable"; clocks = <&clk_ap_ahb_gates 5>; }; diff --git a/Documentation/devicetree/bindings/dma/xilinx/xilinx_dma.txt b/Documentation/devicetree/bindings/dma/xilinx/xilinx_dma.txt index 325aca52cd438b8508ac4608050759e5e7c86dc0..d1700a5c36bf835abf6753459e57870ed8c9bdc7 100644 --- a/Documentation/devicetree/bindings/dma/xilinx/xilinx_dma.txt +++ b/Documentation/devicetree/bindings/dma/xilinx/xilinx_dma.txt @@ -110,7 +110,11 @@ axi_vdma_0: axivdma@40030000 { Required properties: - dmas: a list of <[Video DMA device phandle] [Channel ID]> pairs, where Channel ID is '0' for write/tx and '1' for read/rx - channel. + channel. For MCMDA, MM2S channel(write/tx) ID start from + '0' and is in [0-15] range. S2MM channel(read/rx) ID start + from '16' and is in [16-31] range. These channels ID are + fixed irrespective of IP configuration. + - dma-names: a list of DMA channel names, one per "dmas" entry Example: diff --git a/Documentation/devicetree/bindings/i2c/renesas,rcar-i2c.yaml b/Documentation/devicetree/bindings/i2c/renesas,rcar-i2c.yaml index c30107833a5145f9b7a6693cb060fd028334b245..f9929578c7613f0799d774ed28a00a5b745c01a2 100644 --- a/Documentation/devicetree/bindings/i2c/renesas,rcar-i2c.yaml +++ b/Documentation/devicetree/bindings/i2c/renesas,rcar-i2c.yaml @@ -46,11 +46,11 @@ properties: - renesas,i2c-r8a77980 # R-Car V3H - renesas,i2c-r8a77990 # R-Car E3 - renesas,i2c-r8a77995 # R-Car D3 - - renesas,i2c-r8a779a0 # R-Car V3U - const: renesas,rcar-gen3-i2c # R-Car Gen3 and RZ/G2 - items: - enum: + - renesas,i2c-r8a779a0 # R-Car V3U - renesas,i2c-r8a779f0 # R-Car S4-8 - const: renesas,rcar-gen4-i2c # R-Car Gen4 diff --git a/Documentation/devicetree/bindings/input/allwinner,sun4i-a10-lradc-keys.yaml b/Documentation/devicetree/bindings/input/allwinner,sun4i-a10-lradc-keys.yaml index d74f2002409e4f635edc68a660fd9c17e0271fb8..3399fc288afbad8ad9d2e57120617feac31d3076 100644 --- a/Documentation/devicetree/bindings/input/allwinner,sun4i-a10-lradc-keys.yaml +++ b/Documentation/devicetree/bindings/input/allwinner,sun4i-a10-lradc-keys.yaml @@ -18,10 +18,20 @@ properties: - items: - const: allwinner,sun50i-a64-lradc - const: allwinner,sun8i-a83t-r-lradc + - const: allwinner,sun50i-r329-lradc + - items: + - const: allwinner,sun20i-d1-lradc + - const: allwinner,sun50i-r329-lradc reg: maxItems: 1 + clocks: + maxItems: 1 + + resets: + maxItems: 1 + interrupts: maxItems: 1 @@ -68,6 +78,18 @@ required: - interrupts - vref-supply +if: + properties: + compatible: + contains: + enum: + - allwinner,sun50i-r329-lradc + +then: + required: + - clocks + - resets + additionalProperties: false examples: diff --git a/Documentation/devicetree/bindings/input/azoteq,iqs7222.yaml b/Documentation/devicetree/bindings/input/azoteq,iqs7222.yaml new file mode 100644 index 0000000000000000000000000000000000000000..a3a1e5a65306ba129f273ca3fd07ae0dd07886f4 --- /dev/null +++ b/Documentation/devicetree/bindings/input/azoteq,iqs7222.yaml @@ -0,0 +1,960 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/input/azoteq,iqs7222.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Azoteq IQS7222A/B/C Capacitive Touch Controller + +maintainers: + - Jeff LaBundy + +description: | + The Azoteq IQS7222A, IQS7222B and IQS7222C are multichannel capacitive touch + controllers that feature additional sensing capabilities. + + Link to datasheets: https://www.azoteq.com/ + +properties: + compatible: + enum: + - azoteq,iqs7222a + - azoteq,iqs7222b + - azoteq,iqs7222c + + reg: + maxItems: 1 + + irq-gpios: + maxItems: 1 + description: + Specifies the GPIO connected to the device's active-low RDY output. + + reset-gpios: + maxItems: 1 + description: + Specifies the GPIO connected to the device's active-low MCLR input. The + device is temporarily held in hardware reset prior to initialization if + this property is present. + + azoteq,rf-filt-enable: + type: boolean + description: Enables the device's internal RF filter. + + azoteq,max-counts: + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1, 2, 3] + description: | + Specifies the maximum number of conversion periods (counts) that can be + reported as follows: + 0: 1023 + 1: 2047 + 2: 4095 + 3: 16384 + + azoteq,auto-mode: + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1, 2, 3] + description: | + Specifies the number of conversions to occur before an interrupt is + generated as follows: + 0: 4 + 1: 8 + 2: 16 + 3: 32 + + azoteq,ati-frac-div-fine: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 31 + description: Specifies the preloaded ATI fine fractional divider. + + azoteq,ati-frac-div-coarse: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 31 + description: Specifies the preloaded ATI coarse fractional divider. + + azoteq,ati-comp-select: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 1023 + description: Specifies the preloaded ATI compensation selection. + + azoteq,lta-beta-lp: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 15 + description: + Specifies the long-term average filter damping factor to be applied during + low-power mode. + + azoteq,lta-beta-np: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 15 + description: + Specifies the long-term average filter damping factor to be applied during + normal-power mode. + + azoteq,counts-beta-lp: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 15 + description: + Specifies the counts filter damping factor to be applied during low-power + mode. + + azoteq,counts-beta-np: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 15 + description: + Specifies the counts filter damping factor to be applied during normal- + power mode. + + azoteq,lta-fast-beta-lp: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 15 + description: + Specifies the long-term average filter fast damping factor to be applied + during low-power mode. + + azoteq,lta-fast-beta-np: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 15 + description: + Specifies the long-term average filter fast damping factor to be applied + during normal-power mode. + + azoteq,timeout-ati-ms: + multipleOf: 500 + minimum: 0 + maximum: 32767500 + description: + Specifies the delay (in ms) before ATI is retried following an ATI error. + + azoteq,rate-ati-ms: + minimum: 0 + maximum: 65535 + description: Specifies the rate (in ms) at which ATI status is evaluated. + + azoteq,timeout-np-ms: + minimum: 0 + maximum: 65535 + description: + Specifies the length of time (in ms) to wait for an event before moving + from normal-power mode to low-power mode. + + azoteq,rate-np-ms: + minimum: 0 + maximum: 3000 + description: Specifies the report rate (in ms) during normal-power mode. + + azoteq,timeout-lp-ms: + minimum: 0 + maximum: 65535 + description: + Specifies the length of time (in ms) to wait for an event before moving + from low-power mode to ultra-low-power mode. + + azoteq,rate-lp-ms: + minimum: 0 + maximum: 3000 + description: Specifies the report rate (in ms) during low-power mode. + + azoteq,timeout-ulp-ms: + minimum: 0 + maximum: 65535 + description: + Specifies the rate (in ms) at which channels not regularly sampled during + ultra-low-power mode are updated. + + azoteq,rate-ulp-ms: + minimum: 0 + maximum: 3000 + description: Specifies the report rate (in ms) during ultra-low-power mode. + +patternProperties: + "^cycle-[0-9]$": + type: object + description: Represents a conversion cycle serving two sensing channels. + + properties: + azoteq,conv-period: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 255 + description: Specifies the cycle's conversion period. + + azoteq,conv-frac: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 255 + description: Specifies the cycle's conversion frequency fraction. + + azoteq,tx-enable: + $ref: /schemas/types.yaml#/definitions/uint32-array + minItems: 1 + maxItems: 9 + items: + minimum: 0 + maximum: 8 + description: Specifies the CTx pin(s) associated with the cycle. + + azoteq,rx-float-inactive: + type: boolean + description: Floats any inactive CRx pins instead of grounding them. + + azoteq,dead-time-enable: + type: boolean + description: + Increases the denominator of the conversion frequency formula by one. + + azoteq,tx-freq-fosc: + type: boolean + description: + Fixes the conversion frequency to that of the device's core clock. + + azoteq,vbias-enable: + type: boolean + description: Enables the bias voltage for use during inductive sensing. + + azoteq,sense-mode: + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1, 2, 3] + description: | + Specifies the cycle's sensing mode as follows: + 0: None + 1: Self capacitive + 2: Mutual capacitive + 3: Inductive + + Note that in the case of IQS7222A, cycles 5 and 6 are restricted to + Hall-effect sensing. + + azoteq,iref-enable: + type: boolean + description: + Enables the current reference for use during various sensing modes. + + azoteq,iref-level: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 15 + description: Specifies the cycle's current reference level. + + azoteq,iref-trim: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 15 + description: Specifies the cycle's current reference trim. + + dependencies: + azoteq,iref-level: ["azoteq,iref-enable"] + azoteq,iref-trim: ["azoteq,iref-enable"] + + additionalProperties: false + + "^channel-([0-9]|1[0-9])$": + type: object + description: + Represents a single sensing channel. A channel is active if defined and + inactive otherwise. + + Note that in the case of IQS7222A, channels 10 and 11 are restricted to + Hall-effect sensing with events reported on channel 10 only. + + properties: + azoteq,ulp-allow: + type: boolean + description: + Permits the device to enter ultra-low-power mode while the channel + lies in a state of touch or proximity. + + azoteq,ref-select: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 9 + description: Specifies a separate reference channel to be followed. + + azoteq,ref-weight: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 65535 + description: Specifies the relative weight of the reference channel. + + azoteq,use-prox: + type: boolean + description: + Activates the reference channel in response to proximity events + instead of touch events. + + azoteq,ati-band: + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1, 2, 3] + description: | + Specifies the channel's ATI band as a fraction of its ATI target as + follows: + 0: 1/16 + 1: 1/8 + 2: 1/4 + 3: 1/2 + + azoteq,global-halt: + type: boolean + description: + Specifies that the channel's long-term average is to freeze if any + other participating channel lies in a proximity or touch state. + + azoteq,invert-enable: + type: boolean + description: + Inverts the polarity of the states reported for proximity and touch + events relative to their respective thresholds. + + azoteq,dual-direction: + type: boolean + description: + Specifies that the channel's long-term average is to freeze in the + presence of either increasing or decreasing counts, thereby permit- + ting events to be reported in either direction. + + azoteq,rx-enable: + $ref: /schemas/types.yaml#/definitions/uint32-array + minItems: 1 + maxItems: 4 + items: + minimum: 0 + maximum: 7 + description: Specifies the CRx pin(s) associated with the channel. + + azoteq,samp-cap-double: + type: boolean + description: Doubles the sampling capacitance from 40 pF to 80 pF. + + azoteq,vref-half: + type: boolean + description: Halves the discharge threshold from 1.0 V to 0.5 V. + + azoteq,proj-bias: + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1, 2, 3] + description: | + Specifies the bias current applied during mutual (projected) + capacitive sensing as follows: + 0: 2 uA + 1: 5 uA + 2: 7 uA + 3: 10 uA + + azoteq,ati-target: + $ref: /schemas/types.yaml#/definitions/uint32 + multipleOf: 8 + minimum: 0 + maximum: 2040 + description: Specifies the channel's ATI target. + + azoteq,ati-base: + $ref: /schemas/types.yaml#/definitions/uint32 + multipleOf: 16 + minimum: 0 + maximum: 496 + description: Specifies the channel's ATI base. + + azoteq,ati-mode: + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1, 2, 3, 4, 5] + description: | + Specifies the channel's ATI mode as follows: + 0: Disabled + 1: Compensation + 2: Compensation divider + 3: Fine fractional divider + 4: Coarse fractional divider + 5: Full + + azoteq,ati-frac-div-fine: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 31 + description: Specifies the channel's ATI fine fractional divider. + + azoteq,ati-frac-mult-coarse: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 15 + description: Specifies the channel's ATI coarse fractional multiplier. + + azoteq,ati-frac-div-coarse: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 31 + description: Specifies the channel's ATI coarse fractional divider. + + azoteq,ati-comp-div: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 31 + description: Specifies the channel's ATI compensation divider. + + azoteq,ati-comp-select: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 1023 + description: Specifies the channel's ATI compensation selection. + + azoteq,debounce-enter: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 15 + description: Specifies the channel's debounce entrance factor. + + azoteq,debounce-exit: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 15 + description: Specifies the channel's debounce exit factor. + + patternProperties: + "^event-(prox|touch)$": + type: object + description: + Represents a proximity or touch event reported by the channel. + + properties: + azoteq,gpio-select: + $ref: /schemas/types.yaml#/definitions/uint32-array + minItems: 1 + maxItems: 3 + items: + minimum: 0 + maximum: 2 + description: | + Specifies one or more GPIO mapped to the event as follows: + 0: GPIO0 + 1: GPIO3 (IQS7222C only) + 2: GPIO4 (IQS7222C only) + + Note that although multiple events can be mapped to a single + GPIO, they must all be of the same type (proximity, touch or + slider gesture). + + azoteq,thresh: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + Specifies the threshold for the event. Valid entries range from + 0-127 and 0-255 for proximity and touch events, respectively. + + azoteq,hyst: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 255 + description: + Specifies the hysteresis for the event (touch events only). + + azoteq,timeout-press-ms: + multipleOf: 500 + minimum: 0 + maximum: 127500 + description: + Specifies the length of time (in ms) to wait before automatically + releasing a press event. Specify zero to allow the press state to + persist indefinitely. + + The IQS7222B does not feature channel-specific timeouts; the time- + out specified for any one channel applies to all channels. + + linux,code: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + Numeric key or switch code associated with the event. Specify + KEY_RESERVED (0) to opt out of event reporting. + + linux,input-type: + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [1, 5] + default: 1 + description: + Specifies whether the event is to be interpreted as a key (1) + or a switch (5). + + required: + - linux,code + + additionalProperties: false + + dependencies: + azoteq,ref-weight: ["azoteq,ref-select"] + azoteq,use-prox: ["azoteq,ref-select"] + + additionalProperties: false + + "^slider-[0-1]$": + type: object + description: Represents a slider comprising three or four channels. + + properties: + azoteq,channel-select: + $ref: /schemas/types.yaml#/definitions/uint32-array + minItems: 3 + maxItems: 4 + items: + minimum: 0 + maximum: 9 + description: + Specifies the order of the channels that participate in the slider. + + azoteq,slider-size: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 65535 + description: + Specifies the slider's one-dimensional resolution, equal to the + maximum coordinate plus one. + + azoteq,lower-cal: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 255 + description: Specifies the slider's lower starting point. + + azoteq,upper-cal: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 255 + description: Specifies the slider's upper starting point. + + azoteq,top-speed: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 65535 + description: + Specifies the speed of movement after which coordinate filtering is + no longer applied. + + azoteq,bottom-speed: + $ref: /schemas/types.yaml#/definitions/uint32 + multipleOf: 4 + minimum: 0 + maximum: 1020 + description: + Specifies the speed of movement after which coordinate filtering is + linearly reduced. + + azoteq,bottom-beta: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 7 + description: + Specifies the coordinate filter damping factor to be applied + while the speed of movement is below that which is specified + by azoteq,bottom-speed. + + azoteq,static-beta: + type: boolean + description: + Applies the coordinate filter damping factor specified by + azoteq,bottom-beta regardless of the speed of movement. + + azoteq,use-prox: + type: boolean + description: + Directs the slider to respond to the proximity states of the selected + channels instead of their corresponding touch states. Note the slider + cannot report granular coordinates during a state of proximity. + + linux,axis: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + Specifies the absolute axis to which coordinates are mapped. Specify + ABS_WHEEL to operate the slider as a wheel (IQS7222C only). + + patternProperties: + "^event-(press|tap|(swipe|flick)-(pos|neg))$": + type: object + description: + Represents a press or gesture (IQS7222A only) event reported by + the slider. + + properties: + linux,code: + $ref: /schemas/types.yaml#/definitions/uint32 + description: Numeric key code associated with the event. + + azoteq,gesture-max-ms: + multipleOf: 4 + minimum: 0 + maximum: 1020 + description: + Specifies the length of time (in ms) within which a tap, swipe + or flick gesture must be completed in order to be acknowledged + by the device. The number specified for any one swipe or flick + gesture applies to all remaining swipe or flick gestures. + + azoteq,gesture-min-ms: + multipleOf: 4 + minimum: 0 + maximum: 124 + description: + Specifies the length of time (in ms) for which a tap gesture must + be held in order to be acknowledged by the device. + + azoteq,gesture-dist: + $ref: /schemas/types.yaml#/definitions/uint32 + multipleOf: 16 + minimum: 0 + maximum: 4080 + description: + Specifies the distance across which a swipe or flick gesture must + travel in order to be acknowledged by the device. The number spec- + ified for any one swipe or flick gesture applies to all remaining + swipe or flick gestures. + + azoteq,gpio-select: + $ref: /schemas/types.yaml#/definitions/uint32-array + minItems: 1 + maxItems: 1 + items: + minimum: 0 + maximum: 0 + description: | + Specifies an individual GPIO mapped to a tap, swipe or flick + gesture as follows: + 0: GPIO0 + 1: GPIO3 (reserved) + 2: GPIO4 (reserved) + + Note that although multiple events can be mapped to a single + GPIO, they must all be of the same type (proximity, touch or + slider gesture). + + required: + - linux,code + + additionalProperties: false + + required: + - azoteq,channel-select + + additionalProperties: false + + "^gpio-[0-2]$": + type: object + description: | + Represents a GPIO mapped to one or more events as follows: + gpio-0: GPIO0 + gpio-1: GPIO3 (IQS7222C only) + gpio-2: GPIO4 (IQS7222C only) + + allOf: + - $ref: ../pinctrl/pincfg-node.yaml# + + properties: + drive-open-drain: true + + additionalProperties: false + +allOf: + - if: + properties: + compatible: + contains: + const: azoteq,iqs7222b + + then: + patternProperties: + "^cycle-[0-9]$": + properties: + azoteq,iref-enable: false + + "^channel-([0-9]|1[0-9])$": + properties: + azoteq,ref-select: false + + patternProperties: + "^event-(prox|touch)$": + properties: + azoteq,gpio-select: false + + "^slider-[0-1]$": false + + "^gpio-[0-2]$": false + + - if: + properties: + compatible: + contains: + const: azoteq,iqs7222a + + then: + patternProperties: + "^channel-([0-9]|1[0-9])$": + patternProperties: + "^event-(prox|touch)$": + properties: + azoteq,gpio-select: + maxItems: 1 + items: + maximum: 0 + + "^slider-[0-1]$": + properties: + azoteq,slider-size: + multipleOf: 16 + maximum: 4080 + + azoteq,top-speed: + multipleOf: 4 + maximum: 1020 + + else: + patternProperties: + "^channel-([0-9]|1[0-9])$": + properties: + azoteq,ulp-allow: false + + "^slider-[0-1]$": + patternProperties: + "^event-(press|tap|(swipe|flick)-(pos|neg))$": + properties: + azoteq,gesture-max-ms: false + + azoteq,gesture-min-ms: false + + azoteq,gesture-dist: false + + azoteq,gpio-select: false + +required: + - compatible + - reg + - irq-gpios + +additionalProperties: false + +examples: + - | + #include + #include + + i2c { + #address-cells = <1>; + #size-cells = <0>; + + iqs7222a@44 { + compatible = "azoteq,iqs7222a"; + reg = <0x44>; + irq-gpios = <&gpio 4 GPIO_ACTIVE_LOW>; + azoteq,lta-beta-lp = <7>; + azoteq,lta-beta-np = <8>; + azoteq,counts-beta-lp = <2>; + azoteq,counts-beta-np = <3>; + azoteq,lta-fast-beta-lp = <3>; + azoteq,lta-fast-beta-np = <4>; + + cycle-0 { + azoteq,conv-period = <5>; + azoteq,conv-frac = <127>; + azoteq,tx-enable = <1>, <2>, <4>, <5>; + azoteq,dead-time-enable; + azoteq,sense-mode = <2>; + }; + + cycle-1 { + azoteq,conv-period = <5>; + azoteq,conv-frac = <127>; + azoteq,tx-enable = <5>; + azoteq,dead-time-enable; + azoteq,sense-mode = <2>; + }; + + cycle-2 { + azoteq,conv-period = <5>; + azoteq,conv-frac = <127>; + azoteq,tx-enable = <4>; + azoteq,dead-time-enable; + azoteq,sense-mode = <2>; + }; + + cycle-3 { + azoteq,conv-period = <5>; + azoteq,conv-frac = <127>; + azoteq,tx-enable = <2>; + azoteq,dead-time-enable; + azoteq,sense-mode = <2>; + }; + + cycle-4 { + azoteq,conv-period = <5>; + azoteq,conv-frac = <127>; + azoteq,tx-enable = <1>; + azoteq,dead-time-enable; + azoteq,sense-mode = <2>; + }; + + cycle-5 { + azoteq,conv-period = <2>; + azoteq,conv-frac = <0>; + }; + + cycle-6 { + azoteq,conv-period = <2>; + azoteq,conv-frac = <0>; + }; + + channel-0 { + azoteq,ulp-allow; + azoteq,global-halt; + azoteq,invert-enable; + azoteq,rx-enable = <3>; + azoteq,ati-target = <800>; + azoteq,ati-base = <208>; + azoteq,ati-mode = <5>; + }; + + channel-1 { + azoteq,global-halt; + azoteq,invert-enable; + azoteq,rx-enable = <3>; + azoteq,ati-target = <496>; + azoteq,ati-base = <208>; + azoteq,ati-mode = <5>; + }; + + channel-2 { + azoteq,global-halt; + azoteq,invert-enable; + azoteq,rx-enable = <3>; + azoteq,ati-target = <496>; + azoteq,ati-base = <208>; + azoteq,ati-mode = <5>; + }; + + channel-3 { + azoteq,global-halt; + azoteq,invert-enable; + azoteq,rx-enable = <3>; + azoteq,ati-target = <496>; + azoteq,ati-base = <208>; + azoteq,ati-mode = <5>; + }; + + channel-4 { + azoteq,global-halt; + azoteq,invert-enable; + azoteq,rx-enable = <3>; + azoteq,ati-target = <496>; + azoteq,ati-base = <208>; + azoteq,ati-mode = <5>; + }; + + channel-5 { + azoteq,ulp-allow; + azoteq,global-halt; + azoteq,invert-enable; + azoteq,rx-enable = <6>; + azoteq,ati-target = <800>; + azoteq,ati-base = <144>; + azoteq,ati-mode = <5>; + }; + + channel-6 { + azoteq,global-halt; + azoteq,invert-enable; + azoteq,rx-enable = <6>; + azoteq,ati-target = <496>; + azoteq,ati-base = <160>; + azoteq,ati-mode = <5>; + + event-touch { + linux,code = ; + }; + }; + + channel-7 { + azoteq,global-halt; + azoteq,invert-enable; + azoteq,rx-enable = <6>; + azoteq,ati-target = <496>; + azoteq,ati-base = <160>; + azoteq,ati-mode = <5>; + + event-touch { + linux,code = ; + }; + }; + + channel-8 { + azoteq,global-halt; + azoteq,invert-enable; + azoteq,rx-enable = <6>; + azoteq,ati-target = <496>; + azoteq,ati-base = <160>; + azoteq,ati-mode = <5>; + + event-touch { + linux,code = ; + }; + }; + + channel-9 { + azoteq,global-halt; + azoteq,invert-enable; + azoteq,rx-enable = <6>; + azoteq,ati-target = <496>; + azoteq,ati-base = <160>; + azoteq,ati-mode = <5>; + + event-touch { + linux,code = ; + }; + }; + + channel-10 { + azoteq,ulp-allow; + azoteq,ati-target = <496>; + azoteq,ati-base = <112>; + + event-touch { + linux,code = ; + linux,input-type = ; + }; + }; + + channel-11 { + azoteq,ati-target = <496>; + azoteq,ati-base = <112>; + }; + + slider-0 { + azoteq,channel-select = <1>, <2>, <3>, <4>; + azoteq,slider-size = <4080>; + azoteq,upper-cal = <50>; + azoteq,lower-cal = <30>; + azoteq,top-speed = <200>; + azoteq,bottom-speed = <1>; + azoteq,bottom-beta = <3>; + + event-tap { + linux,code = ; + azoteq,gesture-max-ms = <600>; + azoteq,gesture-min-ms = <24>; + }; + + event-flick-pos { + linux,code = ; + azoteq,gesture-max-ms = <600>; + azoteq,gesture-dist = <816>; + }; + + event-flick-neg { + linux,code = ; + }; + }; + }; + }; + +... diff --git a/Documentation/devicetree/bindings/input/google,cros-ec-keyb.yaml b/Documentation/devicetree/bindings/input/google,cros-ec-keyb.yaml index aa61fe64be63ccb99976584d1851b19b2a6cd777..e05690b3e963cf407cfe4a24fd7b66618c71aae2 100644 --- a/Documentation/devicetree/bindings/input/google,cros-ec-keyb.yaml +++ b/Documentation/devicetree/bindings/input/google,cros-ec-keyb.yaml @@ -15,14 +15,16 @@ description: | Google's ChromeOS EC Keyboard is a simple matrix keyboard implemented on a separate EC (Embedded Controller) device. It provides a message for reading key scans from the EC. These are then converted - into keycodes for processing by the kernel. - -allOf: - - $ref: "/schemas/input/matrix-keymap.yaml#" + into keycodes for processing by the kernel. This device also supports + switches/buttons like power and volume buttons. properties: compatible: - const: google,cros-ec-keyb + oneOf: + - description: ChromeOS EC with only buttons/switches + const: google,cros-ec-keyb-switches + - description: ChromeOS EC with keyboard and possibly buttons/switches + const: google,cros-ec-keyb google,needs-ghost-filter: description: @@ -42,15 +44,31 @@ properties: where the lower 16 bits are reserved. This property is specified only when the keyboard has a custom design for the top row keys. +dependencies: + function-row-phsymap: [ 'linux,keymap' ] + google,needs-ghost-filter: [ 'linux,keymap' ] + required: - compatible +if: + properties: + compatible: + contains: + const: google,cros-ec-keyb +then: + $ref: "/schemas/input/matrix-keymap.yaml#" + required: + - keypad,num-rows + - keypad,num-columns + - linux,keymap + unevaluatedProperties: false examples: - | #include - cros-ec-keyb { + keyboard-controller { compatible = "google,cros-ec-keyb"; keypad,num-rows = <8>; keypad,num-columns = <13>; @@ -114,3 +132,9 @@ examples: /* UP LEFT */ 0x070b0067 0x070c0069>; }; + - | + /* No matrix keyboard, just buttons/switches */ + keyboard-controller { + compatible = "google,cros-ec-keyb-switches"; + }; +... diff --git a/Documentation/devicetree/bindings/interrupt-controller/qcom,pdc.txt b/Documentation/devicetree/bindings/interrupt-controller/qcom,pdc.txt index 3b7b1134dea99785b55640ace51397aeace70244..159a423e558690b9f09f1c16e07f2aad7b7b63d0 100644 --- a/Documentation/devicetree/bindings/interrupt-controller/qcom,pdc.txt +++ b/Documentation/devicetree/bindings/interrupt-controller/qcom,pdc.txt @@ -22,6 +22,7 @@ Properties: - "qcom,sc7280-pdc": For SC7280 - "qcom,sdm845-pdc": For SDM845 - "qcom,sm6350-pdc": For SM6350 + - "qcom,sm8150-pdc": For SM8150 - "qcom,sm8250-pdc": For SM8250 - "qcom,sm8350-pdc": For SM8350 diff --git a/Documentation/devicetree/bindings/iommu/arm,smmu.yaml b/Documentation/devicetree/bindings/iommu/arm,smmu.yaml index da5381c8ee11cf3f0911d4e06f6bcb459600e5aa..76fc2c0f4d54912045b2683e12e1ad67159ffc42 100644 --- a/Documentation/devicetree/bindings/iommu/arm,smmu.yaml +++ b/Documentation/devicetree/bindings/iommu/arm,smmu.yaml @@ -37,8 +37,10 @@ properties: - qcom,sc7180-smmu-500 - qcom,sc7280-smmu-500 - qcom,sc8180x-smmu-500 + - qcom,sc8280xp-smmu-500 - qcom,sdm845-smmu-500 - qcom,sdx55-smmu-500 + - qcom,sdx65-smmu-500 - qcom,sm6350-smmu-500 - qcom,sm8150-smmu-500 - qcom,sm8250-smmu-500 @@ -62,8 +64,9 @@ properties: for improved performance. items: - enum: - - nvidia,tegra194-smmu - nvidia,tegra186-smmu + - nvidia,tegra194-smmu + - nvidia,tegra234-smmu - const: nvidia,smmu-500 - items: - const: arm,mmu-500 @@ -157,6 +160,17 @@ properties: power-domains: maxItems: 1 + nvidia,memory-controller: + description: | + A phandle to the memory controller on NVIDIA Tegra186 and later SoCs. + The memory controller needs to be programmed with a mapping of memory + client IDs to ARM SMMU stream IDs. + + If this property is absent, the mapping programmed by early firmware + will be used and it is not guaranteed that IOMMU translations will be + enabled for any given device. + $ref: /schemas/types.yaml#/definitions/phandle + required: - compatible - reg @@ -172,13 +186,20 @@ allOf: compatible: contains: enum: - - nvidia,tegra194-smmu - nvidia,tegra186-smmu + - nvidia,tegra194-smmu + - nvidia,tegra234-smmu then: properties: reg: minItems: 1 maxItems: 2 + + # The reference to the memory controller is required to ensure that the + # memory client to stream ID mapping can be done synchronously with the + # IOMMU attachment. + required: + - nvidia,memory-controller else: properties: reg: diff --git a/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml b/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml index 97e8c471a5e8df25fb480a8cb360017678d49ef6..2ae3bbad7f1a4c5370bb39cea8edac8d6671e900 100644 --- a/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml +++ b/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml @@ -76,7 +76,11 @@ properties: - mediatek,mt8167-m4u # generation two - mediatek,mt8173-m4u # generation two - mediatek,mt8183-m4u # generation two + - mediatek,mt8186-iommu-mm # generation two - mediatek,mt8192-m4u # generation two + - mediatek,mt8195-iommu-vdo # generation two + - mediatek,mt8195-iommu-vpp # generation two + - mediatek,mt8195-iommu-infra # generation two - description: mt7623 generation one items: @@ -119,7 +123,9 @@ properties: dt-binding/memory/mt8167-larb-port.h for mt8167, dt-binding/memory/mt8173-larb-port.h for mt8173, dt-binding/memory/mt8183-larb-port.h for mt8183, + dt-binding/memory/mt8186-memory-port.h for mt8186, dt-binding/memory/mt8192-larb-port.h for mt8192. + dt-binding/memory/mt8195-memory-port.h for mt8195. power-domains: maxItems: 1 @@ -128,7 +134,6 @@ required: - compatible - reg - interrupts - - mediatek,larbs - '#iommu-cells' allOf: @@ -140,7 +145,10 @@ allOf: - mediatek,mt2701-m4u - mediatek,mt2712-m4u - mediatek,mt8173-m4u + - mediatek,mt8186-iommu-mm - mediatek,mt8192-m4u + - mediatek,mt8195-iommu-vdo + - mediatek,mt8195-iommu-vpp then: required: @@ -150,12 +158,26 @@ allOf: properties: compatible: enum: + - mediatek,mt8186-iommu-mm - mediatek,mt8192-m4u + - mediatek,mt8195-iommu-vdo + - mediatek,mt8195-iommu-vpp then: required: - power-domains + - if: # The IOMMUs don't have larbs. + not: + properties: + compatible: + contains: + const: mediatek,mt8195-iommu-infra + + then: + required: + - mediatek,larbs + additionalProperties: false examples: @@ -173,13 +195,3 @@ examples: <&larb3>, <&larb4>, <&larb5>; #iommu-cells = <1>; }; - - - | - #include - - /* Example for a client device */ - display { - compatible = "mediatek,mt8173-disp"; - iommus = <&iommu M4U_PORT_DISP_OVL0>, - <&iommu M4U_PORT_DISP_RDMA0>; - }; diff --git a/Documentation/devicetree/bindings/iommu/samsung,sysmmu.yaml b/Documentation/devicetree/bindings/iommu/samsung,sysmmu.yaml index 783c6b37c9f0a020e7c0b677c87ff60048e760c9..672a0beea600b2b2b22e4803d75be3ce45ed3793 100644 --- a/Documentation/devicetree/bindings/iommu/samsung,sysmmu.yaml +++ b/Documentation/devicetree/bindings/iommu/samsung,sysmmu.yaml @@ -86,16 +86,6 @@ examples: - | #include - gsc_0: scaler@13e00000 { - compatible = "samsung,exynos5-gsc"; - reg = <0x13e00000 0x1000>; - interrupts = <0 85 0>; - power-domains = <&pd_gsc>; - clocks = <&clock CLK_GSCL0>; - clock-names = "gscl"; - iommus = <&sysmmu_gsc0>; - }; - sysmmu_gsc0: iommu@13e80000 { compatible = "samsung,exynos-sysmmu"; reg = <0x13E80000 0x1000>; diff --git a/Documentation/devicetree/bindings/mfd/google,cros-ec.yaml b/Documentation/devicetree/bindings/mfd/google,cros-ec.yaml index afec0bd2f1de47b3a04e12fa2cb77ff683510d09..e25caf8ef9f4e1fd4ef00388e4b0952c9f80dad0 100644 --- a/Documentation/devicetree/bindings/mfd/google,cros-ec.yaml +++ b/Documentation/devicetree/bindings/mfd/google,cros-ec.yaml @@ -57,7 +57,7 @@ properties: mediatek,rpmsg-name: description: Must be defined if the cros-ec is a rpmsg device for a Mediatek - ARM Cortex M4 Co-processor. Contains the name pf the rpmsg + ARM Cortex M4 Co-processor. Contains the name of the rpmsg device. Used to match the subnode to the rpmsg device announced by the SCP. $ref: "/schemas/types.yaml#/definitions/string" diff --git a/Documentation/devicetree/bindings/mfd/rk808.txt b/Documentation/devicetree/bindings/mfd/rk808.txt deleted file mode 100644 index 23a17a6663ec5cf48441822c16d3a02f12c2b6f1..0000000000000000000000000000000000000000 --- a/Documentation/devicetree/bindings/mfd/rk808.txt +++ /dev/null @@ -1,465 +0,0 @@ -RK8XX Power Management Integrated Circuit - -The rk8xx family current members: -rk805 -rk808 -rk809 -rk817 -rk818 - -Required properties: -- compatible: "rockchip,rk805" -- compatible: "rockchip,rk808" -- compatible: "rockchip,rk809" -- compatible: "rockchip,rk817" -- compatible: "rockchip,rk818" -- reg: I2C slave address -- interrupts: the interrupt outputs of the controller. -- #clock-cells: from common clock binding; shall be set to 1 (multiple clock - outputs). See for clock IDs. - -Optional properties: -- clock-output-names: From common clock binding to override the - default output clock name -- rockchip,system-power-controller: Telling whether or not this pmic is controlling - the system power. -- wakeup-source: Device can be used as a wakeup source. - -Optional RK805 properties: -- vcc1-supply: The input supply for DCDC_REG1 -- vcc2-supply: The input supply for DCDC_REG2 -- vcc3-supply: The input supply for DCDC_REG3 -- vcc4-supply: The input supply for DCDC_REG4 -- vcc5-supply: The input supply for LDO_REG1 and LDO_REG2 -- vcc6-supply: The input supply for LDO_REG3 - -Optional RK808 properties: -- vcc1-supply: The input supply for DCDC_REG1 -- vcc2-supply: The input supply for DCDC_REG2 -- vcc3-supply: The input supply for DCDC_REG3 -- vcc4-supply: The input supply for DCDC_REG4 -- vcc6-supply: The input supply for LDO_REG1 and LDO_REG2 -- vcc7-supply: The input supply for LDO_REG3 and LDO_REG7 -- vcc8-supply: The input supply for SWITCH_REG1 -- vcc9-supply: The input supply for LDO_REG4 and LDO_REG5 -- vcc10-supply: The input supply for LDO_REG6 -- vcc11-supply: The input supply for LDO_REG8 -- vcc12-supply: The input supply for SWITCH_REG2 -- dvs-gpios: buck1/2 can be controlled by gpio dvs, this is GPIO specifiers - for 2 host gpio's used for dvs. The format of the gpio specifier depends in - the gpio controller. If DVS GPIOs aren't present, voltage changes will happen - very quickly with no slow ramp time. - -Optional shared RK809 and RK817 properties: -- vcc1-supply: The input supply for DCDC_REG1 -- vcc2-supply: The input supply for DCDC_REG2 -- vcc3-supply: The input supply for DCDC_REG3 -- vcc4-supply: The input supply for DCDC_REG4 -- vcc5-supply: The input supply for LDO_REG1, LDO_REG2, LDO_REG3 -- vcc6-supply: The input supply for LDO_REG4, LDO_REG5, LDO_REG6 -- vcc7-supply: The input supply for LDO_REG7, LDO_REG8, LDO_REG9 - -Optional RK809 properties: -- vcc8-supply: The input supply for SWITCH_REG1 -- vcc9-supply: The input supply for DCDC_REG5, SWITCH_REG2 - -Optional RK817 properties: -- clocks: The input clock for the audio codec -- clock-names: The clock name for the codec clock. Should be "mclk". -- #sound-dai-cells: Needed for the interpretation of sound dais. Should be 0. - -- vcc8-supply: The input supply for BOOST -- vcc9-supply: The input supply for OTG_SWITCH -- codec: The child node for the codec to hold additional properties. - If no additional properties are required for the codec, this - node can be omitted. - -- rockchip,mic-in-differential: Telling if the microphone uses differential - mode. Should be under the codec child node. - -Optional RK818 properties: -- vcc1-supply: The input supply for DCDC_REG1 -- vcc2-supply: The input supply for DCDC_REG2 -- vcc3-supply: The input supply for DCDC_REG3 -- vcc4-supply: The input supply for DCDC_REG4 -- boost-supply: The input supply for DCDC_BOOST -- vcc6-supply: The input supply for LDO_REG1 and LDO_REG2 -- vcc7-supply: The input supply for LDO_REG3, LDO_REG5 and LDO_REG7 -- vcc8-supply: The input supply for LDO_REG4, LDO_REG6 and LDO_REG8 -- vcc9-supply: The input supply for LDO_REG9 and SWITCH_REG -- h_5v-supply: The input supply for HDMI_SWITCH -- usb-supply: The input supply for OTG_SWITCH - -Regulators: All the regulators of RK8XX to be instantiated shall be -listed in a child node named 'regulators'. Each regulator is represented -by a child node of the 'regulators' node. - - regulator-name { - /* standard regulator bindings here */ - }; - -Following regulators of the RK805 PMIC regulators are supported. Note that -the 'n' in regulator name, as in DCDC_REGn or LDOn, represents the DCDC or LDO -number as described in RK805 datasheet. - - - DCDC_REGn - - valid values for n are 1 to 4. - - LDO_REGn - - valid values for n are 1 to 3 - -Following regulators of the RK808 PMIC block are supported. Note that -the 'n' in regulator name, as in DCDC_REGn or LDOn, represents the DCDC or LDO -number as described in RK808 datasheet. - - - DCDC_REGn - - valid values for n are 1 to 4. - - LDO_REGn - - valid values for n are 1 to 8. - - SWITCH_REGn - - valid values for n are 1 to 2 - -Following regulators of the RK809 and RK817 PMIC blocks are supported. Note that -the 'n' in regulator name, as in DCDC_REGn or LDOn, represents the DCDC or LDO -number as described in RK809 and RK817 datasheets. - - - DCDC_REGn - - valid values for n are 1 to 5 for RK809. - - valid values for n are 1 to 4 for RK817. - - LDO_REGn - - valid values for n are 1 to 9 for RK809. - - valid values for n are 1 to 9 for RK817. - - SWITCH_REGn - - valid values for n are 1 to 2 for RK809. - - BOOST for RK817 - - OTG_SWITCH for RK817 - -Following regulators of the RK818 PMIC block are supported. Note that -the 'n' in regulator name, as in DCDC_REGn or LDOn, represents the DCDC or LDO -number as described in RK818 datasheet. - - - DCDC_REGn - - valid values for n are 1 to 4. - - LDO_REGn - - valid values for n are 1 to 9. - - SWITCH_REG - - HDMI_SWITCH - - OTG_SWITCH - -It is necessary to configure three pins for both the RK809 and RK817, the three -pins are "gpio_ts" "gpio_gt" "gpio_slp". - The gpio_gt and gpio_ts pins support the gpio function. - The gpio_slp pin is for controlling the pmic states, as below: - - reset - - power down - - sleep - -Standard regulator bindings are used inside regulator subnodes. Check - Documentation/devicetree/bindings/regulator/regulator.txt -for more details - -Example: - rk808: pmic@1b { - compatible = "rockchip,rk808"; - clock-output-names = "xin32k", "rk808-clkout2"; - interrupt-parent = <&gpio0>; - interrupts = <4 IRQ_TYPE_LEVEL_LOW>; - pinctrl-names = "default"; - pinctrl-0 = <&pmic_int &dvs_1 &dvs_2>; - dvs-gpios = <&gpio7 11 GPIO_ACTIVE_HIGH>, - <&gpio7 15 GPIO_ACTIVE_HIGH>; - reg = <0x1b>; - rockchip,system-power-controller; - wakeup-source; - #clock-cells = <1>; - - vcc8-supply = <&vcc_18>; - vcc9-supply = <&vcc_io>; - vcc10-supply = <&vcc_io>; - vcc12-supply = <&vcc_io>; - vddio-supply = <&vccio_pmu>; - - regulators { - vdd_cpu: DCDC_REG1 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <750000>; - regulator-max-microvolt = <1300000>; - regulator-name = "vdd_arm"; - }; - - vdd_gpu: DCDC_REG2 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <850000>; - regulator-max-microvolt = <1250000>; - regulator-name = "vdd_gpu"; - }; - - vcc_ddr: DCDC_REG3 { - regulator-always-on; - regulator-boot-on; - regulator-name = "vcc_ddr"; - }; - - vcc_io: DCDC_REG4 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - regulator-name = "vcc_io"; - }; - - vccio_pmu: LDO_REG1 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - regulator-name = "vccio_pmu"; - }; - - vcc_tp: LDO_REG2 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - regulator-name = "vcc_tp"; - }; - - vdd_10: LDO_REG3 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <1000000>; - regulator-max-microvolt = <1000000>; - regulator-name = "vdd_10"; - }; - - vcc18_lcd: LDO_REG4 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - regulator-name = "vcc18_lcd"; - }; - - vccio_sd: LDO_REG5 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3300000>; - regulator-name = "vccio_sd"; - }; - - vdd10_lcd: LDO_REG6 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <1000000>; - regulator-max-microvolt = <1000000>; - regulator-name = "vdd10_lcd"; - }; - - vcc_18: LDO_REG7 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - regulator-name = "vcc_18"; - }; - - vcca_codec: LDO_REG8 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - regulator-name = "vcca_codec"; - }; - - vcc_wl: SWITCH_REG1 { - regulator-always-on; - regulator-boot-on; - regulator-name = "vcc_wl"; - }; - - vcc_lcd: SWITCH_REG2 { - regulator-always-on; - regulator-boot-on; - regulator-name = "vcc_lcd"; - }; - }; - }; - - rk817: pmic@20 { - compatible = "rockchip,rk817"; - reg = <0x20>; - interrupt-parent = <&gpio0>; - interrupts = ; - clock-output-names = "rk808-clkout1", "xin32k"; - clock-names = "mclk"; - clocks = <&cru SCLK_I2S1_OUT>; - pinctrl-names = "default"; - pinctrl-0 = <&pmic_int>, <&i2s1_2ch_mclk>; - wakeup-source; - #clock-cells = <1>; - #sound-dai-cells = <0>; - - vcc1-supply = <&vccsys>; - vcc2-supply = <&vccsys>; - vcc3-supply = <&vccsys>; - vcc4-supply = <&vccsys>; - vcc5-supply = <&vccsys>; - vcc6-supply = <&vccsys>; - vcc7-supply = <&vccsys>; - - regulators { - vdd_logic: DCDC_REG1 { - regulator-name = "vdd_logic"; - regulator-min-microvolt = <950000>; - regulator-max-microvolt = <1150000>; - regulator-ramp-delay = <6001>; - regulator-always-on; - regulator-boot-on; - - regulator-state-mem { - regulator-on-in-suspend; - regulator-suspend-microvolt = <950000>; - }; - }; - - vdd_arm: DCDC_REG2 { - regulator-name = "vdd_arm"; - regulator-min-microvolt = <950000>; - regulator-max-microvolt = <1350000>; - regulator-ramp-delay = <6001>; - regulator-always-on; - regulator-boot-on; - - regulator-state-mem { - regulator-off-in-suspend; - regulator-suspend-microvolt = <950000>; - }; - }; - - vcc_ddr: DCDC_REG3 { - regulator-name = "vcc_ddr"; - regulator-always-on; - regulator-boot-on; - - regulator-state-mem { - regulator-on-in-suspend; - }; - }; - - vcc_3v3: DCDC_REG4 { - regulator-name = "vcc_3v3"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - regulator-always-on; - regulator-boot-on; - - regulator-state-mem { - regulator-off-in-suspend; - regulator-suspend-microvolt = <3300000>; - }; - }; - - vcc_1v8: LDO_REG2 { - regulator-name = "vcc_1v8"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - regulator-always-on; - regulator-boot-on; - - regulator-state-mem { - regulator-on-in-suspend; - regulator-suspend-microvolt = <1800000>; - }; - }; - - vdd_1v0: LDO_REG3 { - regulator-name = "vdd_1v0"; - regulator-min-microvolt = <1000000>; - regulator-max-microvolt = <1000000>; - regulator-always-on; - regulator-boot-on; - - regulator-state-mem { - regulator-on-in-suspend; - regulator-suspend-microvolt = <1000000>; - }; - }; - - vcc3v3_pmu: LDO_REG4 { - regulator-name = "vcc3v3_pmu"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - regulator-always-on; - regulator-boot-on; - - regulator-state-mem { - regulator-on-in-suspend; - regulator-suspend-microvolt = <3300000>; - }; - }; - - vccio_sd: LDO_REG5 { - regulator-name = "vccio_sd"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3300000>; - regulator-always-on; - regulator-boot-on; - - regulator-state-mem { - regulator-on-in-suspend; - regulator-suspend-microvolt = <3300000>; - }; - }; - - vcc_sd: LDO_REG6 { - regulator-name = "vcc_sd"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - regulator-boot-on; - - regulator-state-mem { - regulator-on-in-suspend; - regulator-suspend-microvolt = <3300000>; - }; - }; - - vcc_bl: LDO_REG7 { - regulator-name = "vcc_bl"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - - regulator-state-mem { - regulator-off-in-suspend; - regulator-suspend-microvolt = <3300000>; - }; - }; - - vcc_lcd: LDO_REG8 { - regulator-name = "vcc_lcd"; - regulator-min-microvolt = <2800000>; - regulator-max-microvolt = <2800000>; - - regulator-state-mem { - regulator-off-in-suspend; - regulator-suspend-microvolt = <2800000>; - }; - }; - - vcc_cam: LDO_REG9 { - regulator-name = "vcc_cam"; - regulator-min-microvolt = <3000000>; - regulator-max-microvolt = <3000000>; - - regulator-state-mem { - regulator-off-in-suspend; - regulator-suspend-microvolt = <3000000>; - }; - }; - }; - - rk817_codec: codec { - rockchip,mic-in-differential; - }; - }; diff --git a/Documentation/devicetree/bindings/mfd/rockchip,rk805.yaml b/Documentation/devicetree/bindings/mfd/rockchip,rk805.yaml new file mode 100644 index 0000000000000000000000000000000000000000..4992f71b6fc3f0eab8ed596b7af53942c1ac8e26 --- /dev/null +++ b/Documentation/devicetree/bindings/mfd/rockchip,rk805.yaml @@ -0,0 +1,219 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/mfd/rockchip,rk805.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: RK805 Power Management Integrated Circuit + +maintainers: + - Chris Zhong + - Zhang Qing + +description: | + Rockchip RK805 series PMIC. This device consists of an i2c controlled MFD + that includes multiple switchable regulators. + +properties: + compatible: + enum: + - rockchip,rk805 + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + '#clock-cells': + description: + See for clock IDs. + minimum: 0 + maximum: 1 + + clock-output-names: + description: + From common clock binding to override the default output clock name. + + gpio-controller: true + + '#gpio-cells': + const: 2 + + rockchip,system-power-controller: + type: boolean + description: + Telling whether or not this PMIC is controlling the system power. + + wakeup-source: + type: boolean + description: + Device can be used as a wakeup source. + + vcc1-supply: + description: + The input supply for DCDC_REG1. + + vcc2-supply: + description: + The input supply for DCDC_REG2. + + vcc3-supply: + description: + The input supply for DCDC_REG3. + + vcc4-supply: + description: + The input supply for DCDC_REG4. + + vcc5-supply: + description: + The input supply for LDO_REG1 and LDO_REG2. + + vcc6-supply: + description: + The input supply for LDO_REG3. + + regulators: + type: object + patternProperties: + "^(DCDC_REG[1-4]|LDO_REG[1-3])$": + type: object + $ref: ../regulator/regulator.yaml# + unevaluatedProperties: false + +allOf: + - if: + properties: + '#clock-cells': + const: 0 + + then: + properties: + clock-output-names: + maxItems: 1 + + else: + properties: + clock-output-names: + maxItems: 2 + +required: + - compatible + - reg + - interrupts + - "#clock-cells" + +additionalProperties: false + +examples: + - | + #include + #include + #include + i2c { + #address-cells = <1>; + #size-cells = <0>; + + pmic@18 { + compatible = "rockchip,rk805"; + reg = <0x18>; + interrupt-parent = <&gpio2>; + interrupts = ; + pinctrl-names = "default"; + pinctrl-0 = <&pmic_int_l>; + rockchip,system-power-controller; + wakeup-source; + #clock-cells = <0>; + + vcc1-supply = <&vcc_sys>; + vcc2-supply = <&vcc_sys>; + vcc3-supply = <&vcc_sys>; + vcc4-supply = <&vcc_sys>; + vcc5-supply = <&vcc_io>; + vcc6-supply = <&vcc_io>; + + regulators { + vdd_logic: DCDC_REG1 { + regulator-name = "vdd_logic"; + regulator-min-microvolt = <700000>; + regulator-max-microvolt = <1350000>; + regulator-always-on; + regulator-boot-on; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1000000>; + }; + }; + + vdd_arm: DCDC_REG2 { + regulator-name = "vdd_arm"; + regulator-min-microvolt = <700000>; + regulator-max-microvolt = <1350000>; + regulator-always-on; + regulator-boot-on; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <950000>; + }; + }; + + vcc_ddr: DCDC_REG3 { + regulator-name = "vcc_ddr"; + regulator-always-on; + regulator-boot-on; + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vcc_io: DCDC_REG4 { + regulator-name = "vcc_io"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vdd_18: LDO_REG1 { + regulator-name = "vdd_18"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vcc18_emmc: LDO_REG2 { + regulator-name = "vcc_18emmc"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vdd_11: LDO_REG3 { + regulator-name = "vdd_11"; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1100000>; + regulator-always-on; + regulator-boot-on; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1100000>; + }; + }; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/mfd/rockchip,rk808.yaml b/Documentation/devicetree/bindings/mfd/rockchip,rk808.yaml new file mode 100644 index 0000000000000000000000000000000000000000..f5908fa01a61af063604ef199f6711a8512a891f --- /dev/null +++ b/Documentation/devicetree/bindings/mfd/rockchip,rk808.yaml @@ -0,0 +1,257 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/mfd/rockchip,rk808.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: RK808 Power Management Integrated Circuit + +maintainers: + - Chris Zhong + - Zhang Qing + +description: | + Rockchip RK808 series PMIC. This device consists of an i2c controlled MFD + that includes regulators, an RTC, and a power button. + +properties: + compatible: + enum: + - rockchip,rk808 + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + '#clock-cells': + description: + See for clock IDs. + const: 1 + + clock-output-names: + description: + From common clock binding to override the default output clock name. + maxItems: 2 + + rockchip,system-power-controller: + type: boolean + description: + Telling whether or not this PMIC is controlling the system power. + + wakeup-source: + type: boolean + description: + Device can be used as a wakeup source. + + vcc1-supply: + description: + The input supply for DCDC_REG1. + + vcc2-supply: + description: + The input supply for DCDC_REG2. + + vcc3-supply: + description: + The input supply for DCDC_REG3. + + vcc4-supply: + description: + The input supply for DCDC_REG4. + + vcc6-supply: + description: + The input supply for LDO_REG1 and LDO_REG2. + + vcc7-supply: + description: + The input supply for LDO_REG3 and LDO_REG7. + + vcc8-supply: + description: + The input supply for SWITCH_REG1. + + vcc9-supply: + description: + The input supply for LDO_REG4 and LDO_REG5. + + vcc10-supply: + description: + The input supply for LDO_REG6. + + vcc11-supply: + description: + The input supply for LDO_REG8. + + vcc12-supply: + description: + The input supply for SWITCH_REG2. + + vddio-supply: + description: + The input supply for digital IO. + + dvs-gpios: + description: | + buck1/2 can be controlled by gpio dvs, this is GPIO specifiers for + 2 host gpio's used for dvs. The format of the gpio specifier + depends in the gpio controller. If DVS GPIOs aren't present, + voltage changes will happen very quickly with no slow ramp time. + maxItems: 2 + + regulators: + type: object + patternProperties: + "^(DCDC_REG[1-4]|LDO_REG[1-8]|SWITCH_REG[1-2])$": + type: object + $ref: ../regulator/regulator.yaml# + unevaluatedProperties: false + +required: + - compatible + - reg + - interrupts + - "#clock-cells" + +additionalProperties: false + +examples: + - | + #include + #include + #include + i2c { + #address-cells = <1>; + #size-cells = <0>; + + rk808: pmic@1b { + compatible = "rockchip,rk808"; + clock-output-names = "xin32k", "rk808-clkout2"; + interrupt-parent = <&gpio0>; + interrupts = <4 IRQ_TYPE_LEVEL_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&pmic_int &dvs_1 &dvs_2>; + dvs-gpios = <&gpio7 11 GPIO_ACTIVE_HIGH>, + <&gpio7 15 GPIO_ACTIVE_HIGH>; + reg = <0x1b>; + rockchip,system-power-controller; + wakeup-source; + #clock-cells = <1>; + + vcc8-supply = <&vcc_18>; + vcc9-supply = <&vcc_io>; + vcc10-supply = <&vcc_io>; + vcc12-supply = <&vcc_io>; + vddio-supply = <&vccio_pmu>; + + regulators { + vdd_cpu: DCDC_REG1 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <1300000>; + regulator-name = "vdd_arm"; + }; + + vdd_gpu: DCDC_REG2 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <1250000>; + regulator-name = "vdd_gpu"; + }; + + vcc_ddr: DCDC_REG3 { + regulator-always-on; + regulator-boot-on; + regulator-name = "vcc_ddr"; + }; + + vcc_io: DCDC_REG4 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc_io"; + }; + + vccio_pmu: LDO_REG1 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vccio_pmu"; + }; + + vcc_tp: LDO_REG2 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc_tp"; + }; + + vdd_10: LDO_REG3 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + regulator-name = "vdd_10"; + }; + + vcc18_lcd: LDO_REG4 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "vcc18_lcd"; + }; + + vccio_sd: LDO_REG5 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vccio_sd"; + }; + + vdd10_lcd: LDO_REG6 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + regulator-name = "vdd10_lcd"; + }; + + vcc_18: LDO_REG7 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "vcc_18"; + }; + + vcca_codec: LDO_REG8 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcca_codec"; + }; + + vcc_wl: SWITCH_REG1 { + regulator-always-on; + regulator-boot-on; + regulator-name = "vcc_wl"; + }; + + vcc_lcd: SWITCH_REG2 { + regulator-always-on; + regulator-boot-on; + regulator-name = "vcc_lcd"; + }; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/mfd/rockchip,rk809.yaml b/Documentation/devicetree/bindings/mfd/rockchip,rk809.yaml new file mode 100644 index 0000000000000000000000000000000000000000..7fb849ac74a7cddb7832c7393b7c70290eaa08ad --- /dev/null +++ b/Documentation/devicetree/bindings/mfd/rockchip,rk809.yaml @@ -0,0 +1,284 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/mfd/rockchip,rk809.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: RK809 Power Management Integrated Circuit + +maintainers: + - Chris Zhong + - Zhang Qing + +description: | + Rockchip RK809 series PMIC. This device consists of an i2c controlled MFD + that includes regulators, an RTC, and power button. + +properties: + compatible: + enum: + - rockchip,rk809 + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + '#clock-cells': + description: | + See for clock IDs. + minimum: 0 + maximum: 1 + + clock-output-names: + description: + From common clock binding to override the default output clock name. + + rockchip,system-power-controller: + type: boolean + description: + Telling whether or not this PMIC is controlling the system power. + + wakeup-source: + type: boolean + description: + Device can be used as a wakeup source. + + vcc1-supply: + description: + The input supply for DCDC_REG1. + + vcc2-supply: + description: + The input supply for DCDC_REG2. + + vcc3-supply: + description: + The input supply for DCDC_REG3. + + vcc4-supply: + description: + The input supply for DCDC_REG4. + + vcc5-supply: + description: + The input supply for LDO_REG1, LDO_REG2, and LDO_REG3. + + vcc6-supply: + description: + The input supply for LDO_REG4, LDO_REG5, and LDO_REG6. + + vcc7-supply: + description: + The input supply for LDO_REG7, LDO_REG8, and LDO_REG9. + + vcc8-supply: + description: + The input supply for SWITCH_REG1. + + vcc9-supply: + description: + The input supply for DCDC_REG5 and SWITCH_REG2. + + regulators: + type: object + patternProperties: + "^(LDO_REG[1-9]|DCDC_REG[1-5]|SWITCH_REG[1-2])$": + type: object + $ref: ../regulator/regulator.yaml# + unevaluatedProperties: false + +allOf: + - if: + properties: + '#clock-cells': + const: 0 + + then: + properties: + clock-output-names: + maxItems: 1 + + else: + properties: + clock-output-names: + maxItems: 2 + +required: + - compatible + - reg + - interrupts + - "#clock-cells" + +additionalProperties: false + +examples: + - | + #include + #include + #include + i2c { + #address-cells = <1>; + #size-cells = <0>; + + rk808: pmic@1b { + compatible = "rockchip,rk808"; + reg = <0x1b>; + #clock-cells = <1>; + clock-output-names = "xin32k", "rk808-clkout2"; + interrupt-parent = <&gpio3>; + interrupts = <10 IRQ_TYPE_LEVEL_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&pmic_int_l_pin>; + rockchip,system-power-controller; + wakeup-source; + + vcc1-supply = <&vcc_sysin>; + vcc2-supply = <&vcc_sysin>; + vcc3-supply = <&vcc_sysin>; + vcc4-supply = <&vcc_sysin>; + vcc6-supply = <&vcc_sysin>; + vcc7-supply = <&vcc_sysin>; + vcc8-supply = <&vcc3v3_sys>; + vcc9-supply = <&vcc_sysin>; + vcc10-supply = <&vcc_sysin>; + vcc11-supply = <&vcc_sysin>; + vcc12-supply = <&vcc3v3_sys>; + + regulators { + vdd_center: DCDC_REG1 { + regulator-name = "vdd_center"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <1350000>; + regulator-ramp-delay = <6001>; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_cpu_l: DCDC_REG2 { + regulator-name = "vdd_cpu_l"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <1350000>; + regulator-ramp-delay = <6001>; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_ddr: DCDC_REG3 { + regulator-name = "vcc_ddr"; + regulator-always-on; + regulator-boot-on; + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vcc_1v8: vcc_wl: DCDC_REG4 { + regulator-name = "vcc_1v8"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vcc1v8_pmupll: LDO_REG3 { + regulator-name = "vcc1v8_pmupll"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vcc_sdio: LDO_REG4 { + regulator-name = "vcc_sdio"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3000000>; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3000000>; + }; + }; + + vcca3v0_codec: LDO_REG5 { + regulator-name = "vcca3v0_codec"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_1v5: LDO_REG6 { + regulator-name = "vcc_1v5"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1500000>; + regulator-max-microvolt = <1500000>; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1500000>; + }; + }; + + vcca1v8_codec: LDO_REG7 { + regulator-name = "vcca1v8_codec"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_3v0: LDO_REG8 { + regulator-name = "vcc_3v0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3000000>; + }; + }; + + vcc3v3_s3: SWITCH_REG1 { + regulator-name = "vcc3v3_s3"; + regulator-always-on; + regulator-boot-on; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc3v3_s0: SWITCH_REG2 { + regulator-name = "vcc3v3_s0"; + regulator-always-on; + regulator-boot-on; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/mfd/rockchip,rk817.yaml b/Documentation/devicetree/bindings/mfd/rockchip,rk817.yaml new file mode 100644 index 0000000000000000000000000000000000000000..bfc1720adc43b17bfe79d4769c13b06092f5e1fb --- /dev/null +++ b/Documentation/devicetree/bindings/mfd/rockchip,rk817.yaml @@ -0,0 +1,330 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/mfd/rockchip,rk817.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: RK817 Power Management Integrated Circuit + +maintainers: + - Chris Zhong + - Zhang Qing + +description: | + Rockchip RK817 series PMIC. This device consists of an i2c controlled MFD + that includes regulators, an RTC, a power button, an audio codec, and a + battery charger manager. + +properties: + compatible: + enum: + - rockchip,rk817 + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + '#clock-cells': + description: + See for clock IDs. + minimum: 0 + maximum: 1 + + clock-output-names: + description: + From common clock binding to override the default output clock name. + + rockchip,system-power-controller: + type: boolean + description: + Telling whether or not this PMIC is controlling the system power. + + wakeup-source: + type: boolean + description: + Device can be used as a wakeup source. + + vcc1-supply: + description: + The input supply for DCDC_REG1. + + vcc2-supply: + description: + The input supply for DCDC_REG2. + + vcc3-supply: + description: + The input supply for DCDC_REG3. + + vcc4-supply: + description: + The input supply for DCDC_REG4. + + vcc5-supply: + description: + The input supply for LDO_REG1, LDO_REG2, and LDO_REG3. + + vcc6-supply: + description: + The input supply for LDO_REG4, LDO_REG5, and LDO_REG6. + + vcc7-supply: + description: + The input supply for LDO_REG7, LDO_REG8, and LDO_REG9. + + vcc8-supply: + description: + The input supply for BOOST. + + vcc9-supply: + description: + The input supply for OTG_SWITCH. + + regulators: + type: object + patternProperties: + "^(LDO_REG[1-9]|DCDC_REG[1-4]|BOOST|OTG_SWITCH)$": + type: object + $ref: ../regulator/regulator.yaml# + unevaluatedProperties: false + + clocks: + description: + The input clock for the audio codec. + + clock-names: + description: + The clock name for the codec clock. + items: + - const: mclk + + '#sound-dai-cells': + description: + Needed for the interpretation of sound dais. + const: 0 + + codec: + description: | + The child node for the codec to hold additional properties. If no + additional properties are required for the codec, this node can be + omitted. + type: object + properties: + rockchip,mic-in-differential: + type: boolean + description: + Describes if the microphone uses differential mode. + +allOf: + - if: + properties: + '#clock-cells': + const: 0 + + then: + properties: + clock-output-names: + maxItems: 1 + + else: + properties: + clock-output-names: + maxItems: 2 + +required: + - compatible + - reg + - interrupts + - "#clock-cells" + +additionalProperties: false + +examples: + - | + #include + #include + #include + #include + i2c { + #address-cells = <1>; + #size-cells = <0>; + + rk817: pmic@20 { + compatible = "rockchip,rk817"; + reg = <0x20>; + interrupt-parent = <&gpio0>; + interrupts = ; + clock-output-names = "rk808-clkout1", "xin32k"; + clock-names = "mclk"; + clocks = <&cru SCLK_I2S1_OUT>; + pinctrl-names = "default"; + pinctrl-0 = <&pmic_int>, <&i2s1_2ch_mclk>; + wakeup-source; + #clock-cells = <1>; + #sound-dai-cells = <0>; + + vcc1-supply = <&vccsys>; + vcc2-supply = <&vccsys>; + vcc3-supply = <&vccsys>; + vcc4-supply = <&vccsys>; + vcc5-supply = <&vccsys>; + vcc6-supply = <&vccsys>; + vcc7-supply = <&vccsys>; + + regulators { + vdd_logic: DCDC_REG1 { + regulator-name = "vdd_logic"; + regulator-min-microvolt = <950000>; + regulator-max-microvolt = <1150000>; + regulator-ramp-delay = <6001>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <950000>; + }; + }; + + vdd_arm: DCDC_REG2 { + regulator-name = "vdd_arm"; + regulator-min-microvolt = <950000>; + regulator-max-microvolt = <1350000>; + regulator-ramp-delay = <6001>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <950000>; + }; + }; + + vcc_ddr: DCDC_REG3 { + regulator-name = "vcc_ddr"; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vcc_3v3: DCDC_REG4 { + regulator-name = "vcc_3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcc_1v8: LDO_REG2 { + regulator-name = "vcc_1v8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vdd_1v0: LDO_REG3 { + regulator-name = "vdd_1v0"; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1000000>; + }; + }; + + vcc3v3_pmu: LDO_REG4 { + regulator-name = "vcc3v3_pmu"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vccio_sd: LDO_REG5 { + regulator-name = "vccio_sd"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcc_sd: LDO_REG6 { + regulator-name = "vcc_sd"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcc_bl: LDO_REG7 { + regulator-name = "vcc_bl"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcc_lcd: LDO_REG8 { + regulator-name = "vcc_lcd"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <2800000>; + }; + }; + + vcc_cam: LDO_REG9 { + regulator-name = "vcc_cam"; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <3000000>; + }; + }; + }; + + rk817_codec: codec { + rockchip,mic-in-differential; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/mfd/rockchip,rk818.yaml b/Documentation/devicetree/bindings/mfd/rockchip,rk818.yaml new file mode 100644 index 0000000000000000000000000000000000000000..b57c4b005cf455882dc644d1e4299b185f78b114 --- /dev/null +++ b/Documentation/devicetree/bindings/mfd/rockchip,rk818.yaml @@ -0,0 +1,282 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/mfd/rockchip,rk818.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: RK818 Power Management Integrated Circuit + +maintainers: + - Chris Zhong + - Zhang Qing + +description: | + Rockchip RK818 series PMIC. This device consists of an i2c controlled MFD + that includes regulators, an RTC, and a power button. + +properties: + compatible: + enum: + - rockchip,rk818 + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + '#clock-cells': + description: | + See for clock IDs. + const: 1 + + clock-output-names: + description: + From common clock binding to override the default output clock name. + maxItems: 2 + + rockchip,system-power-controller: + type: boolean + description: + Telling whether or not this PMIC is controlling the system power. + + wakeup-source: + type: boolean + description: + Device can be used as a wakeup source. + + vcc1-supply: + description: + The input supply for DCDC_REG1. + + vcc2-supply: + description: + The input supply for DCDC_REG2. + + vcc3-supply: + description: + The input supply for DCDC_REG3. + + vcc4-supply: + description: + The input supply for DCDC_REG4. + + boost-supply: + description: + The input supply for DCDC_BOOST + + vcc6-supply: + description: + The input supply for LDO_REG1 and LDO_REG2. + + vcc7-supply: + description: + The input supply for LDO_REG3, LDO_REG5, and LDO_REG7. + + vcc8-supply: + description: + The input supply for LDO_REG4, LDO_REG6, and LDO_REG8. + + vcc9-supply: + description: + The input supply for LDO_REG9 and SWITCH_REG. + + vddio-supply: + description: + The input supply for digital IO. + + h_5v-supply: + description: + The input supply for HDMI_SWITCH. + + usb-supply: + description: + The input supply for OTG_SWITCH. + + regulators: + type: object + patternProperties: + "^(DCDC_REG[1-4]|DCDC_BOOST|LDO_REG[1-9]|SWITCH_REG|HDMI_SWITCH|OTG_SWITCH)$": + type: object + $ref: ../regulator/regulator.yaml# + unevaluatedProperties: false + +required: + - compatible + - reg + - interrupts + - "#clock-cells" + +additionalProperties: false + +examples: + - | + #include + #include + #include + #include + i2c { + #address-cells = <1>; + #size-cells = <0>; + + rk818: pmic@1c { + compatible = "rockchip,rk818"; + reg = <0x1c>; + interrupt-parent = <&gpio0>; + interrupts = <4 IRQ_TYPE_LEVEL_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&pmic_int>; + rockchip,system-power-controller; + wakeup-source; + #clock-cells = <1>; + + vcc1-supply = <&vdd_sys>; + vcc2-supply = <&vdd_sys>; + vcc3-supply = <&vdd_sys>; + vcc4-supply = <&vdd_sys>; + boost-supply = <&vdd_in_otg_out>; + vcc6-supply = <&vdd_sys>; + vcc7-supply = <&vdd_misc_1v8>; + vcc8-supply = <&vdd_misc_1v8>; + vcc9-supply = <&vdd_3v3_io>; + vddio-supply = <&vdd_3v3_io>; + + regulators { + vdd_log: DCDC_REG1 { + regulator-name = "vdd_log"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1100000>; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_gpu: DCDC_REG2 { + regulator-name = "vdd_gpu"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <1250000>; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1000000>; + }; + }; + + vcc_ddr: DCDC_REG3 { + regulator-name = "vcc_ddr"; + regulator-always-on; + regulator-boot-on; + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vdd_3v3_io: DCDC_REG4 { + regulator-name = "vdd_3v3_io"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vdd_sys: DCDC_BOOST { + regulator-name = "vdd_sys"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <5000000>; + }; + }; + + vdd_sd: SWITCH_REG { + regulator-name = "vdd_sd"; + regulator-always-on; + regulator-boot-on; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_eth_2v5: LDO_REG2 { + regulator-name = "vdd_eth_2v5"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <2500000>; + regulator-max-microvolt = <2500000>; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <2500000>; + }; + }; + + vdd_1v0: LDO_REG3 { + regulator-name = "vdd_1v0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1000000>; + }; + }; + + vdd_1v8_lcd_ldo: LDO_REG4 { + regulator-name = "vdd_1v8_lcd_ldo"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vdd_1v0_lcd: LDO_REG6 { + regulator-name = "vdd_1v0_lcd"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1000000>; + }; + }; + + vdd_1v8_ldo: LDO_REG7 { + regulator-name = "vdd_1v8_ldo"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vdd_io_sd: LDO_REG9 { + regulator-name = "vdd_io_sd"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/mfd/samsung,exynos5433-lpass.yaml b/Documentation/devicetree/bindings/mfd/samsung,exynos5433-lpass.yaml index f7bb67d10eff3618fe9542ff096402863a7b67bf..b97b0684872931348fd576237c806409815ad253 100644 --- a/Documentation/devicetree/bindings/mfd/samsung,exynos5433-lpass.yaml +++ b/Documentation/devicetree/bindings/mfd/samsung,exynos5433-lpass.yaml @@ -79,8 +79,8 @@ examples: clocks = <&cmu_aud CLK_ACLK_DMAC>; clock-names = "apb_pclk"; #dma-cells = <1>; - #dma-channels = <8>; - #dma-requests = <32>; + dma-channels = <8>; + dma-requests = <32>; power-domains = <&pd_aud>; }; diff --git a/Documentation/devicetree/bindings/mfd/syscon.yaml b/Documentation/devicetree/bindings/mfd/syscon.yaml index 13baa452cc9d7dd8e7825bf29f999a7e26540d69..fb784045013f5676ab14fa73d24db821f872c09d 100644 --- a/Documentation/devicetree/bindings/mfd/syscon.yaml +++ b/Documentation/devicetree/bindings/mfd/syscon.yaml @@ -100,12 +100,4 @@ examples: compatible = "allwinner,sun8i-h3-system-controller", "syscon"; reg = <0x01c00000 0x1000>; }; - - - | - gpr: iomuxc-gpr@20e0000 { - compatible = "fsl,imx6q-iomuxc-gpr", "syscon"; - reg = <0x020e0000 0x38>; - hwlocks = <&hwlock1 1>; - }; - ... diff --git a/Documentation/devicetree/bindings/mfd/wlf,arizona.yaml b/Documentation/devicetree/bindings/mfd/wlf,arizona.yaml index 9e762d474218ad664427a5ccc27d7d042fd7e049..ea3337dafaf5366e1980d89ad4cfbb0552a98d65 100644 --- a/Documentation/devicetree/bindings/mfd/wlf,arizona.yaml +++ b/Documentation/devicetree/bindings/mfd/wlf,arizona.yaml @@ -14,6 +14,7 @@ description: | range of analogue I/O. allOf: + - $ref: /schemas/spi/spi-peripheral-props.yaml - $ref: /schemas/sound/wlf,arizona.yaml# - $ref: /schemas/regulator/wlf,arizona.yaml# - $ref: /schemas/extcon/wlf,arizona.yaml# diff --git a/Documentation/devicetree/bindings/mux/reg-mux.yaml b/Documentation/devicetree/bindings/mux/reg-mux.yaml index 3b030b8fb47c45cf564266c97ce7ba48c70fb5cd..dfd9ea582bb7acfc94fd5cccacf6d01b5490f4ee 100644 --- a/Documentation/devicetree/bindings/mux/reg-mux.yaml +++ b/Documentation/devicetree/bindings/mux/reg-mux.yaml @@ -100,7 +100,6 @@ examples: #include syscon@1000 { - compatible = "fsl,imx7d-iomuxc-gpr", "fsl,imx6q-iomuxc-gpr", "syscon", "simple-mfd"; reg = <0x1000 0x100>; mux2: mux-controller { diff --git a/Documentation/devicetree/bindings/opp/opp-v2-kryo-cpu.yaml b/Documentation/devicetree/bindings/opp/opp-v2-kryo-cpu.yaml index 8c2e9ac5f68d0c24b40d5ffa8b2e824b381d181d..30f7b596d609bf71d6fd98ab3aa5632207df7164 100644 --- a/Documentation/devicetree/bindings/opp/opp-v2-kryo-cpu.yaml +++ b/Documentation/devicetree/bindings/opp/opp-v2-kryo-cpu.yaml @@ -17,10 +17,10 @@ description: | the CPU frequencies subset and voltage value of each OPP varies based on the silicon variant in use. Qualcomm Technologies, Inc. Process Voltage Scaling Tables - defines the voltage and frequency value based on the msm-id in SMEM - and speedbin blown in the efuse combination. - The qcom-cpufreq-nvmem driver reads the msm-id and efuse value from the SoC - to provide the OPP framework with required information (existing HW bitmap). + defines the voltage and frequency value based on the speedbin blown in + the efuse combination. + The qcom-cpufreq-nvmem driver reads the efuse value from the SoC to provide + the OPP framework with required information (existing HW bitmap). This is used to determine the voltage and frequency value for each OPP of operating-points-v2 table when it is parsed by the OPP framework. @@ -50,15 +50,11 @@ patternProperties: description: | A single 32 bit bitmap value, representing compatible HW. Bitmap: - 0: MSM8996 V3, speedbin 0 - 1: MSM8996 V3, speedbin 1 - 2: MSM8996 V3, speedbin 2 - 3: unused - 4: MSM8996 SG, speedbin 0 - 5: MSM8996 SG, speedbin 1 - 6: MSM8996 SG, speedbin 2 - 7-31: unused - maximum: 0x77 + 0: MSM8996, speedbin 0 + 1: MSM8996, speedbin 1 + 2: MSM8996, speedbin 2 + 3-31: unused + maximum: 0x7 clock-latency-ns: true @@ -184,19 +180,19 @@ examples: opp-307200000 { opp-hz = /bits/ 64 <307200000>; opp-microvolt = <905000 905000 1140000>; - opp-supported-hw = <0x77>; + opp-supported-hw = <0x7>; clock-latency-ns = <200000>; }; - opp-1593600000 { - opp-hz = /bits/ 64 <1593600000>; + opp-1401600000 { + opp-hz = /bits/ 64 <1401600000>; opp-microvolt = <1140000 905000 1140000>; - opp-supported-hw = <0x71>; + opp-supported-hw = <0x5>; clock-latency-ns = <200000>; }; - opp-2188800000 { - opp-hz = /bits/ 64 <2188800000>; + opp-1593600000 { + opp-hz = /bits/ 64 <1593600000>; opp-microvolt = <1140000 905000 1140000>; - opp-supported-hw = <0x10>; + opp-supported-hw = <0x1>; clock-latency-ns = <200000>; }; }; @@ -209,25 +205,25 @@ examples: opp-307200000 { opp-hz = /bits/ 64 <307200000>; opp-microvolt = <905000 905000 1140000>; - opp-supported-hw = <0x77>; + opp-supported-hw = <0x7>; clock-latency-ns = <200000>; }; - opp-1593600000 { - opp-hz = /bits/ 64 <1593600000>; + opp-1804800000 { + opp-hz = /bits/ 64 <1804800000>; opp-microvolt = <1140000 905000 1140000>; - opp-supported-hw = <0x70>; + opp-supported-hw = <0x6>; clock-latency-ns = <200000>; }; - opp-2150400000 { - opp-hz = /bits/ 64 <2150400000>; + opp-1900800000 { + opp-hz = /bits/ 64 <1900800000>; opp-microvolt = <1140000 905000 1140000>; - opp-supported-hw = <0x31>; + opp-supported-hw = <0x4>; clock-latency-ns = <200000>; }; - opp-2342400000 { - opp-hz = /bits/ 64 <2342400000>; + opp-2150400000 { + opp-hz = /bits/ 64 <2150400000>; opp-microvolt = <1140000 905000 1140000>; - opp-supported-hw = <0x10>; + opp-supported-hw = <0x1>; clock-latency-ns = <200000>; }; }; diff --git a/Documentation/devicetree/bindings/pinctrl/aspeed,ast2500-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/aspeed,ast2500-pinctrl.yaml index 7c25c8d51116df06ed7fae23a452bff8a9483c0b..9db904a528ee245b0786c9909d87f70f29de950c 100644 --- a/Documentation/devicetree/bindings/pinctrl/aspeed,ast2500-pinctrl.yaml +++ b/Documentation/devicetree/bindings/pinctrl/aspeed,ast2500-pinctrl.yaml @@ -76,73 +76,24 @@ additionalProperties: false examples: - | #include - apb { - compatible = "simple-bus"; - #address-cells = <1>; - #size-cells = <1>; - ranges; - - syscon: scu@1e6e2000 { - compatible = "aspeed,ast2500-scu", "syscon", "simple-mfd"; - reg = <0x1e6e2000 0x1a8>; - #clock-cells = <1>; - #reset-cells = <1>; - - pinctrl: pinctrl { - compatible = "aspeed,ast2500-pinctrl"; - aspeed,external-nodes = <&gfx>, <&lhc>; - - pinctrl_i2c3_default: i2c3_default { - function = "I2C3"; - groups = "I2C3"; - }; - - pinctrl_gpioh0_unbiased_default: gpioh0 { - pins = "A18"; - bias-disable; - }; + scu@1e6e2000 { + compatible = "aspeed,ast2500-scu", "syscon", "simple-mfd"; + reg = <0x1e6e2000 0x1a8>; + #clock-cells = <1>; + #reset-cells = <1>; + + pinctrl: pinctrl { + compatible = "aspeed,ast2500-pinctrl"; + aspeed,external-nodes = <&gfx>, <&lhc>; + + pinctrl_i2c3_default: i2c3_default { + function = "I2C3"; + groups = "I2C3"; }; - }; - - gfx: display@1e6e6000 { - compatible = "aspeed,ast2500-gfx", "syscon"; - reg = <0x1e6e6000 0x1000>; - reg-io-width = <4>; - clocks = <&syscon ASPEED_CLK_GATE_D1CLK>; - resets = <&syscon ASPEED_RESET_CRT1>; - interrupts = <0x19>; - syscon = <&syscon>; - memory-region = <&gfx_memory>; - }; - }; - - lpc: lpc@1e789000 { - compatible = "aspeed,ast2500-lpc", "simple-mfd"; - reg = <0x1e789000 0x1000>; - - #address-cells = <1>; - #size-cells = <1>; - ranges = <0x0 0x1e789000 0x1000>; - - lpc_host: lpc-host@80 { - compatible = "aspeed,ast2500-lpc-host", "simple-mfd", "syscon"; - reg = <0x80 0x1e0>; - reg-io-width = <4>; - #address-cells = <1>; - #size-cells = <1>; - ranges = <0x0 0x80 0x1e0>; - - lhc: lhc@20 { - compatible = "aspeed,ast2500-lhc"; - reg = <0x20 0x24>, <0x48 0x8>; + pinctrl_gpioh0_unbiased_default: gpioh0 { + pins = "A18"; + bias-disable; }; }; }; - - gfx_memory: framebuffer { - size = <0x01000000>; - alignment = <0x01000000>; - compatible = "shared-dma-pool"; - reusable; - }; diff --git a/Documentation/devicetree/bindings/pinctrl/fsl,imx7d-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/fsl,imx7d-pinctrl.txt deleted file mode 100644 index bfab5ca49fd1211a78922f3984c65b170b72f985..0000000000000000000000000000000000000000 --- a/Documentation/devicetree/bindings/pinctrl/fsl,imx7d-pinctrl.txt +++ /dev/null @@ -1,87 +0,0 @@ -* Freescale i.MX7 Dual IOMUX Controller - -iMX7D supports two iomuxc controllers, fsl,imx7d-iomuxc controller is similar -as previous iMX SoC generation and fsl,imx7d-iomuxc-lpsr which provides low -power state retention capabilities on gpios that are part of iomuxc-lpsr -(GPIO1_IO7..GPIO1_IO0). While iomuxc-lpsr provides its own set of registers for -mux and pad control settings, it shares the input select register from main -iomuxc controller for daisy chain settings, the fsl,input-sel property extends -fsl,imx-pinctrl driver to support iomuxc-lpsr controller. - -iomuxc_lpsr: iomuxc-lpsr@302c0000 { - compatible = "fsl,imx7d-iomuxc-lpsr"; - reg = <0x302c0000 0x10000>; - fsl,input-sel = <&iomuxc>; -}; - -iomuxc: iomuxc@30330000 { - compatible = "fsl,imx7d-iomuxc"; - reg = <0x30330000 0x10000>; -}; - -Peripherals using pads from iomuxc-lpsr support low state retention power -state, under LPSR mode GPIO's state of pads are retain. - -Please refer to fsl,imx-pinctrl.txt in this directory for common binding part -and usage. - -Required properties: -- compatible: "fsl,imx7d-iomuxc" for main IOMUXC controller, or - "fsl,imx7d-iomuxc-lpsr" for Low Power State Retention IOMUXC controller. -- fsl,pins: each entry consists of 6 integers and represents the mux and config - setting for one pin. The first 5 integers are specified using a PIN_FUNC_ID macro, which can be found in - imx7d-pinfunc.h under device tree source folder. The last integer CONFIG is - the pad setting value like pull-up on this pin. Please refer to i.MX7 Dual - Reference Manual for detailed CONFIG settings. -- fsl,input-sel: required property for iomuxc-lpsr controller, this property is - a phandle for main iomuxc controller which shares the input select register for - daisy chain settings. - -CONFIG bits definition: -PAD_CTL_PUS_100K_DOWN (0 << 5) -PAD_CTL_PUS_5K_UP (1 << 5) -PAD_CTL_PUS_47K_UP (2 << 5) -PAD_CTL_PUS_100K_UP (3 << 5) -PAD_CTL_PUE (1 << 4) -PAD_CTL_HYS (1 << 3) -PAD_CTL_SRE_SLOW (1 << 2) -PAD_CTL_SRE_FAST (0 << 2) -PAD_CTL_DSE_X1 (0 << 0) -PAD_CTL_DSE_X4 (1 << 0) -PAD_CTL_DSE_X2 (2 << 0) -PAD_CTL_DSE_X6 (3 << 0) - -Examples: -While iomuxc-lpsr is intended to be used by dedicated peripherals to take -advantages of LPSR power mode, is also possible that an IP to use pads from -any of the iomux controllers. For example the I2C1 IP can use SCL pad from -iomuxc-lpsr controller and SDA pad from iomuxc controller as: - -i2c1: i2c@30a20000 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_i2c1_1>, <&pinctrl_i2c1_2>; -}; - -iomuxc-lpsr@302c0000 { - compatible = "fsl,imx7d-iomuxc-lpsr"; - reg = <0x302c0000 0x10000>; - fsl,input-sel = <&iomuxc>; - - pinctrl_i2c1_1: i2c1grp-1 { - fsl,pins = < - MX7D_PAD_GPIO1_IO04__I2C1_SCL 0x4000007f - >; - }; -}; - -iomuxc@30330000 { - compatible = "fsl,imx7d-iomuxc"; - reg = <0x30330000 0x10000>; - - pinctrl_i2c1_2: i2c1grp-2 { - fsl,pins = < - MX7D_PAD_I2C1_SDA__I2C1_SDA 0x4000007f - >; - }; -}; diff --git a/Documentation/devicetree/bindings/pinctrl/fsl,imx7d-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/fsl,imx7d-pinctrl.yaml new file mode 100644 index 0000000000000000000000000000000000000000..62103866218813b66fb08a5ba91ae1f11daeb25a --- /dev/null +++ b/Documentation/devicetree/bindings/pinctrl/fsl,imx7d-pinctrl.yaml @@ -0,0 +1,113 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/pinctrl/fsl,imx7d-pinctrl.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Freescale IMX7D IOMUX Controller + +maintainers: + - Dong Aisheng + +description: + Please refer to fsl,imx-pinctrl.txt and pinctrl-bindings.txt in this directory + for common binding part and usage. + +properties: + compatible: + oneOf: + - enum: + - fsl,imx7d-iomuxc + - fsl,imx7d-iomuxc-lpsr + + reg: + maxItems: 1 + + fsl,input-sel: + description: + phandle for main iomuxc controller which shares the input select + register for daisy chain settings. + $ref: /schemas/types.yaml#/definitions/phandle + +# Client device subnode's properties +patternProperties: + 'grp$': + type: object + description: + Pinctrl node's client devices use subnodes for desired pin configuration. + Client device subnodes use below standard properties. + + properties: + fsl,pins: + description: + each entry consists of 6 integers and represents the mux and config + setting for one pin. The first 5 integers are specified using a PIN_FUNC_ID macro, which can + be found in . The last integer + CONFIG is the pad setting value like pull-up on this pin. Please + refer to i.MX7D Reference Manual for detailed CONFIG settings. + $ref: /schemas/types.yaml#/definitions/uint32-matrix + items: + items: + - description: | + "mux_reg" indicates the offset of mux register. + - description: | + "conf_reg" indicates the offset of pad configuration register. + - description: | + "input_reg" indicates the offset of select input register. + - description: | + "mux_val" indicates the mux value to be applied. + - description: | + "input_val" indicates the select input value to be applied. + - description: | + "pad_setting" indicates the pad configuration value to be applied. + + required: + - fsl,pins + + additionalProperties: false + +allOf: + - $ref: "pinctrl.yaml#" + +required: + - compatible + - reg + +if: + properties: + compatible: + contains: + enum: + - fsl,imx7d-iomuxc-lpsr + +then: + required: + - fsl,input-sel + +additionalProperties: false + +examples: + - | + iomuxc: pinctrl@30330000 { + compatible = "fsl,imx7d-iomuxc"; + reg = <0x30330000 0x10000>; + + pinctrl_uart5: uart5grp { + fsl,pins = + <0x0160 0x03D0 0x0714 0x1 0x0 0x7e>, + <0x0164 0x03D4 0x0000 0x1 0x0 0x76>; + }; + }; + - | + iomuxc_lpsr: pinctrl@302c0000 { + compatible = "fsl,imx7d-iomuxc-lpsr"; + reg = <0x302c0000 0x10000>; + fsl,input-sel = <&iomuxc>; + + pinctrl_gpio_lpsr: gpio1-grp { + fsl,pins = + <0x0008 0x0038 0x0000 0x0 0x0 0x59>, + <0x000C 0x003C 0x0000 0x0 0x0 0x59>; + }; + }; diff --git a/Documentation/devicetree/bindings/pinctrl/fsl,imxrt1170.yaml b/Documentation/devicetree/bindings/pinctrl/fsl,imxrt1170.yaml new file mode 100644 index 0000000000000000000000000000000000000000..2e880b3e537c13ecff4d9e39aba04ba1d2435f01 --- /dev/null +++ b/Documentation/devicetree/bindings/pinctrl/fsl,imxrt1170.yaml @@ -0,0 +1,77 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/pinctrl/fsl,imxrt1170.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Freescale i.MXRT1170 IOMUX Controller + +maintainers: + - Giulio Benetti + - Jesse Taube + +description: + Please refer to fsl,imx-pinctrl.txt and pinctrl-bindings.txt in this directory + for common binding part and usage. + +properties: + compatible: + const: fsl,imxrt1170-iomuxc + + reg: + maxItems: 1 + +# Client device subnode's properties +patternProperties: + 'grp$': + type: object + description: + Pinctrl node's client devices use subnodes for desired pin configuration. + Client device subnodes use below standard properties. + + properties: + fsl,pins: + description: + each entry consists of 6 integers and represents the mux and config + setting for one pin. The first 5 integers are specified using a PIN_FUNC_ID macro, which can + be found in . The last + integer CONFIG is the pad setting value like pull-up on this pin. Please + refer to i.MXRT1170 Reference Manual for detailed CONFIG settings. + $ref: /schemas/types.yaml#/definitions/uint32-matrix + items: + items: + - description: | + "mux_reg" indicates the offset of mux register. + - description: | + "conf_reg" indicates the offset of pad configuration register. + - description: | + "input_reg" indicates the offset of select input register. + - description: | + "mux_val" indicates the mux value to be applied. + - description: | + "input_val" indicates the select input value to be applied. + - description: | + "pad_setting" indicates the pad configuration value to be applied. + required: + - fsl,pins + + additionalProperties: false + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + iomuxc: iomuxc@400e8000 { + compatible = "fsl,imxrt1170-iomuxc"; + reg = <0x400e8000 0x4000>; + pinctrl_lpuart1: lpuart1grp { + fsl,pins = + <0x16C 0x3B0 0x620 0x0 0x0 0xf1>, + <0x170 0x3B4 0x61C 0x0 0x0 0xf1>; + }; + }; diff --git a/Documentation/devicetree/bindings/pinctrl/marvell,ac5-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/marvell,ac5-pinctrl.yaml new file mode 100644 index 0000000000000000000000000000000000000000..a651b2744caf35b01592afa997e0cebaca68c88f --- /dev/null +++ b/Documentation/devicetree/bindings/pinctrl/marvell,ac5-pinctrl.yaml @@ -0,0 +1,72 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/pinctrl/marvell,ac5-pinctrl.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Marvell AC5 pin controller + +maintainers: + - Chris Packham + +description: + Bindings for Marvell's AC5 memory-mapped pin controller. + +properties: + compatible: + items: + - const: marvell,ac5-pinctrl + + reg: + maxItems: 1 + +patternProperties: + '-pins$': + type: object + $ref: pinmux-node.yaml# + + properties: + marvell,function: + $ref: "/schemas/types.yaml#/definitions/string" + description: + Indicates the function to select. + enum: [ dev_init_done, ge, gpio, i2c0, i2c1, int_out, led, nand, pcie, ptp, sdio, + spi0, spi1, synce, tsen_int, uart0, uart1, uart2, uart3, uartsd, wd_int, xg ] + + marvell,pins: + $ref: /schemas/types.yaml#/definitions/string-array + description: + Array of MPP pins to be used for the given function. + minItems: 1 + items: + enum: [ mpp0, mpp1, mpp2, mpp3, mpp4, mpp5, mpp6, mpp7, mpp8, mpp9, + mpp10, mpp11, mpp12, mpp13, mpp14, mpp15, mpp16, mpp17, mpp18, mpp19, + mpp20, mpp21, mpp22, mpp23, mpp24, mpp25, mpp26, mpp27, mpp28, mpp29, + mpp30, mpp31, mpp32, mpp33, mpp34, mpp35, mpp36, mpp37, mpp38, mpp39, + mpp40, mpp41, mpp42, mpp43, mpp44, mpp45 ] + +allOf: + - $ref: "pinctrl.yaml#" + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + pinctrl@80020100 { + compatible = "marvell,ac5-pinctrl"; + reg = <0x80020100 0x20>; + + i2c0_pins: i2c0-pins { + marvell,pins = "mpp26", "mpp27"; + marvell,function = "i2c0"; + }; + + i2c0_gpio: i2c0-gpio-pins { + marvell,pins = "mpp26", "mpp27"; + marvell,function = "gpio"; + }; + }; diff --git a/Documentation/devicetree/bindings/pinctrl/mediatek,pinctrl-mt6795.yaml b/Documentation/devicetree/bindings/pinctrl/mediatek,pinctrl-mt6795.yaml new file mode 100644 index 0000000000000000000000000000000000000000..73ae6e11410b3d40a6d701aed00b520b70502862 --- /dev/null +++ b/Documentation/devicetree/bindings/pinctrl/mediatek,pinctrl-mt6795.yaml @@ -0,0 +1,224 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/pinctrl/mediatek,pinctrl-mt6795.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Mediatek MT6795 Pin Controller + +maintainers: + - AngeloGioacchino Del Regno + - Sean Wang + +description: | + The Mediatek's Pin controller is used to control SoC pins. + +properties: + compatible: + const: mediatek,mt6795-pinctrl + + gpio-controller: true + + '#gpio-cells': + description: | + Number of cells in GPIO specifier. Since the generic GPIO binding is used, + the amount of cells must be specified as 2. See the below + mentioned gpio binding representation for description of particular cells. + const: 2 + + gpio-ranges: + description: GPIO valid number range. + maxItems: 1 + + reg: + description: + Physical address base for gpio base and eint registers. + minItems: 2 + + reg-names: + items: + - const: base + - const: eint + + interrupt-controller: true + + '#interrupt-cells': + const: 2 + + interrupts: + description: The interrupt outputs to sysirq. + maxItems: 1 + +# PIN CONFIGURATION NODES +patternProperties: + '-pins$': + type: object + additionalProperties: false + patternProperties: + '^pins': + type: object + additionalProperties: false + description: | + A pinctrl node should contain at least one subnodes representing the + pinctrl groups available on the machine. Each subnode will list the + pins it needs, and how they should be configured, with regard to muxer + configuration, pullups, drive strength, input enable/disable and + input schmitt. + An example of using macro: + pincontroller { + /* GPIO0 set as multifunction GPIO0 */ + gpio-pins { + pins { + pinmux = ; + } + }; + /* GPIO45 set as multifunction SDA0 */ + i2c0-pins { + pins { + pinmux = ; + } + }; + }; + $ref: "pinmux-node.yaml" + + properties: + pinmux: + description: | + Integer array, represents gpio pin number and mux setting. + Supported pin number and mux varies for different SoCs, and are + defined as macros in dt-bindings/pinctrl/-pinfunc.h + directly. + + drive-strength: + enum: [2, 4, 6, 8, 10, 12, 14, 16] + + bias-pull-down: + oneOf: + - type: boolean + - enum: [100, 101, 102, 103] + description: mt6795 pull down PUPD/R0/R1 type define value. + description: | + For normal pull down type, it is not necessary to specify R1R0 + values; When pull down type is PUPD/R0/R1, adding R1R0 defines + will set different resistance values. + + bias-pull-up: + oneOf: + - type: boolean + - enum: [100, 101, 102, 103] + description: mt6795 pull up PUPD/R0/R1 type define value. + description: | + For normal pull up type, it is not necessary to specify R1R0 + values; When pull up type is PUPD/R0/R1, adding R1R0 defines + will set different resistance values. + + bias-disable: true + + output-high: true + + output-low: true + + input-enable: true + + input-disable: true + + input-schmitt-enable: true + + input-schmitt-disable: true + + mediatek,pull-up-adv: + description: | + Pull up setings for 2 pull resistors, R0 and R1. User can + configure those special pins. Valid arguments are described as below: + 0: (R1, R0) = (0, 0) which means R1 disabled and R0 disabled. + 1: (R1, R0) = (0, 1) which means R1 disabled and R0 enabled. + 2: (R1, R0) = (1, 0) which means R1 enabled and R0 disabled. + 3: (R1, R0) = (1, 1) which means R1 enabled and R0 enabled. + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1, 2, 3] + + mediatek,pull-down-adv: + description: | + Pull down settings for 2 pull resistors, R0 and R1. User can + configure those special pins. Valid arguments are described as below: + 0: (R1, R0) = (0, 0) which means R1 disabled and R0 disabled. + 1: (R1, R0) = (0, 1) which means R1 disabled and R0 enabled. + 2: (R1, R0) = (1, 0) which means R1 enabled and R0 disabled. + 3: (R1, R0) = (1, 1) which means R1 enabled and R0 enabled. + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1, 2, 3] + + required: + - pinmux + +allOf: + - $ref: "pinctrl.yaml#" + +required: + - compatible + - reg + - reg-names + - interrupts + - interrupt-controller + - '#interrupt-cells' + - gpio-controller + - '#gpio-cells' + - gpio-ranges + +additionalProperties: false + +examples: + - | + #include + #include + #include + + soc { + #address-cells = <2>; + #size-cells = <2>; + + pio: pinctrl@10005000 { + compatible = "mediatek,mt6795-pinctrl"; + reg = <0 0x10005000 0 0x1000>, <0 0x1000b000 0 0x1000>; + reg-names = "base", "eint"; + gpio-controller; + #gpio-cells = <2>; + gpio-ranges = <&pio 0 0 196>; + interrupt-controller; + interrupts = ; + #interrupt-cells = <2>; + + i2c0-pins { + pins-sda-scl { + pinmux = , + ; + }; + }; + + mmc0-pins { + pins-cmd-dat { + pinmux = , + , + , + , + , + , + , + , + ; + input-enable; + bias-pull-up = ; + }; + + pins-clk { + pinmux = ; + bias-pull-down = ; + }; + + pins-rst { + pinmux = ; + bias-pull-up = ; + }; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/pinctrl/mscc,ocelot-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/mscc,ocelot-pinctrl.txt deleted file mode 100644 index 5d84fd299ccf09d8390671a2ee2275e2ab34a660..0000000000000000000000000000000000000000 --- a/Documentation/devicetree/bindings/pinctrl/mscc,ocelot-pinctrl.txt +++ /dev/null @@ -1,42 +0,0 @@ -Microsemi Ocelot pin controller Device Tree Bindings ----------------------------------------------------- - -Required properties: - - compatible : Should be "mscc,ocelot-pinctrl", - "mscc,jaguar2-pinctrl", "microchip,sparx5-pinctrl", - "mscc,luton-pinctrl", "mscc,serval-pinctrl", - "microchip,lan966x-pinctrl" or "mscc,servalt-pinctrl" - - reg : Address and length of the register set for the device - - gpio-controller : Indicates this device is a GPIO controller - - #gpio-cells : Must be 2. - The first cell is the pin number and the - second cell specifies GPIO flags, as defined in - . - - gpio-ranges : Range of pins managed by the GPIO controller. - - -The ocelot-pinctrl driver uses the generic pin multiplexing and generic pin -configuration documented in pinctrl-bindings.txt. - -The following generic properties are supported: - - function - - pins - -Example: - gpio: pinctrl@71070034 { - compatible = "mscc,ocelot-pinctrl"; - reg = <0x71070034 0x28>; - gpio-controller; - #gpio-cells = <2>; - gpio-ranges = <&gpio 0 0 22>; - - uart_pins: uart-pins { - pins = "GPIO_6", "GPIO_7"; - function = "uart"; - }; - - uart2_pins: uart2-pins { - pins = "GPIO_12", "GPIO_13"; - function = "uart2"; - }; - }; diff --git a/Documentation/devicetree/bindings/pinctrl/mscc,ocelot-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/mscc,ocelot-pinctrl.yaml new file mode 100644 index 0000000000000000000000000000000000000000..98d547c34ef37c3696fec69b77be78d71c679cbf --- /dev/null +++ b/Documentation/devicetree/bindings/pinctrl/mscc,ocelot-pinctrl.yaml @@ -0,0 +1,116 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/pinctrl/mscc,ocelot-pinctrl.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Microsemi Ocelot pin controller + +maintainers: + - Alexandre Belloni + - Lars Povlsen + +properties: + compatible: + enum: + - microchip,lan966x-pinctrl + - microchip,sparx5-pinctrl + - mscc,jaguar2-pinctrl + - mscc,luton-pinctrl + - mscc,ocelot-pinctrl + - mscc,serval-pinctrl + - mscc,servalt-pinctrl + + reg: + items: + - description: Base address + - description: Extended pin configuration registers + minItems: 1 + + gpio-controller: true + + '#gpio-cells': + const: 2 + + gpio-ranges: true + + interrupts: + maxItems: 1 + + interrupt-controller: true + + "#interrupt-cells": + const: 2 + + resets: + maxItems: 1 + + reset-names: + description: Optional shared switch reset. + items: + - const: switch + +patternProperties: + '-pins$': + type: object + allOf: + - $ref: "pinmux-node.yaml" + - $ref: "pincfg-node.yaml" + + properties: + function: true + pins: true + output-high: true + output-low: true + drive-strength: true + + required: + - function + - pins + + additionalProperties: false + +required: + - compatible + - reg + - gpio-controller + - '#gpio-cells' + - gpio-ranges + +allOf: + - $ref: "pinctrl.yaml#" + - if: + properties: + compatible: + contains: + enum: + - microchip,lan966x-pinctrl + - microchip,sparx5-pinctrl + then: + properties: + reg: + minItems: 2 + +additionalProperties: false + +examples: + - | + gpio: pinctrl@71070034 { + compatible = "mscc,ocelot-pinctrl"; + reg = <0x71070034 0x28>; + gpio-controller; + #gpio-cells = <2>; + gpio-ranges = <&gpio 0 0 22>; + + uart_pins: uart-pins { + pins = "GPIO_6", "GPIO_7"; + function = "uart"; + }; + + uart2_pins: uart2-pins { + pins = "GPIO_12", "GPIO_13"; + function = "uart2"; + }; + }; + +... diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-mt8192.yaml b/Documentation/devicetree/bindings/pinctrl/pinctrl-mt8192.yaml index 3c84676a167dfb860cc124394ef74699b5981a80..c90a132fbc790e325cbb5629a781a89b633f9362 100644 --- a/Documentation/devicetree/bindings/pinctrl/pinctrl-mt8192.yaml +++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-mt8192.yaml @@ -29,6 +29,8 @@ properties: description: gpio valid number range. maxItems: 1 + gpio-line-names: true + reg: description: | Physical address base for gpio base registers. There are 11 GPIO @@ -51,62 +53,92 @@ properties: #PIN CONFIGURATION NODES patternProperties: - '^pins': + '-pins$': type: object - description: | - A pinctrl node should contain at least one subnodes representing the - pinctrl groups available on the machine. Each subnode will list the - pins it needs, and how they should be configured, with regard to muxer - configuration, pullups, drive strength, input enable/disable and - input schmitt. - An example of using macro: - pincontroller { - /* GPIO0 set as multifunction GPIO0 */ - state_0_node_a { - pinmux = ; - }; - /* GPIO1 set as multifunction PWM */ - state_0_node_b { - pinmux = ; - }; - }; - $ref: "pinmux-node.yaml" - - properties: - pinmux: - description: | - Integer array, represents gpio pin number and mux setting. - Supported pin number and mux varies for different SoCs, and are defined - as macros in dt-bindings/pinctrl/-pinfunc.h directly. - - drive-strength: - description: | - It can support some arguments, such as MTK_DRIVE_4mA, MTK_DRIVE_6mA, etc. See - dt-bindings/pinctrl/mt65xx.h. It can only support 2/4/6/8/10/12/14/16mA in mt8192. - enum: [2, 4, 6, 8, 10, 12, 14, 16] - - bias-pull-down: true - - bias-pull-up: true - - bias-disable: true - - output-high: true - - output-low: true - - input-enable: true - - input-disable: true - - input-schmitt-enable: true - - input-schmitt-disable: true - - required: - - pinmux - additionalProperties: false + patternProperties: + '^pins': + type: object + description: | + A pinctrl node should contain at least one subnodes representing the + pinctrl groups available on the machine. Each subnode will list the + pins it needs, and how they should be configured, with regard to muxer + configuration, pullups, drive strength, input enable/disable and + input schmitt. + $ref: "pinmux-node.yaml" + + properties: + pinmux: + description: | + Integer array, represents gpio pin number and mux setting. + Supported pin number and mux varies for different SoCs, and are defined + as macros in dt-bindings/pinctrl/-pinfunc.h directly. + + drive-strength: + description: | + It can support some arguments, such as MTK_DRIVE_4mA, MTK_DRIVE_6mA, etc. See + dt-bindings/pinctrl/mt65xx.h. It can only support 2/4/6/8/10/12/14/16mA in mt8192. + enum: [2, 4, 6, 8, 10, 12, 14, 16] + + mediatek,drive-strength-adv: + description: | + Describe the specific driving setup property. + For I2C pins, the existing generic driving setup can only support + 2/4/6/8/10/12/14/16mA driving. But in specific driving setup, they + can support 0.125/0.25/0.5/1mA adjustment. If we enable specific + driving setup, the existing generic setup will be disabled. + The specific driving setup is controlled by E1E0EN. + When E1=0/E0=0, the strength is 0.125mA. + When E1=0/E0=1, the strength is 0.25mA. + When E1=1/E0=0, the strength is 0.5mA. + When E1=1/E0=1, the strength is 1mA. + EN is used to enable or disable the specific driving setup. + Valid arguments are described as below: + 0: (E1, E0, EN) = (0, 0, 0) + 1: (E1, E0, EN) = (0, 0, 1) + 2: (E1, E0, EN) = (0, 1, 0) + 3: (E1, E0, EN) = (0, 1, 1) + 4: (E1, E0, EN) = (1, 0, 0) + 5: (E1, E0, EN) = (1, 0, 1) + 6: (E1, E0, EN) = (1, 1, 0) + 7: (E1, E0, EN) = (1, 1, 1) + So the valid arguments are from 0 to 7. + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1, 2, 3, 4, 5, 6, 7] + + mediatek,pull-up-adv: + description: | + Pull up settings for 2 pull resistors, R0 and R1. User can + configure those special pins. Valid arguments are described as below: + 0: (R1, R0) = (0, 0) which means R1 disabled and R0 disabled. + 1: (R1, R0) = (0, 1) which means R1 disabled and R0 enabled. + 2: (R1, R0) = (1, 0) which means R1 enabled and R0 disabled. + 3: (R1, R0) = (1, 1) which means R1 enabled and R0 enabled. + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1, 2, 3] + + bias-pull-down: true + + bias-pull-up: true + + bias-disable: true + + output-high: true + + output-low: true + + input-enable: true + + input-disable: true + + input-schmitt-enable: true + + input-schmitt-disable: true + + required: + - pinmux + + additionalProperties: false allOf: - $ref: "pinctrl.yaml#" @@ -151,8 +183,17 @@ examples: interrupts = ; #interrupt-cells = <2>; - pins { - pinmux = ; - output-low; + spi1-default-pins { + pins-cs-mosi-clk { + pinmux = , + , + ; + bias-disable; + }; + + pins-miso { + pinmux = ; + bias-pull-down; + }; }; }; diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,pmic-gpio.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,pmic-gpio.yaml index fe2bcf0694d98407708ddb1ea8bfe97d9b7e82d8..6f2efc3772cbe54d3633ba107270ffd6d2a3c387 100644 --- a/Documentation/devicetree/bindings/pinctrl/qcom,pmic-gpio.yaml +++ b/Documentation/devicetree/bindings/pinctrl/qcom,pmic-gpio.yaml @@ -20,6 +20,7 @@ properties: - qcom,pm2250-gpio - qcom,pm660-gpio - qcom,pm660l-gpio + - qcom,pm6125-gpio - qcom,pm6150-gpio - qcom,pm6150l-gpio - qcom,pm6350-gpio @@ -32,6 +33,7 @@ properties: - qcom,pm8058-gpio - qcom,pm8150-gpio - qcom,pm8150b-gpio + - qcom,pm8150l-gpio - qcom,pm8226-gpio - qcom,pm8350-gpio - qcom,pm8350b-gpio @@ -49,10 +51,12 @@ properties: - qcom,pmi8994-gpio - qcom,pmi8998-gpio - qcom,pmk8350-gpio + - qcom,pmm8155au-gpio - qcom,pmr735a-gpio - qcom,pmr735b-gpio - qcom,pms405-gpio - qcom,pmx55-gpio + - qcom,pmx65-gpio - enum: - qcom,spmi-gpio @@ -71,6 +75,16 @@ properties: gpio-ranges: maxItems: 1 + gpio-line-names: + minItems: 2 + maxItems: 44 + + gpio-reserved-ranges: + minItems: 1 + # maxItems as half of total number of GPIOs, as there has to be at + # least one usable GPIO between each reserved range. + maxItems: 22 + '#gpio-cells': const: 2 description: @@ -87,13 +101,278 @@ required: - gpio-ranges - interrupt-controller +allOf: + - if: + properties: + compatible: + contains: + enum: + - qcom,pm8008-gpio + - qcom,pmi8950-gpio + then: + properties: + gpio-line-names: + minItems: 2 + maxItems: 2 + gpio-reserved-ranges: + maxItems: 1 + + - if: + properties: + compatible: + contains: + enum: + - qcom,pm8005-gpio + - qcom,pm8450-gpio + - qcom,pm8916-gpio + - qcom,pmk8350-gpio + - qcom,pmr735a-gpio + - qcom,pmr735b-gpio + then: + properties: + gpio-line-names: + minItems: 4 + maxItems: 4 + gpio-reserved-ranges: + minItems: 1 + maxItems: 2 + + - if: + properties: + compatible: + contains: + enum: + - qcom,pm8018-gpio + - qcom,pm8019-gpio + then: + properties: + gpio-line-names: + minItems: 6 + maxItems: 6 + gpio-reserved-ranges: + minItems: 1 + maxItems: 3 + + - if: + properties: + compatible: + contains: + enum: + - qcom,pm8350b-gpio + - qcom,pm8950-gpio + then: + properties: + gpio-line-names: + minItems: 8 + maxItems: 8 + gpio-reserved-ranges: + minItems: 1 + maxItems: 4 + + - if: + properties: + compatible: + contains: + enum: + - qcom,pm6350-gpio + - qcom,pm8350c-gpio + then: + properties: + gpio-line-names: + minItems: 9 + maxItems: 9 + gpio-reserved-ranges: + minItems: 1 + maxItems: 5 + + - if: + properties: + compatible: + contains: + enum: + - qcom,pm2250-gpio + - qcom,pm6150-gpio + - qcom,pm7325-gpio + - qcom,pm8150-gpio + - qcom,pm8350-gpio + - qcom,pmc8180-gpio + - qcom,pmi8994-gpio + - qcom,pmm8155au-gpio + then: + properties: + gpio-line-names: + minItems: 10 + maxItems: 10 + gpio-reserved-ranges: + minItems: 1 + maxItems: 5 + + - if: + properties: + compatible: + contains: + enum: + - qcom,pmx55-gpio + then: + properties: + gpio-line-names: + minItems: 11 + maxItems: 11 + gpio-reserved-ranges: + minItems: 1 + maxItems: 6 + + - if: + properties: + compatible: + contains: + enum: + - qcom,pm660l-gpio + - qcom,pm6150l-gpio + - qcom,pm8038-gpio + - qcom,pm8150b-gpio + - qcom,pm8150l-gpio + - qcom,pmc8180c-gpio + - qcom,pms405-gpio + then: + properties: + gpio-line-names: + minItems: 12 + maxItems: 12 + gpio-reserved-ranges: + minItems: 1 + maxItems: 6 + + - if: + properties: + compatible: + contains: + enum: + - qcom,pm660-gpio + then: + properties: + gpio-line-names: + minItems: 13 + maxItems: 13 + gpio-reserved-ranges: + minItems: 1 + maxItems: 7 + + - if: + properties: + compatible: + contains: + enum: + - qcom,pmi8998-gpio + then: + properties: + gpio-line-names: + minItems: 14 + maxItems: 14 + gpio-reserved-ranges: + minItems: 1 + maxItems: 7 + + - if: + properties: + compatible: + contains: + enum: + - qcom,pmx65-gpio + then: + properties: + gpio-line-names: + minItems: 16 + maxItems: 16 + gpio-reserved-ranges: + minItems: 1 + maxItems: 8 + + - if: + properties: + compatible: + contains: + enum: + - qcom,pm8994-gpio + - qcom,pma8084-gpio + then: + properties: + gpio-line-names: + minItems: 22 + maxItems: 22 + gpio-reserved-ranges: + minItems: 1 + maxItems: 11 + + - if: + properties: + compatible: + contains: + enum: + - qcom,pm8998-gpio + then: + properties: + gpio-line-names: + minItems: 26 + maxItems: 26 + gpio-reserved-ranges: + minItems: 1 + maxItems: 13 + + - if: + properties: + compatible: + contains: + enum: + - qcom,pm8941-gpio + then: + properties: + gpio-line-names: + minItems: 36 + maxItems: 36 + gpio-reserved-ranges: + minItems: 1 + maxItems: 18 + + - if: + properties: + compatible: + contains: + enum: + - qcom,pm8917-gpio + then: + properties: + gpio-line-names: + minItems: 38 + maxItems: 38 + gpio-reserved-ranges: + minItems: 1 + maxItems: 19 + + - if: + properties: + compatible: + contains: + enum: + - qcom,pm8058-gpio + - qcom,pm8921-gpio + then: + properties: + gpio-line-names: + minItems: 44 + maxItems: 44 + gpio-reserved-ranges: + minItems: 1 + maxItems: 22 + patternProperties: '-state$': oneOf: - $ref: "#/$defs/qcom-pmic-gpio-state" - patternProperties: - ".*": + "(pinconf|-pins)$": $ref: "#/$defs/qcom-pmic-gpio-state" + additionalProperties: false $defs: qcom-pmic-gpio-state: @@ -106,6 +385,7 @@ $defs: description: List of gpio pins affected by the properties specified in this subnode. Valid pins are + - gpio1-gpio9 for pm6125 - gpio1-gpio10 for pm6150 - gpio1-gpio12 for pm6150l - gpio1-gpio9 for pm6350 @@ -134,12 +414,14 @@ $defs: - gpio1-gpio2 for pmi8950 - gpio1-gpio10 for pmi8994 - gpio1-gpio4 for pmk8350 + - gpio1-gpio10 for pmm8155au - gpio1-gpio4 for pmr735a - gpio1-gpio4 for pmr735b - gpio1-gpio12 for pms405 (holes on gpio1, gpio9 and gpio10) - gpio1-gpio11 for pmx55 (holes on gpio3, gpio7, gpio10 and gpio11) + - gpio1-gpio16 for pmx65 items: pattern: "^gpio([0-9]+)$" @@ -174,6 +456,7 @@ $defs: bias-high-impedance: true input-enable: true + input-disable: true output-high: true output-low: true output-enable: true @@ -232,7 +515,7 @@ examples: #gpio-cells = <2>; pm8921_gpio_keys: gpio-keys-state { - volume-keys { + volume-keys-pins { pins = "gpio20", "gpio21"; function = "normal"; diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,qcm2290-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,qcm2290-pinctrl.yaml index 206f4f2387364491fa0d91ab00c1504f4f208424..3f4f1c0360b517bfd83e8c5de61acbe2a7c73989 100644 --- a/Documentation/devicetree/bindings/pinctrl/qcom,qcm2290-pinctrl.yaml +++ b/Documentation/devicetree/bindings/pinctrl/qcom,qcm2290-pinctrl.yaml @@ -42,8 +42,7 @@ properties: gpio-ranges: maxItems: 1 - wakeup-parent: - maxItems: 1 + wakeup-parent: true #PIN CONFIGURATION NODES patternProperties: diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,sc7280-lpass-lpi-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,sc7280-lpass-lpi-pinctrl.yaml new file mode 100644 index 0000000000000000000000000000000000000000..d32ee32776e8f6481d1e7f65e6c8a96115a952e4 --- /dev/null +++ b/Documentation/devicetree/bindings/pinctrl/qcom,sc7280-lpass-lpi-pinctrl.yaml @@ -0,0 +1,115 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/pinctrl/qcom,sc7280-lpass-lpi-pinctrl.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Technologies, Inc. Low Power Audio SubSystem (LPASS) + Low Power Island (LPI) TLMM block + +maintainers: + - Srinivasa Rao Mandadapu + - Srinivas Kandagatla + +description: | + This binding describes the Top Level Mode Multiplexer block found in the + LPASS LPI IP on most Qualcomm SoCs + +properties: + compatible: + const: qcom,sc7280-lpass-lpi-pinctrl + + reg: + minItems: 2 + maxItems: 2 + + gpio-controller: true + + '#gpio-cells': + description: Specifying the pin number and flags, as defined in + include/dt-bindings/gpio/gpio.h + const: 2 + + gpio-ranges: + maxItems: 1 + +#PIN CONFIGURATION NODES +patternProperties: + '-pins$': + type: object + description: + Pinctrl node's client devices use subnodes for desired pin configuration. + Client device subnodes use below standard properties. + $ref: "/schemas/pinctrl/pincfg-node.yaml" + + properties: + pins: + description: + List of gpio pins affected by the properties specified in this + subnode. + items: + oneOf: + - pattern: "^gpio([0-9]|[1-9][0-9])$" + minItems: 1 + maxItems: 15 + + function: + enum: [ gpio, swr_tx_clk, qua_mi2s_sclk, swr_tx_data, qua_mi2s_ws, + qua_mi2s_data, swr_rx_clk, swr_rx_data, dmic1_clk, i2s1_clk, + dmic1_data, i2s1_ws, dmic2_clk, dmic2_data, i2s1_data, + i2s2_clk, wsa_swr_clk, i2s2_ws, wsa_swr_data, dmic3_clk, + dmic3_data, i2s2_data ] + description: + Specify the alternative function to be configured for the specified + pins. + + drive-strength: + enum: [2, 4, 6, 8, 10, 12, 14, 16] + default: 2 + description: + Selects the drive strength for the specified pins, in mA. + + slew-rate: + enum: [0, 1, 2, 3] + default: 0 + description: | + 0: No adjustments + 1: Higher Slew rate (faster edges) + 2: Lower Slew rate (slower edges) + 3: Reserved (No adjustments) + + bias-pull-down: true + + bias-pull-up: true + + bias-disable: true + + output-high: true + + output-low: true + + required: + - pins + - function + + additionalProperties: false + +required: + - compatible + - reg + - gpio-controller + - '#gpio-cells' + - gpio-ranges + +additionalProperties: false + +examples: + - | + lpass_tlmm: pinctrl@33c0000 { + compatible = "qcom,sc7280-lpass-lpi-pinctrl"; + reg = <0x33c0000 0x20000>, + <0x3550000 0x10000>; + gpio-controller; + #gpio-cells = <2>; + gpio-ranges = <&lpass_tlmm 0 0 15>; + }; diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,sc7280-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,sc7280-pinctrl.yaml index 6c7c3f6a140e4c5fc60475b7e94dce39e45f8a46..2d228164357c2cffbccc3a685791c82b5205c16d 100644 --- a/Documentation/devicetree/bindings/pinctrl/qcom,sc7280-pinctrl.yaml +++ b/Documentation/devicetree/bindings/pinctrl/qcom,sc7280-pinctrl.yaml @@ -42,8 +42,7 @@ properties: gpio-ranges: maxItems: 1 - wakeup-parent: - maxItems: 1 + wakeup-parent: true #PIN CONFIGURATION NODES patternProperties: diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,sm6115-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,sm6115-pinctrl.yaml index cfcde405d30a0c4436ecdb754f39e5078521366c..a7a2bb8bff467cb5fdf24d50a67e22f76424f259 100644 --- a/Documentation/devicetree/bindings/pinctrl/qcom,sm6115-pinctrl.yaml +++ b/Documentation/devicetree/bindings/pinctrl/qcom,sm6115-pinctrl.yaml @@ -49,8 +49,7 @@ properties: gpio-ranges: maxItems: 1 - wakeup-parent: - maxItems: 1 + wakeup-parent: true #PIN CONFIGURATION NODES patternProperties: diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,lpass-lpi-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,sm8250-lpass-lpi-pinctrl.yaml similarity index 97% rename from Documentation/devicetree/bindings/pinctrl/qcom,lpass-lpi-pinctrl.yaml rename to Documentation/devicetree/bindings/pinctrl/qcom,sm8250-lpass-lpi-pinctrl.yaml index 5c5542f1627ce5075ea03475375b470a146dbfb8..06efb1382876c57601cbf3294535964a34634651 100644 --- a/Documentation/devicetree/bindings/pinctrl/qcom,lpass-lpi-pinctrl.yaml +++ b/Documentation/devicetree/bindings/pinctrl/qcom,sm8250-lpass-lpi-pinctrl.yaml @@ -1,7 +1,7 @@ # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) %YAML 1.2 --- -$id: http://devicetree.org/schemas/pinctrl/qcom,lpass-lpi-pinctrl.yaml# +$id: http://devicetree.org/schemas/pinctrl/qcom,sm8250-lpass-lpi-pinctrl.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# title: Qualcomm Technologies, Inc. Low Power Audio SubSystem (LPASS) diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,sm8250-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,sm8250-pinctrl.yaml index cfa2c50fdb9363f6d62961ac75e34e950600657d..15bb1018cf21a80dde06d042ba19bdb2d5e18d92 100644 --- a/Documentation/devicetree/bindings/pinctrl/qcom,sm8250-pinctrl.yaml +++ b/Documentation/devicetree/bindings/pinctrl/qcom,sm8250-pinctrl.yaml @@ -49,8 +49,7 @@ properties: gpio-ranges: maxItems: 1 - wakeup-parent: - maxItems: 1 + wakeup-parent: true #PIN CONFIGURATION NODES patternProperties: diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,tlmm-common.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,tlmm-common.yaml index 780f15bb5e4099501ad3f5476949a82b4fda19da..c88c8dcb69d9cfef4c5ad4bb3e3d61f70ff35836 100644 --- a/Documentation/devicetree/bindings/pinctrl/qcom,tlmm-common.yaml +++ b/Documentation/devicetree/bindings/pinctrl/qcom,tlmm-common.yaml @@ -42,7 +42,6 @@ properties: description: Specifying the interrupt-controller used to wake up the system when the TLMM block has been powered down. - maxItems: 1 gpio-reserved-ranges: description: diff --git a/Documentation/devicetree/bindings/pinctrl/ralink,mt7620-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/ralink,mt7620-pinctrl.yaml new file mode 100644 index 0000000000000000000000000000000000000000..4d820df24b89f2a386a52cf073cfd66b8d31bc51 --- /dev/null +++ b/Documentation/devicetree/bindings/pinctrl/ralink,mt7620-pinctrl.yaml @@ -0,0 +1,91 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/pinctrl/ralink,mt7620-pinctrl.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Ralink MT7620 Pin Controller + +maintainers: + - Arınç ÜNAL + - Sergio Paracuellos + +description: + Ralink MT7620 pin controller for MT7620, MT7628 and MT7688 SoCs. + The pin controller can only set the muxing of pin groups. Muxing individual + pins is not supported. There is no pinconf support. + +properties: + compatible: + const: ralink,mt7620-pinctrl + +patternProperties: + '-pins$': + type: object + patternProperties: + '^(.*-)?pinmux$': + type: object + description: node for pinctrl. + $ref: pinmux-node.yaml# + + properties: + groups: + description: The pin group to select. + enum: [ + # For MT7620 SoC + ephy, i2c, mdio, nd_sd, pa, pcie, rgmii1, rgmii2, spi, spi refclk, + uartf, uartlite, wdt, wled, + + # For MT7628 and MT7688 SoCs + gpio, i2c, i2s, p0led_an, p0led_kn, p1led_an, p1led_kn, p2led_an, + p2led_kn, p3led_an, p3led_kn, p4led_an, p4led_kn, perst, pwm0, + pwm1, refclk, sdmode, spi, spi cs1, spis, uart0, uart1, uart2, + wdt, wled_an, wled_kn, + ] + + function: + description: The mux function to select. + enum: [ + # For MT7620 SoC + ephy, gpio, gpio i2s, gpio uartf, i2c, i2s uartf, mdio, nand, pa, + pcie refclk, pcie rst, pcm gpio, pcm i2s, pcm uartf, refclk, + rgmii1, rgmii2, sd, spi, spi refclk, uartf, uartlite, wdt refclk, + wdt rst, wled, + + # For MT7628 and MT7688 SoCs + antenna, debug, gpio, i2c, i2s, jtag, p0led_an, p0led_kn, + p1led_an, p1led_kn, p2led_an, p2led_kn, p3led_an, p3led_kn, + p4led_an, p4led_kn, pcie, pcm, perst, pwm, pwm0, pwm1, pwm_uart2, + refclk, rsvd, sdxc, sdxc d5 d4, sdxc d6, sdxc d7, spi, spi cs1, + spis, sw_r, uart0, uart1, uart2, utif, wdt, wled_an, wled_kn, -, + ] + + required: + - groups + - function + + additionalProperties: false + + additionalProperties: false + +allOf: + - $ref: "pinctrl.yaml#" + +required: + - compatible + +additionalProperties: false + +examples: + # Pinmux controller node + - | + pinctrl { + compatible = "ralink,mt7620-pinctrl"; + + i2c_pins: i2c0-pins { + pinmux { + groups = "i2c"; + function = "i2c"; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/pinctrl/ralink,rt2880-pinmux.yaml b/Documentation/devicetree/bindings/pinctrl/ralink,mt7621-pinctrl.yaml similarity index 63% rename from Documentation/devicetree/bindings/pinctrl/ralink,rt2880-pinmux.yaml rename to Documentation/devicetree/bindings/pinctrl/ralink,mt7621-pinctrl.yaml index 9de8b0c075e25dac817584d7bcc833002acebff1..61e5c847e8c8bab1c9ca2b9cb4d67a37d2705ede 100644 --- a/Documentation/devicetree/bindings/pinctrl/ralink,rt2880-pinmux.yaml +++ b/Documentation/devicetree/bindings/pinctrl/ralink,mt7621-pinctrl.yaml @@ -1,21 +1,23 @@ # SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause %YAML 1.2 --- -$id: http://devicetree.org/schemas/pinctrl/ralink,rt2880-pinmux.yaml# +$id: http://devicetree.org/schemas/pinctrl/ralink,mt7621-pinctrl.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# -title: Ralink rt2880 pinmux controller +title: Ralink MT7621 Pin Controller maintainers: + - Arınç ÜNAL - Sergio Paracuellos description: - The rt2880 pinmux can only set the muxing of pin groups. Muxing indiviual pins - is not supported. There is no pinconf support. + Ralink MT7621 pin controller for MT7621 SoC. + The pin controller can only set the muxing of pin groups. Muxing individual + pins is not supported. There is no pinconf support. properties: compatible: - const: ralink,rt2880-pinmux + const: ralink,mt7621-pinctrl patternProperties: '-pins$': @@ -28,14 +30,15 @@ patternProperties: properties: groups: - description: Name of the pin group to use for the functions. - enum: [i2c, jtag, mdio, pcie, rgmii1, rgmii2, sdhci, spi, - uart1, uart2, uart3, wdt] + description: The pin group to select. + enum: [i2c, jtag, mdio, pcie, rgmii1, rgmii2, sdhci, spi, uart1, + uart2, uart3, wdt] + function: - description: The mux function to select + description: The mux function to select. enum: [gpio, i2c, i2s, jtag, mdio, nand1, nand2, pcie refclk, - pcie rst, pcm, rgmii1, rgmii2, sdhci, spdif2, spdif3, - spi, uart1, uart2, uart3, wdt refclk, wdt rst] + pcie rst, pcm, rgmii1, rgmii2, sdhci, spdif2, spdif3, spi, + uart1, uart2, uart3, wdt refclk, wdt rst] required: - groups @@ -57,7 +60,7 @@ examples: # Pinmux controller node - | pinctrl { - compatible = "ralink,rt2880-pinmux"; + compatible = "ralink,mt7621-pinctrl"; i2c_pins: i2c0-pins { pinmux { diff --git a/Documentation/devicetree/bindings/pinctrl/ralink,rt2880-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/ralink,rt2880-pinctrl.yaml new file mode 100644 index 0000000000000000000000000000000000000000..56e5becabcfdd32ffafc64ba8efd3162c64c11ea --- /dev/null +++ b/Documentation/devicetree/bindings/pinctrl/ralink,rt2880-pinctrl.yaml @@ -0,0 +1,68 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/pinctrl/ralink,rt2880-pinctrl.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Ralink RT2880 Pin Controller + +maintainers: + - Arınç ÜNAL + - Sergio Paracuellos + +description: + Ralink RT2880 pin controller for RT2880 SoC. + The pin controller can only set the muxing of pin groups. Muxing individual + pins is not supported. There is no pinconf support. + +properties: + compatible: + const: ralink,rt2880-pinctrl + +patternProperties: + '-pins$': + type: object + patternProperties: + '^(.*-)?pinmux$': + type: object + description: node for pinctrl. + $ref: pinmux-node.yaml# + + properties: + groups: + description: The pin group to select. + enum: [i2c, spi, uartlite, jtag, mdio, sdram, pci] + + function: + description: The mux function to select. + enum: [gpio, i2c, spi, uartlite, jtag, mdio, sdram, pci] + + required: + - groups + - function + + additionalProperties: false + + additionalProperties: false + +allOf: + - $ref: "pinctrl.yaml#" + +required: + - compatible + +additionalProperties: false + +examples: + # Pinmux controller node + - | + pinctrl { + compatible = "ralink,rt2880-pinctrl"; + + i2c_pins: i2c0-pins { + pinmux { + groups = "i2c"; + function = "i2c"; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/pinctrl/ralink,rt305x-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/ralink,rt305x-pinctrl.yaml new file mode 100644 index 0000000000000000000000000000000000000000..425401c542696b4929ce2e31aa6d071ecf2dcf08 --- /dev/null +++ b/Documentation/devicetree/bindings/pinctrl/ralink,rt305x-pinctrl.yaml @@ -0,0 +1,92 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/pinctrl/ralink,rt305x-pinctrl.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Ralink RT305X Pin Controller + +maintainers: + - Arınç ÜNAL + - Sergio Paracuellos + +description: + Ralink RT305X pin controller for RT3050, RT3052, RT3350, RT3352 and RT5350 + SoCs. + The pin controller can only set the muxing of pin groups. Muxing individual + pins is not supported. There is no pinconf support. + +properties: + compatible: + const: ralink,rt305x-pinctrl + +patternProperties: + '-pins$': + type: object + patternProperties: + '^(.*-)?pinmux$': + type: object + description: node for pinctrl. + $ref: pinmux-node.yaml# + + properties: + groups: + description: The pin group to select. + enum: [ + # For RT3050, RT3052 and RT3350 SoCs + i2c, jtag, mdio, rgmii, sdram, spi, uartf, uartlite, + + # For RT3352 SoC + i2c, jtag, led, lna, mdio, pa, rgmii, spi, spi_cs1, uartf, + uartlite, + + # For RT5350 SoC + i2c, jtag, led, spi, spi_cs1, uartf, uartlite, + ] + + function: + description: The mux function to select. + enum: [ + # For RT3050, RT3052 and RT3350 SoCs + gpio, gpio i2s, gpio uartf, i2c, i2s uartf, jtag, mdio, pcm gpio, + pcm i2s, pcm uartf, rgmii, sdram, spi, uartf, uartlite, + + # For RT3352 SoC + gpio, gpio i2s, gpio uartf, i2c, i2s uartf, jtag, led, lna, mdio, + pa, pcm gpio, pcm i2s, pcm uartf, rgmii, spi, spi_cs1, uartf, + uartlite, wdg_cs1, + + # For RT5350 SoC + gpio, gpio i2s, gpio uartf, i2c, i2s uartf, jtag, led, pcm gpio, + pcm i2s, pcm uartf, spi, spi_cs1, uartf, uartlite, wdg_cs1, + ] + + required: + - groups + - function + + additionalProperties: false + + additionalProperties: false + +allOf: + - $ref: "pinctrl.yaml#" + +required: + - compatible + +additionalProperties: false + +examples: + # Pinmux controller node + - | + pinctrl { + compatible = "ralink,rt305x-pinctrl"; + + i2c_pins: i2c0-pins { + pinmux { + groups = "i2c"; + function = "i2c"; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/pinctrl/ralink,rt3883-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/ralink,rt3883-pinctrl.yaml new file mode 100644 index 0000000000000000000000000000000000000000..feb6e66dcb6133613f9afafdc001a01f8505d19c --- /dev/null +++ b/Documentation/devicetree/bindings/pinctrl/ralink,rt3883-pinctrl.yaml @@ -0,0 +1,71 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/pinctrl/ralink,rt3883-pinctrl.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Ralink RT3883 Pin Controller + +maintainers: + - Arınç ÜNAL + - Sergio Paracuellos + +description: + Ralink RT3883 pin controller for RT3883 SoC. + The pin controller can only set the muxing of pin groups. Muxing individual + pins is not supported. There is no pinconf support. + +properties: + compatible: + const: ralink,rt3883-pinctrl + +patternProperties: + '-pins$': + type: object + patternProperties: + '^(.*-)?pinmux$': + type: object + description: node for pinctrl. + $ref: pinmux-node.yaml# + + properties: + groups: + description: The pin group to select. + enum: [ge1, ge2, i2c, jtag, lna a, lna g, mdio, pci, spi, uartf, + uartlite] + + function: + description: The mux function to select. + enum: [ge1, ge2, gpio, gpio i2s, gpio uartf, i2c, i2s uartf, jtag, + lna a, lna g, mdio, pci-dev, pci-fnc, pci-host1, pci-host2, + pcm gpio, pcm i2s, pcm uartf, spi, uartf, uartlite] + + required: + - groups + - function + + additionalProperties: false + + additionalProperties: false + +allOf: + - $ref: "pinctrl.yaml#" + +required: + - compatible + +additionalProperties: false + +examples: + # Pinmux controller node + - | + pinctrl { + compatible = "ralink,rt3883-pinctrl"; + + i2c_pins: i2c0-pins { + pinmux { + groups = "i2c"; + function = "i2c"; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/pinctrl/renesas,rzg2l-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/renesas,rzg2l-pinctrl.yaml index 9ccf54870aa489a07892b2d3a140d37fd12aac92..52df1b1461745f97e67f8765a4b346e7b5c4a64c 100644 --- a/Documentation/devicetree/bindings/pinctrl/renesas,rzg2l-pinctrl.yaml +++ b/Documentation/devicetree/bindings/pinctrl/renesas,rzg2l-pinctrl.yaml @@ -11,8 +11,8 @@ maintainers: - Lad Prabhakar description: - The Renesas SoCs of the RZ/{G2L,V2L} series feature a combined Pin and GPIO - controller. + The Renesas SoCs of the RZ/{G2L,V2L} alike series feature a combined Pin and + GPIO controller. Pin multiplexing and GPIO configuration is performed on a per-pin basis. Each port features up to 8 pins, each of them configurable for GPIO function (port mode) or in alternate function mode. @@ -23,6 +23,7 @@ properties: oneOf: - items: - enum: + - renesas,r9a07g043-pinctrl # RZ/G2UL{Type-1,Type-2} - renesas,r9a07g044-pinctrl # RZ/G2{L,LC} - items: diff --git a/Documentation/devicetree/bindings/pinctrl/rockchip,pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/rockchip,pinctrl.yaml index b0eae3a67ab1198055e06bd4c62691b1a66494a4..677a285ca416985c539d7341b2750396434d926b 100644 --- a/Documentation/devicetree/bindings/pinctrl/rockchip,pinctrl.yaml +++ b/Documentation/devicetree/bindings/pinctrl/rockchip,pinctrl.yaml @@ -33,6 +33,7 @@ properties: enum: - rockchip,px30-pinctrl - rockchip,rk2928-pinctrl + - rockchip,rk3036-pinctrl - rockchip,rk3066a-pinctrl - rockchip,rk3066b-pinctrl - rockchip,rk3128-pinctrl @@ -44,6 +45,7 @@ properties: - rockchip,rk3368-pinctrl - rockchip,rk3399-pinctrl - rockchip,rk3568-pinctrl + - rockchip,rk3588-pinctrl - rockchip,rv1108-pinctrl rockchip,grf: @@ -129,7 +131,7 @@ additionalProperties: description: Pin bank index. - minimum: 0 - maximum: 6 + maximum: 10 description: Mux 0 means GPIO and mux 1 to N means the specific device function. diff --git a/Documentation/devicetree/bindings/powerpc/fsl/cache_sram.txt b/Documentation/devicetree/bindings/powerpc/fsl/cache_sram.txt deleted file mode 100644 index 781955f5217d55cec05746dd2316a96ac04cdbad..0000000000000000000000000000000000000000 --- a/Documentation/devicetree/bindings/powerpc/fsl/cache_sram.txt +++ /dev/null @@ -1,20 +0,0 @@ -* Freescale PQ3 and QorIQ based Cache SRAM - -Freescale's mpc85xx and some QorIQ platforms provide an -option of configuring a part of (or full) cache memory -as SRAM. This cache SRAM representation in the device -tree should be done as under:- - -Required properties: - -- compatible : should be "fsl,p2020-cache-sram" -- fsl,cache-sram-ctlr-handle : points to the L2 controller -- reg : offset and length of the cache-sram. - -Example: - -cache-sram@fff00000 { - fsl,cache-sram-ctlr-handle = <&L2>; - reg = <0 0xfff00000 0 0x10000>; - compatible = "fsl,p2020-cache-sram"; -}; diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,smd-rpm.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom,smd-rpm.yaml index 2a4b6c06e7c9926dac57deb28f630eb55848de66..f0f1bf06aea6ae00ffea1ee25be1958809b2f15a 100644 --- a/Documentation/devicetree/bindings/soc/qcom/qcom,smd-rpm.yaml +++ b/Documentation/devicetree/bindings/soc/qcom/qcom,smd-rpm.yaml @@ -47,6 +47,10 @@ properties: - qcom,rpm-qcm2290 - qcom,rpm-qcs404 + clock-controller: + $ref: /schemas/clock/qcom,rpmcc.yaml# + unevaluatedProperties: false + qcom,smd-channels: $ref: /schemas/types.yaml#/definitions/string-array description: Channel name used for the RPM communication diff --git a/Documentation/devicetree/bindings/trivial-devices.yaml b/Documentation/devicetree/bindings/trivial-devices.yaml index 05f01f4acca845d7bd94344fb0a65de5ed3a0f6e..6aafa71806a3d6478901440f70a115f5567b6bee 100644 --- a/Documentation/devicetree/bindings/trivial-devices.yaml +++ b/Documentation/devicetree/bindings/trivial-devices.yaml @@ -47,7 +47,9 @@ properties: - at,24c08 # i2c trusted platform module (TPM) - atmel,at97sc3204t - # i2c h/w symmetric crypto module + # ATSHA204 - i2c h/w symmetric crypto module + - atmel,atsha204 + # ATSHA204A - i2c h/w symmetric crypto module - atmel,atsha204a # i2c h/w elliptic curve crypto module - atmel,atecc508a diff --git a/Documentation/driver-api/dmaengine/provider.rst b/Documentation/driver-api/dmaengine/provider.rst index 0072c9c7efd3407ca15d132fec443b48282941ca..1e0f1f85d10e52da69f2259758efb6de517f345e 100644 --- a/Documentation/driver-api/dmaengine/provider.rst +++ b/Documentation/driver-api/dmaengine/provider.rst @@ -206,6 +206,12 @@ Currently, the types available are: - The device is able to perform parity check using RAID6 P+Q algorithm against a memory buffer. +- DMA_MEMSET + + - The device is able to fill memory with the provided pattern + + - The pattern is treated as a single byte signed value. + - DMA_INTERRUPT - The device is able to trigger a dummy transfer that will @@ -457,7 +463,7 @@ supported. - Should use dma_set_residue to report it - In the case of a cyclic transfer, it should only take into - account the current period. + account the total size of the cyclic buffer. - Should return DMA_OUT_OF_ORDER if the device does not support in order completion and is completing the operation out of order. diff --git a/Documentation/driver-api/gpio/driver.rst b/Documentation/driver-api/gpio/driver.rst index a1ddefa1f55f45849001fb1794712bc284ad2c1d..70ff43ac4fcc1bedf69832b1f431215a81114b25 100644 --- a/Documentation/driver-api/gpio/driver.rst +++ b/Documentation/driver-api/gpio/driver.rst @@ -429,7 +429,8 @@ call into the core gpiolib code: static void my_gpio_mask_irq(struct irq_data *d) { - struct gpio_chip *gc = irq_desc_get_handler_data(d); + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + irq_hw_number_t hwirq = irqd_to_hwirq(d); /* * Perform any necessary action to mask the interrupt, @@ -437,14 +438,15 @@ call into the core gpiolib code: * state. */ - gpiochip_disable_irq(gc, d->hwirq); + gpiochip_disable_irq(gc, hwirq); } static void my_gpio_unmask_irq(struct irq_data *d) { - struct gpio_chip *gc = irq_desc_get_handler_data(d); + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + irq_hw_number_t hwirq = irqd_to_hwirq(d); - gpiochip_enable_irq(gc, d->hwirq); + gpiochip_enable_irq(gc, hwirq); /* * Perform any necessary action to unmask the interrupt, @@ -501,7 +503,8 @@ the interrupt separately and go with it: static void my_gpio_mask_irq(struct irq_data *d) { - struct gpio_chip *gc = irq_desc_get_handler_data(d); + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + irq_hw_number_t hwirq = irqd_to_hwirq(d); /* * Perform any necessary action to mask the interrupt, @@ -509,14 +512,15 @@ the interrupt separately and go with it: * state. */ - gpiochip_disable_irq(gc, d->hwirq); + gpiochip_disable_irq(gc, hwirq); } static void my_gpio_unmask_irq(struct irq_data *d) { - struct gpio_chip *gc = irq_desc_get_handler_data(d); + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + irq_hw_number_t hwirq = irqd_to_hwirq(d); - gpiochip_enable_irq(gc, d->hwirq); + gpiochip_enable_irq(gc, hwirq); /* * Perform any necessary action to unmask the interrupt, @@ -576,7 +580,8 @@ In this case the typical set-up will look like this: static void my_gpio_mask_irq(struct irq_data *d) { - struct gpio_chip *gc = irq_desc_get_handler_data(d); + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + irq_hw_number_t hwirq = irqd_to_hwirq(d); /* * Perform any necessary action to mask the interrupt, @@ -584,15 +589,16 @@ In this case the typical set-up will look like this: * state. */ - gpiochip_disable_irq(gc, d->hwirq); + gpiochip_disable_irq(gc, hwirq); irq_mask_mask_parent(d); } static void my_gpio_unmask_irq(struct irq_data *d) { - struct gpio_chip *gc = irq_desc_get_handler_data(d); + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + irq_hw_number_t hwirq = irqd_to_hwirq(d); - gpiochip_enable_irq(gc, d->hwirq); + gpiochip_enable_irq(gc, hwirq); /* * Perform any necessary action to unmask the interrupt, diff --git a/Documentation/i2c/writing-clients.rst b/Documentation/i2c/writing-clients.rst index 978cc8210bf3b13a0ba04ab2074d59be5d56d774..e3b126cf4a3bb5045c5e9b53ec707d52c978240c 100644 --- a/Documentation/i2c/writing-clients.rst +++ b/Documentation/i2c/writing-clients.rst @@ -46,7 +46,7 @@ driver model device node, and its I2C address. }, .id_table = foo_idtable, - .probe = foo_probe, + .probe_new = foo_probe, .remove = foo_remove, /* if device autodetection is needed: */ .class = I2C_CLASS_SOMETHING, @@ -155,8 +155,7 @@ those devices, and a remove() method to unbind. :: - static int foo_probe(struct i2c_client *client, - const struct i2c_device_id *id); + static int foo_probe(struct i2c_client *client); static int foo_remove(struct i2c_client *client); Remember that the i2c_driver does not create those client handles. The @@ -165,8 +164,12 @@ handle may be used during foo_probe(). If foo_probe() reports success foo_remove() returns. That binding model is used by most Linux drivers. The probe function is called when an entry in the id_table name field -matches the device's name. It is passed the entry that was matched so -the driver knows which one in the table matched. +matches the device's name. If the probe function needs that entry, it +can retrieve it using + +:: + + const struct i2c_device_id *id = i2c_match_id(foo_idtable, client); Device Creation diff --git a/Documentation/powerpc/dawr-power9.rst b/Documentation/powerpc/dawr-power9.rst index e55ac6a24b97f944119fc54b7667152392e212c6..310f2e0cea812a3870ab43fbce628f8007fe5dfb 100644 --- a/Documentation/powerpc/dawr-power9.rst +++ b/Documentation/powerpc/dawr-power9.rst @@ -2,15 +2,23 @@ DAWR issues on POWER9 ===================== -On POWER9 the Data Address Watchpoint Register (DAWR) can cause a checkstop -if it points to cache inhibited (CI) memory. Currently Linux has no way to -distinguish CI memory when configuring the DAWR, so (for now) the DAWR is -disabled by this commit:: - - commit 9654153158d3e0684a1bdb76dbababdb7111d5a0 - Author: Michael Neuling - Date: Tue Mar 27 15:37:24 2018 +1100 - powerpc: Disable DAWR in the base POWER9 CPU features +On older POWER9 processors, the Data Address Watchpoint Register (DAWR) can +cause a checkstop if it points to cache inhibited (CI) memory. Currently Linux +has no way to distinguish CI memory when configuring the DAWR, so on affected +systems, the DAWR is disabled. + +Affected processor revisions +============================ + +This issue is only present on processors prior to v2.3. The revision can be +found in /proc/cpuinfo:: + + processor : 0 + cpu : POWER9, altivec supported + clock : 3800.000000MHz + revision : 2.3 (pvr 004e 1203) + +On a system with the issue, the DAWR is disabled as detailed below. Technical Details: ================== diff --git a/Documentation/powerpc/kasan.txt b/Documentation/powerpc/kasan.txt new file mode 100644 index 0000000000000000000000000000000000000000..f032b4eaf2051401d875533e36d905ba0ceca2fd --- /dev/null +++ b/Documentation/powerpc/kasan.txt @@ -0,0 +1,58 @@ +KASAN is supported on powerpc on 32-bit and Radix 64-bit only. + +32 bit support +============== + +KASAN is supported on both hash and nohash MMUs on 32-bit. + +The shadow area sits at the top of the kernel virtual memory space above the +fixmap area and occupies one eighth of the total kernel virtual memory space. + +Instrumentation of the vmalloc area is optional, unless built with modules, +in which case it is required. + +64 bit support +============== + +Currently, only the radix MMU is supported. There have been versions for hash +and Book3E processors floating around on the mailing list, but nothing has been +merged. + +KASAN support on Book3S is a bit tricky to get right: + + - It would be good to support inline instrumentation so as to be able to catch + stack issues that cannot be caught with outline mode. + + - Inline instrumentation requires a fixed offset. + + - Book3S runs code with translations off ("real mode") during boot, including a + lot of generic device-tree parsing code which is used to determine MMU + features. + + - Some code - most notably a lot of KVM code - also runs with translations off + after boot. + + - Therefore any offset has to point to memory that is valid with + translations on or off. + +One approach is just to give up on inline instrumentation. This way boot-time +checks can be delayed until after the MMU is set is up, and we can just not +instrument any code that runs with translations off after booting. This is the +current approach. + +To avoid this limitiation, the KASAN shadow would have to be placed inside the +linear mapping, using the same high-bits trick we use for the rest of the linear +mapping. This is tricky: + + - We'd like to place it near the start of physical memory. In theory we can do + this at run-time based on how much physical memory we have, but this requires + being able to arbitrarily relocate the kernel, which is basically the tricky + part of KASLR. Not being game to implement both tricky things at once, this + is hopefully something we can revisit once we get KASLR for Book3S. + + - Alternatively, we can place the shadow at the _end_ of memory, but this + requires knowing how much contiguous physical memory a system has _at compile + time_. This is a big hammer, and has some unfortunate consequences: inablity + to handle discontiguous physical memory, total failure to boot on machines + with less memory than specified, and that machines with more memory than + specified can't use it. This was deemed unacceptable. diff --git a/Documentation/tools/rtla/Makefile b/Documentation/tools/rtla/Makefile index 9f2b84af1a6c77c23ed3e974540e8551cbf09862..093af6d7a0e93da0f8b96e19757cf731f95922df 100644 --- a/Documentation/tools/rtla/Makefile +++ b/Documentation/tools/rtla/Makefile @@ -17,9 +17,21 @@ DOC_MAN1 = $(addprefix $(OUTPUT),$(_DOC_MAN1)) RST2MAN_DEP := $(shell command -v rst2man 2>/dev/null) RST2MAN_OPTS += --verbose +TEST_RST2MAN = $(shell sh -c "rst2man --version > /dev/null 2>&1 || echo n") + $(OUTPUT)%.1: %.rst ifndef RST2MAN_DEP - $(error "rst2man not found, but required to generate man pages") + $(info ********************************************) + $(info ** NOTICE: rst2man not found) + $(info **) + $(info ** Consider installing the latest rst2man from your) + $(info ** distribution, e.g., 'dnf install python3-docutils' on Fedora,) + $(info ** or from source:) + $(info **) + $(info ** https://docutils.sourceforge.io/docs/dev/repository.html ) + $(info **) + $(info ********************************************) + $(error NOTICE: rst2man required to generate man pages) endif rst2man $(RST2MAN_OPTS) $< > $@ diff --git a/Documentation/trace/ftrace.rst b/Documentation/trace/ftrace.rst index 45b8c56af67a74230cea7ed1a9c7eeccf558c436..b37dc19e4d40950fb46d9016cb99f4b905271580 100644 --- a/Documentation/trace/ftrace.rst +++ b/Documentation/trace/ftrace.rst @@ -517,6 +517,18 @@ of ftrace. Here is a list of some of the key files: processing should be able to handle them. See comments in the ktime_get_boot_fast_ns() function for more information. + tai: + This is the tai clock (CLOCK_TAI) and is derived from the wall- + clock time. However, this clock does not experience + discontinuities and backwards jumps caused by NTP inserting leap + seconds. Since the clock access is designed for use in tracing, + side effects are possible. The clock access may yield wrong + readouts in case the internal TAI offset is updated e.g., caused + by setting the system time or using adjtimex() with an offset. + These effects are rare and post processing should be able to + handle them. See comments in the ktime_get_tai_fast_ns() + function for more information. + To set a clock, simply echo the clock name into this file:: # echo global > trace_clock diff --git a/Documentation/trace/timerlat-tracer.rst b/Documentation/trace/timerlat-tracer.rst index 64d1fe6e9b9388b5046ee464a41a90954b085055..d643c95c01eb1684fbdb7b75a26ab506cf8e9348 100644 --- a/Documentation/trace/timerlat-tracer.rst +++ b/Documentation/trace/timerlat-tracer.rst @@ -74,8 +74,9 @@ directory. The timerlat configs are: - stop_tracing_total_us: stop the system tracing if a timer latency at the *thread* context is higher than the configured value happens. Writing 0 disables this option. - - print_stack: save the stack of the IRQ occurrence, and print - it after the *thread context* event". + - print_stack: save the stack of the IRQ occurrence. The stack is printed + after the *thread context* event, or at the IRQ handler if *stop_tracing_us* + is hit. timerlat and osnoise ---------------------------- diff --git a/MAINTAINERS b/MAINTAINERS index 41b61aa79365d9f28f4a1b12a36d507fa0db3c1a..790b80f8ac915820592468f3fb733633b124bf0e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -820,7 +820,7 @@ S: Maintained F: drivers/mailbox/mailbox-altera.c ALTERA MSGDMA IP CORE DRIVER -M: Olivier Dautricourt +M: Olivier Dautricourt R: Stefan Roese L: dmaengine@vger.kernel.org S: Odd Fixes @@ -1375,14 +1375,6 @@ L: linux-input@vger.kernel.org S: Odd fixes F: drivers/input/mouse/bcm5974.c -APPLE DART IOMMU DRIVER -M: Sven Peter -R: Alyssa Rosenzweig -L: iommu@lists.linux-foundation.org -S: Maintained -F: Documentation/devicetree/bindings/iommu/apple,dart.yaml -F: drivers/iommu/apple-dart.c - APPLE PCIE CONTROLLER DRIVER M: Alyssa Rosenzweig M: Marc Zyngier @@ -1834,6 +1826,7 @@ F: Documentation/devicetree/bindings/arm/apple/* F: Documentation/devicetree/bindings/clock/apple,nco.yaml F: Documentation/devicetree/bindings/i2c/apple,i2c.yaml F: Documentation/devicetree/bindings/interrupt-controller/apple,* +F: Documentation/devicetree/bindings/iommu/apple,dart.yaml F: Documentation/devicetree/bindings/iommu/apple,sart.yaml F: Documentation/devicetree/bindings/mailbox/apple,mailbox.yaml F: Documentation/devicetree/bindings/nvme/apple,nvme-ans.yaml @@ -1845,6 +1838,7 @@ F: arch/arm64/boot/dts/apple/ F: drivers/clk/clk-apple-nco.c F: drivers/i2c/busses/i2c-pasemi-core.c F: drivers/i2c/busses/i2c-pasemi-platform.c +F: drivers/iommu/apple-dart.c F: drivers/irqchip/irq-apple-aic.c F: drivers/mailbox/apple-mailbox.c F: drivers/nvme/host/apple.c @@ -7517,6 +7511,7 @@ S: Maintained F: Documentation/admin-guide/bootconfig.rst F: fs/proc/bootconfig.c F: include/linux/bootconfig.h +F: lib/bootconfig-data.S F: lib/bootconfig.c F: tools/bootconfig/* F: tools/bootconfig/scripts/* @@ -16654,6 +16649,13 @@ L: linux-mips@vger.kernel.org S: Maintained F: arch/mips/boot/dts/ralink/mt7621* +RALINK PINCTRL DRIVER +M: Arınç ÜNAL +M: Sergio Paracuellos +L: linux-mips@vger.kernel.org +S: Maintained +F: drivers/pinctrl/ralink/ + RALINK RT2X00 WIRELESS LAN DRIVER M: Stanislaw Gruszka M: Helmut Schaa @@ -19201,6 +19203,7 @@ SYNOPSYS DESIGNWARE DMAC DRIVER M: Viresh Kumar R: Andy Shevchenko S: Maintained +F: Documentation/devicetree/bindings/dma/renesas,rzn1-dmamux.yaml F: Documentation/devicetree/bindings/dma/snps,dma-spear1340.yaml F: drivers/dma/dw/ F: include/dt-bindings/dma/dw-dmac.h @@ -20119,8 +20122,8 @@ M: Ingo Molnar S: Maintained T: git git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace.git F: Documentation/trace/ftrace.rst -F: arch/*/*/*/ftrace.h -F: arch/*/kernel/ftrace.c +F: arch/*/*/*/*ftrace* +F: arch/*/*/*ftrace* F: fs/tracefs/ F: include/*/ftrace.h F: include/linux/trace*.h diff --git a/arch/Kconfig b/arch/Kconfig index 904ed51736d4fd230127b584fdf291be69371c8c..81a3439a72bc3e3c0bdc540367adadcfd79ebe86 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -1019,12 +1019,10 @@ config PAGE_SIZE_LESS_THAN_64KB depends on !IA64_PAGE_SIZE_64KB depends on !PAGE_SIZE_64KB depends on !PARISC_PAGE_SIZE_64KB - depends on !PPC_64K_PAGES depends on PAGE_SIZE_LESS_THAN_256KB config PAGE_SIZE_LESS_THAN_256KB def_bool y - depends on !PPC_256K_PAGES depends on !PAGE_SIZE_256KB # This allows to use a set of generic functions to determine mmap base diff --git a/arch/arm/kernel/ftrace.c b/arch/arm/kernel/ftrace.c index 83cc068586bc5c25dbb2e63cc2378229f43c801f..a0b6d1e3812fdba8f25aa4b59406044904150526 100644 --- a/arch/arm/kernel/ftrace.c +++ b/arch/arm/kernel/ftrace.c @@ -79,16 +79,14 @@ static unsigned long __ref adjust_address(struct dyn_ftrace *rec, return (unsigned long)&ftrace_regs_caller_from_init; } -int ftrace_arch_code_modify_prepare(void) +void ftrace_arch_code_modify_prepare(void) { - return 0; } -int ftrace_arch_code_modify_post_process(void) +void ftrace_arch_code_modify_post_process(void) { /* Make sure any TLB misses during machine stop are cleared. */ flush_tlb_all(); - return 0; } static unsigned long ftrace_call_replace(unsigned long pc, unsigned long addr, diff --git a/arch/arm/kernel/reboot.c b/arch/arm/kernel/reboot.c index 3044fcb8d073623d71a0129e6ed23a8a889b83de..2cb943422554eddbbf65a260dfdc8c37cbf55034 100644 --- a/arch/arm/kernel/reboot.c +++ b/arch/arm/kernel/reboot.c @@ -116,9 +116,7 @@ void machine_power_off(void) { local_irq_disable(); smp_send_stop(); - - if (pm_power_off) - pm_power_off(); + do_kernel_power_off(); } /* diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index a4968845e67f5e14fb4b65eb7c0bc0ae7276cf25..1652a9800ebee645616948df2249e186e948baff 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -2157,10 +2157,6 @@ config DMI endmenu # "Boot options" -config SYSVIPC_COMPAT - def_bool y - depends on COMPAT && SYSVIPC - menu "Power management options" source "kernel/power/Kconfig" diff --git a/arch/arm64/crypto/Kconfig b/arch/arm64/crypto/Kconfig index 2a965aa0188dd57132f62fb4a1281b1ccf82848e..ac85682c013c143ea76f02fb60a6d37b41f6a455 100644 --- a/arch/arm64/crypto/Kconfig +++ b/arch/arm64/crypto/Kconfig @@ -45,13 +45,25 @@ config CRYPTO_SM3_ARM64_CE tristate "SM3 digest algorithm (ARMv8.2 Crypto Extensions)" depends on KERNEL_MODE_NEON select CRYPTO_HASH - select CRYPTO_LIB_SM3 + select CRYPTO_SM3 config CRYPTO_SM4_ARM64_CE tristate "SM4 symmetric cipher (ARMv8.2 Crypto Extensions)" depends on KERNEL_MODE_NEON select CRYPTO_ALGAPI - select CRYPTO_LIB_SM4 + select CRYPTO_SM4 + +config CRYPTO_SM4_ARM64_CE_BLK + tristate "SM4 in ECB/CBC/CFB/CTR modes using ARMv8 Crypto Extensions" + depends on KERNEL_MODE_NEON + select CRYPTO_SKCIPHER + select CRYPTO_SM4 + +config CRYPTO_SM4_ARM64_NEON_BLK + tristate "SM4 in ECB/CBC/CFB/CTR modes using NEON instructions" + depends on KERNEL_MODE_NEON + select CRYPTO_SKCIPHER + select CRYPTO_SM4 config CRYPTO_GHASH_ARM64_CE tristate "GHASH/AES-GCM using ARMv8 Crypto Extensions" diff --git a/arch/arm64/crypto/Makefile b/arch/arm64/crypto/Makefile index 09a805cc32d7c4487e18be463cad1d8998f5511e..bea8995133b1fd8951f44076a673279c7e85762d 100644 --- a/arch/arm64/crypto/Makefile +++ b/arch/arm64/crypto/Makefile @@ -20,9 +20,15 @@ sha3-ce-y := sha3-ce-glue.o sha3-ce-core.o obj-$(CONFIG_CRYPTO_SM3_ARM64_CE) += sm3-ce.o sm3-ce-y := sm3-ce-glue.o sm3-ce-core.o -obj-$(CONFIG_CRYPTO_SM4_ARM64_CE) += sm4-ce.o +obj-$(CONFIG_CRYPTO_SM4_ARM64_CE) += sm4-ce-cipher.o +sm4-ce-cipher-y := sm4-ce-cipher-glue.o sm4-ce-cipher-core.o + +obj-$(CONFIG_CRYPTO_SM4_ARM64_CE_BLK) += sm4-ce.o sm4-ce-y := sm4-ce-glue.o sm4-ce-core.o +obj-$(CONFIG_CRYPTO_SM4_ARM64_NEON_BLK) += sm4-neon.o +sm4-neon-y := sm4-neon-glue.o sm4-neon-core.o + obj-$(CONFIG_CRYPTO_GHASH_ARM64_CE) += ghash-ce.o ghash-ce-y := ghash-ce-glue.o ghash-ce-core.o diff --git a/arch/arm64/crypto/sm4-ce-cipher-core.S b/arch/arm64/crypto/sm4-ce-cipher-core.S new file mode 100644 index 0000000000000000000000000000000000000000..4ac6cfbc57970e2449067144aaa4e27c6d4373d4 --- /dev/null +++ b/arch/arm64/crypto/sm4-ce-cipher-core.S @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include +#include + + .irp b, 0, 1, 2, 3, 4, 5, 6, 7, 8 + .set .Lv\b\().4s, \b + .endr + + .macro sm4e, rd, rn + .inst 0xcec08400 | .L\rd | (.L\rn << 5) + .endm + + /* + * void sm4_ce_do_crypt(const u32 *rk, u32 *out, const u32 *in); + */ + .text +SYM_FUNC_START(sm4_ce_do_crypt) + ld1 {v8.4s}, [x2] + ld1 {v0.4s-v3.4s}, [x0], #64 +CPU_LE( rev32 v8.16b, v8.16b ) + ld1 {v4.4s-v7.4s}, [x0] + sm4e v8.4s, v0.4s + sm4e v8.4s, v1.4s + sm4e v8.4s, v2.4s + sm4e v8.4s, v3.4s + sm4e v8.4s, v4.4s + sm4e v8.4s, v5.4s + sm4e v8.4s, v6.4s + sm4e v8.4s, v7.4s + rev64 v8.4s, v8.4s + ext v8.16b, v8.16b, v8.16b, #8 +CPU_LE( rev32 v8.16b, v8.16b ) + st1 {v8.4s}, [x1] + ret +SYM_FUNC_END(sm4_ce_do_crypt) diff --git a/arch/arm64/crypto/sm4-ce-cipher-glue.c b/arch/arm64/crypto/sm4-ce-cipher-glue.c new file mode 100644 index 0000000000000000000000000000000000000000..76a34ef4abbbf198d1fe62e898c37da4c4d3e365 --- /dev/null +++ b/arch/arm64/crypto/sm4-ce-cipher-glue.c @@ -0,0 +1,82 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include +#include +#include +#include +#include +#include +#include +#include + +MODULE_ALIAS_CRYPTO("sm4"); +MODULE_ALIAS_CRYPTO("sm4-ce"); +MODULE_DESCRIPTION("SM4 symmetric cipher using ARMv8 Crypto Extensions"); +MODULE_AUTHOR("Ard Biesheuvel "); +MODULE_LICENSE("GPL v2"); + +asmlinkage void sm4_ce_do_crypt(const u32 *rk, void *out, const void *in); + +static int sm4_ce_setkey(struct crypto_tfm *tfm, const u8 *key, + unsigned int key_len) +{ + struct sm4_ctx *ctx = crypto_tfm_ctx(tfm); + + return sm4_expandkey(ctx, key, key_len); +} + +static void sm4_ce_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) +{ + const struct sm4_ctx *ctx = crypto_tfm_ctx(tfm); + + if (!crypto_simd_usable()) { + sm4_crypt_block(ctx->rkey_enc, out, in); + } else { + kernel_neon_begin(); + sm4_ce_do_crypt(ctx->rkey_enc, out, in); + kernel_neon_end(); + } +} + +static void sm4_ce_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) +{ + const struct sm4_ctx *ctx = crypto_tfm_ctx(tfm); + + if (!crypto_simd_usable()) { + sm4_crypt_block(ctx->rkey_dec, out, in); + } else { + kernel_neon_begin(); + sm4_ce_do_crypt(ctx->rkey_dec, out, in); + kernel_neon_end(); + } +} + +static struct crypto_alg sm4_ce_alg = { + .cra_name = "sm4", + .cra_driver_name = "sm4-ce", + .cra_priority = 300, + .cra_flags = CRYPTO_ALG_TYPE_CIPHER, + .cra_blocksize = SM4_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct sm4_ctx), + .cra_module = THIS_MODULE, + .cra_u.cipher = { + .cia_min_keysize = SM4_KEY_SIZE, + .cia_max_keysize = SM4_KEY_SIZE, + .cia_setkey = sm4_ce_setkey, + .cia_encrypt = sm4_ce_encrypt, + .cia_decrypt = sm4_ce_decrypt + } +}; + +static int __init sm4_ce_mod_init(void) +{ + return crypto_register_alg(&sm4_ce_alg); +} + +static void __exit sm4_ce_mod_fini(void) +{ + crypto_unregister_alg(&sm4_ce_alg); +} + +module_cpu_feature_match(SM4, sm4_ce_mod_init); +module_exit(sm4_ce_mod_fini); diff --git a/arch/arm64/crypto/sm4-ce-core.S b/arch/arm64/crypto/sm4-ce-core.S index 4ac6cfbc57970e2449067144aaa4e27c6d4373d4..934e0f093279968362d7ddc2e4c1e7774c34077e 100644 --- a/arch/arm64/crypto/sm4-ce-core.S +++ b/arch/arm64/crypto/sm4-ce-core.S @@ -1,36 +1,660 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * SM4 Cipher Algorithm for ARMv8 with Crypto Extensions + * as specified in + * https://tools.ietf.org/id/draft-ribose-cfrg-sm4-10.html + * + * Copyright (C) 2022, Alibaba Group. + * Copyright (C) 2022 Tianjia Zhang + */ #include #include - .irp b, 0, 1, 2, 3, 4, 5, 6, 7, 8 - .set .Lv\b\().4s, \b - .endr - - .macro sm4e, rd, rn - .inst 0xcec08400 | .L\rd | (.L\rn << 5) - .endm - - /* - * void sm4_ce_do_crypt(const u32 *rk, u32 *out, const u32 *in); - */ - .text -SYM_FUNC_START(sm4_ce_do_crypt) - ld1 {v8.4s}, [x2] - ld1 {v0.4s-v3.4s}, [x0], #64 -CPU_LE( rev32 v8.16b, v8.16b ) - ld1 {v4.4s-v7.4s}, [x0] - sm4e v8.4s, v0.4s - sm4e v8.4s, v1.4s - sm4e v8.4s, v2.4s - sm4e v8.4s, v3.4s - sm4e v8.4s, v4.4s - sm4e v8.4s, v5.4s - sm4e v8.4s, v6.4s - sm4e v8.4s, v7.4s - rev64 v8.4s, v8.4s - ext v8.16b, v8.16b, v8.16b, #8 -CPU_LE( rev32 v8.16b, v8.16b ) - st1 {v8.4s}, [x1] - ret -SYM_FUNC_END(sm4_ce_do_crypt) +.arch armv8-a+crypto + +.irp b, 0, 1, 2, 3, 4, 5, 6, 7, 16, 20, 24, 25, 26, 27, 28, 29, 30, 31 + .set .Lv\b\().4s, \b +.endr + +.macro sm4e, vd, vn + .inst 0xcec08400 | (.L\vn << 5) | .L\vd +.endm + +.macro sm4ekey, vd, vn, vm + .inst 0xce60c800 | (.L\vm << 16) | (.L\vn << 5) | .L\vd +.endm + +/* Register macros */ + +#define RTMP0 v16 +#define RTMP1 v17 +#define RTMP2 v18 +#define RTMP3 v19 + +#define RIV v20 + +/* Helper macros. */ + +#define PREPARE \ + ld1 {v24.16b-v27.16b}, [x0], #64; \ + ld1 {v28.16b-v31.16b}, [x0]; + +#define SM4_CRYPT_BLK(b0) \ + rev32 b0.16b, b0.16b; \ + sm4e b0.4s, v24.4s; \ + sm4e b0.4s, v25.4s; \ + sm4e b0.4s, v26.4s; \ + sm4e b0.4s, v27.4s; \ + sm4e b0.4s, v28.4s; \ + sm4e b0.4s, v29.4s; \ + sm4e b0.4s, v30.4s; \ + sm4e b0.4s, v31.4s; \ + rev64 b0.4s, b0.4s; \ + ext b0.16b, b0.16b, b0.16b, #8; \ + rev32 b0.16b, b0.16b; + +#define SM4_CRYPT_BLK4(b0, b1, b2, b3) \ + rev32 b0.16b, b0.16b; \ + rev32 b1.16b, b1.16b; \ + rev32 b2.16b, b2.16b; \ + rev32 b3.16b, b3.16b; \ + sm4e b0.4s, v24.4s; \ + sm4e b1.4s, v24.4s; \ + sm4e b2.4s, v24.4s; \ + sm4e b3.4s, v24.4s; \ + sm4e b0.4s, v25.4s; \ + sm4e b1.4s, v25.4s; \ + sm4e b2.4s, v25.4s; \ + sm4e b3.4s, v25.4s; \ + sm4e b0.4s, v26.4s; \ + sm4e b1.4s, v26.4s; \ + sm4e b2.4s, v26.4s; \ + sm4e b3.4s, v26.4s; \ + sm4e b0.4s, v27.4s; \ + sm4e b1.4s, v27.4s; \ + sm4e b2.4s, v27.4s; \ + sm4e b3.4s, v27.4s; \ + sm4e b0.4s, v28.4s; \ + sm4e b1.4s, v28.4s; \ + sm4e b2.4s, v28.4s; \ + sm4e b3.4s, v28.4s; \ + sm4e b0.4s, v29.4s; \ + sm4e b1.4s, v29.4s; \ + sm4e b2.4s, v29.4s; \ + sm4e b3.4s, v29.4s; \ + sm4e b0.4s, v30.4s; \ + sm4e b1.4s, v30.4s; \ + sm4e b2.4s, v30.4s; \ + sm4e b3.4s, v30.4s; \ + sm4e b0.4s, v31.4s; \ + sm4e b1.4s, v31.4s; \ + sm4e b2.4s, v31.4s; \ + sm4e b3.4s, v31.4s; \ + rev64 b0.4s, b0.4s; \ + rev64 b1.4s, b1.4s; \ + rev64 b2.4s, b2.4s; \ + rev64 b3.4s, b3.4s; \ + ext b0.16b, b0.16b, b0.16b, #8; \ + ext b1.16b, b1.16b, b1.16b, #8; \ + ext b2.16b, b2.16b, b2.16b, #8; \ + ext b3.16b, b3.16b, b3.16b, #8; \ + rev32 b0.16b, b0.16b; \ + rev32 b1.16b, b1.16b; \ + rev32 b2.16b, b2.16b; \ + rev32 b3.16b, b3.16b; + +#define SM4_CRYPT_BLK8(b0, b1, b2, b3, b4, b5, b6, b7) \ + rev32 b0.16b, b0.16b; \ + rev32 b1.16b, b1.16b; \ + rev32 b2.16b, b2.16b; \ + rev32 b3.16b, b3.16b; \ + rev32 b4.16b, b4.16b; \ + rev32 b5.16b, b5.16b; \ + rev32 b6.16b, b6.16b; \ + rev32 b7.16b, b7.16b; \ + sm4e b0.4s, v24.4s; \ + sm4e b1.4s, v24.4s; \ + sm4e b2.4s, v24.4s; \ + sm4e b3.4s, v24.4s; \ + sm4e b4.4s, v24.4s; \ + sm4e b5.4s, v24.4s; \ + sm4e b6.4s, v24.4s; \ + sm4e b7.4s, v24.4s; \ + sm4e b0.4s, v25.4s; \ + sm4e b1.4s, v25.4s; \ + sm4e b2.4s, v25.4s; \ + sm4e b3.4s, v25.4s; \ + sm4e b4.4s, v25.4s; \ + sm4e b5.4s, v25.4s; \ + sm4e b6.4s, v25.4s; \ + sm4e b7.4s, v25.4s; \ + sm4e b0.4s, v26.4s; \ + sm4e b1.4s, v26.4s; \ + sm4e b2.4s, v26.4s; \ + sm4e b3.4s, v26.4s; \ + sm4e b4.4s, v26.4s; \ + sm4e b5.4s, v26.4s; \ + sm4e b6.4s, v26.4s; \ + sm4e b7.4s, v26.4s; \ + sm4e b0.4s, v27.4s; \ + sm4e b1.4s, v27.4s; \ + sm4e b2.4s, v27.4s; \ + sm4e b3.4s, v27.4s; \ + sm4e b4.4s, v27.4s; \ + sm4e b5.4s, v27.4s; \ + sm4e b6.4s, v27.4s; \ + sm4e b7.4s, v27.4s; \ + sm4e b0.4s, v28.4s; \ + sm4e b1.4s, v28.4s; \ + sm4e b2.4s, v28.4s; \ + sm4e b3.4s, v28.4s; \ + sm4e b4.4s, v28.4s; \ + sm4e b5.4s, v28.4s; \ + sm4e b6.4s, v28.4s; \ + sm4e b7.4s, v28.4s; \ + sm4e b0.4s, v29.4s; \ + sm4e b1.4s, v29.4s; \ + sm4e b2.4s, v29.4s; \ + sm4e b3.4s, v29.4s; \ + sm4e b4.4s, v29.4s; \ + sm4e b5.4s, v29.4s; \ + sm4e b6.4s, v29.4s; \ + sm4e b7.4s, v29.4s; \ + sm4e b0.4s, v30.4s; \ + sm4e b1.4s, v30.4s; \ + sm4e b2.4s, v30.4s; \ + sm4e b3.4s, v30.4s; \ + sm4e b4.4s, v30.4s; \ + sm4e b5.4s, v30.4s; \ + sm4e b6.4s, v30.4s; \ + sm4e b7.4s, v30.4s; \ + sm4e b0.4s, v31.4s; \ + sm4e b1.4s, v31.4s; \ + sm4e b2.4s, v31.4s; \ + sm4e b3.4s, v31.4s; \ + sm4e b4.4s, v31.4s; \ + sm4e b5.4s, v31.4s; \ + sm4e b6.4s, v31.4s; \ + sm4e b7.4s, v31.4s; \ + rev64 b0.4s, b0.4s; \ + rev64 b1.4s, b1.4s; \ + rev64 b2.4s, b2.4s; \ + rev64 b3.4s, b3.4s; \ + rev64 b4.4s, b4.4s; \ + rev64 b5.4s, b5.4s; \ + rev64 b6.4s, b6.4s; \ + rev64 b7.4s, b7.4s; \ + ext b0.16b, b0.16b, b0.16b, #8; \ + ext b1.16b, b1.16b, b1.16b, #8; \ + ext b2.16b, b2.16b, b2.16b, #8; \ + ext b3.16b, b3.16b, b3.16b, #8; \ + ext b4.16b, b4.16b, b4.16b, #8; \ + ext b5.16b, b5.16b, b5.16b, #8; \ + ext b6.16b, b6.16b, b6.16b, #8; \ + ext b7.16b, b7.16b, b7.16b, #8; \ + rev32 b0.16b, b0.16b; \ + rev32 b1.16b, b1.16b; \ + rev32 b2.16b, b2.16b; \ + rev32 b3.16b, b3.16b; \ + rev32 b4.16b, b4.16b; \ + rev32 b5.16b, b5.16b; \ + rev32 b6.16b, b6.16b; \ + rev32 b7.16b, b7.16b; + + +.align 3 +SYM_FUNC_START(sm4_ce_expand_key) + /* input: + * x0: 128-bit key + * x1: rkey_enc + * x2: rkey_dec + * x3: fk array + * x4: ck array + */ + ld1 {v0.16b}, [x0]; + rev32 v0.16b, v0.16b; + ld1 {v1.16b}, [x3]; + /* load ck */ + ld1 {v24.16b-v27.16b}, [x4], #64; + ld1 {v28.16b-v31.16b}, [x4]; + + /* input ^ fk */ + eor v0.16b, v0.16b, v1.16b; + + sm4ekey v0.4s, v0.4s, v24.4s; + sm4ekey v1.4s, v0.4s, v25.4s; + sm4ekey v2.4s, v1.4s, v26.4s; + sm4ekey v3.4s, v2.4s, v27.4s; + sm4ekey v4.4s, v3.4s, v28.4s; + sm4ekey v5.4s, v4.4s, v29.4s; + sm4ekey v6.4s, v5.4s, v30.4s; + sm4ekey v7.4s, v6.4s, v31.4s; + + st1 {v0.16b-v3.16b}, [x1], #64; + st1 {v4.16b-v7.16b}, [x1]; + rev64 v7.4s, v7.4s; + rev64 v6.4s, v6.4s; + rev64 v5.4s, v5.4s; + rev64 v4.4s, v4.4s; + rev64 v3.4s, v3.4s; + rev64 v2.4s, v2.4s; + rev64 v1.4s, v1.4s; + rev64 v0.4s, v0.4s; + ext v7.16b, v7.16b, v7.16b, #8; + ext v6.16b, v6.16b, v6.16b, #8; + ext v5.16b, v5.16b, v5.16b, #8; + ext v4.16b, v4.16b, v4.16b, #8; + ext v3.16b, v3.16b, v3.16b, #8; + ext v2.16b, v2.16b, v2.16b, #8; + ext v1.16b, v1.16b, v1.16b, #8; + ext v0.16b, v0.16b, v0.16b, #8; + st1 {v7.16b}, [x2], #16; + st1 {v6.16b}, [x2], #16; + st1 {v5.16b}, [x2], #16; + st1 {v4.16b}, [x2], #16; + st1 {v3.16b}, [x2], #16; + st1 {v2.16b}, [x2], #16; + st1 {v1.16b}, [x2], #16; + st1 {v0.16b}, [x2]; + + ret; +SYM_FUNC_END(sm4_ce_expand_key) + +.align 3 +SYM_FUNC_START(sm4_ce_crypt_block) + /* input: + * x0: round key array, CTX + * x1: dst + * x2: src + */ + PREPARE; + + ld1 {v0.16b}, [x2]; + SM4_CRYPT_BLK(v0); + st1 {v0.16b}, [x1]; + + ret; +SYM_FUNC_END(sm4_ce_crypt_block) + +.align 3 +SYM_FUNC_START(sm4_ce_crypt) + /* input: + * x0: round key array, CTX + * x1: dst + * x2: src + * w3: nblocks + */ + PREPARE; + +.Lcrypt_loop_blk: + sub w3, w3, #8; + tbnz w3, #31, .Lcrypt_tail8; + + ld1 {v0.16b-v3.16b}, [x2], #64; + ld1 {v4.16b-v7.16b}, [x2], #64; + + SM4_CRYPT_BLK8(v0, v1, v2, v3, v4, v5, v6, v7); + + st1 {v0.16b-v3.16b}, [x1], #64; + st1 {v4.16b-v7.16b}, [x1], #64; + + cbz w3, .Lcrypt_end; + b .Lcrypt_loop_blk; + +.Lcrypt_tail8: + add w3, w3, #8; + cmp w3, #4; + blt .Lcrypt_tail4; + + sub w3, w3, #4; + + ld1 {v0.16b-v3.16b}, [x2], #64; + SM4_CRYPT_BLK4(v0, v1, v2, v3); + st1 {v0.16b-v3.16b}, [x1], #64; + + cbz w3, .Lcrypt_end; + +.Lcrypt_tail4: + sub w3, w3, #1; + + ld1 {v0.16b}, [x2], #16; + SM4_CRYPT_BLK(v0); + st1 {v0.16b}, [x1], #16; + + cbnz w3, .Lcrypt_tail4; + +.Lcrypt_end: + ret; +SYM_FUNC_END(sm4_ce_crypt) + +.align 3 +SYM_FUNC_START(sm4_ce_cbc_enc) + /* input: + * x0: round key array, CTX + * x1: dst + * x2: src + * x3: iv (big endian, 128 bit) + * w4: nblocks + */ + PREPARE; + + ld1 {RIV.16b}, [x3]; + +.Lcbc_enc_loop: + sub w4, w4, #1; + + ld1 {RTMP0.16b}, [x2], #16; + eor RIV.16b, RIV.16b, RTMP0.16b; + + SM4_CRYPT_BLK(RIV); + + st1 {RIV.16b}, [x1], #16; + + cbnz w4, .Lcbc_enc_loop; + + /* store new IV */ + st1 {RIV.16b}, [x3]; + + ret; +SYM_FUNC_END(sm4_ce_cbc_enc) + +.align 3 +SYM_FUNC_START(sm4_ce_cbc_dec) + /* input: + * x0: round key array, CTX + * x1: dst + * x2: src + * x3: iv (big endian, 128 bit) + * w4: nblocks + */ + PREPARE; + + ld1 {RIV.16b}, [x3]; + +.Lcbc_loop_blk: + sub w4, w4, #8; + tbnz w4, #31, .Lcbc_tail8; + + ld1 {v0.16b-v3.16b}, [x2], #64; + ld1 {v4.16b-v7.16b}, [x2]; + + SM4_CRYPT_BLK8(v0, v1, v2, v3, v4, v5, v6, v7); + + sub x2, x2, #64; + eor v0.16b, v0.16b, RIV.16b; + ld1 {RTMP0.16b-RTMP3.16b}, [x2], #64; + eor v1.16b, v1.16b, RTMP0.16b; + eor v2.16b, v2.16b, RTMP1.16b; + eor v3.16b, v3.16b, RTMP2.16b; + st1 {v0.16b-v3.16b}, [x1], #64; + + eor v4.16b, v4.16b, RTMP3.16b; + ld1 {RTMP0.16b-RTMP3.16b}, [x2], #64; + eor v5.16b, v5.16b, RTMP0.16b; + eor v6.16b, v6.16b, RTMP1.16b; + eor v7.16b, v7.16b, RTMP2.16b; + + mov RIV.16b, RTMP3.16b; + st1 {v4.16b-v7.16b}, [x1], #64; + + cbz w4, .Lcbc_end; + b .Lcbc_loop_blk; + +.Lcbc_tail8: + add w4, w4, #8; + cmp w4, #4; + blt .Lcbc_tail4; + + sub w4, w4, #4; + + ld1 {v0.16b-v3.16b}, [x2]; + + SM4_CRYPT_BLK4(v0, v1, v2, v3); + + eor v0.16b, v0.16b, RIV.16b; + ld1 {RTMP0.16b-RTMP3.16b}, [x2], #64; + eor v1.16b, v1.16b, RTMP0.16b; + eor v2.16b, v2.16b, RTMP1.16b; + eor v3.16b, v3.16b, RTMP2.16b; + + mov RIV.16b, RTMP3.16b; + st1 {v0.16b-v3.16b}, [x1], #64; + + cbz w4, .Lcbc_end; + +.Lcbc_tail4: + sub w4, w4, #1; + + ld1 {v0.16b}, [x2]; + + SM4_CRYPT_BLK(v0); + + eor v0.16b, v0.16b, RIV.16b; + ld1 {RIV.16b}, [x2], #16; + st1 {v0.16b}, [x1], #16; + + cbnz w4, .Lcbc_tail4; + +.Lcbc_end: + /* store new IV */ + st1 {RIV.16b}, [x3]; + + ret; +SYM_FUNC_END(sm4_ce_cbc_dec) + +.align 3 +SYM_FUNC_START(sm4_ce_cfb_enc) + /* input: + * x0: round key array, CTX + * x1: dst + * x2: src + * x3: iv (big endian, 128 bit) + * w4: nblocks + */ + PREPARE; + + ld1 {RIV.16b}, [x3]; + +.Lcfb_enc_loop: + sub w4, w4, #1; + + SM4_CRYPT_BLK(RIV); + + ld1 {RTMP0.16b}, [x2], #16; + eor RIV.16b, RIV.16b, RTMP0.16b; + st1 {RIV.16b}, [x1], #16; + + cbnz w4, .Lcfb_enc_loop; + + /* store new IV */ + st1 {RIV.16b}, [x3]; + + ret; +SYM_FUNC_END(sm4_ce_cfb_enc) + +.align 3 +SYM_FUNC_START(sm4_ce_cfb_dec) + /* input: + * x0: round key array, CTX + * x1: dst + * x2: src + * x3: iv (big endian, 128 bit) + * w4: nblocks + */ + PREPARE; + + ld1 {v0.16b}, [x3]; + +.Lcfb_loop_blk: + sub w4, w4, #8; + tbnz w4, #31, .Lcfb_tail8; + + ld1 {v1.16b, v2.16b, v3.16b}, [x2], #48; + ld1 {v4.16b-v7.16b}, [x2]; + + SM4_CRYPT_BLK8(v0, v1, v2, v3, v4, v5, v6, v7); + + sub x2, x2, #48; + ld1 {RTMP0.16b-RTMP3.16b}, [x2], #64; + eor v0.16b, v0.16b, RTMP0.16b; + eor v1.16b, v1.16b, RTMP1.16b; + eor v2.16b, v2.16b, RTMP2.16b; + eor v3.16b, v3.16b, RTMP3.16b; + st1 {v0.16b-v3.16b}, [x1], #64; + + ld1 {RTMP0.16b-RTMP3.16b}, [x2], #64; + eor v4.16b, v4.16b, RTMP0.16b; + eor v5.16b, v5.16b, RTMP1.16b; + eor v6.16b, v6.16b, RTMP2.16b; + eor v7.16b, v7.16b, RTMP3.16b; + st1 {v4.16b-v7.16b}, [x1], #64; + + mov v0.16b, RTMP3.16b; + + cbz w4, .Lcfb_end; + b .Lcfb_loop_blk; + +.Lcfb_tail8: + add w4, w4, #8; + cmp w4, #4; + blt .Lcfb_tail4; + + sub w4, w4, #4; + + ld1 {v1.16b, v2.16b, v3.16b}, [x2]; + + SM4_CRYPT_BLK4(v0, v1, v2, v3); + + ld1 {RTMP0.16b-RTMP3.16b}, [x2], #64; + eor v0.16b, v0.16b, RTMP0.16b; + eor v1.16b, v1.16b, RTMP1.16b; + eor v2.16b, v2.16b, RTMP2.16b; + eor v3.16b, v3.16b, RTMP3.16b; + st1 {v0.16b-v3.16b}, [x1], #64; + + mov v0.16b, RTMP3.16b; + + cbz w4, .Lcfb_end; + +.Lcfb_tail4: + sub w4, w4, #1; + + SM4_CRYPT_BLK(v0); + + ld1 {RTMP0.16b}, [x2], #16; + eor v0.16b, v0.16b, RTMP0.16b; + st1 {v0.16b}, [x1], #16; + + mov v0.16b, RTMP0.16b; + + cbnz w4, .Lcfb_tail4; + +.Lcfb_end: + /* store new IV */ + st1 {v0.16b}, [x3]; + + ret; +SYM_FUNC_END(sm4_ce_cfb_dec) + +.align 3 +SYM_FUNC_START(sm4_ce_ctr_enc) + /* input: + * x0: round key array, CTX + * x1: dst + * x2: src + * x3: ctr (big endian, 128 bit) + * w4: nblocks + */ + PREPARE; + + ldp x7, x8, [x3]; + rev x7, x7; + rev x8, x8; + +.Lctr_loop_blk: + sub w4, w4, #8; + tbnz w4, #31, .Lctr_tail8; + +#define inc_le128(vctr) \ + mov vctr.d[1], x8; \ + mov vctr.d[0], x7; \ + adds x8, x8, #1; \ + adc x7, x7, xzr; \ + rev64 vctr.16b, vctr.16b; + + /* construct CTRs */ + inc_le128(v0); /* +0 */ + inc_le128(v1); /* +1 */ + inc_le128(v2); /* +2 */ + inc_le128(v3); /* +3 */ + inc_le128(v4); /* +4 */ + inc_le128(v5); /* +5 */ + inc_le128(v6); /* +6 */ + inc_le128(v7); /* +7 */ + + SM4_CRYPT_BLK8(v0, v1, v2, v3, v4, v5, v6, v7); + + ld1 {RTMP0.16b-RTMP3.16b}, [x2], #64; + eor v0.16b, v0.16b, RTMP0.16b; + eor v1.16b, v1.16b, RTMP1.16b; + eor v2.16b, v2.16b, RTMP2.16b; + eor v3.16b, v3.16b, RTMP3.16b; + st1 {v0.16b-v3.16b}, [x1], #64; + + ld1 {RTMP0.16b-RTMP3.16b}, [x2], #64; + eor v4.16b, v4.16b, RTMP0.16b; + eor v5.16b, v5.16b, RTMP1.16b; + eor v6.16b, v6.16b, RTMP2.16b; + eor v7.16b, v7.16b, RTMP3.16b; + st1 {v4.16b-v7.16b}, [x1], #64; + + cbz w4, .Lctr_end; + b .Lctr_loop_blk; + +.Lctr_tail8: + add w4, w4, #8; + cmp w4, #4; + blt .Lctr_tail4; + + sub w4, w4, #4; + + /* construct CTRs */ + inc_le128(v0); /* +0 */ + inc_le128(v1); /* +1 */ + inc_le128(v2); /* +2 */ + inc_le128(v3); /* +3 */ + + SM4_CRYPT_BLK4(v0, v1, v2, v3); + + ld1 {RTMP0.16b-RTMP3.16b}, [x2], #64; + eor v0.16b, v0.16b, RTMP0.16b; + eor v1.16b, v1.16b, RTMP1.16b; + eor v2.16b, v2.16b, RTMP2.16b; + eor v3.16b, v3.16b, RTMP3.16b; + st1 {v0.16b-v3.16b}, [x1], #64; + + cbz w4, .Lctr_end; + +.Lctr_tail4: + sub w4, w4, #1; + + /* construct CTRs */ + inc_le128(v0); + + SM4_CRYPT_BLK(v0); + + ld1 {RTMP0.16b}, [x2], #16; + eor v0.16b, v0.16b, RTMP0.16b; + st1 {v0.16b}, [x1], #16; + + cbnz w4, .Lctr_tail4; + +.Lctr_end: + /* store new CTR */ + rev x7, x7; + rev x8, x8; + stp x7, x8, [x3]; + + ret; +SYM_FUNC_END(sm4_ce_ctr_enc) diff --git a/arch/arm64/crypto/sm4-ce-glue.c b/arch/arm64/crypto/sm4-ce-glue.c index 9c93cfc4841bc3527eef0371fa0f579cb49a1842..496d55c0d01a4617ca3c014382ad3e9ea246f866 100644 --- a/arch/arm64/crypto/sm4-ce-glue.c +++ b/arch/arm64/crypto/sm4-ce-glue.c @@ -1,82 +1,372 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * SM4 Cipher Algorithm, using ARMv8 Crypto Extensions + * as specified in + * https://tools.ietf.org/id/draft-ribose-cfrg-sm4-10.html + * + * Copyright (C) 2022, Alibaba Group. + * Copyright (C) 2022 Tianjia Zhang + */ +#include +#include +#include +#include #include #include -#include #include -#include -#include -#include -#include +#include +#include -MODULE_ALIAS_CRYPTO("sm4"); -MODULE_ALIAS_CRYPTO("sm4-ce"); -MODULE_DESCRIPTION("SM4 symmetric cipher using ARMv8 Crypto Extensions"); -MODULE_AUTHOR("Ard Biesheuvel "); -MODULE_LICENSE("GPL v2"); +#define BYTES2BLKS(nbytes) ((nbytes) >> 4) + +asmlinkage void sm4_ce_expand_key(const u8 *key, u32 *rkey_enc, u32 *rkey_dec, + const u32 *fk, const u32 *ck); +asmlinkage void sm4_ce_crypt_block(const u32 *rkey, u8 *dst, const u8 *src); +asmlinkage void sm4_ce_crypt(const u32 *rkey, u8 *dst, const u8 *src, + unsigned int nblks); +asmlinkage void sm4_ce_cbc_enc(const u32 *rkey, u8 *dst, const u8 *src, + u8 *iv, unsigned int nblks); +asmlinkage void sm4_ce_cbc_dec(const u32 *rkey, u8 *dst, const u8 *src, + u8 *iv, unsigned int nblks); +asmlinkage void sm4_ce_cfb_enc(const u32 *rkey, u8 *dst, const u8 *src, + u8 *iv, unsigned int nblks); +asmlinkage void sm4_ce_cfb_dec(const u32 *rkey, u8 *dst, const u8 *src, + u8 *iv, unsigned int nblks); +asmlinkage void sm4_ce_ctr_enc(const u32 *rkey, u8 *dst, const u8 *src, + u8 *iv, unsigned int nblks); + +static int sm4_setkey(struct crypto_skcipher *tfm, const u8 *key, + unsigned int key_len) +{ + struct sm4_ctx *ctx = crypto_skcipher_ctx(tfm); + + if (key_len != SM4_KEY_SIZE) + return -EINVAL; + + sm4_ce_expand_key(key, ctx->rkey_enc, ctx->rkey_dec, + crypto_sm4_fk, crypto_sm4_ck); + return 0; +} + +static int sm4_ecb_do_crypt(struct skcipher_request *req, const u32 *rkey) +{ + struct skcipher_walk walk; + unsigned int nbytes; + int err; + + err = skcipher_walk_virt(&walk, req, false); + + while ((nbytes = walk.nbytes) > 0) { + const u8 *src = walk.src.virt.addr; + u8 *dst = walk.dst.virt.addr; + unsigned int nblks; + + kernel_neon_begin(); + + nblks = BYTES2BLKS(nbytes); + if (nblks) { + sm4_ce_crypt(rkey, dst, src, nblks); + nbytes -= nblks * SM4_BLOCK_SIZE; + } + + kernel_neon_end(); + + err = skcipher_walk_done(&walk, nbytes); + } + + return err; +} + +static int sm4_ecb_encrypt(struct skcipher_request *req) +{ + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); + struct sm4_ctx *ctx = crypto_skcipher_ctx(tfm); + + return sm4_ecb_do_crypt(req, ctx->rkey_enc); +} + +static int sm4_ecb_decrypt(struct skcipher_request *req) +{ + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); + struct sm4_ctx *ctx = crypto_skcipher_ctx(tfm); + + return sm4_ecb_do_crypt(req, ctx->rkey_dec); +} + +static int sm4_cbc_encrypt(struct skcipher_request *req) +{ + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); + struct sm4_ctx *ctx = crypto_skcipher_ctx(tfm); + struct skcipher_walk walk; + unsigned int nbytes; + int err; + + err = skcipher_walk_virt(&walk, req, false); + + while ((nbytes = walk.nbytes) > 0) { + const u8 *src = walk.src.virt.addr; + u8 *dst = walk.dst.virt.addr; + unsigned int nblks; + + kernel_neon_begin(); + + nblks = BYTES2BLKS(nbytes); + if (nblks) { + sm4_ce_cbc_enc(ctx->rkey_enc, dst, src, walk.iv, nblks); + nbytes -= nblks * SM4_BLOCK_SIZE; + } + + kernel_neon_end(); -asmlinkage void sm4_ce_do_crypt(const u32 *rk, void *out, const void *in); + err = skcipher_walk_done(&walk, nbytes); + } + + return err; +} -static int sm4_ce_setkey(struct crypto_tfm *tfm, const u8 *key, - unsigned int key_len) +static int sm4_cbc_decrypt(struct skcipher_request *req) { - struct sm4_ctx *ctx = crypto_tfm_ctx(tfm); + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); + struct sm4_ctx *ctx = crypto_skcipher_ctx(tfm); + struct skcipher_walk walk; + unsigned int nbytes; + int err; + + err = skcipher_walk_virt(&walk, req, false); + + while ((nbytes = walk.nbytes) > 0) { + const u8 *src = walk.src.virt.addr; + u8 *dst = walk.dst.virt.addr; + unsigned int nblks; + + kernel_neon_begin(); + + nblks = BYTES2BLKS(nbytes); + if (nblks) { + sm4_ce_cbc_dec(ctx->rkey_dec, dst, src, walk.iv, nblks); + nbytes -= nblks * SM4_BLOCK_SIZE; + } + + kernel_neon_end(); + + err = skcipher_walk_done(&walk, nbytes); + } - return sm4_expandkey(ctx, key, key_len); + return err; } -static void sm4_ce_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) +static int sm4_cfb_encrypt(struct skcipher_request *req) { - const struct sm4_ctx *ctx = crypto_tfm_ctx(tfm); + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); + struct sm4_ctx *ctx = crypto_skcipher_ctx(tfm); + struct skcipher_walk walk; + unsigned int nbytes; + int err; + + err = skcipher_walk_virt(&walk, req, false); + + while ((nbytes = walk.nbytes) > 0) { + const u8 *src = walk.src.virt.addr; + u8 *dst = walk.dst.virt.addr; + unsigned int nblks; - if (!crypto_simd_usable()) { - sm4_crypt_block(ctx->rkey_enc, out, in); - } else { kernel_neon_begin(); - sm4_ce_do_crypt(ctx->rkey_enc, out, in); + + nblks = BYTES2BLKS(nbytes); + if (nblks) { + sm4_ce_cfb_enc(ctx->rkey_enc, dst, src, walk.iv, nblks); + dst += nblks * SM4_BLOCK_SIZE; + src += nblks * SM4_BLOCK_SIZE; + nbytes -= nblks * SM4_BLOCK_SIZE; + } + + /* tail */ + if (walk.nbytes == walk.total && nbytes > 0) { + u8 keystream[SM4_BLOCK_SIZE]; + + sm4_ce_crypt_block(ctx->rkey_enc, keystream, walk.iv); + crypto_xor_cpy(dst, src, keystream, nbytes); + nbytes = 0; + } + kernel_neon_end(); + + err = skcipher_walk_done(&walk, nbytes); } + + return err; } -static void sm4_ce_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) +static int sm4_cfb_decrypt(struct skcipher_request *req) { - const struct sm4_ctx *ctx = crypto_tfm_ctx(tfm); + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); + struct sm4_ctx *ctx = crypto_skcipher_ctx(tfm); + struct skcipher_walk walk; + unsigned int nbytes; + int err; + + err = skcipher_walk_virt(&walk, req, false); + + while ((nbytes = walk.nbytes) > 0) { + const u8 *src = walk.src.virt.addr; + u8 *dst = walk.dst.virt.addr; + unsigned int nblks; - if (!crypto_simd_usable()) { - sm4_crypt_block(ctx->rkey_dec, out, in); - } else { kernel_neon_begin(); - sm4_ce_do_crypt(ctx->rkey_dec, out, in); + + nblks = BYTES2BLKS(nbytes); + if (nblks) { + sm4_ce_cfb_dec(ctx->rkey_enc, dst, src, walk.iv, nblks); + dst += nblks * SM4_BLOCK_SIZE; + src += nblks * SM4_BLOCK_SIZE; + nbytes -= nblks * SM4_BLOCK_SIZE; + } + + /* tail */ + if (walk.nbytes == walk.total && nbytes > 0) { + u8 keystream[SM4_BLOCK_SIZE]; + + sm4_ce_crypt_block(ctx->rkey_enc, keystream, walk.iv); + crypto_xor_cpy(dst, src, keystream, nbytes); + nbytes = 0; + } + kernel_neon_end(); + + err = skcipher_walk_done(&walk, nbytes); } + + return err; } -static struct crypto_alg sm4_ce_alg = { - .cra_name = "sm4", - .cra_driver_name = "sm4-ce", - .cra_priority = 200, - .cra_flags = CRYPTO_ALG_TYPE_CIPHER, - .cra_blocksize = SM4_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct sm4_ctx), - .cra_module = THIS_MODULE, - .cra_u.cipher = { - .cia_min_keysize = SM4_KEY_SIZE, - .cia_max_keysize = SM4_KEY_SIZE, - .cia_setkey = sm4_ce_setkey, - .cia_encrypt = sm4_ce_encrypt, - .cia_decrypt = sm4_ce_decrypt +static int sm4_ctr_crypt(struct skcipher_request *req) +{ + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); + struct sm4_ctx *ctx = crypto_skcipher_ctx(tfm); + struct skcipher_walk walk; + unsigned int nbytes; + int err; + + err = skcipher_walk_virt(&walk, req, false); + + while ((nbytes = walk.nbytes) > 0) { + const u8 *src = walk.src.virt.addr; + u8 *dst = walk.dst.virt.addr; + unsigned int nblks; + + kernel_neon_begin(); + + nblks = BYTES2BLKS(nbytes); + if (nblks) { + sm4_ce_ctr_enc(ctx->rkey_enc, dst, src, walk.iv, nblks); + dst += nblks * SM4_BLOCK_SIZE; + src += nblks * SM4_BLOCK_SIZE; + nbytes -= nblks * SM4_BLOCK_SIZE; + } + + /* tail */ + if (walk.nbytes == walk.total && nbytes > 0) { + u8 keystream[SM4_BLOCK_SIZE]; + + sm4_ce_crypt_block(ctx->rkey_enc, keystream, walk.iv); + crypto_inc(walk.iv, SM4_BLOCK_SIZE); + crypto_xor_cpy(dst, src, keystream, nbytes); + nbytes = 0; + } + + kernel_neon_end(); + + err = skcipher_walk_done(&walk, nbytes); + } + + return err; +} + +static struct skcipher_alg sm4_algs[] = { + { + .base = { + .cra_name = "ecb(sm4)", + .cra_driver_name = "ecb-sm4-ce", + .cra_priority = 400, + .cra_blocksize = SM4_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct sm4_ctx), + .cra_module = THIS_MODULE, + }, + .min_keysize = SM4_KEY_SIZE, + .max_keysize = SM4_KEY_SIZE, + .setkey = sm4_setkey, + .encrypt = sm4_ecb_encrypt, + .decrypt = sm4_ecb_decrypt, + }, { + .base = { + .cra_name = "cbc(sm4)", + .cra_driver_name = "cbc-sm4-ce", + .cra_priority = 400, + .cra_blocksize = SM4_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct sm4_ctx), + .cra_module = THIS_MODULE, + }, + .min_keysize = SM4_KEY_SIZE, + .max_keysize = SM4_KEY_SIZE, + .ivsize = SM4_BLOCK_SIZE, + .setkey = sm4_setkey, + .encrypt = sm4_cbc_encrypt, + .decrypt = sm4_cbc_decrypt, + }, { + .base = { + .cra_name = "cfb(sm4)", + .cra_driver_name = "cfb-sm4-ce", + .cra_priority = 400, + .cra_blocksize = 1, + .cra_ctxsize = sizeof(struct sm4_ctx), + .cra_module = THIS_MODULE, + }, + .min_keysize = SM4_KEY_SIZE, + .max_keysize = SM4_KEY_SIZE, + .ivsize = SM4_BLOCK_SIZE, + .chunksize = SM4_BLOCK_SIZE, + .setkey = sm4_setkey, + .encrypt = sm4_cfb_encrypt, + .decrypt = sm4_cfb_decrypt, + }, { + .base = { + .cra_name = "ctr(sm4)", + .cra_driver_name = "ctr-sm4-ce", + .cra_priority = 400, + .cra_blocksize = 1, + .cra_ctxsize = sizeof(struct sm4_ctx), + .cra_module = THIS_MODULE, + }, + .min_keysize = SM4_KEY_SIZE, + .max_keysize = SM4_KEY_SIZE, + .ivsize = SM4_BLOCK_SIZE, + .chunksize = SM4_BLOCK_SIZE, + .setkey = sm4_setkey, + .encrypt = sm4_ctr_crypt, + .decrypt = sm4_ctr_crypt, } }; -static int __init sm4_ce_mod_init(void) +static int __init sm4_init(void) { - return crypto_register_alg(&sm4_ce_alg); + return crypto_register_skciphers(sm4_algs, ARRAY_SIZE(sm4_algs)); } -static void __exit sm4_ce_mod_fini(void) +static void __exit sm4_exit(void) { - crypto_unregister_alg(&sm4_ce_alg); + crypto_unregister_skciphers(sm4_algs, ARRAY_SIZE(sm4_algs)); } -module_cpu_feature_match(SM4, sm4_ce_mod_init); -module_exit(sm4_ce_mod_fini); +module_cpu_feature_match(SM4, sm4_init); +module_exit(sm4_exit); + +MODULE_DESCRIPTION("SM4 ECB/CBC/CFB/CTR using ARMv8 Crypto Extensions"); +MODULE_ALIAS_CRYPTO("sm4-ce"); +MODULE_ALIAS_CRYPTO("sm4"); +MODULE_ALIAS_CRYPTO("ecb(sm4)"); +MODULE_ALIAS_CRYPTO("cbc(sm4)"); +MODULE_ALIAS_CRYPTO("cfb(sm4)"); +MODULE_ALIAS_CRYPTO("ctr(sm4)"); +MODULE_AUTHOR("Tianjia Zhang "); +MODULE_LICENSE("GPL v2"); diff --git a/arch/arm64/crypto/sm4-neon-core.S b/arch/arm64/crypto/sm4-neon-core.S new file mode 100644 index 0000000000000000000000000000000000000000..3d5256b354d27fb2f5464fc810f595ab17b1a115 --- /dev/null +++ b/arch/arm64/crypto/sm4-neon-core.S @@ -0,0 +1,487 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * SM4 Cipher Algorithm for ARMv8 NEON + * as specified in + * https://tools.ietf.org/id/draft-ribose-cfrg-sm4-10.html + * + * Copyright (C) 2022, Alibaba Group. + * Copyright (C) 2022 Tianjia Zhang + */ + +#include +#include + +/* Register macros */ + +#define RTMP0 v8 +#define RTMP1 v9 +#define RTMP2 v10 +#define RTMP3 v11 + +#define RX0 v12 +#define RX1 v13 +#define RKEY v14 +#define RIV v15 + +/* Helper macros. */ + +#define PREPARE \ + adr_l x5, crypto_sm4_sbox; \ + ld1 {v16.16b-v19.16b}, [x5], #64; \ + ld1 {v20.16b-v23.16b}, [x5], #64; \ + ld1 {v24.16b-v27.16b}, [x5], #64; \ + ld1 {v28.16b-v31.16b}, [x5]; + +#define transpose_4x4(s0, s1, s2, s3) \ + zip1 RTMP0.4s, s0.4s, s1.4s; \ + zip1 RTMP1.4s, s2.4s, s3.4s; \ + zip2 RTMP2.4s, s0.4s, s1.4s; \ + zip2 RTMP3.4s, s2.4s, s3.4s; \ + zip1 s0.2d, RTMP0.2d, RTMP1.2d; \ + zip2 s1.2d, RTMP0.2d, RTMP1.2d; \ + zip1 s2.2d, RTMP2.2d, RTMP3.2d; \ + zip2 s3.2d, RTMP2.2d, RTMP3.2d; + +#define rotate_clockwise_90(s0, s1, s2, s3) \ + zip1 RTMP0.4s, s1.4s, s0.4s; \ + zip2 RTMP1.4s, s1.4s, s0.4s; \ + zip1 RTMP2.4s, s3.4s, s2.4s; \ + zip2 RTMP3.4s, s3.4s, s2.4s; \ + zip1 s0.2d, RTMP2.2d, RTMP0.2d; \ + zip2 s1.2d, RTMP2.2d, RTMP0.2d; \ + zip1 s2.2d, RTMP3.2d, RTMP1.2d; \ + zip2 s3.2d, RTMP3.2d, RTMP1.2d; + +#define ROUND4(round, s0, s1, s2, s3) \ + dup RX0.4s, RKEY.s[round]; \ + /* rk ^ s1 ^ s2 ^ s3 */ \ + eor RTMP1.16b, s2.16b, s3.16b; \ + eor RX0.16b, RX0.16b, s1.16b; \ + eor RX0.16b, RX0.16b, RTMP1.16b; \ + \ + /* sbox, non-linear part */ \ + movi RTMP3.16b, #64; /* sizeof(sbox) / 4 */ \ + tbl RTMP0.16b, {v16.16b-v19.16b}, RX0.16b; \ + sub RX0.16b, RX0.16b, RTMP3.16b; \ + tbx RTMP0.16b, {v20.16b-v23.16b}, RX0.16b; \ + sub RX0.16b, RX0.16b, RTMP3.16b; \ + tbx RTMP0.16b, {v24.16b-v27.16b}, RX0.16b; \ + sub RX0.16b, RX0.16b, RTMP3.16b; \ + tbx RTMP0.16b, {v28.16b-v31.16b}, RX0.16b; \ + \ + /* linear part */ \ + shl RTMP1.4s, RTMP0.4s, #8; \ + shl RTMP2.4s, RTMP0.4s, #16; \ + shl RTMP3.4s, RTMP0.4s, #24; \ + sri RTMP1.4s, RTMP0.4s, #(32-8); \ + sri RTMP2.4s, RTMP0.4s, #(32-16); \ + sri RTMP3.4s, RTMP0.4s, #(32-24); \ + /* RTMP1 = x ^ rol32(x, 8) ^ rol32(x, 16) */ \ + eor RTMP1.16b, RTMP1.16b, RTMP0.16b; \ + eor RTMP1.16b, RTMP1.16b, RTMP2.16b; \ + /* RTMP3 = x ^ rol32(x, 24) ^ rol32(RTMP1, 2) */ \ + eor RTMP3.16b, RTMP3.16b, RTMP0.16b; \ + shl RTMP2.4s, RTMP1.4s, 2; \ + sri RTMP2.4s, RTMP1.4s, #(32-2); \ + eor RTMP3.16b, RTMP3.16b, RTMP2.16b; \ + /* s0 ^= RTMP3 */ \ + eor s0.16b, s0.16b, RTMP3.16b; + +#define SM4_CRYPT_BLK4(b0, b1, b2, b3) \ + rev32 b0.16b, b0.16b; \ + rev32 b1.16b, b1.16b; \ + rev32 b2.16b, b2.16b; \ + rev32 b3.16b, b3.16b; \ + \ + transpose_4x4(b0, b1, b2, b3); \ + \ + mov x6, 8; \ +4: \ + ld1 {RKEY.4s}, [x0], #16; \ + subs x6, x6, #1; \ + \ + ROUND4(0, b0, b1, b2, b3); \ + ROUND4(1, b1, b2, b3, b0); \ + ROUND4(2, b2, b3, b0, b1); \ + ROUND4(3, b3, b0, b1, b2); \ + \ + bne 4b; \ + \ + rotate_clockwise_90(b0, b1, b2, b3); \ + rev32 b0.16b, b0.16b; \ + rev32 b1.16b, b1.16b; \ + rev32 b2.16b, b2.16b; \ + rev32 b3.16b, b3.16b; \ + \ + /* repoint to rkey */ \ + sub x0, x0, #128; + +#define ROUND8(round, s0, s1, s2, s3, t0, t1, t2, t3) \ + /* rk ^ s1 ^ s2 ^ s3 */ \ + dup RX0.4s, RKEY.s[round]; \ + eor RTMP0.16b, s2.16b, s3.16b; \ + mov RX1.16b, RX0.16b; \ + eor RTMP1.16b, t2.16b, t3.16b; \ + eor RX0.16b, RX0.16b, s1.16b; \ + eor RX1.16b, RX1.16b, t1.16b; \ + eor RX0.16b, RX0.16b, RTMP0.16b; \ + eor RX1.16b, RX1.16b, RTMP1.16b; \ + \ + /* sbox, non-linear part */ \ + movi RTMP3.16b, #64; /* sizeof(sbox) / 4 */ \ + tbl RTMP0.16b, {v16.16b-v19.16b}, RX0.16b; \ + tbl RTMP1.16b, {v16.16b-v19.16b}, RX1.16b; \ + sub RX0.16b, RX0.16b, RTMP3.16b; \ + sub RX1.16b, RX1.16b, RTMP3.16b; \ + tbx RTMP0.16b, {v20.16b-v23.16b}, RX0.16b; \ + tbx RTMP1.16b, {v20.16b-v23.16b}, RX1.16b; \ + sub RX0.16b, RX0.16b, RTMP3.16b; \ + sub RX1.16b, RX1.16b, RTMP3.16b; \ + tbx RTMP0.16b, {v24.16b-v27.16b}, RX0.16b; \ + tbx RTMP1.16b, {v24.16b-v27.16b}, RX1.16b; \ + sub RX0.16b, RX0.16b, RTMP3.16b; \ + sub RX1.16b, RX1.16b, RTMP3.16b; \ + tbx RTMP0.16b, {v28.16b-v31.16b}, RX0.16b; \ + tbx RTMP1.16b, {v28.16b-v31.16b}, RX1.16b; \ + \ + /* linear part */ \ + shl RX0.4s, RTMP0.4s, #8; \ + shl RX1.4s, RTMP1.4s, #8; \ + shl RTMP2.4s, RTMP0.4s, #16; \ + shl RTMP3.4s, RTMP1.4s, #16; \ + sri RX0.4s, RTMP0.4s, #(32 - 8); \ + sri RX1.4s, RTMP1.4s, #(32 - 8); \ + sri RTMP2.4s, RTMP0.4s, #(32 - 16); \ + sri RTMP3.4s, RTMP1.4s, #(32 - 16); \ + /* RX = x ^ rol32(x, 8) ^ rol32(x, 16) */ \ + eor RX0.16b, RX0.16b, RTMP0.16b; \ + eor RX1.16b, RX1.16b, RTMP1.16b; \ + eor RX0.16b, RX0.16b, RTMP2.16b; \ + eor RX1.16b, RX1.16b, RTMP3.16b; \ + /* RTMP0/1 ^= x ^ rol32(x, 24) ^ rol32(RX, 2) */ \ + shl RTMP2.4s, RTMP0.4s, #24; \ + shl RTMP3.4s, RTMP1.4s, #24; \ + sri RTMP2.4s, RTMP0.4s, #(32 - 24); \ + sri RTMP3.4s, RTMP1.4s, #(32 - 24); \ + eor RTMP0.16b, RTMP0.16b, RTMP2.16b; \ + eor RTMP1.16b, RTMP1.16b, RTMP3.16b; \ + shl RTMP2.4s, RX0.4s, #2; \ + shl RTMP3.4s, RX1.4s, #2; \ + sri RTMP2.4s, RX0.4s, #(32 - 2); \ + sri RTMP3.4s, RX1.4s, #(32 - 2); \ + eor RTMP0.16b, RTMP0.16b, RTMP2.16b; \ + eor RTMP1.16b, RTMP1.16b, RTMP3.16b; \ + /* s0/t0 ^= RTMP0/1 */ \ + eor s0.16b, s0.16b, RTMP0.16b; \ + eor t0.16b, t0.16b, RTMP1.16b; + +#define SM4_CRYPT_BLK8(b0, b1, b2, b3, b4, b5, b6, b7) \ + rev32 b0.16b, b0.16b; \ + rev32 b1.16b, b1.16b; \ + rev32 b2.16b, b2.16b; \ + rev32 b3.16b, b3.16b; \ + rev32 b4.16b, b4.16b; \ + rev32 b5.16b, b5.16b; \ + rev32 b6.16b, b6.16b; \ + rev32 b7.16b, b7.16b; \ + \ + transpose_4x4(b0, b1, b2, b3); \ + transpose_4x4(b4, b5, b6, b7); \ + \ + mov x6, 8; \ +8: \ + ld1 {RKEY.4s}, [x0], #16; \ + subs x6, x6, #1; \ + \ + ROUND8(0, b0, b1, b2, b3, b4, b5, b6, b7); \ + ROUND8(1, b1, b2, b3, b0, b5, b6, b7, b4); \ + ROUND8(2, b2, b3, b0, b1, b6, b7, b4, b5); \ + ROUND8(3, b3, b0, b1, b2, b7, b4, b5, b6); \ + \ + bne 8b; \ + \ + rotate_clockwise_90(b0, b1, b2, b3); \ + rotate_clockwise_90(b4, b5, b6, b7); \ + rev32 b0.16b, b0.16b; \ + rev32 b1.16b, b1.16b; \ + rev32 b2.16b, b2.16b; \ + rev32 b3.16b, b3.16b; \ + rev32 b4.16b, b4.16b; \ + rev32 b5.16b, b5.16b; \ + rev32 b6.16b, b6.16b; \ + rev32 b7.16b, b7.16b; \ + \ + /* repoint to rkey */ \ + sub x0, x0, #128; + + +.align 3 +SYM_FUNC_START_LOCAL(__sm4_neon_crypt_blk1_4) + /* input: + * x0: round key array, CTX + * x1: dst + * x2: src + * w3: num blocks (1..4) + */ + PREPARE; + + ld1 {v0.16b}, [x2], #16; + mov v1.16b, v0.16b; + mov v2.16b, v0.16b; + mov v3.16b, v0.16b; + cmp w3, #2; + blt .Lblk4_load_input_done; + ld1 {v1.16b}, [x2], #16; + beq .Lblk4_load_input_done; + ld1 {v2.16b}, [x2], #16; + cmp w3, #3; + beq .Lblk4_load_input_done; + ld1 {v3.16b}, [x2]; + +.Lblk4_load_input_done: + SM4_CRYPT_BLK4(v0, v1, v2, v3); + + st1 {v0.16b}, [x1], #16; + cmp w3, #2; + blt .Lblk4_store_output_done; + st1 {v1.16b}, [x1], #16; + beq .Lblk4_store_output_done; + st1 {v2.16b}, [x1], #16; + cmp w3, #3; + beq .Lblk4_store_output_done; + st1 {v3.16b}, [x1]; + +.Lblk4_store_output_done: + ret; +SYM_FUNC_END(__sm4_neon_crypt_blk1_4) + +.align 3 +SYM_FUNC_START(sm4_neon_crypt_blk1_8) + /* input: + * x0: round key array, CTX + * x1: dst + * x2: src + * w3: num blocks (1..8) + */ + cmp w3, #5; + blt __sm4_neon_crypt_blk1_4; + + PREPARE; + + ld1 {v0.16b-v3.16b}, [x2], #64; + ld1 {v4.16b}, [x2], #16; + mov v5.16b, v4.16b; + mov v6.16b, v4.16b; + mov v7.16b, v4.16b; + beq .Lblk8_load_input_done; + ld1 {v5.16b}, [x2], #16; + cmp w3, #7; + blt .Lblk8_load_input_done; + ld1 {v6.16b}, [x2], #16; + beq .Lblk8_load_input_done; + ld1 {v7.16b}, [x2]; + +.Lblk8_load_input_done: + SM4_CRYPT_BLK8(v0, v1, v2, v3, v4, v5, v6, v7); + + cmp w3, #6; + st1 {v0.16b-v3.16b}, [x1], #64; + st1 {v4.16b}, [x1], #16; + blt .Lblk8_store_output_done; + st1 {v5.16b}, [x1], #16; + beq .Lblk8_store_output_done; + st1 {v6.16b}, [x1], #16; + cmp w3, #7; + beq .Lblk8_store_output_done; + st1 {v7.16b}, [x1]; + +.Lblk8_store_output_done: + ret; +SYM_FUNC_END(sm4_neon_crypt_blk1_8) + +.align 3 +SYM_FUNC_START(sm4_neon_crypt_blk8) + /* input: + * x0: round key array, CTX + * x1: dst + * x2: src + * w3: nblocks (multiples of 8) + */ + PREPARE; + +.Lcrypt_loop_blk: + subs w3, w3, #8; + bmi .Lcrypt_end; + + ld1 {v0.16b-v3.16b}, [x2], #64; + ld1 {v4.16b-v7.16b}, [x2], #64; + + SM4_CRYPT_BLK8(v0, v1, v2, v3, v4, v5, v6, v7); + + st1 {v0.16b-v3.16b}, [x1], #64; + st1 {v4.16b-v7.16b}, [x1], #64; + + b .Lcrypt_loop_blk; + +.Lcrypt_end: + ret; +SYM_FUNC_END(sm4_neon_crypt_blk8) + +.align 3 +SYM_FUNC_START(sm4_neon_cbc_dec_blk8) + /* input: + * x0: round key array, CTX + * x1: dst + * x2: src + * x3: iv (big endian, 128 bit) + * w4: nblocks (multiples of 8) + */ + PREPARE; + + ld1 {RIV.16b}, [x3]; + +.Lcbc_loop_blk: + subs w4, w4, #8; + bmi .Lcbc_end; + + ld1 {v0.16b-v3.16b}, [x2], #64; + ld1 {v4.16b-v7.16b}, [x2]; + + SM4_CRYPT_BLK8(v0, v1, v2, v3, v4, v5, v6, v7); + + sub x2, x2, #64; + eor v0.16b, v0.16b, RIV.16b; + ld1 {RTMP0.16b-RTMP3.16b}, [x2], #64; + eor v1.16b, v1.16b, RTMP0.16b; + eor v2.16b, v2.16b, RTMP1.16b; + eor v3.16b, v3.16b, RTMP2.16b; + st1 {v0.16b-v3.16b}, [x1], #64; + + eor v4.16b, v4.16b, RTMP3.16b; + ld1 {RTMP0.16b-RTMP3.16b}, [x2], #64; + eor v5.16b, v5.16b, RTMP0.16b; + eor v6.16b, v6.16b, RTMP1.16b; + eor v7.16b, v7.16b, RTMP2.16b; + + mov RIV.16b, RTMP3.16b; + st1 {v4.16b-v7.16b}, [x1], #64; + + b .Lcbc_loop_blk; + +.Lcbc_end: + /* store new IV */ + st1 {RIV.16b}, [x3]; + + ret; +SYM_FUNC_END(sm4_neon_cbc_dec_blk8) + +.align 3 +SYM_FUNC_START(sm4_neon_cfb_dec_blk8) + /* input: + * x0: round key array, CTX + * x1: dst + * x2: src + * x3: iv (big endian, 128 bit) + * w4: nblocks (multiples of 8) + */ + PREPARE; + + ld1 {v0.16b}, [x3]; + +.Lcfb_loop_blk: + subs w4, w4, #8; + bmi .Lcfb_end; + + ld1 {v1.16b, v2.16b, v3.16b}, [x2], #48; + ld1 {v4.16b-v7.16b}, [x2]; + + SM4_CRYPT_BLK8(v0, v1, v2, v3, v4, v5, v6, v7); + + sub x2, x2, #48; + ld1 {RTMP0.16b-RTMP3.16b}, [x2], #64; + eor v0.16b, v0.16b, RTMP0.16b; + eor v1.16b, v1.16b, RTMP1.16b; + eor v2.16b, v2.16b, RTMP2.16b; + eor v3.16b, v3.16b, RTMP3.16b; + st1 {v0.16b-v3.16b}, [x1], #64; + + ld1 {RTMP0.16b-RTMP3.16b}, [x2], #64; + eor v4.16b, v4.16b, RTMP0.16b; + eor v5.16b, v5.16b, RTMP1.16b; + eor v6.16b, v6.16b, RTMP2.16b; + eor v7.16b, v7.16b, RTMP3.16b; + st1 {v4.16b-v7.16b}, [x1], #64; + + mov v0.16b, RTMP3.16b; + + b .Lcfb_loop_blk; + +.Lcfb_end: + /* store new IV */ + st1 {v0.16b}, [x3]; + + ret; +SYM_FUNC_END(sm4_neon_cfb_dec_blk8) + +.align 3 +SYM_FUNC_START(sm4_neon_ctr_enc_blk8) + /* input: + * x0: round key array, CTX + * x1: dst + * x2: src + * x3: ctr (big endian, 128 bit) + * w4: nblocks (multiples of 8) + */ + PREPARE; + + ldp x7, x8, [x3]; + rev x7, x7; + rev x8, x8; + +.Lctr_loop_blk: + subs w4, w4, #8; + bmi .Lctr_end; + +#define inc_le128(vctr) \ + mov vctr.d[1], x8; \ + mov vctr.d[0], x7; \ + adds x8, x8, #1; \ + adc x7, x7, xzr; \ + rev64 vctr.16b, vctr.16b; + + /* construct CTRs */ + inc_le128(v0); /* +0 */ + inc_le128(v1); /* +1 */ + inc_le128(v2); /* +2 */ + inc_le128(v3); /* +3 */ + inc_le128(v4); /* +4 */ + inc_le128(v5); /* +5 */ + inc_le128(v6); /* +6 */ + inc_le128(v7); /* +7 */ + + SM4_CRYPT_BLK8(v0, v1, v2, v3, v4, v5, v6, v7); + + ld1 {RTMP0.16b-RTMP3.16b}, [x2], #64; + eor v0.16b, v0.16b, RTMP0.16b; + eor v1.16b, v1.16b, RTMP1.16b; + eor v2.16b, v2.16b, RTMP2.16b; + eor v3.16b, v3.16b, RTMP3.16b; + st1 {v0.16b-v3.16b}, [x1], #64; + + ld1 {RTMP0.16b-RTMP3.16b}, [x2], #64; + eor v4.16b, v4.16b, RTMP0.16b; + eor v5.16b, v5.16b, RTMP1.16b; + eor v6.16b, v6.16b, RTMP2.16b; + eor v7.16b, v7.16b, RTMP3.16b; + st1 {v4.16b-v7.16b}, [x1], #64; + + b .Lctr_loop_blk; + +.Lctr_end: + /* store new CTR */ + rev x7, x7; + rev x8, x8; + stp x7, x8, [x3]; + + ret; +SYM_FUNC_END(sm4_neon_ctr_enc_blk8) diff --git a/arch/arm64/crypto/sm4-neon-glue.c b/arch/arm64/crypto/sm4-neon-glue.c new file mode 100644 index 0000000000000000000000000000000000000000..03a6a6866a3112f0dc10dc2fc119f7d53c867a1d --- /dev/null +++ b/arch/arm64/crypto/sm4-neon-glue.c @@ -0,0 +1,442 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * SM4 Cipher Algorithm, using ARMv8 NEON + * as specified in + * https://tools.ietf.org/id/draft-ribose-cfrg-sm4-10.html + * + * Copyright (C) 2022, Alibaba Group. + * Copyright (C) 2022 Tianjia Zhang + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define BYTES2BLKS(nbytes) ((nbytes) >> 4) +#define BYTES2BLK8(nbytes) (((nbytes) >> 4) & ~(8 - 1)) + +asmlinkage void sm4_neon_crypt_blk1_8(const u32 *rkey, u8 *dst, const u8 *src, + unsigned int nblks); +asmlinkage void sm4_neon_crypt_blk8(const u32 *rkey, u8 *dst, const u8 *src, + unsigned int nblks); +asmlinkage void sm4_neon_cbc_dec_blk8(const u32 *rkey, u8 *dst, const u8 *src, + u8 *iv, unsigned int nblks); +asmlinkage void sm4_neon_cfb_dec_blk8(const u32 *rkey, u8 *dst, const u8 *src, + u8 *iv, unsigned int nblks); +asmlinkage void sm4_neon_ctr_enc_blk8(const u32 *rkey, u8 *dst, const u8 *src, + u8 *iv, unsigned int nblks); + +static int sm4_setkey(struct crypto_skcipher *tfm, const u8 *key, + unsigned int key_len) +{ + struct sm4_ctx *ctx = crypto_skcipher_ctx(tfm); + + return sm4_expandkey(ctx, key, key_len); +} + +static int sm4_ecb_do_crypt(struct skcipher_request *req, const u32 *rkey) +{ + struct skcipher_walk walk; + unsigned int nbytes; + int err; + + err = skcipher_walk_virt(&walk, req, false); + + while ((nbytes = walk.nbytes) > 0) { + const u8 *src = walk.src.virt.addr; + u8 *dst = walk.dst.virt.addr; + unsigned int nblks; + + kernel_neon_begin(); + + nblks = BYTES2BLK8(nbytes); + if (nblks) { + sm4_neon_crypt_blk8(rkey, dst, src, nblks); + dst += nblks * SM4_BLOCK_SIZE; + src += nblks * SM4_BLOCK_SIZE; + nbytes -= nblks * SM4_BLOCK_SIZE; + } + + nblks = BYTES2BLKS(nbytes); + if (nblks) { + sm4_neon_crypt_blk1_8(rkey, dst, src, nblks); + nbytes -= nblks * SM4_BLOCK_SIZE; + } + + kernel_neon_end(); + + err = skcipher_walk_done(&walk, nbytes); + } + + return err; +} + +static int sm4_ecb_encrypt(struct skcipher_request *req) +{ + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); + struct sm4_ctx *ctx = crypto_skcipher_ctx(tfm); + + return sm4_ecb_do_crypt(req, ctx->rkey_enc); +} + +static int sm4_ecb_decrypt(struct skcipher_request *req) +{ + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); + struct sm4_ctx *ctx = crypto_skcipher_ctx(tfm); + + return sm4_ecb_do_crypt(req, ctx->rkey_dec); +} + +static int sm4_cbc_encrypt(struct skcipher_request *req) +{ + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); + struct sm4_ctx *ctx = crypto_skcipher_ctx(tfm); + struct skcipher_walk walk; + unsigned int nbytes; + int err; + + err = skcipher_walk_virt(&walk, req, false); + + while ((nbytes = walk.nbytes) > 0) { + const u8 *iv = walk.iv; + const u8 *src = walk.src.virt.addr; + u8 *dst = walk.dst.virt.addr; + + while (nbytes >= SM4_BLOCK_SIZE) { + crypto_xor_cpy(dst, src, iv, SM4_BLOCK_SIZE); + sm4_crypt_block(ctx->rkey_enc, dst, dst); + iv = dst; + src += SM4_BLOCK_SIZE; + dst += SM4_BLOCK_SIZE; + nbytes -= SM4_BLOCK_SIZE; + } + if (iv != walk.iv) + memcpy(walk.iv, iv, SM4_BLOCK_SIZE); + + err = skcipher_walk_done(&walk, nbytes); + } + + return err; +} + +static int sm4_cbc_decrypt(struct skcipher_request *req) +{ + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); + struct sm4_ctx *ctx = crypto_skcipher_ctx(tfm); + struct skcipher_walk walk; + unsigned int nbytes; + int err; + + err = skcipher_walk_virt(&walk, req, false); + + while ((nbytes = walk.nbytes) > 0) { + const u8 *src = walk.src.virt.addr; + u8 *dst = walk.dst.virt.addr; + unsigned int nblks; + + kernel_neon_begin(); + + nblks = BYTES2BLK8(nbytes); + if (nblks) { + sm4_neon_cbc_dec_blk8(ctx->rkey_dec, dst, src, + walk.iv, nblks); + dst += nblks * SM4_BLOCK_SIZE; + src += nblks * SM4_BLOCK_SIZE; + nbytes -= nblks * SM4_BLOCK_SIZE; + } + + nblks = BYTES2BLKS(nbytes); + if (nblks) { + u8 keystream[SM4_BLOCK_SIZE * 8]; + u8 iv[SM4_BLOCK_SIZE]; + int i; + + sm4_neon_crypt_blk1_8(ctx->rkey_dec, keystream, + src, nblks); + + src += ((int)nblks - 2) * SM4_BLOCK_SIZE; + dst += (nblks - 1) * SM4_BLOCK_SIZE; + memcpy(iv, src + SM4_BLOCK_SIZE, SM4_BLOCK_SIZE); + + for (i = nblks - 1; i > 0; i--) { + crypto_xor_cpy(dst, src, + &keystream[i * SM4_BLOCK_SIZE], + SM4_BLOCK_SIZE); + src -= SM4_BLOCK_SIZE; + dst -= SM4_BLOCK_SIZE; + } + crypto_xor_cpy(dst, walk.iv, + keystream, SM4_BLOCK_SIZE); + memcpy(walk.iv, iv, SM4_BLOCK_SIZE); + nbytes -= nblks * SM4_BLOCK_SIZE; + } + + kernel_neon_end(); + + err = skcipher_walk_done(&walk, nbytes); + } + + return err; +} + +static int sm4_cfb_encrypt(struct skcipher_request *req) +{ + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); + struct sm4_ctx *ctx = crypto_skcipher_ctx(tfm); + struct skcipher_walk walk; + unsigned int nbytes; + int err; + + err = skcipher_walk_virt(&walk, req, false); + + while ((nbytes = walk.nbytes) > 0) { + u8 keystream[SM4_BLOCK_SIZE]; + const u8 *iv = walk.iv; + const u8 *src = walk.src.virt.addr; + u8 *dst = walk.dst.virt.addr; + + while (nbytes >= SM4_BLOCK_SIZE) { + sm4_crypt_block(ctx->rkey_enc, keystream, iv); + crypto_xor_cpy(dst, src, keystream, SM4_BLOCK_SIZE); + iv = dst; + src += SM4_BLOCK_SIZE; + dst += SM4_BLOCK_SIZE; + nbytes -= SM4_BLOCK_SIZE; + } + if (iv != walk.iv) + memcpy(walk.iv, iv, SM4_BLOCK_SIZE); + + /* tail */ + if (walk.nbytes == walk.total && nbytes > 0) { + sm4_crypt_block(ctx->rkey_enc, keystream, walk.iv); + crypto_xor_cpy(dst, src, keystream, nbytes); + nbytes = 0; + } + + err = skcipher_walk_done(&walk, nbytes); + } + + return err; +} + +static int sm4_cfb_decrypt(struct skcipher_request *req) +{ + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); + struct sm4_ctx *ctx = crypto_skcipher_ctx(tfm); + struct skcipher_walk walk; + unsigned int nbytes; + int err; + + err = skcipher_walk_virt(&walk, req, false); + + while ((nbytes = walk.nbytes) > 0) { + const u8 *src = walk.src.virt.addr; + u8 *dst = walk.dst.virt.addr; + unsigned int nblks; + + kernel_neon_begin(); + + nblks = BYTES2BLK8(nbytes); + if (nblks) { + sm4_neon_cfb_dec_blk8(ctx->rkey_enc, dst, src, + walk.iv, nblks); + dst += nblks * SM4_BLOCK_SIZE; + src += nblks * SM4_BLOCK_SIZE; + nbytes -= nblks * SM4_BLOCK_SIZE; + } + + nblks = BYTES2BLKS(nbytes); + if (nblks) { + u8 keystream[SM4_BLOCK_SIZE * 8]; + + memcpy(keystream, walk.iv, SM4_BLOCK_SIZE); + if (nblks > 1) + memcpy(&keystream[SM4_BLOCK_SIZE], src, + (nblks - 1) * SM4_BLOCK_SIZE); + memcpy(walk.iv, src + (nblks - 1) * SM4_BLOCK_SIZE, + SM4_BLOCK_SIZE); + + sm4_neon_crypt_blk1_8(ctx->rkey_enc, keystream, + keystream, nblks); + + crypto_xor_cpy(dst, src, keystream, + nblks * SM4_BLOCK_SIZE); + dst += nblks * SM4_BLOCK_SIZE; + src += nblks * SM4_BLOCK_SIZE; + nbytes -= nblks * SM4_BLOCK_SIZE; + } + + kernel_neon_end(); + + /* tail */ + if (walk.nbytes == walk.total && nbytes > 0) { + u8 keystream[SM4_BLOCK_SIZE]; + + sm4_crypt_block(ctx->rkey_enc, keystream, walk.iv); + crypto_xor_cpy(dst, src, keystream, nbytes); + nbytes = 0; + } + + err = skcipher_walk_done(&walk, nbytes); + } + + return err; +} + +static int sm4_ctr_crypt(struct skcipher_request *req) +{ + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); + struct sm4_ctx *ctx = crypto_skcipher_ctx(tfm); + struct skcipher_walk walk; + unsigned int nbytes; + int err; + + err = skcipher_walk_virt(&walk, req, false); + + while ((nbytes = walk.nbytes) > 0) { + const u8 *src = walk.src.virt.addr; + u8 *dst = walk.dst.virt.addr; + unsigned int nblks; + + kernel_neon_begin(); + + nblks = BYTES2BLK8(nbytes); + if (nblks) { + sm4_neon_ctr_enc_blk8(ctx->rkey_enc, dst, src, + walk.iv, nblks); + dst += nblks * SM4_BLOCK_SIZE; + src += nblks * SM4_BLOCK_SIZE; + nbytes -= nblks * SM4_BLOCK_SIZE; + } + + nblks = BYTES2BLKS(nbytes); + if (nblks) { + u8 keystream[SM4_BLOCK_SIZE * 8]; + int i; + + for (i = 0; i < nblks; i++) { + memcpy(&keystream[i * SM4_BLOCK_SIZE], + walk.iv, SM4_BLOCK_SIZE); + crypto_inc(walk.iv, SM4_BLOCK_SIZE); + } + sm4_neon_crypt_blk1_8(ctx->rkey_enc, keystream, + keystream, nblks); + + crypto_xor_cpy(dst, src, keystream, + nblks * SM4_BLOCK_SIZE); + dst += nblks * SM4_BLOCK_SIZE; + src += nblks * SM4_BLOCK_SIZE; + nbytes -= nblks * SM4_BLOCK_SIZE; + } + + kernel_neon_end(); + + /* tail */ + if (walk.nbytes == walk.total && nbytes > 0) { + u8 keystream[SM4_BLOCK_SIZE]; + + sm4_crypt_block(ctx->rkey_enc, keystream, walk.iv); + crypto_inc(walk.iv, SM4_BLOCK_SIZE); + crypto_xor_cpy(dst, src, keystream, nbytes); + nbytes = 0; + } + + err = skcipher_walk_done(&walk, nbytes); + } + + return err; +} + +static struct skcipher_alg sm4_algs[] = { + { + .base = { + .cra_name = "ecb(sm4)", + .cra_driver_name = "ecb-sm4-neon", + .cra_priority = 200, + .cra_blocksize = SM4_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct sm4_ctx), + .cra_module = THIS_MODULE, + }, + .min_keysize = SM4_KEY_SIZE, + .max_keysize = SM4_KEY_SIZE, + .setkey = sm4_setkey, + .encrypt = sm4_ecb_encrypt, + .decrypt = sm4_ecb_decrypt, + }, { + .base = { + .cra_name = "cbc(sm4)", + .cra_driver_name = "cbc-sm4-neon", + .cra_priority = 200, + .cra_blocksize = SM4_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct sm4_ctx), + .cra_module = THIS_MODULE, + }, + .min_keysize = SM4_KEY_SIZE, + .max_keysize = SM4_KEY_SIZE, + .ivsize = SM4_BLOCK_SIZE, + .setkey = sm4_setkey, + .encrypt = sm4_cbc_encrypt, + .decrypt = sm4_cbc_decrypt, + }, { + .base = { + .cra_name = "cfb(sm4)", + .cra_driver_name = "cfb-sm4-neon", + .cra_priority = 200, + .cra_blocksize = 1, + .cra_ctxsize = sizeof(struct sm4_ctx), + .cra_module = THIS_MODULE, + }, + .min_keysize = SM4_KEY_SIZE, + .max_keysize = SM4_KEY_SIZE, + .ivsize = SM4_BLOCK_SIZE, + .chunksize = SM4_BLOCK_SIZE, + .setkey = sm4_setkey, + .encrypt = sm4_cfb_encrypt, + .decrypt = sm4_cfb_decrypt, + }, { + .base = { + .cra_name = "ctr(sm4)", + .cra_driver_name = "ctr-sm4-neon", + .cra_priority = 200, + .cra_blocksize = 1, + .cra_ctxsize = sizeof(struct sm4_ctx), + .cra_module = THIS_MODULE, + }, + .min_keysize = SM4_KEY_SIZE, + .max_keysize = SM4_KEY_SIZE, + .ivsize = SM4_BLOCK_SIZE, + .chunksize = SM4_BLOCK_SIZE, + .setkey = sm4_setkey, + .encrypt = sm4_ctr_crypt, + .decrypt = sm4_ctr_crypt, + } +}; + +static int __init sm4_init(void) +{ + return crypto_register_skciphers(sm4_algs, ARRAY_SIZE(sm4_algs)); +} + +static void __exit sm4_exit(void) +{ + crypto_unregister_skciphers(sm4_algs, ARRAY_SIZE(sm4_algs)); +} + +module_init(sm4_init); +module_exit(sm4_exit); + +MODULE_DESCRIPTION("SM4 ECB/CBC/CFB/CTR using ARMv8 NEON"); +MODULE_ALIAS_CRYPTO("sm4-neon"); +MODULE_ALIAS_CRYPTO("sm4"); +MODULE_ALIAS_CRYPTO("ecb(sm4)"); +MODULE_ALIAS_CRYPTO("cbc(sm4)"); +MODULE_ALIAS_CRYPTO("cfb(sm4)"); +MODULE_ALIAS_CRYPTO("ctr(sm4)"); +MODULE_AUTHOR("Tianjia Zhang "); +MODULE_LICENSE("GPL v2"); diff --git a/arch/arm64/include/asm/compat.h b/arch/arm64/include/asm/compat.h index eaa6ca062d89b6a1c2f3fe353ae7c32216c480dd..9f362274a4f7cf126e3a657366fc92fc0758a7cf 100644 --- a/arch/arm64/include/asm/compat.h +++ b/arch/arm64/include/asm/compat.h @@ -8,6 +8,15 @@ #define compat_mode_t compat_mode_t typedef u16 compat_mode_t; +#define __compat_uid_t __compat_uid_t +typedef u16 __compat_uid_t; +typedef u16 __compat_gid_t; + +#define compat_ipc_pid_t compat_ipc_pid_t +typedef u16 compat_ipc_pid_t; + +#define compat_statfs compat_statfs + #include #ifdef CONFIG_COMPAT @@ -19,21 +28,15 @@ typedef u16 compat_mode_t; #include #include -#define COMPAT_USER_HZ 100 #ifdef __AARCH64EB__ #define COMPAT_UTS_MACHINE "armv8b\0\0" #else #define COMPAT_UTS_MACHINE "armv8l\0\0" #endif -typedef u16 __compat_uid_t; -typedef u16 __compat_gid_t; typedef u16 __compat_uid16_t; typedef u16 __compat_gid16_t; -typedef u32 compat_dev_t; typedef s32 compat_nlink_t; -typedef u16 compat_ipc_pid_t; -typedef __kernel_fsid_t compat_fsid_t; struct compat_stat { #ifdef __AARCH64EB__ @@ -65,26 +68,6 @@ struct compat_stat { compat_ulong_t __unused4[2]; }; -struct compat_flock { - short l_type; - short l_whence; - compat_off_t l_start; - compat_off_t l_len; - compat_pid_t l_pid; -}; - -#define F_GETLK64 12 /* using 'struct flock64' */ -#define F_SETLK64 13 -#define F_SETLKW64 14 - -struct compat_flock64 { - short l_type; - short l_whence; - compat_loff_t l_start; - compat_loff_t l_len; - compat_pid_t l_pid; -}; - struct compat_statfs { int f_type; int f_bsize; @@ -107,64 +90,6 @@ struct compat_statfs { #define compat_user_stack_pointer() (user_stack_pointer(task_pt_regs(current))) #define COMPAT_MINSIGSTKSZ 2048 -struct compat_ipc64_perm { - compat_key_t key; - __compat_uid32_t uid; - __compat_gid32_t gid; - __compat_uid32_t cuid; - __compat_gid32_t cgid; - unsigned short mode; - unsigned short __pad1; - unsigned short seq; - unsigned short __pad2; - compat_ulong_t unused1; - compat_ulong_t unused2; -}; - -struct compat_semid64_ds { - struct compat_ipc64_perm sem_perm; - compat_ulong_t sem_otime; - compat_ulong_t sem_otime_high; - compat_ulong_t sem_ctime; - compat_ulong_t sem_ctime_high; - compat_ulong_t sem_nsems; - compat_ulong_t __unused3; - compat_ulong_t __unused4; -}; - -struct compat_msqid64_ds { - struct compat_ipc64_perm msg_perm; - compat_ulong_t msg_stime; - compat_ulong_t msg_stime_high; - compat_ulong_t msg_rtime; - compat_ulong_t msg_rtime_high; - compat_ulong_t msg_ctime; - compat_ulong_t msg_ctime_high; - compat_ulong_t msg_cbytes; - compat_ulong_t msg_qnum; - compat_ulong_t msg_qbytes; - compat_pid_t msg_lspid; - compat_pid_t msg_lrpid; - compat_ulong_t __unused4; - compat_ulong_t __unused5; -}; - -struct compat_shmid64_ds { - struct compat_ipc64_perm shm_perm; - compat_size_t shm_segsz; - compat_ulong_t shm_atime; - compat_ulong_t shm_atime_high; - compat_ulong_t shm_dtime; - compat_ulong_t shm_dtime_high; - compat_ulong_t shm_ctime; - compat_ulong_t shm_ctime_high; - compat_pid_t shm_cpid; - compat_pid_t shm_lpid; - compat_ulong_t shm_nattch; - compat_ulong_t __unused4; - compat_ulong_t __unused5; -}; - static inline int is_compat_task(void) { return test_thread_flag(TIF_32BIT); diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h index ddb18b99af8ed594636d408eff4cdd93cf655312..a9b22ef95c5ebda063d0edabd3a749bc42bd88fd 100644 --- a/arch/arm64/include/asm/processor.h +++ b/arch/arm64/include/asm/processor.h @@ -93,8 +93,8 @@ #endif /* CONFIG_COMPAT */ #ifndef CONFIG_ARM64_FORCE_52BIT -#define arch_get_mmap_end(addr) ((addr > DEFAULT_MAP_WINDOW) ? TASK_SIZE :\ - DEFAULT_MAP_WINDOW) +#define arch_get_mmap_end(addr, len, flags) \ + (((addr) > DEFAULT_MAP_WINDOW) ? TASK_SIZE : DEFAULT_MAP_WINDOW) #define arch_get_mmap_base(addr, base) ((addr > DEFAULT_MAP_WINDOW) ? \ base + TASK_SIZE - DEFAULT_MAP_WINDOW :\ diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h index 4e65da3445c7aa09b30d926b249433034fd96b04..037feba03a51d85de6b3bdbf580d18baa7a8afcb 100644 --- a/arch/arm64/include/asm/unistd.h +++ b/arch/arm64/include/asm/unistd.h @@ -3,6 +3,7 @@ * Copyright (C) 2012 ARM Ltd. */ #ifdef CONFIG_COMPAT +#define __ARCH_WANT_COMPAT_STAT #define __ARCH_WANT_COMPAT_STAT64 #define __ARCH_WANT_SYS_GETHOSTNAME #define __ARCH_WANT_SYS_PAUSE diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c index efdf6eecdfb4b1a297a29abfa562916a7aba5aa9..4ac62986d54dffa7d47e389599d164cf2c76e16b 100644 --- a/arch/arm64/kernel/process.c +++ b/arch/arm64/kernel/process.c @@ -113,8 +113,7 @@ void machine_power_off(void) { local_irq_disable(); smp_send_stop(); - if (pm_power_off) - pm_power_off(); + do_kernel_power_off(); } /* diff --git a/arch/csky/kernel/power.c b/arch/csky/kernel/power.c index 923ee4e381b8151180e75add8f66f9a612d3a558..86ee202906f8d4a1fe28ea4eb0864c5c77867dea 100644 --- a/arch/csky/kernel/power.c +++ b/arch/csky/kernel/power.c @@ -9,16 +9,14 @@ EXPORT_SYMBOL(pm_power_off); void machine_power_off(void) { local_irq_disable(); - if (pm_power_off) - pm_power_off(); + do_kernel_power_off(); asm volatile ("bkpt"); } void machine_halt(void) { local_irq_disable(); - if (pm_power_off) - pm_power_off(); + do_kernel_power_off(); asm volatile ("bkpt"); } diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c index d7a256bd9d6b76e555fd53a7bfcb0e06c7b3fea4..89025e3b3f61cf0594cd1249dd25108d92c16ffd 100644 --- a/arch/ia64/kernel/process.c +++ b/arch/ia64/kernel/process.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -599,8 +600,7 @@ machine_halt (void) void machine_power_off (void) { - if (pm_power_off) - pm_power_off(); + do_kernel_power_off(); machine_halt(); } diff --git a/arch/m68k/Kconfig.bus b/arch/m68k/Kconfig.bus index d1e93a39cd3bcd9dc66b7b08d1599848dc90c3ae..d5c0b2990ee1efd0466d79492152a383089f1b21 100644 --- a/arch/m68k/Kconfig.bus +++ b/arch/m68k/Kconfig.bus @@ -56,16 +56,6 @@ config ATARI_ROM_ISA The only driver currently using this adapter is the EtherNEC driver for RTL8019AS based NE2000 compatible network cards. -config GENERIC_ISA_DMA - def_bool ISA - source "drivers/zorro/Kconfig" endif - -if COLDFIRE - -config ISA_DMA_API - def_bool !M5272 - -endif diff --git a/arch/m68k/Kconfig.cpu b/arch/m68k/Kconfig.cpu index 3d5da25c73b5af8aa70f5dbe745557bd6298b49b..f3aa44156969b523554d24f46733b979a1d4b391 100644 --- a/arch/m68k/Kconfig.cpu +++ b/arch/m68k/Kconfig.cpu @@ -37,7 +37,7 @@ endchoice if M68KCLASSIC config M68000 - bool + def_bool y depends on !MMU select CPU_HAS_NO_BITFIELDS select CPU_HAS_NO_CAS diff --git a/arch/m68k/Kconfig.machine b/arch/m68k/Kconfig.machine index 188a8f8a0104ae545dfed5e268df88fd2765a5e7..a1042568b9ad1590231b4e5cd488b79131bee24f 100644 --- a/arch/m68k/Kconfig.machine +++ b/arch/m68k/Kconfig.machine @@ -352,6 +352,7 @@ comment "Machine Options" config UBOOT bool "Support for U-Boot command line parameters" + depends on COLDFIRE help If you say Y here kernel will try to collect command line parameters from the initial u-boot stack. diff --git a/arch/m68k/coldfire/Makefile b/arch/m68k/coldfire/Makefile index a3e18d73d8b84224d9e2dc837520662c361eb43f..9419a6c1f036dd6f304dafecdf375928786d7ad5 100644 --- a/arch/m68k/coldfire/Makefile +++ b/arch/m68k/coldfire/Makefile @@ -15,7 +15,7 @@ asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1 -obj-$(CONFIG_COLDFIRE) += cache.o clk.o device.o dma.o entry.o vectors.o +obj-$(CONFIG_COLDFIRE) += cache.o clk.o device.o entry.o vectors.o obj-$(CONFIG_M5206) += m5206.o intc.o reset.o obj-$(CONFIG_M5206e) += m5206.o intc.o reset.o obj-$(CONFIG_M520x) += m520x.o intc-simr.o reset.o diff --git a/arch/m68k/coldfire/dma.c b/arch/m68k/coldfire/dma.c deleted file mode 100644 index c3279f7467d7cbc5ca8d249dce570a23db0f40b4..0000000000000000000000000000000000000000 --- a/arch/m68k/coldfire/dma.c +++ /dev/null @@ -1,43 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/***************************************************************************/ - -/* - * dma.c -- Freescale ColdFire DMA support - * - * Copyright (C) 2007, Greg Ungerer (gerg@snapgear.com) - */ - -/***************************************************************************/ - -#include -#include -#include -#include -#include -#include - -/***************************************************************************/ - -/* - * DMA channel base address table. - */ -unsigned int dma_base_addr[MAX_M68K_DMA_CHANNELS] = { -#ifdef MCFDMA_BASE0 - MCFDMA_BASE0, -#endif -#ifdef MCFDMA_BASE1 - MCFDMA_BASE1, -#endif -#ifdef MCFDMA_BASE2 - MCFDMA_BASE2, -#endif -#ifdef MCFDMA_BASE3 - MCFDMA_BASE3, -#endif -}; -EXPORT_SYMBOL(dma_base_addr); - -unsigned int dma_device_address[MAX_M68K_DMA_CHANNELS]; -EXPORT_SYMBOL(dma_device_address); - -/***************************************************************************/ diff --git a/arch/m68k/coldfire/intc.c b/arch/m68k/coldfire/intc.c index cce2574203885412b9c5f742405928f74fb0ae3b..20c084e932c89347731e99faa218d69ec359314e 100644 --- a/arch/m68k/coldfire/intc.c +++ b/arch/m68k/coldfire/intc.c @@ -28,7 +28,7 @@ unsigned char mcf_irq2imr[NR_IRQS]; /* - * Define the miniumun and maximum external interrupt numbers. + * Define the minimum and maximum external interrupt numbers. * This is also used as the "level" interrupt numbers. */ #define EIRQ1 25 diff --git a/arch/m68k/coldfire/m53xx.c b/arch/m68k/coldfire/m53xx.c index bd033e1975bfe31862987eae894504e7fa52d52a..17af5f67379698e39e389538fbb9579067837713 100644 --- a/arch/m68k/coldfire/m53xx.c +++ b/arch/m68k/coldfire/m53xx.c @@ -532,7 +532,7 @@ int clock_pll(int fsys, int flags) writel(readl(MCF_SDRAMC_SDCR) | MCF_SDRAMC_SDCR_CKE, MCF_SDRAMC_SDCR); - /* Errata - workaround for SDRAM opeartion after exiting LIMP mode */ + /* Errata - workaround for SDRAM operation after exiting LIMP mode */ writel(MCF_SDRAMC_REFRESH, MCF_SDRAMC_LIMP_FIX); /* wait for DQS logic to relock */ diff --git a/arch/m68k/coldfire/pci.c b/arch/m68k/coldfire/pci.c index 84eab0f5e00afcca64b2df762c9ffac5e7c72590..ceb5775b8d239428b17542a24d6355ca47bc4835 100644 --- a/arch/m68k/coldfire/pci.c +++ b/arch/m68k/coldfire/pci.c @@ -31,7 +31,7 @@ static struct pci_bus *rootbus; static unsigned long iospace; /* - * We need to be carefull probing on bus 0 (directly connected to host + * We need to be careful probing on bus 0 (directly connected to host * bridge). We should only access the well defined possible devices in * use, ignore aliases and the like. */ diff --git a/arch/m68k/emu/natfeat.c b/arch/m68k/emu/natfeat.c index 71b78ecee75c64773921bb9aed81aefbf24dae73..b19dc00026d9953b5353bbf25ba8bd8fdc33ccc9 100644 --- a/arch/m68k/emu/natfeat.c +++ b/arch/m68k/emu/natfeat.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -90,5 +91,5 @@ void __init nf_init(void) pr_info("NatFeats found (%s, %lu.%lu)\n", buf, version >> 16, version & 0xffff); - mach_power_off = nf_poweroff; + register_platform_power_off(nf_poweroff); } diff --git a/arch/m68k/hp300/config.c b/arch/m68k/hp300/config.c index 2c92843397c3476f790b2b7d753e9de31ef2b4d7..e4bd6913f50e9ef3d392d789fbbdce06202f0954 100644 --- a/arch/m68k/hp300/config.c +++ b/arch/m68k/hp300/config.c @@ -240,12 +240,6 @@ static int hp300_hwclk(int op, struct rtc_time *t) return 0; } -static unsigned int hp300_get_ss(void) -{ - return hp300_rtc_read(RTC_REG_SEC1) * 10 + - hp300_rtc_read(RTC_REG_SEC2); -} - static void __init hp300_init_IRQ(void) { } @@ -256,7 +250,6 @@ void __init config_hp300(void) mach_init_IRQ = hp300_init_IRQ; mach_get_model = hp300_get_model; mach_hwclk = hp300_hwclk; - mach_get_ss = hp300_get_ss; mach_reset = hp300_reset; #ifdef CONFIG_HEARTBEAT mach_heartbeat = hp300_pulse; diff --git a/arch/m68k/include/asm/dma.h b/arch/m68k/include/asm/dma.h index ae2021964e32d36f7dfc6949ee8935b20c5961b5..f6c5e0dfb4e5bc96f78ab8a2abdc614760959bff 100644 --- a/arch/m68k/include/asm/dma.h +++ b/arch/m68k/include/asm/dma.h @@ -2,493 +2,10 @@ #ifndef _M68K_DMA_H #define _M68K_DMA_H 1 -#ifdef CONFIG_COLDFIRE -/* - * ColdFire DMA Model: - * ColdFire DMA supports two forms of DMA: Single and Dual address. Single - * address mode emits a source address, and expects that the device will either - * pick up the data (DMA READ) or source data (DMA WRITE). This implies that - * the device will place data on the correct byte(s) of the data bus, as the - * memory transactions are always 32 bits. This implies that only 32 bit - * devices will find single mode transfers useful. Dual address DMA mode - * performs two cycles: source read and destination write. ColdFire will - * align the data so that the device will always get the correct bytes, thus - * is useful for 8 and 16 bit devices. This is the mode that is supported - * below. - * - * AUG/22/2000 : added support for 32-bit Dual-Address-Mode (K) 2000 - * Oliver Kamphenkel (O.Kamphenkel@tu-bs.de) - * - * AUG/25/2000 : added support for 8, 16 and 32-bit Single-Address-Mode (K)2000 - * Oliver Kamphenkel (O.Kamphenkel@tu-bs.de) - * - * APR/18/2002 : added proper support for MCF5272 DMA controller. - * Arthur Shipkowski (art@videon-central.com) - */ - -#include -#include -#include - -/* - * Set number of channels of DMA on ColdFire for different implementations. - */ -#if defined(CONFIG_M5249) || defined(CONFIG_M5307) || defined(CONFIG_M5407) || \ - defined(CONFIG_M523x) || defined(CONFIG_M527x) || \ - defined(CONFIG_M528x) || defined(CONFIG_M525x) - -#define MAX_M68K_DMA_CHANNELS 4 -#elif defined(CONFIG_M5272) -#define MAX_M68K_DMA_CHANNELS 1 -#elif defined(CONFIG_M53xx) -#define MAX_M68K_DMA_CHANNELS 0 -#else -#define MAX_M68K_DMA_CHANNELS 2 -#endif - -extern unsigned int dma_base_addr[MAX_M68K_DMA_CHANNELS]; -extern unsigned int dma_device_address[MAX_M68K_DMA_CHANNELS]; - -#if !defined(CONFIG_M5272) -#define DMA_MODE_WRITE_BIT 0x01 /* Memory/IO to IO/Memory select */ -#define DMA_MODE_WORD_BIT 0x02 /* 8 or 16 bit transfers */ -#define DMA_MODE_LONG_BIT 0x04 /* or 32 bit transfers */ -#define DMA_MODE_SINGLE_BIT 0x08 /* single-address-mode */ - -/* I/O to memory, 8 bits, mode */ -#define DMA_MODE_READ 0 -/* memory to I/O, 8 bits, mode */ -#define DMA_MODE_WRITE 1 -/* I/O to memory, 16 bits, mode */ -#define DMA_MODE_READ_WORD 2 -/* memory to I/O, 16 bits, mode */ -#define DMA_MODE_WRITE_WORD 3 -/* I/O to memory, 32 bits, mode */ -#define DMA_MODE_READ_LONG 4 -/* memory to I/O, 32 bits, mode */ -#define DMA_MODE_WRITE_LONG 5 -/* I/O to memory, 8 bits, single-address-mode */ -#define DMA_MODE_READ_SINGLE 8 -/* memory to I/O, 8 bits, single-address-mode */ -#define DMA_MODE_WRITE_SINGLE 9 -/* I/O to memory, 16 bits, single-address-mode */ -#define DMA_MODE_READ_WORD_SINGLE 10 -/* memory to I/O, 16 bits, single-address-mode */ -#define DMA_MODE_WRITE_WORD_SINGLE 11 -/* I/O to memory, 32 bits, single-address-mode */ -#define DMA_MODE_READ_LONG_SINGLE 12 -/* memory to I/O, 32 bits, single-address-mode */ -#define DMA_MODE_WRITE_LONG_SINGLE 13 - -#else /* CONFIG_M5272 is defined */ - -/* Source static-address mode */ -#define DMA_MODE_SRC_SA_BIT 0x01 -/* Two bits to select between all four modes */ -#define DMA_MODE_SSIZE_MASK 0x06 -/* Offset to shift bits in */ -#define DMA_MODE_SSIZE_OFF 0x01 -/* Destination static-address mode */ -#define DMA_MODE_DES_SA_BIT 0x10 -/* Two bits to select between all four modes */ -#define DMA_MODE_DSIZE_MASK 0x60 -/* Offset to shift bits in */ -#define DMA_MODE_DSIZE_OFF 0x05 -/* Size modifiers */ -#define DMA_MODE_SIZE_LONG 0x00 -#define DMA_MODE_SIZE_BYTE 0x01 -#define DMA_MODE_SIZE_WORD 0x02 -#define DMA_MODE_SIZE_LINE 0x03 - -/* - * Aliases to help speed quick ports; these may be suboptimal, however. They - * do not include the SINGLE mode modifiers since the MCF5272 does not have a - * mode where the device is in control of its addressing. - */ - -/* I/O to memory, 8 bits, mode */ -#define DMA_MODE_READ ((DMA_MODE_SIZE_BYTE << DMA_MODE_DSIZE_OFF) | (DMA_MODE_SIZE_BYTE << DMA_MODE_SSIZE_OFF) | DMA_SRC_SA_BIT) -/* memory to I/O, 8 bits, mode */ -#define DMA_MODE_WRITE ((DMA_MODE_SIZE_BYTE << DMA_MODE_DSIZE_OFF) | (DMA_MODE_SIZE_BYTE << DMA_MODE_SSIZE_OFF) | DMA_DES_SA_BIT) -/* I/O to memory, 16 bits, mode */ -#define DMA_MODE_READ_WORD ((DMA_MODE_SIZE_WORD << DMA_MODE_DSIZE_OFF) | (DMA_MODE_SIZE_WORD << DMA_MODE_SSIZE_OFF) | DMA_SRC_SA_BIT) -/* memory to I/O, 16 bits, mode */ -#define DMA_MODE_WRITE_WORD ((DMA_MODE_SIZE_WORD << DMA_MODE_DSIZE_OFF) | (DMA_MODE_SIZE_WORD << DMA_MODE_SSIZE_OFF) | DMA_DES_SA_BIT) -/* I/O to memory, 32 bits, mode */ -#define DMA_MODE_READ_LONG ((DMA_MODE_SIZE_LONG << DMA_MODE_DSIZE_OFF) | (DMA_MODE_SIZE_LONG << DMA_MODE_SSIZE_OFF) | DMA_SRC_SA_BIT) -/* memory to I/O, 32 bits, mode */ -#define DMA_MODE_WRITE_LONG ((DMA_MODE_SIZE_LONG << DMA_MODE_DSIZE_OFF) | (DMA_MODE_SIZE_LONG << DMA_MODE_SSIZE_OFF) | DMA_DES_SA_BIT) - -#endif /* !defined(CONFIG_M5272) */ - -#if !defined(CONFIG_M5272) -/* enable/disable a specific DMA channel */ -static __inline__ void enable_dma(unsigned int dmanr) -{ - volatile unsigned short *dmawp; - -#ifdef DMA_DEBUG - printk("enable_dma(dmanr=%d)\n", dmanr); -#endif - - dmawp = (unsigned short *) dma_base_addr[dmanr]; - dmawp[MCFDMA_DCR] |= MCFDMA_DCR_EEXT; -} - -static __inline__ void disable_dma(unsigned int dmanr) -{ - volatile unsigned short *dmawp; - volatile unsigned char *dmapb; - -#ifdef DMA_DEBUG - printk("disable_dma(dmanr=%d)\n", dmanr); -#endif - - dmawp = (unsigned short *) dma_base_addr[dmanr]; - dmapb = (unsigned char *) dma_base_addr[dmanr]; - - /* Turn off external requests, and stop any DMA in progress */ - dmawp[MCFDMA_DCR] &= ~MCFDMA_DCR_EEXT; - dmapb[MCFDMA_DSR] = MCFDMA_DSR_DONE; -} - -/* - * Clear the 'DMA Pointer Flip Flop'. - * Write 0 for LSB/MSB, 1 for MSB/LSB access. - * Use this once to initialize the FF to a known state. - * After that, keep track of it. :-) - * --- In order to do that, the DMA routines below should --- - * --- only be used while interrupts are disabled! --- - * - * This is a NOP for ColdFire. Provide a stub for compatibility. - */ -static __inline__ void clear_dma_ff(unsigned int dmanr) -{ -} - -/* set mode (above) for a specific DMA channel */ -static __inline__ void set_dma_mode(unsigned int dmanr, char mode) -{ - - volatile unsigned char *dmabp; - volatile unsigned short *dmawp; - -#ifdef DMA_DEBUG - printk("set_dma_mode(dmanr=%d,mode=%d)\n", dmanr, mode); -#endif - - dmabp = (unsigned char *) dma_base_addr[dmanr]; - dmawp = (unsigned short *) dma_base_addr[dmanr]; - - /* Clear config errors */ - dmabp[MCFDMA_DSR] = MCFDMA_DSR_DONE; - - /* Set command register */ - dmawp[MCFDMA_DCR] = - MCFDMA_DCR_INT | /* Enable completion irq */ - MCFDMA_DCR_CS | /* Force one xfer per request */ - MCFDMA_DCR_AA | /* Enable auto alignment */ - /* single-address-mode */ - ((mode & DMA_MODE_SINGLE_BIT) ? MCFDMA_DCR_SAA : 0) | - /* sets s_rw (-> r/w) high if Memory to I/0 */ - ((mode & DMA_MODE_WRITE_BIT) ? MCFDMA_DCR_S_RW : 0) | - /* Memory to I/O or I/O to Memory */ - ((mode & DMA_MODE_WRITE_BIT) ? MCFDMA_DCR_SINC : MCFDMA_DCR_DINC) | - /* 32 bit, 16 bit or 8 bit transfers */ - ((mode & DMA_MODE_WORD_BIT) ? MCFDMA_DCR_SSIZE_WORD : - ((mode & DMA_MODE_LONG_BIT) ? MCFDMA_DCR_SSIZE_LONG : - MCFDMA_DCR_SSIZE_BYTE)) | - ((mode & DMA_MODE_WORD_BIT) ? MCFDMA_DCR_DSIZE_WORD : - ((mode & DMA_MODE_LONG_BIT) ? MCFDMA_DCR_DSIZE_LONG : - MCFDMA_DCR_DSIZE_BYTE)); - -#ifdef DEBUG_DMA - printk("%s(%d): dmanr=%d DSR[%x]=%x DCR[%x]=%x\n", __FILE__, __LINE__, - dmanr, (int) &dmabp[MCFDMA_DSR], dmabp[MCFDMA_DSR], - (int) &dmawp[MCFDMA_DCR], dmawp[MCFDMA_DCR]); -#endif -} - -/* Set transfer address for specific DMA channel */ -static __inline__ void set_dma_addr(unsigned int dmanr, unsigned int a) -{ - volatile unsigned short *dmawp; - volatile unsigned int *dmalp; - -#ifdef DMA_DEBUG - printk("set_dma_addr(dmanr=%d,a=%x)\n", dmanr, a); -#endif - - dmawp = (unsigned short *) dma_base_addr[dmanr]; - dmalp = (unsigned int *) dma_base_addr[dmanr]; - - /* Determine which address registers are used for memory/device accesses */ - if (dmawp[MCFDMA_DCR] & MCFDMA_DCR_SINC) { - /* Source incrementing, must be memory */ - dmalp[MCFDMA_SAR] = a; - /* Set dest address, must be device */ - dmalp[MCFDMA_DAR] = dma_device_address[dmanr]; - } else { - /* Destination incrementing, must be memory */ - dmalp[MCFDMA_DAR] = a; - /* Set source address, must be device */ - dmalp[MCFDMA_SAR] = dma_device_address[dmanr]; - } - -#ifdef DEBUG_DMA - printk("%s(%d): dmanr=%d DCR[%x]=%x SAR[%x]=%08x DAR[%x]=%08x\n", - __FILE__, __LINE__, dmanr, (int) &dmawp[MCFDMA_DCR], dmawp[MCFDMA_DCR], - (int) &dmalp[MCFDMA_SAR], dmalp[MCFDMA_SAR], - (int) &dmalp[MCFDMA_DAR], dmalp[MCFDMA_DAR]); -#endif -} - -/* - * Specific for Coldfire - sets device address. - * Should be called after the mode set call, and before set DMA address. - */ -static __inline__ void set_dma_device_addr(unsigned int dmanr, unsigned int a) -{ -#ifdef DMA_DEBUG - printk("set_dma_device_addr(dmanr=%d,a=%x)\n", dmanr, a); -#endif - - dma_device_address[dmanr] = a; -} - -/* - * NOTE 2: "count" represents _bytes_. - */ -static __inline__ void set_dma_count(unsigned int dmanr, unsigned int count) -{ - volatile unsigned short *dmawp; - -#ifdef DMA_DEBUG - printk("set_dma_count(dmanr=%d,count=%d)\n", dmanr, count); -#endif - - dmawp = (unsigned short *) dma_base_addr[dmanr]; - dmawp[MCFDMA_BCR] = (unsigned short)count; -} - -/* - * Get DMA residue count. After a DMA transfer, this - * should return zero. Reading this while a DMA transfer is - * still in progress will return unpredictable results. - * Otherwise, it returns the number of _bytes_ left to transfer. - */ -static __inline__ int get_dma_residue(unsigned int dmanr) -{ - volatile unsigned short *dmawp; - unsigned short count; - -#ifdef DMA_DEBUG - printk("get_dma_residue(dmanr=%d)\n", dmanr); -#endif - - dmawp = (unsigned short *) dma_base_addr[dmanr]; - count = dmawp[MCFDMA_BCR]; - return((int) count); -} -#else /* CONFIG_M5272 is defined */ - -/* - * The MCF5272 DMA controller is very different than the controller defined above - * in terms of register mapping. For instance, with the exception of the 16-bit - * interrupt register (IRQ#85, for reference), all of the registers are 32-bit. - * - * The big difference, however, is the lack of device-requested DMA. All modes - * are dual address transfer, and there is no 'device' setup or direction bit. - * You can DMA between a device and memory, between memory and memory, or even between - * two devices directly, with any combination of incrementing and non-incrementing - * addresses you choose. This puts a crimp in distinguishing between the 'device - * address' set up by set_dma_device_addr. - * - * Therefore, there are two options. One is to use set_dma_addr and set_dma_device_addr, - * which will act exactly as above in -- it will look to see if the source is set to - * autoincrement, and if so it will make the source use the set_dma_addr value and the - * destination the set_dma_device_addr value. Otherwise the source will be set to the - * set_dma_device_addr value and the destination will get the set_dma_addr value. - * - * The other is to use the provided set_dma_src_addr and set_dma_dest_addr functions - * and make it explicit. Depending on what you're doing, one of these two should work - * for you, but don't mix them in the same transfer setup. - */ - -/* enable/disable a specific DMA channel */ -static __inline__ void enable_dma(unsigned int dmanr) -{ - volatile unsigned int *dmalp; - -#ifdef DMA_DEBUG - printk("enable_dma(dmanr=%d)\n", dmanr); -#endif - - dmalp = (unsigned int *) dma_base_addr[dmanr]; - dmalp[MCFDMA_DMR] |= MCFDMA_DMR_EN; -} - -static __inline__ void disable_dma(unsigned int dmanr) -{ - volatile unsigned int *dmalp; - -#ifdef DMA_DEBUG - printk("disable_dma(dmanr=%d)\n", dmanr); -#endif - - dmalp = (unsigned int *) dma_base_addr[dmanr]; - - /* Turn off external requests, and stop any DMA in progress */ - dmalp[MCFDMA_DMR] &= ~MCFDMA_DMR_EN; - dmalp[MCFDMA_DMR] |= MCFDMA_DMR_RESET; -} - -/* - * Clear the 'DMA Pointer Flip Flop'. - * Write 0 for LSB/MSB, 1 for MSB/LSB access. - * Use this once to initialize the FF to a known state. - * After that, keep track of it. :-) - * --- In order to do that, the DMA routines below should --- - * --- only be used while interrupts are disabled! --- - * - * This is a NOP for ColdFire. Provide a stub for compatibility. - */ -static __inline__ void clear_dma_ff(unsigned int dmanr) -{ -} - -/* set mode (above) for a specific DMA channel */ -static __inline__ void set_dma_mode(unsigned int dmanr, char mode) -{ - - volatile unsigned int *dmalp; - volatile unsigned short *dmawp; - -#ifdef DMA_DEBUG - printk("set_dma_mode(dmanr=%d,mode=%d)\n", dmanr, mode); -#endif - dmalp = (unsigned int *) dma_base_addr[dmanr]; - dmawp = (unsigned short *) dma_base_addr[dmanr]; - - /* Clear config errors */ - dmalp[MCFDMA_DMR] |= MCFDMA_DMR_RESET; - - /* Set command register */ - dmalp[MCFDMA_DMR] = - MCFDMA_DMR_RQM_DUAL | /* Mandatory Request Mode setting */ - MCFDMA_DMR_DSTT_SD | /* Set up addressing types; set to supervisor-data. */ - MCFDMA_DMR_SRCT_SD | /* Set up addressing types; set to supervisor-data. */ - /* source static-address-mode */ - ((mode & DMA_MODE_SRC_SA_BIT) ? MCFDMA_DMR_SRCM_SA : MCFDMA_DMR_SRCM_IA) | - /* dest static-address-mode */ - ((mode & DMA_MODE_DES_SA_BIT) ? MCFDMA_DMR_DSTM_SA : MCFDMA_DMR_DSTM_IA) | - /* burst, 32 bit, 16 bit or 8 bit transfers are separately configurable on the MCF5272 */ - (((mode & DMA_MODE_SSIZE_MASK) >> DMA_MODE_SSIZE_OFF) << MCFDMA_DMR_DSTS_OFF) | - (((mode & DMA_MODE_SSIZE_MASK) >> DMA_MODE_SSIZE_OFF) << MCFDMA_DMR_SRCS_OFF); - - dmawp[MCFDMA_DIR] |= MCFDMA_DIR_ASCEN; /* Enable completion interrupts */ - -#ifdef DEBUG_DMA - printk("%s(%d): dmanr=%d DMR[%x]=%x DIR[%x]=%x\n", __FILE__, __LINE__, - dmanr, (int) &dmalp[MCFDMA_DMR], dmalp[MCFDMA_DMR], - (int) &dmawp[MCFDMA_DIR], dmawp[MCFDMA_DIR]); -#endif -} - -/* Set transfer address for specific DMA channel */ -static __inline__ void set_dma_addr(unsigned int dmanr, unsigned int a) -{ - volatile unsigned int *dmalp; - -#ifdef DMA_DEBUG - printk("set_dma_addr(dmanr=%d,a=%x)\n", dmanr, a); -#endif - - dmalp = (unsigned int *) dma_base_addr[dmanr]; - - /* Determine which address registers are used for memory/device accesses */ - if (dmalp[MCFDMA_DMR] & MCFDMA_DMR_SRCM) { - /* Source incrementing, must be memory */ - dmalp[MCFDMA_DSAR] = a; - /* Set dest address, must be device */ - dmalp[MCFDMA_DDAR] = dma_device_address[dmanr]; - } else { - /* Destination incrementing, must be memory */ - dmalp[MCFDMA_DDAR] = a; - /* Set source address, must be device */ - dmalp[MCFDMA_DSAR] = dma_device_address[dmanr]; - } - -#ifdef DEBUG_DMA - printk("%s(%d): dmanr=%d DMR[%x]=%x SAR[%x]=%08x DAR[%x]=%08x\n", - __FILE__, __LINE__, dmanr, (int) &dmalp[MCFDMA_DMR], dmalp[MCFDMA_DMR], - (int) &dmalp[MCFDMA_DSAR], dmalp[MCFDMA_DSAR], - (int) &dmalp[MCFDMA_DDAR], dmalp[MCFDMA_DDAR]); -#endif -} - -/* - * Specific for Coldfire - sets device address. - * Should be called after the mode set call, and before set DMA address. - */ -static __inline__ void set_dma_device_addr(unsigned int dmanr, unsigned int a) -{ -#ifdef DMA_DEBUG - printk("set_dma_device_addr(dmanr=%d,a=%x)\n", dmanr, a); -#endif - - dma_device_address[dmanr] = a; -} - -/* - * NOTE 2: "count" represents _bytes_. - * - * NOTE 3: While a 32-bit register, "count" is only a maximum 24-bit value. - */ -static __inline__ void set_dma_count(unsigned int dmanr, unsigned int count) -{ - volatile unsigned int *dmalp; - -#ifdef DMA_DEBUG - printk("set_dma_count(dmanr=%d,count=%d)\n", dmanr, count); -#endif - - dmalp = (unsigned int *) dma_base_addr[dmanr]; - dmalp[MCFDMA_DBCR] = count; -} - -/* - * Get DMA residue count. After a DMA transfer, this - * should return zero. Reading this while a DMA transfer is - * still in progress will return unpredictable results. - * Otherwise, it returns the number of _bytes_ left to transfer. - */ -static __inline__ int get_dma_residue(unsigned int dmanr) -{ - volatile unsigned int *dmalp; - unsigned int count; - -#ifdef DMA_DEBUG - printk("get_dma_residue(dmanr=%d)\n", dmanr); -#endif - - dmalp = (unsigned int *) dma_base_addr[dmanr]; - count = dmalp[MCFDMA_DBCR]; - return(count); -} - -#endif /* !defined(CONFIG_M5272) */ -#endif /* CONFIG_COLDFIRE */ - /* it's useless on the m68k, but unfortunately needed by the new bootmem allocator (but this should do it for this) */ #define MAX_DMA_ADDRESS PAGE_OFFSET -#define MAX_DMA_CHANNELS 8 - -extern int request_dma(unsigned int dmanr, const char * device_id); /* reserve a DMA channel */ -extern void free_dma(unsigned int dmanr); /* release it again */ - #ifdef CONFIG_PCI extern int isa_dma_bridge_buggy; #else diff --git a/arch/m68k/include/asm/elf.h b/arch/m68k/include/asm/elf.h index 3d387ceaea3fdfe2dc0489525640b6e90fe94db8..2def06a99b08b2186fc341ab94bc4d7ce7ed1f35 100644 --- a/arch/m68k/include/asm/elf.h +++ b/arch/m68k/include/asm/elf.h @@ -60,6 +60,13 @@ typedef struct user_m68kfp_struct elf_fpregset_t; is actually used on ASV. */ #define ELF_PLAT_INIT(_r, load_addr) _r->a1 = 0 +#define ELF_FDPIC_PLAT_INIT(_r, _exec_map_addr, _interp_map_addr, dynamic_addr) \ + do { \ + (_r)->d3 = _exec_map_addr; \ + (_r)->d4 = _interp_map_addr; \ + (_r)->d5 = dynamic_addr; \ + } while(0) + #if defined(CONFIG_SUN3) || defined(CONFIG_COLDFIRE) #define ELF_EXEC_PAGESIZE 8192 #else @@ -114,4 +121,6 @@ typedef struct user_m68kfp_struct elf_fpregset_t; #define ELF_PLATFORM (NULL) +#define ELF_FDPIC_CORE_EFLAGS 0 + #endif diff --git a/arch/m68k/include/asm/machdep.h b/arch/m68k/include/asm/machdep.h index 8fd80ef1b77e12057a204e040c82200e9c2b8dad..48d27f1fecc70cd95d029b8d6467cab985fc3a7d 100644 --- a/arch/m68k/include/asm/machdep.h +++ b/arch/m68k/include/asm/machdep.h @@ -19,12 +19,10 @@ extern void (*mach_get_model) (char *model); extern void (*mach_get_hardware_list) (struct seq_file *m); /* machine dependent timer functions */ extern int (*mach_hwclk)(int, struct rtc_time*); -extern unsigned int (*mach_get_ss)(void); extern int (*mach_get_rtc_pll)(struct rtc_pll_info *); extern int (*mach_set_rtc_pll)(struct rtc_pll_info *); extern void (*mach_reset)( void ); extern void (*mach_halt)( void ); -extern void (*mach_power_off)( void ); extern unsigned long (*mach_hd_init) (unsigned long, unsigned long); extern void (*mach_hd_setup)(char *, int *); extern void (*mach_heartbeat) (int); diff --git a/arch/m68k/include/asm/mmu.h b/arch/m68k/include/asm/mmu.h index 5c15aacb137093e055be4aa7084c5ad548a7f341..e00672425b004852fd9e0cdb612e6f7e51995a12 100644 --- a/arch/m68k/include/asm/mmu.h +++ b/arch/m68k/include/asm/mmu.h @@ -6,9 +6,7 @@ /* Default "unsigned long" context */ typedef unsigned long mm_context_t; #else -typedef struct { - unsigned long end_brk; -} mm_context_t; +#include #endif #endif diff --git a/arch/m68k/include/asm/pgtable_no.h b/arch/m68k/include/asm/pgtable_no.h index 87151d67d91e77988112763cf15a9630895e77f4..bce5ca56c3883dea12147eff894e99b968d964fb 100644 --- a/arch/m68k/include/asm/pgtable_no.h +++ b/arch/m68k/include/asm/pgtable_no.h @@ -42,7 +42,8 @@ extern void paging_init(void); * ZERO_PAGE is a global shared page that is always zero: used * for zero-mapped memory areas etc.. */ -#define ZERO_PAGE(vaddr) (virt_to_page(0)) +extern void *empty_zero_page; +#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page)) /* * All 32bit addresses are effectively valid for vmalloc... diff --git a/arch/m68k/include/uapi/asm/ptrace.h b/arch/m68k/include/uapi/asm/ptrace.h index 19a1b9d0d858148599a732825bcd84c55be0a351..5b50ea592e002d09902d13d9889f0103a2a25c8c 100644 --- a/arch/m68k/include/uapi/asm/ptrace.h +++ b/arch/m68k/include/uapi/asm/ptrace.h @@ -74,7 +74,12 @@ struct switch_stack { #define PTRACE_GET_THREAD_AREA 25 +#define PTRACE_GETFDPIC 31 + #define PTRACE_SINGLEBLOCK 33 /* resume execution until next branch */ +#define PTRACE_GETFDPIC_EXEC 0 +#define PTRACE_GETFDPIC_INTERP 1 + #endif /* __ASSEMBLY__ */ #endif /* _UAPI_M68K_PTRACE_H */ diff --git a/arch/m68k/kernel/process.c b/arch/m68k/kernel/process.c index a6030dbaa0891675735c418ac8041ddaf455a543..e160a7c57bd3c4db663d9533d584f2c9f3a48e32 100644 --- a/arch/m68k/kernel/process.c +++ b/arch/m68k/kernel/process.c @@ -67,12 +67,11 @@ void machine_halt(void) void machine_power_off(void) { - if (mach_power_off) - mach_power_off(); + do_kernel_power_off(); for (;;); } -void (*pm_power_off)(void) = machine_power_off; +void (*pm_power_off)(void); EXPORT_SYMBOL(pm_power_off); void show_regs(struct pt_regs * regs) diff --git a/arch/m68k/kernel/ptrace.c b/arch/m68k/kernel/ptrace.c index daebccdd2c09398d8ebe61b46b830f1fe0602c94..0a4184a37461b0ab40fe559e07ce57dd46664abb 100644 --- a/arch/m68k/kernel/ptrace.c +++ b/arch/m68k/kernel/ptrace.c @@ -19,6 +19,8 @@ #include #include #include +#include +#include #include #include @@ -284,3 +286,59 @@ asmlinkage void syscall_trace_leave(void) if (test_thread_flag(TIF_SYSCALL_TRACE)) ptrace_report_syscall_exit(task_pt_regs(current), 0); } + +#if defined(CONFIG_BINFMT_ELF_FDPIC) && defined(CONFIG_ELF_CORE) +/* + * Currently the only thing that needs to use regsets for m68k is the + * coredump support of the elf_fdpic loader. Implement the minimum + * definitions required for that. + */ +static int m68k_regset_get(struct task_struct *target, + const struct user_regset *regset, + struct membuf to) +{ + struct pt_regs *ptregs = task_pt_regs(target); + u32 uregs[ELF_NGREG]; + + ELF_CORE_COPY_REGS(uregs, ptregs); + return membuf_write(&to, uregs, sizeof(uregs)); +} + +enum m68k_regset { + REGSET_GPR, +#ifdef CONFIG_FPU + REGSET_FPU, +#endif +}; + +static const struct user_regset m68k_user_regsets[] = { + [REGSET_GPR] = { + .core_note_type = NT_PRSTATUS, + .n = ELF_NGREG, + .size = sizeof(u32), + .align = sizeof(u16), + .regset_get = m68k_regset_get, + }, +#ifdef CONFIG_FPU + [REGSET_FPU] = { + .core_note_type = NT_PRFPREG, + .n = sizeof(struct user_m68kfp_struct) / sizeof(u32), + .size = sizeof(u32), + .align = sizeof(u32), + } +#endif /* CONFIG_FPU */ +}; + +static const struct user_regset_view user_m68k_view = { + .name = "m68k", + .e_machine = EM_68K, + .ei_osabi = ELF_OSABI, + .regsets = m68k_user_regsets, + .n = ARRAY_SIZE(m68k_user_regsets) +}; + +const struct user_regset_view *task_user_regset_view(struct task_struct *task) +{ + return &user_m68k_view; +} +#endif /* CONFIG_BINFMT_ELF_FDPIC && CONFIG_ELF_CORE */ diff --git a/arch/m68k/kernel/setup_mm.c b/arch/m68k/kernel/setup_mm.c index 78ab562beb315f87b9abb7aed46db92056c1074a..e62fa8f2149b3574df6bed602e28571aa7d73d0c 100644 --- a/arch/m68k/kernel/setup_mm.c +++ b/arch/m68k/kernel/setup_mm.c @@ -87,18 +87,8 @@ void (*mach_sched_init) (void) __initdata = NULL; void (*mach_init_IRQ) (void) __initdata = NULL; void (*mach_get_model) (char *model); void (*mach_get_hardware_list) (struct seq_file *m); -/* machine dependent timer functions */ -int (*mach_hwclk) (int, struct rtc_time*); -EXPORT_SYMBOL(mach_hwclk); -unsigned int (*mach_get_ss)(void); -int (*mach_get_rtc_pll)(struct rtc_pll_info *); -int (*mach_set_rtc_pll)(struct rtc_pll_info *); -EXPORT_SYMBOL(mach_get_ss); -EXPORT_SYMBOL(mach_get_rtc_pll); -EXPORT_SYMBOL(mach_set_rtc_pll); void (*mach_reset)( void ); void (*mach_halt)( void ); -void (*mach_power_off)( void ); #ifdef CONFIG_HEARTBEAT void (*mach_heartbeat) (int); EXPORT_SYMBOL(mach_heartbeat); diff --git a/arch/m68k/kernel/setup_no.c b/arch/m68k/kernel/setup_no.c index 5e4104f07a4430b4e65add06c7eaca5ba6f7a68b..cb6def585851e6c2fb9b3055239eecf612b377a4 100644 --- a/arch/m68k/kernel/setup_no.c +++ b/arch/m68k/kernel/setup_no.c @@ -50,12 +50,10 @@ char __initdata command_line[COMMAND_LINE_SIZE]; /* machine dependent timer functions */ void (*mach_sched_init)(void) __initdata = NULL; -int (*mach_hwclk) (int, struct rtc_time*); /* machine dependent reboot functions */ void (*mach_reset)(void); void (*mach_halt)(void); -void (*mach_power_off)(void); #ifdef CONFIG_M68000 #if defined(CONFIG_M68328) diff --git a/arch/m68k/kernel/time.c b/arch/m68k/kernel/time.c index 340ffeea0a9dcf323da1c273d5e959f1afc9281f..a97600b2af5021df6243c6e609b8aa8a0c2ba4e3 100644 --- a/arch/m68k/kernel/time.c +++ b/arch/m68k/kernel/time.c @@ -63,6 +63,15 @@ void timer_heartbeat(void) #endif /* CONFIG_HEARTBEAT */ #ifdef CONFIG_M68KCLASSIC +/* machine dependent timer functions */ +int (*mach_hwclk) (int, struct rtc_time*); +EXPORT_SYMBOL(mach_hwclk); + +int (*mach_get_rtc_pll)(struct rtc_pll_info *); +int (*mach_set_rtc_pll)(struct rtc_pll_info *); +EXPORT_SYMBOL(mach_get_rtc_pll); +EXPORT_SYMBOL(mach_set_rtc_pll); + #if !IS_BUILTIN(CONFIG_RTC_DRV_GENERIC) void read_persistent_clock64(struct timespec64 *ts) { diff --git a/arch/m68k/mac/config.c b/arch/m68k/mac/config.c index 65d124ec80bb6ec28fa1a5103f5b24f2315d5870..382f656c29eaeef2d8280ee4c5423f65cd0e1f7b 100644 --- a/arch/m68k/mac/config.c +++ b/arch/m68k/mac/config.c @@ -12,6 +12,7 @@ #include #include +#include #include #include #include @@ -140,7 +141,6 @@ void __init config_mac(void) mach_hwclk = mac_hwclk; mach_reset = mac_reset; mach_halt = mac_poweroff; - mach_power_off = mac_poweroff; #if IS_ENABLED(CONFIG_INPUT_M68K_BEEP) mach_beep = mac_mksound; #endif @@ -160,6 +160,8 @@ void __init config_mac(void) if (macintosh_config->ident == MAC_MODEL_IICI) mach_l2_flush = via_l2_flush; + + register_platform_power_off(mac_poweroff); } diff --git a/arch/m68k/mm/motorola.c b/arch/m68k/mm/motorola.c index ecbe948f4c1aa9415ce054abeffa20a55237ac77..df7f797c908a2c28fc8456ce4570c7a54da822a3 100644 --- a/arch/m68k/mm/motorola.c +++ b/arch/m68k/mm/motorola.c @@ -27,7 +27,6 @@ #include #include #include -#include #ifdef CONFIG_ATARI #include #endif diff --git a/arch/m68k/q40/config.c b/arch/m68k/q40/config.c index 9237243077ceea3cbf8e2548f1ef291f0a1a8d2b..c78ee709b45879c741838102133db6cde97c24fd 100644 --- a/arch/m68k/q40/config.c +++ b/arch/m68k/q40/config.c @@ -41,7 +41,6 @@ static void q40_get_model(char *model); extern void q40_sched_init(void); static int q40_hwclk(int, struct rtc_time *); -static unsigned int q40_get_ss(void); static int q40_get_rtc_pll(struct rtc_pll_info *pll); static int q40_set_rtc_pll(struct rtc_pll_info *pll); @@ -169,7 +168,6 @@ void __init config_q40(void) mach_init_IRQ = q40_init_IRQ; mach_hwclk = q40_hwclk; - mach_get_ss = q40_get_ss; mach_get_rtc_pll = q40_get_rtc_pll; mach_set_rtc_pll = q40_set_rtc_pll; @@ -246,11 +244,6 @@ static int q40_hwclk(int op, struct rtc_time *t) return 0; } -static unsigned int q40_get_ss(void) -{ - return bcd2bin(Q40_RTC_SECS); -} - /* get and set PLL calibration of RTC clock */ #define Q40_RTC_PLL_MASK ((1<<5)-1) #define Q40_RTC_PLL_SIGN (1<<5) diff --git a/arch/m68k/virt/config.c b/arch/m68k/virt/config.c index 68d29c8b87e188409405c62599c2ed623199c015..632ba200ad425245eb22f0f73b15307e523b0cd5 100644 --- a/arch/m68k/virt/config.c +++ b/arch/m68k/virt/config.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 +#include #include #include @@ -126,5 +127,6 @@ void __init config_virt(void) mach_get_model = virt_get_model; mach_reset = virt_reset; mach_halt = virt_halt; - mach_power_off = virt_halt; + + register_platform_power_off(virt_halt); } diff --git a/arch/microblaze/include/asm/string.h b/arch/microblaze/include/asm/string.h index 34071a848b6a235a578450f75a1183ed647fbdb7..8798ad2c132af54ad27b7c0f18e20653169f1b2d 100644 --- a/arch/microblaze/include/asm/string.h +++ b/arch/microblaze/include/asm/string.h @@ -8,6 +8,7 @@ #ifdef __KERNEL__ +#ifdef CONFIG_OPT_LIB_FUNCTION #define __HAVE_ARCH_MEMSET #define __HAVE_ARCH_MEMCPY #define __HAVE_ARCH_MEMMOVE @@ -15,6 +16,7 @@ extern void *memset(void *, int, __kernel_size_t); extern void *memcpy(void *, const void *, __kernel_size_t); extern void *memmove(void *, const void *, __kernel_size_t); +#endif #endif /* __KERNEL__ */ diff --git a/arch/microblaze/kernel/kgdb.c b/arch/microblaze/kernel/kgdb.c index 130cd0f064cebcb58b8ea35bb32a53ad0f10964a..df4b9d0112e56e14da15b70e9717243a3767ad7f 100644 --- a/arch/microblaze/kernel/kgdb.c +++ b/arch/microblaze/kernel/kgdb.c @@ -31,7 +31,7 @@ #define GDB_RTLBLO 55 #define GDB_RTLBHI 56 -/* keep pvr separately because it is unchangeble */ +/* keep pvr separately because it is unchangeable */ static struct pvr_s pvr; void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs) diff --git a/arch/microblaze/lib/memcpy.c b/arch/microblaze/lib/memcpy.c index 63041fdf916d7cc02579cab81df8c8d7e8493d28..9966dce55619d56c989cce8dec415705a702c947 100644 --- a/arch/microblaze/lib/memcpy.c +++ b/arch/microblaze/lib/memcpy.c @@ -31,20 +31,7 @@ #include -#ifdef __HAVE_ARCH_MEMCPY -#ifndef CONFIG_OPT_LIB_FUNCTION -void *memcpy(void *v_dst, const void *v_src, __kernel_size_t c) -{ - const char *src = v_src; - char *dst = v_dst; - - /* Simple, byte oriented memcpy. */ - while (c--) - *dst++ = *src++; - - return v_dst; -} -#else /* CONFIG_OPT_LIB_FUNCTION */ +#ifdef CONFIG_OPT_LIB_FUNCTION void *memcpy(void *v_dst, const void *v_src, __kernel_size_t c) { const char *src = v_src; @@ -188,6 +175,5 @@ void *memcpy(void *v_dst, const void *v_src, __kernel_size_t c) return v_dst; } -#endif /* CONFIG_OPT_LIB_FUNCTION */ EXPORT_SYMBOL(memcpy); -#endif /* __HAVE_ARCH_MEMCPY */ +#endif /* CONFIG_OPT_LIB_FUNCTION */ diff --git a/arch/microblaze/lib/memmove.c b/arch/microblaze/lib/memmove.c index 9862f6b1e59d232824454a9a6a8c2749b6c72cde..c1f08c484e20442386c906f6a453625bdbf128ce 100644 --- a/arch/microblaze/lib/memmove.c +++ b/arch/microblaze/lib/memmove.c @@ -30,31 +30,7 @@ #include #include -#ifdef __HAVE_ARCH_MEMMOVE -#ifndef CONFIG_OPT_LIB_FUNCTION -void *memmove(void *v_dst, const void *v_src, __kernel_size_t c) -{ - const char *src = v_src; - char *dst = v_dst; - - if (!c) - return v_dst; - - /* Use memcpy when source is higher than dest */ - if (v_dst <= v_src) - return memcpy(v_dst, v_src, c); - - /* copy backwards, from end to beginning */ - src += c; - dst += c; - - /* Simple, byte oriented memmove. */ - while (c--) - *--dst = *--src; - - return v_dst; -} -#else /* CONFIG_OPT_LIB_FUNCTION */ +#ifdef CONFIG_OPT_LIB_FUNCTION void *memmove(void *v_dst, const void *v_src, __kernel_size_t c) { const char *src = v_src; @@ -102,7 +78,7 @@ void *memmove(void *v_dst, const void *v_src, __kernel_size_t c) i_dst = (void *)dst; /* Choose a copy scheme based on the source */ - /* alignment relative to dstination. */ + /* alignment relative to destination. */ switch ((unsigned long)src & 3) { case 0x0: /* Both byte offsets are aligned */ @@ -215,6 +191,5 @@ void *memmove(void *v_dst, const void *v_src, __kernel_size_t c) } return v_dst; } -#endif /* CONFIG_OPT_LIB_FUNCTION */ EXPORT_SYMBOL(memmove); -#endif /* __HAVE_ARCH_MEMMOVE */ +#endif /* CONFIG_OPT_LIB_FUNCTION */ diff --git a/arch/microblaze/lib/memset.c b/arch/microblaze/lib/memset.c index eb6c8988af0271afbf7187610ed4820755948fae..7c2352d56bb0eb96519582f9510015e047cc13a8 100644 --- a/arch/microblaze/lib/memset.c +++ b/arch/microblaze/lib/memset.c @@ -30,22 +30,7 @@ #include #include -#ifdef __HAVE_ARCH_MEMSET -#ifndef CONFIG_OPT_LIB_FUNCTION -void *memset(void *v_src, int c, __kernel_size_t n) -{ - char *src = v_src; - - /* Truncate c to 8 bits */ - c = (c & 0xFF); - - /* Simple, byte oriented memset or the rest of count. */ - while (n--) - *src++ = c; - - return v_src; -} -#else /* CONFIG_OPT_LIB_FUNCTION */ +#ifdef CONFIG_OPT_LIB_FUNCTION void *memset(void *v_src, int c, __kernel_size_t n) { char *src = v_src; @@ -89,11 +74,21 @@ void *memset(void *v_src, int c, __kernel_size_t n) } /* Simple, byte oriented memset or the rest of count. */ - while (n--) + switch (n) { + case 3: + *src++ = c; + fallthrough; + case 2: *src++ = c; + fallthrough; + case 1: + *src++ = c; + break; + default: + break; + } return v_src; } -#endif /* CONFIG_OPT_LIB_FUNCTION */ EXPORT_SYMBOL(memset); -#endif /* __HAVE_ARCH_MEMSET */ +#endif /* CONFIG_OPT_LIB_FUNCTION */ diff --git a/arch/microblaze/mm/init.c b/arch/microblaze/mm/init.c index 952f35b335b261ddd49ddf5c28f7c4ea69f08494..f4e503461d24467e763b07f98333c90fcbf50247 100644 --- a/arch/microblaze/mm/init.c +++ b/arch/microblaze/mm/init.c @@ -13,6 +13,7 @@ #include #include /* mem_init */ #include +#include #include #include #include @@ -261,8 +262,12 @@ asmlinkage void __init mmu_init(void) parse_early_param(); + early_init_fdt_scan_reserved_mem(); + /* CMA initialization */ dma_contiguous_reserve(memory_start + lowmem_size - 1); + + memblock_dump_all(); } void * __ref zalloc_maybe_bootmem(size_t size, gfp_t mask) diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index de3b32a507d230cad6ae9659d33ce7b61c5d6808..db09d45d59ec751486224f3af38524d0875ed3a0 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -1321,11 +1321,11 @@ config CPU_LOONGSON64 select SWIOTLB select HAVE_KVM help - The Loongson GSx64(GS264/GS464/GS464E/GS464V) series of processor - cores implements the MIPS64R2 instruction set with many extensions, - including most 64-bit Loongson-2 (2H, 2K) and Loongson-3 (3A1000, - 3B1000, 3B1500, 3A2000, 3A3000 and 3A4000) processors. However, old - Loongson-2E/2F is not covered here and will be removed in future. + The Loongson GSx64(GS264/GS464/GS464E/GS464V) series of processor + cores implements the MIPS64R2 instruction set with many extensions, + including most 64-bit Loongson-2 (2H, 2K) and Loongson-3 (3A1000, + 3B1000, 3B1500, 3A2000, 3A3000 and 3A4000) processors. However, old + Loongson-2E/2F is not covered here and will be removed in future. config LOONGSON3_ENHANCEMENT bool "New Loongson-3 CPU Enhancements" @@ -3198,16 +3198,12 @@ config MIPS32_COMPAT config COMPAT bool -config SYSVIPC_COMPAT - bool - config MIPS32_O32 bool "Kernel support for o32 binaries" depends on 64BIT select ARCH_WANT_OLD_COMPAT_IPC select COMPAT select MIPS32_COMPAT - select SYSVIPC_COMPAT if SYSVIPC help Select this option if you want to run o32 binaries. These are pure 32-bit binaries as used by the 32-bit Linux/MIPS port. Most of @@ -3221,7 +3217,6 @@ config MIPS32_N32 select ARCH_WANT_COMPAT_IPC_PARSE_VERSION select COMPAT select MIPS32_COMPAT - select SYSVIPC_COMPAT if SYSVIPC help Select this option if you want to run n32 binaries. These are 64-bit binaries using 32-bit quantities for addressing and certain @@ -3255,7 +3250,7 @@ menu "CPU Power Management" if CPU_SUPPORTS_CPUFREQ && MIPS_EXTERNAL_TIMER source "drivers/cpufreq/Kconfig" -endif +endif # CPU_SUPPORTS_CPUFREQ && MIPS_EXTERNAL_TIMER source "drivers/cpuidle/Kconfig" diff --git a/arch/mips/alchemy/common/dbdma.c b/arch/mips/alchemy/common/dbdma.c index 4ca2c28878e0f7bc970975e75b9458fd3d4ddd8f..5ab0430004092900cb8a7de8013031ff18d862fe 100644 --- a/arch/mips/alchemy/common/dbdma.c +++ b/arch/mips/alchemy/common/dbdma.c @@ -574,7 +574,7 @@ u32 au1xxx_dbdma_ring_alloc(u32 chanid, int entries) dp++; } - /* Make last descrptor point to the first. */ + /* Make last descriptor point to the first. */ dp--; dp->dscr_nxtptr = DSCR_NXTPTR(virt_to_phys(ctp->chan_desc_base)); ctp->get_ptr = ctp->put_ptr = ctp->cur_ptr = ctp->chan_desc_base; diff --git a/arch/mips/bmips/dma.c b/arch/mips/bmips/dma.c index c535f9cb75ec86572e7e34c42b3bad50d33b318e..33788668cbdbfc3ab12862e5f3b8874b15af1ea7 100644 --- a/arch/mips/bmips/dma.c +++ b/arch/mips/bmips/dma.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0+ #include +#include #include #include diff --git a/arch/mips/boot/dts/brcm/bcm97358svmb.dts b/arch/mips/boot/dts/brcm/bcm97358svmb.dts index 522f2c40d6e6e1e5d6d263ca12302928a4bcfec2..c17fc14d4899cc2ac2336d349f29378348e03540 100644 --- a/arch/mips/boot/dts/brcm/bcm97358svmb.dts +++ b/arch/mips/boot/dts/brcm/bcm97358svmb.dts @@ -78,7 +78,7 @@ &qspi { status = "okay"; - m25p80@0 { + flash@0 { compatible = "m25p80"; reg = <0>; spi-max-frequency = <40000000>; diff --git a/arch/mips/boot/dts/brcm/bcm97360svmb.dts b/arch/mips/boot/dts/brcm/bcm97360svmb.dts index 01f215b08dba763debe6537275ea8a693714f3c7..c9b76f41e7a62321ca30ddd085e63bba7fc77de3 100644 --- a/arch/mips/boot/dts/brcm/bcm97360svmb.dts +++ b/arch/mips/boot/dts/brcm/bcm97360svmb.dts @@ -81,7 +81,7 @@ &qspi { status = "okay"; - m25p80@0 { + flash@0 { compatible = "m25p80"; reg = <0>; spi-max-frequency = <40000000>; diff --git a/arch/mips/boot/dts/brcm/bcm97425svmb.dts b/arch/mips/boot/dts/brcm/bcm97425svmb.dts index f389349343499993289ffba61393158f6298986d..289a57b912ef72b180668adea09a3f28ac61c30b 100644 --- a/arch/mips/boot/dts/brcm/bcm97425svmb.dts +++ b/arch/mips/boot/dts/brcm/bcm97425svmb.dts @@ -116,7 +116,7 @@ &qspi { status = "okay"; - m25p80@0 { + flash@0 { compatible = "m25p80"; reg = <0>; spi-max-frequency = <40000000>; diff --git a/arch/mips/boot/dts/ingenic/cu1000-neo.dts b/arch/mips/boot/dts/ingenic/cu1000-neo.dts index f98cf029efc310a1e063255beb0102c77e96b144..c89abf94e74fafbc0bf85cc840670bc9b15aecbb 100644 --- a/arch/mips/boot/dts/ingenic/cu1000-neo.dts +++ b/arch/mips/boot/dts/ingenic/cu1000-neo.dts @@ -31,42 +31,6 @@ }; }; - ssi: spi-gpio { - compatible = "spi-gpio"; - #address-cells = <1>; - #size-cells = <0>; - num-chipselects = <1>; - - mosi-gpios = <&gpd 2 GPIO_ACTIVE_HIGH>; - miso-gpios = <&gpd 3 GPIO_ACTIVE_HIGH>; - sck-gpios = <&gpd 0 GPIO_ACTIVE_HIGH>; - cs-gpios = <&gpd 1 GPIO_ACTIVE_HIGH>; - - status = "okay"; - - spi-max-frequency = <50000000>; - - sc16is752: expander@0 { - compatible = "nxp,sc16is752"; - reg = <0>; /* CE0 */ - spi-max-frequency = <4000000>; - - clocks = <&exclk_sc16is752>; - - interrupt-parent = <&gpc>; - interrupts = <6 IRQ_TYPE_EDGE_FALLING>; - - gpio-controller; - #gpio-cells = <2>; - - exclk_sc16is752: sc16is752 { - compatible = "fixed-clock"; - #clock-cells = <0>; - clock-frequency = <48000000>; - }; - }; - }; - wlan_pwrseq: msc1-pwrseq { compatible = "mmc-pwrseq-simple"; @@ -90,7 +54,7 @@ &ost { /* 1500 kHz for the system timer and clocksource */ - assigned-clocks = <&ost OST_CLK_PERCPU_TIMER>, <&ost OST_CLK_GLOBAL_TIMER>; + assigned-clocks = <&ost OST_CLK_EVENT_TIMER>, <&ost OST_CLK_GLOBAL_TIMER>; assigned-clock-rates = <1500000>, <1500000>; }; @@ -101,6 +65,39 @@ pinctrl-0 = <&pins_uart2>; }; +&ssi { + status = "okay"; + + num-cs = <2>; + cs-gpios = <0>, <&gpc 20 GPIO_ACTIVE_LOW>; + + pinctrl-names = "default"; + pinctrl-0 = <&pins_ssi>; + + sc16is752: expander@0 { + compatible = "nxp,sc16is752"; + reg = <0>; /* CE0 */ + + spi-rx-bus-width = <1>; + spi-tx-bus-width = <1>; + spi-max-frequency = <4000000>; + + clocks = <&exclk_sc16is752>; + + interrupt-parent = <&gpc>; + interrupts = <6 IRQ_TYPE_EDGE_FALLING>; + + gpio-controller; + #gpio-cells = <2>; + + exclk_sc16is752: sc16is752 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <48000000>; + }; + }; +}; + &i2c0 { status = "okay"; @@ -192,6 +189,12 @@ bias-pull-up; }; + pins_ssi: ssi { + function = "ssi"; + groups = "ssi-dt-d", "ssi-dr-d", "ssi-clk-d", "ssi-ce0-d"; + bias-disable; + }; + pins_i2c0: i2c0 { function = "i2c0"; groups = "i2c0-data"; diff --git a/arch/mips/boot/dts/ingenic/cu1830-neo.dts b/arch/mips/boot/dts/ingenic/cu1830-neo.dts index cfcb40edb7d95fc71c9ddb14fba781ad3499f413..3c7784983332dc461c60e3383ec128da171771f1 100644 --- a/arch/mips/boot/dts/ingenic/cu1830-neo.dts +++ b/arch/mips/boot/dts/ingenic/cu1830-neo.dts @@ -31,42 +31,6 @@ }; }; - ssi0: spi-gpio { - compatible = "spi-gpio"; - #address-cells = <1>; - #size-cells = <0>; - num-chipselects = <1>; - - mosi-gpios = <&gpc 12 GPIO_ACTIVE_HIGH>; - miso-gpios = <&gpc 11 GPIO_ACTIVE_HIGH>; - sck-gpios = <&gpc 15 GPIO_ACTIVE_HIGH>; - cs-gpios = <&gpc 16 GPIO_ACTIVE_HIGH>; - - status = "okay"; - - spi-max-frequency = <50000000>; - - sc16is752: expander@0 { - compatible = "nxp,sc16is752"; - reg = <0>; /* CE0 */ - spi-max-frequency = <4000000>; - - clocks = <&exclk_sc16is752>; - - interrupt-parent = <&gpb>; - interrupts = <18 IRQ_TYPE_EDGE_FALLING>; - - gpio-controller; - #gpio-cells = <2>; - - exclk_sc16is752: sc16is752 { - compatible = "fixed-clock"; - #clock-cells = <0>; - clock-frequency = <48000000>; - }; - }; - }; - wlan_pwrseq: msc1-pwrseq { compatible = "mmc-pwrseq-simple"; @@ -90,7 +54,7 @@ &ost { /* 1500 kHz for the system timer and clocksource */ - assigned-clocks = <&ost OST_CLK_PERCPU_TIMER>, <&ost OST_CLK_GLOBAL_TIMER>; + assigned-clocks = <&ost OST_CLK_EVENT_TIMER>, <&ost OST_CLK_GLOBAL_TIMER>; assigned-clock-rates = <1500000>, <1500000>; }; @@ -101,6 +65,38 @@ pinctrl-0 = <&pins_uart1>; }; +&ssi0 { + status = "okay"; + + num-cs = <2>; + + pinctrl-names = "default"; + pinctrl-0 = <&pins_ssi0>; + + sc16is752: expander@0 { + compatible = "nxp,sc16is752"; + reg = <0>; /* CE0 */ + + spi-rx-bus-width = <1>; + spi-tx-bus-width = <1>; + spi-max-frequency = <4000000>; + + clocks = <&exclk_sc16is752>; + + interrupt-parent = <&gpb>; + interrupts = <18 IRQ_TYPE_EDGE_FALLING>; + + gpio-controller; + #gpio-cells = <2>; + + exclk_sc16is752: sc16is752 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <48000000>; + }; + }; +}; + &i2c0 { status = "okay"; @@ -196,6 +192,12 @@ bias-pull-up; }; + pins_ssi0: ssi0 { + function = "ssi0"; + groups = "ssi0-dt", "ssi0-dr", "ssi0-clk", "ssi0-ce0", "ssi0-ce1"; + bias-disable; + }; + pins_i2c0: i2c0 { function = "i2c0"; groups = "i2c0-data"; diff --git a/arch/mips/boot/dts/ingenic/x1000.dtsi b/arch/mips/boot/dts/ingenic/x1000.dtsi index 8bd27edef216b5e5ae6acbcf270e259951e4d09d..ecbfed49dc77088ca404695ae369c6a9243f494e 100644 --- a/arch/mips/boot/dts/ingenic/x1000.dtsi +++ b/arch/mips/boot/dts/ingenic/x1000.dtsi @@ -127,6 +127,18 @@ clocks = <&tcu TCU_CLK_WDT>; clock-names = "wdt"; }; + + pwm: pwm@40 { + compatible = "ingenic,x1000-pwm"; + reg = <0x40 0x50>; + + #pwm-cells = <3>; + + clocks = <&tcu TCU_CLK_TIMER0>, <&tcu TCU_CLK_TIMER1>, + <&tcu TCU_CLK_TIMER2>, <&tcu TCU_CLK_TIMER3>, + <&tcu TCU_CLK_TIMER4>; + clock-names = "timer0", "timer1", "timer2", "timer3", "timer4"; + }; }; rtc: rtc@10003000 { @@ -246,6 +258,25 @@ status = "disabled"; }; + ssi: spi@10043000 { + compatible = "ingenic,x1000-spi"; + reg = <0x10043000 0x20>; + #address-cells = <1>; + #size-cells = <0>; + + interrupt-parent = <&intc>; + interrupts = <8>; + + clocks = <&cgu X1000_CLK_SSI>; + clock-names = "spi"; + + dmas = <&pdma X1000_DMA_SSI0_RX 0xffffffff>, + <&pdma X1000_DMA_SSI0_TX 0xffffffff>; + dma-names = "rx", "tx"; + + status = "disabled"; + }; + i2c0: i2c-controller@10050000 { compatible = "ingenic,x1000-i2c"; reg = <0x10050000 0x1000>; @@ -291,6 +322,7 @@ pdma: dma-controller@13420000 { compatible = "ingenic,x1000-dma"; reg = <0x13420000 0x400>, <0x13421000 0x40>; + #dma-cells = <2>; interrupt-parent = <&intc>; diff --git a/arch/mips/boot/dts/ingenic/x1830.dtsi b/arch/mips/boot/dts/ingenic/x1830.dtsi index 2595df8671c7650a198c342219cbe88a39f1c32b..efd556902cfd06ea4711cec58e1075a5db29e067 100644 --- a/arch/mips/boot/dts/ingenic/x1830.dtsi +++ b/arch/mips/boot/dts/ingenic/x1830.dtsi @@ -120,6 +120,20 @@ clocks = <&tcu TCU_CLK_WDT>; clock-names = "wdt"; }; + + pwm: pwm@40 { + compatible = "ingenic,x1830-pwm", "ingenic,jz4740-pwm"; + reg = <0x40 0x80>; + + #pwm-cells = <3>; + + clocks = <&tcu TCU_CLK_TIMER0>, <&tcu TCU_CLK_TIMER1>, + <&tcu TCU_CLK_TIMER2>, <&tcu TCU_CLK_TIMER3>, + <&tcu TCU_CLK_TIMER4>, <&tcu TCU_CLK_TIMER5>, + <&tcu TCU_CLK_TIMER6>, <&tcu TCU_CLK_TIMER7>; + clock-names = "timer0", "timer1", "timer2", "timer3", + "timer4", "timer5", "timer6", "timer7"; + }; }; rtc: rtc@10003000 { @@ -226,6 +240,44 @@ status = "disabled"; }; + ssi0: spi@10043000 { + compatible = "ingenic,x1830-spi", "ingenic,x1000-spi"; + reg = <0x10043000 0x20>; + #address-cells = <1>; + #size-cells = <0>; + + interrupt-parent = <&intc>; + interrupts = <9>; + + clocks = <&cgu X1830_CLK_SSI0>; + clock-names = "spi"; + + dmas = <&pdma X1830_DMA_SSI0_RX 0xffffffff>, + <&pdma X1830_DMA_SSI0_TX 0xffffffff>; + dma-names = "rx", "tx"; + + status = "disabled"; + }; + + ssi1: spi@10044000 { + compatible = "ingenic,x1830-spi", "ingenic,x1000-spi"; + reg = <0x10044000 0x20>; + #address-cells = <1>; + #size-cells = <0>; + + interrupt-parent = <&intc>; + interrupts = <8>; + + clocks = <&cgu X1830_CLK_SSI1>; + clock-names = "spi"; + + dmas = <&pdma X1830_DMA_SSI1_RX 0xffffffff>, + <&pdma X1830_DMA_SSI1_TX 0xffffffff>; + dma-names = "rx", "tx"; + + status = "disabled"; + }; + i2c0: i2c-controller@10050000 { compatible = "ingenic,x1830-i2c", "ingenic,x1000-i2c"; reg = <0x10050000 0x1000>; @@ -280,6 +332,7 @@ pdma: dma-controller@13420000 { compatible = "ingenic,x1830-dma"; reg = <0x13420000 0x400>, <0x13421000 0x40>; + #dma-cells = <2>; interrupt-parent = <&intc>; diff --git a/arch/mips/boot/dts/mscc/jaguar2_pcb110.dts b/arch/mips/boot/dts/mscc/jaguar2_pcb110.dts index d80cd6842b2ad367c4592eaa781891e6bbccddb3..0ea7bc5b5746842ff616ec663226064440906081 100644 --- a/arch/mips/boot/dts/mscc/jaguar2_pcb110.dts +++ b/arch/mips/boot/dts/mscc/jaguar2_pcb110.dts @@ -180,27 +180,27 @@ pins = "GPIO_49"; function = "si"; }; - i2cmux_pins_i: i2cmux-pins-i { + i2cmux_pins_i: i2cmux-pins { pins = "GPIO_17", "GPIO_18", "GPIO_20", "GPIO_21"; function = "twi_scl_m"; output-low; }; - i2cmux_0: i2cmux-0 { + i2cmux_0: i2cmux-0-pins { pins = "GPIO_17"; function = "twi_scl_m"; output-high; }; - i2cmux_1: i2cmux-1 { + i2cmux_1: i2cmux-1-pins { pins = "GPIO_18"; function = "twi_scl_m"; output-high; }; - i2cmux_2: i2cmux-2 { + i2cmux_2: i2cmux-2-pins { pins = "GPIO_20"; function = "twi_scl_m"; output-high; }; - i2cmux_3: i2cmux-3 { + i2cmux_3: i2cmux-3-pins { pins = "GPIO_21"; function = "twi_scl_m"; output-high; diff --git a/arch/mips/boot/dts/mscc/jaguar2_pcb111.dts b/arch/mips/boot/dts/mscc/jaguar2_pcb111.dts index 813c5e16013caf355955f578ced94ff2022f9c59..05d8c6a96dc4c8c62d8294cffded2ab9ca84797d 100644 --- a/arch/mips/boot/dts/mscc/jaguar2_pcb111.dts +++ b/arch/mips/boot/dts/mscc/jaguar2_pcb111.dts @@ -79,27 +79,27 @@ }; &gpio { - i2cmux_pins_i: i2cmux-pins-i { + i2cmux_pins_i: i2cmux-pins { pins = "GPIO_17", "GPIO_18"; function = "twi_scl_m"; output-low; }; - i2cmux_0: i2cmux-0 { + i2cmux_0: i2cmux-0-pins { pins = "GPIO_17"; function = "twi_scl_m"; output-high; }; - i2cmux_1: i2cmux-1 { + i2cmux_1: i2cmux-1-pins { pins = "GPIO_18"; function = "twi_scl_m"; output-high; }; - i2cmux_2: i2cmux-2 { + i2cmux_2: i2cmux-2-pins { pins = "GPIO_20"; function = "twi_scl_m"; output-high; }; - i2cmux_3: i2cmux-3 { + i2cmux_3: i2cmux-3-pins { pins = "GPIO_21"; function = "twi_scl_m"; output-high; diff --git a/arch/mips/boot/dts/mscc/jaguar2_pcb118.dts b/arch/mips/boot/dts/mscc/jaguar2_pcb118.dts index 27c644f2d17f94cf8a9e60c9194fa1ac9fff18ab..cf2cf591a211b37d0432d0404591474a90d5e9e0 100644 --- a/arch/mips/boot/dts/mscc/jaguar2_pcb118.dts +++ b/arch/mips/boot/dts/mscc/jaguar2_pcb118.dts @@ -39,17 +39,17 @@ }; &gpio { - i2cmux_pins_i: i2cmux-pins-i { + i2cmux_pins_i: i2cmux-pins { pins = "GPIO_17", "GPIO_16"; function = "twi_scl_m"; output-low; }; - i2cmux_0: i2cmux-0 { + i2cmux_0: i2cmux-0-pins { pins = "GPIO_17"; function = "twi_scl_m"; output-high; }; - i2cmux_1: i2cmux-1 { + i2cmux_1: i2cmux-1-pins { pins = "GPIO_16"; function = "twi_scl_m"; output-high; diff --git a/arch/mips/boot/dts/mscc/ocelot.dtsi b/arch/mips/boot/dts/mscc/ocelot.dtsi index e51db651af131abf76b1e96db0104b795b5e7743..cfc219a72bddf2454dde64891e01688a37a867a0 100644 --- a/arch/mips/boot/dts/mscc/ocelot.dtsi +++ b/arch/mips/boot/dts/mscc/ocelot.dtsi @@ -225,7 +225,7 @@ function = "uart2"; }; - miim1: miim1 { + miim1_pins: miim1-pins { pins = "GPIO_14", "GPIO_15"; function = "miim"; }; @@ -261,7 +261,7 @@ reg = <0x10700c0 0x24>; interrupts = <15>; pinctrl-names = "default"; - pinctrl-0 = <&miim1>; + pinctrl-0 = <&miim1_pins>; status = "disabled"; }; diff --git a/arch/mips/boot/dts/mscc/ocelot_pcb120.dts b/arch/mips/boot/dts/mscc/ocelot_pcb120.dts index bd240690cb37edf208670c0de6825c6ab84d9a93..d348742c233db6e7a54ec3db79f1ffc3a4754283 100644 --- a/arch/mips/boot/dts/mscc/ocelot_pcb120.dts +++ b/arch/mips/boot/dts/mscc/ocelot_pcb120.dts @@ -22,12 +22,12 @@ }; &gpio { - phy_int_pins: phy_int_pins { + phy_int_pins: phy-int-pins { pins = "GPIO_4"; function = "gpio"; }; - phy_load_save_pins: phy_load_save_pins { + phy_load_save_pins: phy-load-save-pins { pins = "GPIO_10"; function = "ptp2"; }; @@ -40,7 +40,7 @@ &mdio1 { status = "okay"; pinctrl-names = "default"; - pinctrl-0 = <&miim1>, <&phy_int_pins>, <&phy_load_save_pins>; + pinctrl-0 = <&miim1_pins>, <&phy_int_pins>, <&phy_load_save_pins>; phy7: ethernet-phy@0 { reg = <0>; diff --git a/arch/mips/boot/dts/mscc/serval_common.dtsi b/arch/mips/boot/dts/mscc/serval_common.dtsi index 5b404836db5e67b0332d2c289dc7eb60ff932d94..0893de420e2750c1b3714cf616b437a72c572288 100644 --- a/arch/mips/boot/dts/mscc/serval_common.dtsi +++ b/arch/mips/boot/dts/mscc/serval_common.dtsi @@ -82,38 +82,38 @@ pins = "GPIO_7"; /* No "default" scl for i2c0 */ function = "twi"; }; - i2cmux_pins_i: i2cmux-pins-i { + i2cmux_pins_i: i2cmux-pins { pins = "GPIO_11", "GPIO_12", "GPIO_18", "GPIO_19", "GPIO_20", "GPIO_21"; function = "twi_scl_m"; output-low; }; - i2cmux_0: i2cmux-0 { + i2cmux_0: i2cmux-0-pins { pins = "GPIO_11"; function = "twi_scl_m"; output-high; }; - i2cmux_1: i2cmux-1 { + i2cmux_1: i2cmux-1-pins { pins = "GPIO_12"; function = "twi_scl_m"; output-high; }; - i2cmux_2: i2cmux-2 { + i2cmux_2: i2cmux-2-pins { pins = "GPIO_18"; function = "twi_scl_m"; output-high; }; - i2cmux_3: i2cmux-3 { + i2cmux_3: i2cmux-3-pins { pins = "GPIO_19"; function = "twi_scl_m"; output-high; }; - i2cmux_4: i2cmux-4 { + i2cmux_4: i2cmux-4-pins { pins = "GPIO_20"; function = "twi_scl_m"; output-high; }; - i2cmux_5: i2cmux-5 { + i2cmux_5: i2cmux-5-pins { pins = "GPIO_21"; function = "twi_scl_m"; output-high; diff --git a/arch/mips/boot/dts/ralink/gardena_smart_gateway_mt7688.dts b/arch/mips/boot/dts/ralink/gardena_smart_gateway_mt7688.dts index 6069b33cf09f202fed0561e3c58602d9e76ba1e5..826e91b840a3399a6152f7008222e5d0c58e4213 100644 --- a/arch/mips/boot/dts/ralink/gardena_smart_gateway_mt7688.dts +++ b/arch/mips/boot/dts/ralink/gardena_smart_gateway_mt7688.dts @@ -129,7 +129,7 @@ pinctrl-names = "default"; pinctrl-0 = <&pinmux_spi_spi>, <&pinmux_spi_cs1_cs>; - m25p80@0 { + flash@0 { compatible = "jedec,spi-nor"; reg = <0>; spi-max-frequency = <40000000>; diff --git a/arch/mips/boot/dts/ralink/mt7621-gnubee-gb-pc1.dts b/arch/mips/boot/dts/ralink/mt7621-gnubee-gb-pc1.dts index 5892bcf71595582b4c5acf145de29cb0f8988193..37037e4f3c3bc736fb4fc1c3a5d410e8a41b08e4 100644 --- a/arch/mips/boot/dts/ralink/mt7621-gnubee-gb-pc1.dts +++ b/arch/mips/boot/dts/ralink/mt7621-gnubee-gb-pc1.dts @@ -60,7 +60,7 @@ &spi0 { status = "okay"; - m25p80@0 { + flash@0 { #address-cells = <1>; #size-cells = <1>; compatible = "jedec,spi-nor"; @@ -97,20 +97,15 @@ status = "okay"; }; -&pinctrl { - pinctrl-names = "default"; - pinctrl-0 = <&state_default>; - - state_default: state-default { - gpio-pinmux { - groups = "rgmii2", "uart3", "wdt"; - function = "gpio"; - }; - }; +&gmac1 { + status = "okay"; + phy-handle = <ðphy4>; }; -ðernet { - pinctrl-0 = <&mdio_pins>, <&rgmii1_pins>; +&mdio { + ethphy4: ethernet-phy@4 { + reg = <4>; + }; }; &switch0 { @@ -119,10 +114,5 @@ status = "okay"; label = "ethblack"; }; - - port@4 { - status = "okay"; - label = "ethblue"; - }; }; }; diff --git a/arch/mips/boot/dts/ralink/mt7621-gnubee-gb-pc2.dts b/arch/mips/boot/dts/ralink/mt7621-gnubee-gb-pc2.dts index a7fce8de614721c0e4db32d803b91d61d9f69f4e..a6201a119a1f2674f2d1e4ada9b27518281d0f65 100644 --- a/arch/mips/boot/dts/ralink/mt7621-gnubee-gb-pc2.dts +++ b/arch/mips/boot/dts/ralink/mt7621-gnubee-gb-pc2.dts @@ -44,7 +44,7 @@ &spi0 { status = "okay"; - m25p80@0 { + flash@0 { #address-cells = <1>; #size-cells = <1>; compatible = "jedec,spi-nor"; @@ -81,29 +81,15 @@ status = "okay"; }; -&pinctrl { - pinctrl-names = "default"; - pinctrl-0 = <&state_default>; - - state_default: state-default { - gpio-pinmux { - groups = "wdt"; - function = "gpio"; - }; - }; +&gmac1 { + status = "okay"; + phy-handle = <ðphy7>; }; -ðernet { - gmac1: mac@1 { - status = "okay"; - phy-handle = <ðphy7>; - }; - - mdio-bus { - ethphy7: ethernet-phy@7 { - reg = <7>; - phy-mode = "rgmii-rxid"; - }; +&mdio { + ethphy7: ethernet-phy@7 { + reg = <7>; + phy-mode = "rgmii-rxid"; }; }; diff --git a/arch/mips/boot/dts/ralink/mt7621.dtsi b/arch/mips/boot/dts/ralink/mt7621.dtsi index 3222684915ac6010b9e4cc25187e448d0b301d6a..ee46ace0bcc11a41630e96cefd00e0628c896b88 100644 --- a/arch/mips/boot/dts/ralink/mt7621.dtsi +++ b/arch/mips/boot/dts/ralink/mt7621.dtsi @@ -151,7 +151,7 @@ }; pinctrl: pinctrl { - compatible = "ralink,rt2880-pinmux"; + compatible = "ralink,mt7621-pinctrl"; i2c_pins: i2c0-pins { pinmux { @@ -342,7 +342,7 @@ phy-mode = "rgmii-rxid"; }; - mdio-bus { + mdio: mdio-bus { #address-cells = <1>; #size-cells = <0>; diff --git a/arch/mips/boot/tools/relocs.c b/arch/mips/boot/tools/relocs.c index 1bf53f3524b3248699df9f6a18ad28e0576d6b3b..02fc85f3e8ffe60f95c9ff15db2bdfe3136b8b9c 100644 --- a/arch/mips/boot/tools/relocs.c +++ b/arch/mips/boot/tools/relocs.c @@ -351,7 +351,7 @@ static void read_symtabs(FILE *fp) static void read_relocs(FILE *fp) { - static unsigned long base = 0; + static unsigned long base; int i, j; if (!base) { diff --git a/arch/mips/cavium-octeon/executive/cvmx-bootmem.c b/arch/mips/cavium-octeon/executive/cvmx-bootmem.c index b63ad5d42cc71ca9c51e257f0eb425077567244f..306cee07ce3fe21ae3cfeb632bc772e81ab45d92 100644 --- a/arch/mips/cavium-octeon/executive/cvmx-bootmem.c +++ b/arch/mips/cavium-octeon/executive/cvmx-bootmem.c @@ -318,7 +318,7 @@ int64_t cvmx_bootmem_phy_alloc(uint64_t req_size, uint64_t address_min, } /* - * Determine if this is an entry that can satisify the + * Determine if this is an entry that can satisfy the * request Check to make sure entry is large enough to * satisfy request. */ diff --git a/arch/mips/cavium-octeon/executive/cvmx-helper-xaui.c b/arch/mips/cavium-octeon/executive/cvmx-helper-xaui.c index fea71a85bb29050f7b05d19eb9b98ef12efd1bd9..a92632223497639b30750434e13c53b9ab4e1ee5 100644 --- a/arch/mips/cavium-octeon/executive/cvmx-helper-xaui.c +++ b/arch/mips/cavium-octeon/executive/cvmx-helper-xaui.c @@ -156,8 +156,9 @@ int __cvmx_helper_xaui_enable(int interface) xauiCtl.u64 = cvmx_read_csr(CVMX_PCSXX_CONTROL1_REG(interface)); xauiCtl.s.lo_pwr = 0; - /* Issuing a reset here seems to hang some CN68XX chips. */ - if (!OCTEON_IS_MODEL(OCTEON_CN68XX_PASS1_X) && + /* Issuing a reset here seems to hang some CN66XX/CN68XX chips. */ + if (!OCTEON_IS_MODEL(OCTEON_CN66XX) && + !OCTEON_IS_MODEL(OCTEON_CN68XX_PASS1_X) && !OCTEON_IS_MODEL(OCTEON_CN68XX_PASS2_X)) xauiCtl.s.reset = 1; diff --git a/arch/mips/cavium-octeon/executive/cvmx-helper.c b/arch/mips/cavium-octeon/executive/cvmx-helper.c index b22f664e2d2978793e7556862551315171a869d9..6f49fd9be1f3cce1e7ae1a20c2b8ea42c3d5f522 100644 --- a/arch/mips/cavium-octeon/executive/cvmx-helper.c +++ b/arch/mips/cavium-octeon/executive/cvmx-helper.c @@ -61,6 +61,12 @@ int cvmx_helper_get_number_of_interfaces(void) { if (OCTEON_IS_MODEL(OCTEON_CN68XX)) return 9; + if (OCTEON_IS_MODEL(OCTEON_CN66XX)) { + if (OCTEON_IS_MODEL(OCTEON_CN66XX_PASS1_0)) + return 7; + else + return 8; + } if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN52XX)) return 4; if (OCTEON_IS_MODEL(OCTEON_CN7XXX)) diff --git a/arch/mips/cavium-octeon/executive/cvmx-pko.c b/arch/mips/cavium-octeon/executive/cvmx-pko.c index ae8806e7bce2cedc376b45b3a52d19e78b8579b2..15faca494c80720c120569463b4da3ade29e3c9f 100644 --- a/arch/mips/cavium-octeon/executive/cvmx-pko.c +++ b/arch/mips/cavium-octeon/executive/cvmx-pko.c @@ -377,7 +377,7 @@ cvmx_pko_status_t cvmx_pko_config_port(uint64_t port, uint64_t base_queue, /* * Check to make sure all static priority * queues are contiguous. Also catches some - * cases of static priorites not starting at + * cases of static priorities not starting at * queue 0. */ if (static_priority_end != -1 diff --git a/arch/mips/cavium-octeon/octeon-irq.c b/arch/mips/cavium-octeon/octeon-irq.c index 07d7ff5a981d3ca8e6780f2129426c6a6fca2309..6cdcbf4de7632fa0a8065b5e79f2460d8ef871c5 100644 --- a/arch/mips/cavium-octeon/octeon-irq.c +++ b/arch/mips/cavium-octeon/octeon-irq.c @@ -1405,7 +1405,7 @@ static void octeon_irq_init_ciu2_percpu(void) * completed. * * There are 9 registers and 3 IPX levels with strides 0x1000 - * and 0x200 respectivly. Use loops to clear them. + * and 0x200 respectively. Use loops to clear them. */ for (regx = 0; regx <= 0x8000; regx += 0x1000) { for (ipx = 0; ipx <= 0x400; ipx += 0x200) diff --git a/arch/mips/cavium-octeon/octeon-usb.c b/arch/mips/cavium-octeon/octeon-usb.c index 4df919d26b0820a4912e237e3191bfcc46f5bda7..5cffe1ed2447ed15e472ec03a3d87a54f34949dd 100644 --- a/arch/mips/cavium-octeon/octeon-usb.c +++ b/arch/mips/cavium-octeon/octeon-usb.c @@ -419,7 +419,7 @@ static int dwc3_octeon_clocks_start(struct device *dev, u64 base) /* Step 5c: Enable SuperSpeed. */ uctl_ctl.s.ref_ssp_en = 1; - /* Step 5d: Cofngiure PHYs. SKIP */ + /* Step 5d: Configure PHYs. SKIP */ /* Step 6a & 6b: Power up PHYs. */ uctl_ctl.s.hs_power_en = 1; diff --git a/arch/mips/configs/cu1000-neo_defconfig b/arch/mips/configs/cu1000-neo_defconfig index 9d75f5b77d5d7a8e48ca57b4555a72875830aa5e..5bd55eb32fe55ec256263018312b44b312a419fd 100644 --- a/arch/mips/configs/cu1000-neo_defconfig +++ b/arch/mips/configs/cu1000-neo_defconfig @@ -61,7 +61,7 @@ CONFIG_SERIAL_SC16IS7XX_SPI=y CONFIG_I2C=y CONFIG_I2C_JZ4780=y CONFIG_SPI=y -CONFIG_SPI_GPIO=y +CONFIG_SPI_INGENIC=y CONFIG_GPIO_SYSFS=y CONFIG_SENSORS_ADS7828=m CONFIG_WATCHDOG=y diff --git a/arch/mips/configs/cu1830-neo_defconfig b/arch/mips/configs/cu1830-neo_defconfig index 29decd0003c633cac82eff51c8c7301d13313029..cc69688962e8c348131a0ef4f730ff673958db6c 100644 --- a/arch/mips/configs/cu1830-neo_defconfig +++ b/arch/mips/configs/cu1830-neo_defconfig @@ -64,7 +64,7 @@ CONFIG_SERIAL_SC16IS7XX_SPI=y CONFIG_I2C=y CONFIG_I2C_JZ4780=y CONFIG_SPI=y -CONFIG_SPI_GPIO=y +CONFIG_SPI_INGENIC=y CONFIG_GPIO_SYSFS=y CONFIG_SENSORS_ADS7828=m CONFIG_WATCHDOG=y diff --git a/arch/mips/dec/ioasic-irq.c b/arch/mips/dec/ioasic-irq.c index 130eb67bd3c9e7f0db905fd72c6d472b6e154f0e..971f7b46759be33b56443eb04e9258c987a34d11 100644 --- a/arch/mips/dec/ioasic-irq.c +++ b/arch/mips/dec/ioasic-irq.c @@ -68,13 +68,13 @@ static struct irq_chip ioasic_dma_irq_type = { * I/O ASIC implements two kinds of DMA interrupts, informational and * error interrupts. * - * The formers do not stop DMA and should be cleared as soon as possible + * The former do not stop DMA and should be cleared as soon as possible * so that if they retrigger before the handler has completed, usually as * a side effect of actions taken by the handler, then they are reissued. * These use the `handle_edge_irq' handler that clears the request right * away. * - * The latters stop DMA and do not resume it until the interrupt has been + * The latter stop DMA and do not resume it until the interrupt has been * cleared. This cannot be done until after a corrective action has been * taken and this also means they will not retrigger. Therefore they use * the `handle_fasteoi_irq' handler that only clears the request on the diff --git a/arch/mips/dec/setup.c b/arch/mips/dec/setup.c index 82b00e45ce50a78cf48421ac15582e58d1c5915f..6c3704f51d0de40fee5f851dcc76420bec39123b 100644 --- a/arch/mips/dec/setup.c +++ b/arch/mips/dec/setup.c @@ -71,7 +71,7 @@ volatile u32 *ioasic_base; EXPORT_SYMBOL(ioasic_base); /* - * IRQ routing and priority tables. Priorites are set as follows: + * IRQ routing and priority tables. Priorities are set as follows: * * KN01 KN230 KN02 KN02-BA KN02-CA KN03 * diff --git a/arch/mips/fw/arc/memory.c b/arch/mips/fw/arc/memory.c index ef5fc1ca1b5d4874d3ed976db698e4f484ebd088..66188739f54d20a41ce18acb0a88a4fdf16e8718 100644 --- a/arch/mips/fw/arc/memory.c +++ b/arch/mips/fw/arc/memory.c @@ -32,7 +32,7 @@ static phys_addr_t prom_mem_size[MAX_PROM_MEM] __initdata; static unsigned int nr_prom_mem __initdata; /* - * For ARC firmware memory functions the unit of meassuring memory is always + * For ARC firmware memory functions the unit of measuring memory is always * a 4k page of memory */ #define ARC_PAGE_SHIFT 12 diff --git a/arch/mips/generic/board-ingenic.c b/arch/mips/generic/board-ingenic.c index 3f44f14bdb33f255dcfa18ab8f4f69f71a667a9b..c422bbc890eda3f2ceb0455260058f2d8a0907b0 100644 --- a/arch/mips/generic/board-ingenic.c +++ b/arch/mips/generic/board-ingenic.c @@ -131,36 +131,10 @@ static const struct platform_suspend_ops ingenic_pm_ops __maybe_unused = { static int __init ingenic_pm_init(void) { - struct device_node *cpu_node; - struct clk *cpu0_clk; - int ret; - if (boot_cpu_type() == CPU_XBURST) { if (IS_ENABLED(CONFIG_PM_SLEEP)) suspend_set_ops(&ingenic_pm_ops); _machine_halt = ingenic_halt; - - /* - * Unconditionally enable the clock for the first CPU. - * This makes sure that the PLL that feeds the CPU won't be - * stopped while the kernel is running. - */ - cpu_node = of_get_cpu_node(0, NULL); - if (!cpu_node) { - pr_err("Unable to get CPU node\n"); - } else { - cpu0_clk = of_clk_get(cpu_node, 0); - if (IS_ERR(cpu0_clk)) { - pr_err("Unable to get CPU0 clock\n"); - return PTR_ERR(cpu0_clk); - } - - ret = clk_prepare_enable(cpu0_clk); - if (ret) { - pr_err("Unable to enable CPU0 clock\n"); - return ret; - } - } } return 0; diff --git a/arch/mips/include/asm/checksum.h b/arch/mips/include/asm/checksum.h index 1e6c1354f2456480db163550d6c312d92e7c2bab..4044eaf989ac7dad0f2094c5d4cfab05ac9fb5c3 100644 --- a/arch/mips/include/asm/checksum.h +++ b/arch/mips/include/asm/checksum.h @@ -128,48 +128,45 @@ static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl) static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr, __u32 len, __u8 proto, - __wsum sum) + __wsum isum) { - unsigned long tmp = (__force unsigned long)sum; - - __asm__( - " .set push # csum_tcpudp_nofold\n" - " .set noat \n" -#ifdef CONFIG_32BIT - " addu %0, %2 \n" - " sltu $1, %0, %2 \n" - " addu %0, $1 \n" - - " addu %0, %3 \n" - " sltu $1, %0, %3 \n" - " addu %0, $1 \n" - - " addu %0, %4 \n" - " sltu $1, %0, %4 \n" - " addu %0, $1 \n" -#endif -#ifdef CONFIG_64BIT - " daddu %0, %2 \n" - " daddu %0, %3 \n" - " daddu %0, %4 \n" - " dsll32 $1, %0, 0 \n" - " daddu %0, $1 \n" - " sltu $1, %0, $1 \n" - " dsra32 %0, %0, 0 \n" - " addu %0, $1 \n" -#endif - " .set pop" - : "=r" (tmp) - : "0" ((__force unsigned long)daddr), - "r" ((__force unsigned long)saddr), -#ifdef __MIPSEL__ - "r" ((proto + len) << 8), -#else - "r" (proto + len), -#endif - "r" ((__force unsigned long)sum)); - - return (__force __wsum)tmp; + const unsigned int sh32 = IS_ENABLED(CONFIG_64BIT) ? 32 : 0; + unsigned long sum = (__force unsigned long)daddr; + unsigned long tmp; + __u32 osum; + + tmp = (__force unsigned long)saddr; + sum += tmp; + + if (IS_ENABLED(CONFIG_32BIT)) + sum += sum < tmp; + + /* + * We know PROTO + LEN has the sign bit clear, so cast to a signed + * type to avoid an extraneous zero-extension where TMP is 64-bit. + */ + tmp = (__s32)(proto + len); + tmp <<= IS_ENABLED(CONFIG_CPU_LITTLE_ENDIAN) ? 8 : 0; + sum += tmp; + if (IS_ENABLED(CONFIG_32BIT)) + sum += sum < tmp; + + tmp = (__force unsigned long)isum; + sum += tmp; + + if (IS_ENABLED(CONFIG_32BIT)) { + sum += sum < tmp; + osum = sum; + } else if (IS_ENABLED(CONFIG_64BIT)) { + tmp = sum << sh32; + sum += tmp; + osum = sum < tmp; + osum += sum >> sh32; + } else { + BUILD_BUG(); + } + + return (__force __wsum)osum; } #define csum_tcpudp_nofold csum_tcpudp_nofold diff --git a/arch/mips/include/asm/compat.h b/arch/mips/include/asm/compat.h index bbb3bc5a42fd824c8fe1657647645b8c79dcdc97..ec01dc000a418bb54865b1e0b7597f57995b7f29 100644 --- a/arch/mips/include/asm/compat.h +++ b/arch/mips/include/asm/compat.h @@ -9,28 +9,28 @@ #include #include +#define __compat_uid_t __compat_uid_t typedef s32 __compat_uid_t; typedef s32 __compat_gid_t; + typedef __compat_uid_t __compat_uid32_t; typedef __compat_gid_t __compat_gid32_t; #define __compat_uid32_t __compat_uid32_t -#define __compat_gid32_t __compat_gid32_t + +#define compat_statfs compat_statfs +#define compat_ipc64_perm compat_ipc64_perm #define _COMPAT_NSIG 128 /* Don't ask !$@#% ... */ #define _COMPAT_NSIG_BPW 32 typedef u32 compat_sigset_word; +#define COMPAT_RLIM_INFINITY 0x7fffffffUL + #include -#define COMPAT_USER_HZ 100 #define COMPAT_UTS_MACHINE "mips\0\0\0" -typedef u32 compat_dev_t; typedef u32 compat_nlink_t; -typedef s32 compat_ipc_pid_t; -typedef struct { - s32 val[2]; -} compat_fsid_t; struct compat_stat { compat_dev_t st_dev; @@ -55,27 +55,8 @@ struct compat_stat { s32 st_pad4[14]; }; -struct compat_flock { - short l_type; - short l_whence; - compat_off_t l_start; - compat_off_t l_len; - s32 l_sysid; - compat_pid_t l_pid; - s32 pad[4]; -}; - -#define F_GETLK64 33 -#define F_SETLK64 34 -#define F_SETLKW64 35 - -struct compat_flock64 { - short l_type; - short l_whence; - compat_loff_t l_start; - compat_loff_t l_len; - compat_pid_t l_pid; -}; +#define __ARCH_COMPAT_FLOCK_EXTRA_SYSID s32 l_sysid; +#define __ARCH_COMPAT_FLOCK_PAD s32 pad[4]; struct compat_statfs { int f_type; @@ -92,10 +73,6 @@ struct compat_statfs { int f_spare[5]; }; -#define COMPAT_RLIM_INFINITY 0x7fffffffUL - -#define COMPAT_OFF_T_MAX 0x7fffffff - struct compat_ipc64_perm { compat_key_t key; __compat_uid32_t uid; diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h index de8cb2ccb78129c8db673d190dcfbbf2ad492203..c0983130a44c900b491843528fe37f60eaf18472 100644 --- a/arch/mips/include/asm/cpu-features.h +++ b/arch/mips/include/asm/cpu-features.h @@ -133,6 +133,9 @@ # define raw_cpu_has_fpu 0 # endif #else +# if cpu_has_fpu +# error "Forcing `cpu_has_fpu' to non-zero is not supported" +# endif # define raw_cpu_has_fpu cpu_has_fpu #endif #ifndef cpu_has_32fpr diff --git a/arch/mips/include/asm/mach-ip27/cpu-feature-overrides.h b/arch/mips/include/asm/mach-ip27/cpu-feature-overrides.h index c8385c4e8664a48edc2138b0133b7292ee7c8798..568fe09332eb4d390b53d25313c90a67e62d16ce 100644 --- a/arch/mips/include/asm/mach-ip27/cpu-feature-overrides.h +++ b/arch/mips/include/asm/mach-ip27/cpu-feature-overrides.h @@ -25,7 +25,6 @@ #define cpu_has_4kex 1 #define cpu_has_3k_cache 0 #define cpu_has_4k_cache 1 -#define cpu_has_fpu 1 #define cpu_has_nofpuex 0 #define cpu_has_32fpr 1 #define cpu_has_counter 1 diff --git a/arch/mips/include/asm/mach-ip30/cpu-feature-overrides.h b/arch/mips/include/asm/mach-ip30/cpu-feature-overrides.h index 8ad0c424a9afbd23ad8e1d5a410fc9fbc37a5e7d..ce4e4c6e09e24b441b00021ba44e451626507076 100644 --- a/arch/mips/include/asm/mach-ip30/cpu-feature-overrides.h +++ b/arch/mips/include/asm/mach-ip30/cpu-feature-overrides.h @@ -28,7 +28,6 @@ #define cpu_has_4kex 1 #define cpu_has_3k_cache 0 #define cpu_has_4k_cache 1 -#define cpu_has_fpu 1 #define cpu_has_nofpuex 0 #define cpu_has_32fpr 1 #define cpu_has_counter 1 diff --git a/arch/mips/include/asm/mach-ralink/spaces.h b/arch/mips/include/asm/mach-ralink/spaces.h index f7af11ea2d61297845773df23a88ee258a4664f5..a9f0570d0f044ec972310e6654da7962d2fa8e8e 100644 --- a/arch/mips/include/asm/mach-ralink/spaces.h +++ b/arch/mips/include/asm/mach-ralink/spaces.h @@ -6,7 +6,9 @@ #define PCI_IOSIZE SZ_64K #define IO_SPACE_LIMIT (PCI_IOSIZE - 1) +#ifdef CONFIG_PCI_DRIVERS_GENERIC #define pci_remap_iospace pci_remap_iospace +#endif #include #endif diff --git a/arch/mips/include/asm/octeon/cvmx-bootinfo.h b/arch/mips/include/asm/octeon/cvmx-bootinfo.h index 6c61e0a63924918a5728431d05fa9b5b8a03af8f..c1c0b3230e0a9cbd27393ea6cc307f9a11843abd 100644 --- a/arch/mips/include/asm/octeon/cvmx-bootinfo.h +++ b/arch/mips/include/asm/octeon/cvmx-bootinfo.h @@ -253,6 +253,7 @@ enum cvmx_board_types_enum { CVMX_BOARD_TYPE_REDWING = 43, CVMX_BOARD_TYPE_NIC68_4 = 44, CVMX_BOARD_TYPE_NIC10E_66 = 45, + CVMX_BOARD_TYPE_SNIC10E = 50, CVMX_BOARD_TYPE_MAX, /* @@ -369,6 +370,7 @@ static inline const char *cvmx_board_type_to_string(enum ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_REDWING) ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_NIC68_4) ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_NIC10E_66) + ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_SNIC10E) ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_MAX) /* Customer boards listed here */ diff --git a/arch/mips/include/asm/unistd.h b/arch/mips/include/asm/unistd.h index c2196b1b6604b518e16b83cfddd277746745560d..25a5253db7f45fc94e523c49fb779060d0adf44a 100644 --- a/arch/mips/include/asm/unistd.h +++ b/arch/mips/include/asm/unistd.h @@ -50,6 +50,8 @@ # ifdef CONFIG_32BIT # define __ARCH_WANT_STAT64 # define __ARCH_WANT_SYS_TIME32 +# else +# define __ARCH_WANT_COMPAT_STAT # endif # ifdef CONFIG_MIPS32_O32 # define __ARCH_WANT_SYS_TIME32 diff --git a/arch/mips/include/uapi/asm/fcntl.h b/arch/mips/include/uapi/asm/fcntl.h index 42e13dead54319e2e33d4729a05e939a4c8d5fd9..0369a38e3d4f274dc9c92138ae08ee5130885ee1 100644 --- a/arch/mips/include/uapi/asm/fcntl.h +++ b/arch/mips/include/uapi/asm/fcntl.h @@ -44,36 +44,16 @@ #define F_SETOWN 24 /* for sockets. */ #define F_GETOWN 23 /* for sockets. */ -#ifndef __mips64 +#if __BITS_PER_LONG == 32 || defined(__KERNEL__) #define F_GETLK64 33 /* using 'struct flock64' */ #define F_SETLK64 34 #define F_SETLKW64 35 -#endif - -/* - * The flavours of struct flock. "struct flock" is the ABI compliant - * variant. Finally struct flock64 is the LFS variant of struct flock. As - * a historic accident and inconsistence with the ABI definition it doesn't - * contain all the same fields as struct flock. - */ +#endif /* __BITS_PER_LONG == 32 || defined(__KERNEL__) */ #if _MIPS_SIM != _MIPS_SIM_ABI64 - -#include - -struct flock { - short l_type; - short l_whence; - __kernel_off_t l_start; - __kernel_off_t l_len; - long l_sysid; - __kernel_pid_t l_pid; - long pad[4]; -}; - -#define HAVE_ARCH_STRUCT_FLOCK - -#endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */ +#define __ARCH_FLOCK_EXTRA_SYSID long l_sysid; +#define __ARCH_FLOCK_PAD long pad[4]; +#endif #include diff --git a/arch/mips/jazz/irq.c b/arch/mips/jazz/irq.c index 495ba7cc56ec414ab17867f91ad58ebef97d496f..264d453876aa69e3d19b8a036c31dcfc03e5ce9b 100644 --- a/arch/mips/jazz/irq.c +++ b/arch/mips/jazz/irq.c @@ -141,7 +141,7 @@ void __init plat_time_init(void) /* * Set clock to 100Hz. * - * The R4030 timer receives an input clock of 1kHz which is divieded by + * The R4030 timer receives an input clock of 1kHz which is divided by * a programmable 4-bit divider. This makes it fairly inflexible. */ r4030_write_reg32(JAZZ_TIMER_INTERVAL, 9); diff --git a/arch/mips/kernel/cmpxchg.c b/arch/mips/kernel/cmpxchg.c index ac9c8cfb2ba9e3da7ba337d3044b76a43ce37acd..e974a4954df8530b5bb90633b889db276860bb48 100644 --- a/arch/mips/kernel/cmpxchg.c +++ b/arch/mips/kernel/cmpxchg.c @@ -22,7 +22,7 @@ unsigned long __xchg_small(volatile void *ptr, unsigned long val, unsigned int s /* * Calculate a shift & mask that correspond to the value we wish to - * exchange within the naturally aligned 4 byte integerthat includes + * exchange within the naturally aligned 4 byte integer that includes * it. */ shift = (unsigned long)ptr & 0x3; diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index f0ea9293754633cd26f99b12afc77227e1eda73f..d510f628ee03846fbea0a75c3603231bd14e4b10 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -156,7 +156,7 @@ static inline void check_errata(void) /* * Erratum "RPS May Cause Incorrect Instruction Execution" * This code only handles VPE0, any SMP/RTOS code - * making use of VPE1 will be responsable for that VPE. + * making use of VPE1 will be responsible for that VPE. */ if ((c->processor_id & PRID_REV_MASK) <= PRID_REV_34K_V1_0_2) write_c0_config7(read_c0_config7() | MIPS_CONF7_RPS); diff --git a/arch/mips/kernel/idle.c b/arch/mips/kernel/idle.c index 146d9fa77f751be3ba150fc258afe503f6814dfb..53adcc1b2ed583bad23e15a48a560d1ea5451d28 100644 --- a/arch/mips/kernel/idle.c +++ b/arch/mips/kernel/idle.c @@ -228,7 +228,7 @@ void __init check_wait(void) break; /* - * Another rev is incremeting c0_count at a reduced clock + * Another rev is incrementing c0_count at a reduced clock * rate while in WAIT mode. So we basically have the choice * between using the cp0 timer as clocksource or avoiding * the WAIT instruction. Until more details are known, diff --git a/arch/mips/kernel/kprobes.c b/arch/mips/kernel/kprobes.c index 6c7f3b143fdc25288ad844ccf8a61489d10b559a..316b27d0d2fbd0646460438e25c0314c4a4d3575 100644 --- a/arch/mips/kernel/kprobes.c +++ b/arch/mips/kernel/kprobes.c @@ -44,10 +44,11 @@ static const union mips_instruction breakpoint2_insn = { DEFINE_PER_CPU(struct kprobe *, current_kprobe); DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); -static int __kprobes insn_has_delayslot(union mips_instruction insn) +static int insn_has_delayslot(union mips_instruction insn) { return __insn_has_delay_slot(insn); } +NOKPROBE_SYMBOL(insn_has_delayslot); /* * insn_has_ll_or_sc function checks whether instruction is ll or sc @@ -56,7 +57,7 @@ static int __kprobes insn_has_delayslot(union mips_instruction insn) * instructions; cannot do much about breakpoint in the middle of * ll/sc pair; it is upto user to avoid those places */ -static int __kprobes insn_has_ll_or_sc(union mips_instruction insn) +static int insn_has_ll_or_sc(union mips_instruction insn) { int ret = 0; @@ -72,8 +73,9 @@ static int __kprobes insn_has_ll_or_sc(union mips_instruction insn) } return ret; } +NOKPROBE_SYMBOL(insn_has_ll_or_sc); -int __kprobes arch_prepare_kprobe(struct kprobe *p) +int arch_prepare_kprobe(struct kprobe *p) { union mips_instruction insn; union mips_instruction prev_insn; @@ -132,26 +134,30 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p) out: return ret; } +NOKPROBE_SYMBOL(arch_prepare_kprobe); -void __kprobes arch_arm_kprobe(struct kprobe *p) +void arch_arm_kprobe(struct kprobe *p) { *p->addr = breakpoint_insn; flush_insn_slot(p); } +NOKPROBE_SYMBOL(arch_arm_kprobe); -void __kprobes arch_disarm_kprobe(struct kprobe *p) +void arch_disarm_kprobe(struct kprobe *p) { *p->addr = p->opcode; flush_insn_slot(p); } +NOKPROBE_SYMBOL(arch_disarm_kprobe); -void __kprobes arch_remove_kprobe(struct kprobe *p) +void arch_remove_kprobe(struct kprobe *p) { if (p->ainsn.insn) { free_insn_slot(p->ainsn.insn, 0); p->ainsn.insn = NULL; } } +NOKPROBE_SYMBOL(arch_remove_kprobe); static void save_previous_kprobe(struct kprobe_ctlblk *kcb) { @@ -257,7 +263,7 @@ static void prepare_singlestep(struct kprobe *p, struct pt_regs *regs, * breakpoint trap. In case of branch instructions, the target * epc to be restored. */ -static void __kprobes resume_execution(struct kprobe *p, +static void resume_execution(struct kprobe *p, struct pt_regs *regs, struct kprobe_ctlblk *kcb) { @@ -268,8 +274,9 @@ static void __kprobes resume_execution(struct kprobe *p, regs->cp0_epc = orig_epc + 4; } } +NOKPROBE_SYMBOL(resume_execution); -static int __kprobes kprobe_handler(struct pt_regs *regs) +static int kprobe_handler(struct pt_regs *regs) { struct kprobe *p; int ret = 0; @@ -367,6 +374,7 @@ no_kprobe: return ret; } +NOKPROBE_SYMBOL(kprobe_handler); static inline int post_kprobe_handler(struct pt_regs *regs) { @@ -415,7 +423,7 @@ int kprobe_fault_handler(struct pt_regs *regs, int trapnr) /* * Wrapper routine for handling exceptions. */ -int __kprobes kprobe_exceptions_notify(struct notifier_block *self, +int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val, void *data) { @@ -446,6 +454,7 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, } return ret; } +NOKPROBE_SYMBOL(kprobe_exceptions_notify); /* * Function return probe trampoline: @@ -469,7 +478,7 @@ static void __used kretprobe_trampoline_holder(void) void __kretprobe_trampoline(void); -void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri, +void arch_prepare_kretprobe(struct kretprobe_instance *ri, struct pt_regs *regs) { ri->ret_addr = (kprobe_opcode_t *) regs->regs[31]; @@ -478,11 +487,12 @@ void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri, /* Replace the return addr with trampoline addr */ regs->regs[31] = (unsigned long)__kretprobe_trampoline; } +NOKPROBE_SYMBOL(arch_prepare_kretprobe); /* * Called when the probe at kretprobe trampoline is hit */ -static int __kprobes trampoline_probe_handler(struct kprobe *p, +static int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) { instruction_pointer(regs) = __kretprobe_trampoline_handler(regs, NULL); @@ -493,14 +503,16 @@ static int __kprobes trampoline_probe_handler(struct kprobe *p, */ return 1; } +NOKPROBE_SYMBOL(trampoline_probe_handler); -int __kprobes arch_trampoline_kprobe(struct kprobe *p) +int arch_trampoline_kprobe(struct kprobe *p) { if (p->addr == (kprobe_opcode_t *)__kretprobe_trampoline) return 1; return 0; } +NOKPROBE_SYMBOL(arch_trampoline_kprobe); static struct kprobe trampoline_p = { .addr = (kprobe_opcode_t *)__kretprobe_trampoline, diff --git a/arch/mips/kernel/mips-cpc.c b/arch/mips/kernel/mips-cpc.c index 17aff13cd7ce6ea78d0e6be2d944e7ce4208f9f1..3e386f7e154507c527a64c98da861b548b7c67f1 100644 --- a/arch/mips/kernel/mips-cpc.c +++ b/arch/mips/kernel/mips-cpc.c @@ -28,6 +28,7 @@ phys_addr_t __weak mips_cpc_default_phys_base(void) cpc_node = of_find_compatible_node(of_root, NULL, "mti,mips-cpc"); if (cpc_node) { err = of_address_to_resource(cpc_node, 0, &res); + of_node_put(cpc_node); if (!err) return res.start; } diff --git a/arch/mips/kernel/perf_event_mipsxx.c b/arch/mips/kernel/perf_event_mipsxx.c index 1641d274fe37dabdb70d550d8f50e68c5b2e96bb..c4d6b09136b1e420adb4dd543a167e3c1a29752c 100644 --- a/arch/mips/kernel/perf_event_mipsxx.c +++ b/arch/mips/kernel/perf_event_mipsxx.c @@ -329,7 +329,7 @@ static int mipsxx_pmu_alloc_counter(struct cpu_hw_events *cpuc, for (i = mipspmu.num_counters - 1; i >= 0; i--) { /* * Note that some MIPS perf events can be counted by both - * even and odd counters, wheresas many other are only by + * even and odd counters, whereas many other are only by * even _or_ odd counters. This introduces an issue that * when the former kind of event takes the counter the * latter kind of event wants to use, then the "counter diff --git a/arch/mips/kernel/reset.c b/arch/mips/kernel/reset.c index 6288780b779e7c451f19f9160e0823ac1decb2ff..e7ce07b3e79b9fc1c6ca069afe5c7e65334fbeb8 100644 --- a/arch/mips/kernel/reset.c +++ b/arch/mips/kernel/reset.c @@ -114,8 +114,7 @@ void machine_halt(void) void machine_power_off(void) { - if (pm_power_off) - pm_power_off(); + do_kernel_power_off(); #ifdef CONFIG_SMP preempt_disable(); diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index ef73ba1e0ec10474dd108c89445608039a4043ab..2ca156a5b23198cff29d60b27148d8bdac40286f 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -344,6 +345,11 @@ static int __init early_parse_mem(char *p) { phys_addr_t start, size; + if (!p) { + pr_err("mem parameter is empty, do nothing\n"); + return -EINVAL; + } + /* * If a user specifies memory size, we * blow away any automatically generated @@ -359,7 +365,10 @@ static int __init early_parse_mem(char *p) if (*p == '@') start = memparse(p + 1, &p); - memblock_add(start, size); + if (IS_ENABLED(CONFIG_NUMA)) + memblock_add_node(start, size, pa_to_nid(start), MEMBLOCK_NONE); + else + memblock_add(start, size); return 0; } @@ -554,7 +563,7 @@ static void __init bootcmdline_init(void) * unmodified. */ if (IS_ENABLED(CONFIG_CMDLINE_OVERRIDE)) { - strlcpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE); + strscpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE); return; } @@ -566,7 +575,7 @@ static void __init bootcmdline_init(void) * boot_command_line to undo anything early_init_dt_scan_chosen() did. */ if (IS_ENABLED(CONFIG_MIPS_CMDLINE_BUILTIN_EXTEND)) - strlcpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE); + strscpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE); else boot_command_line[0] = 0; @@ -628,7 +637,7 @@ static void __init arch_mem_init(char **cmdline_p) memblock_set_bottom_up(true); bootcmdline_init(); - strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE); + strscpy(command_line, boot_command_line, COMMAND_LINE_SIZE); *cmdline_p = command_line; parse_early_param(); diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c index 1986d13094100be081563323e4ab2cb0f82c800a..1d93b85271ba887a4dc0ea88ab9220b96f90265e 100644 --- a/arch/mips/kernel/smp.c +++ b/arch/mips/kernel/smp.c @@ -518,6 +518,12 @@ static inline void smp_on_each_tlb(void (*func) (void *info), void *info) void flush_tlb_mm(struct mm_struct *mm) { + if (!mm) + return; + + if (atomic_read(&mm->mm_users) == 0) + return; /* happens as a result of exit_mmap() */ + preempt_disable(); if (cpu_has_mmid) { diff --git a/arch/mips/kvm/tlb.c b/arch/mips/kvm/tlb.c index a3b50d5e3b258efc38f121d086c0b04dcc62a103..4e91971daae143158f1814dad40acb5ed09687bf 100644 --- a/arch/mips/kvm/tlb.c +++ b/arch/mips/kvm/tlb.c @@ -153,7 +153,7 @@ EXPORT_SYMBOL_GPL(kvm_vz_host_tlb_inv); * kvm_vz_guest_tlb_lookup() - Lookup a guest VZ TLB mapping. * @vcpu: KVM VCPU pointer. * @gpa: Guest virtual address in a TLB mapped guest segment. - * @gpa: Ponter to output guest physical address it maps to. + * @gpa: Pointer to output guest physical address it maps to. * * Converts a guest virtual address in a guest TLB mapped segment to a guest * physical address, by probing the guest TLB. diff --git a/arch/mips/loongson32/Kconfig b/arch/mips/loongson32/Kconfig index e27879b4813b497bea79ab86f14aadbe62584eaa..2ef9da0016df1b2b561b17843c85fdd37c3d7eff 100644 --- a/arch/mips/loongson32/Kconfig +++ b/arch/mips/loongson32/Kconfig @@ -46,7 +46,7 @@ menuconfig CEVT_CSRC_LS1X If unsure, say N. choice - prompt "Select clockevent/clocksource" + prompt "Select clockevent/clocksource" depends on CEVT_CSRC_LS1X default TIMER_USE_PWM0 diff --git a/arch/mips/mm/fault.c b/arch/mips/mm/fault.c index 44f98100e84e3ae8ae3b755b6c4cc42fc784ea97..b08bc556d30dd779d973f30754f44a491d6b2038 100644 --- a/arch/mips/mm/fault.c +++ b/arch/mips/mm/fault.c @@ -35,7 +35,7 @@ int show_unhandled_signals = 1; * and the problem, and then passes it off to one of the appropriate * routines. */ -static void __kprobes __do_page_fault(struct pt_regs *regs, unsigned long write, +static void __do_page_fault(struct pt_regs *regs, unsigned long write, unsigned long address) { struct vm_area_struct * vma = NULL; @@ -322,8 +322,9 @@ vmalloc_fault: } #endif } +NOKPROBE_SYMBOL(__do_page_fault); -asmlinkage void __kprobes do_page_fault(struct pt_regs *regs, +asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long write, unsigned long address) { enum ctx_state prev_state; @@ -332,3 +333,4 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs, __do_page_fault(regs, write, address); exception_exit(prev_state); } +NOKPROBE_SYMBOL(do_page_fault); diff --git a/arch/mips/net/bpf_jit_comp32.c b/arch/mips/net/bpf_jit_comp32.c index 044b11b65bcac8a076187873a7542ff64a59a037..83c975d5cca27d6135c3fe0b44ab9ddda45c6449 100644 --- a/arch/mips/net/bpf_jit_comp32.c +++ b/arch/mips/net/bpf_jit_comp32.c @@ -722,7 +722,7 @@ static void emit_atomic_r32(struct jit_context *ctx, 0, JIT_RESERVED_STACK); /* * Argument 1: dst+off if xchg, otherwise src, passed in register a0 - * Argument 2: src if xchg, othersize dst+off, passed in register a1 + * Argument 2: src if xchg, otherwise dst+off, passed in register a1 */ emit(ctx, move, MIPS_R_T9, dst); if (code == BPF_XCHG) { diff --git a/arch/mips/pci/pcie-octeon.c b/arch/mips/pci/pcie-octeon.c index d919a0d813a17a3639f8c6ade767e7dccc822146..c9edd3fb380df5ff7c978a3b81ed55bfa6759eee 100644 --- a/arch/mips/pci/pcie-octeon.c +++ b/arch/mips/pci/pcie-octeon.c @@ -895,7 +895,7 @@ retry: mem_access_subid.s.nsw = 0; /* Enable Snoop for Writes. */ mem_access_subid.s.ror = 0; /* Disable Relaxed Ordering for Reads. */ mem_access_subid.s.row = 0; /* Disable Relaxed Ordering for Writes. */ - mem_access_subid.s.ba = 0; /* PCIe Adddress Bits <63:34>. */ + mem_access_subid.s.ba = 0; /* PCIe Address Bits <63:34>. */ /* * Setup mem access 12-15 for port 0, 16-19 for port 1, @@ -1345,7 +1345,7 @@ static int __cvmx_pcie_rc_initialize_gen2(int pcie_port) mem_access_subid.s.esw = 1; /* Endian-swap for Writes. */ mem_access_subid.s.wtype = 0; /* "No snoop" and "Relaxed ordering" are not set */ mem_access_subid.s.rtype = 0; /* "No snoop" and "Relaxed ordering" are not set */ - /* PCIe Adddress Bits <63:34>. */ + /* PCIe Address Bits <63:34>. */ if (OCTEON_IS_MODEL(OCTEON_CN68XX)) mem_access_subid.cn68xx.ba = 0; else diff --git a/arch/mips/pic32/pic32mzda/config.c b/arch/mips/pic32/pic32mzda/config.c index 36afe1b5b9c75b2e11a9d076fe4fe43f42bb223f..f6953200771746f510c957ba72eedd31ac54fca4 100644 --- a/arch/mips/pic32/pic32mzda/config.c +++ b/arch/mips/pic32/pic32mzda/config.c @@ -111,7 +111,7 @@ void __init pic32_config_init(void) pic32_reset_status = readl(pic32_conf_base + PIC32_RCON); writel(-1, PIC32_CLR(pic32_conf_base + PIC32_RCON)); - /* Device Inforation */ + /* Device Information */ pr_info("Device Id: 0x%08x, Device Ver: 0x%04x\n", pic32_get_device_id(), pic32_get_device_version()); diff --git a/arch/mips/sgi-ip22/ip22-reset.c b/arch/mips/sgi-ip22/ip22-reset.c index 9028dbbb45dd0e83b94ccf36236af3ec44da5ad8..8f0861c580800be0b1c8c1c32c9ff3ee28c18c1d 100644 --- a/arch/mips/sgi-ip22/ip22-reset.c +++ b/arch/mips/sgi-ip22/ip22-reset.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include @@ -41,7 +40,7 @@ static struct timer_list power_timer, blink_timer, debounce_timer; static unsigned long blink_timer_timeout; -#define MACHINE_PANICED 1 +#define MACHINE_PANICKED 1 #define MACHINE_SHUTTING_DOWN 2 static int machine_state; @@ -112,7 +111,7 @@ static void debounce(struct timer_list *unused) return; } - if (machine_state & MACHINE_PANICED) + if (machine_state & MACHINE_PANICKED) sgimc->cpuctrl0 |= SGIMC_CCTRL0_SYSINIT; enable_irq(SGI_PANEL_IRQ); @@ -120,7 +119,7 @@ static void debounce(struct timer_list *unused) static inline void power_button(void) { - if (machine_state & MACHINE_PANICED) + if (machine_state & MACHINE_PANICKED) return; if ((machine_state & MACHINE_SHUTTING_DOWN) || @@ -167,9 +166,9 @@ static irqreturn_t panel_int(int irq, void *dev_id) static int panic_event(struct notifier_block *this, unsigned long event, void *ptr) { - if (machine_state & MACHINE_PANICED) + if (machine_state & MACHINE_PANICKED) return NOTIFY_DONE; - machine_state |= MACHINE_PANICED; + machine_state |= MACHINE_PANICKED; blink_timer_timeout = PANIC_FREQ; blink_timeout(&blink_timer); diff --git a/arch/mips/sgi-ip27/ip27-xtalk.c b/arch/mips/sgi-ip27/ip27-xtalk.c index 000ede156bdc040c8b998903bb523cf767ac612c..e762886d1dda9f900866b47139fd9c5f711d532c 100644 --- a/arch/mips/sgi-ip27/ip27-xtalk.c +++ b/arch/mips/sgi-ip27/ip27-xtalk.c @@ -53,6 +53,8 @@ static void bridge_platform_create(nasid_t nasid, int widget, int masterwid) } platform_device_add_resources(pdev, &w1_res, 1); platform_device_add_data(pdev, wd, sizeof(*wd)); + /* platform_device_add_data() duplicates the data */ + kfree(wd); platform_device_add(pdev); bd = kzalloc(sizeof(*bd), GFP_KERNEL); @@ -83,6 +85,8 @@ static void bridge_platform_create(nasid_t nasid, int widget, int masterwid) bd->io_offset = offset; platform_device_add_data(pdev, bd, sizeof(*bd)); + /* platform_device_add_data() duplicates the data */ + kfree(bd); platform_device_add(pdev); pr_info("xtalk:n%d/%x bridge widget\n", nasid, widget); return; diff --git a/arch/mips/sgi-ip30/ip30-xtalk.c b/arch/mips/sgi-ip30/ip30-xtalk.c index 8a2894645529890370f8ffa92d8d297b2ffd251b..8129524421cb0af89d486fd4d089b4ede5ef33af 100644 --- a/arch/mips/sgi-ip30/ip30-xtalk.c +++ b/arch/mips/sgi-ip30/ip30-xtalk.c @@ -63,6 +63,8 @@ static void bridge_platform_create(int widget, int masterwid) } platform_device_add_resources(pdev, &w1_res, 1); platform_device_add_data(pdev, wd, sizeof(*wd)); + /* platform_device_add_data() duplicates the data */ + kfree(wd); platform_device_add(pdev); bd = kzalloc(sizeof(*bd), GFP_KERNEL); @@ -92,6 +94,8 @@ static void bridge_platform_create(int widget, int masterwid) bd->io_offset = IP30_SWIN_BASE(widget); platform_device_add_data(pdev, bd, sizeof(*bd)); + /* platform_device_add_data() duplicates the data */ + kfree(bd); platform_device_add(pdev); pr_info("xtalk:%x bridge widget\n", widget); return; diff --git a/arch/mips/sibyte/bcm1480/setup.c b/arch/mips/sibyte/bcm1480/setup.c index 6f34b871b08ec000921bc493b3b981b112f09686..e3e807046a9c19a406fe051dbcb8b91dd7a198a2 100644 --- a/arch/mips/sibyte/bcm1480/setup.c +++ b/arch/mips/sibyte/bcm1480/setup.c @@ -34,8 +34,6 @@ static char *pass_str; static int __init setup_bcm1x80_bcm1x55(void) { - int ret = 0; - switch (soc_pass) { case K_SYS_REVISION_BCM1480_S0: periph_rev = 1; @@ -64,7 +62,7 @@ static int __init setup_bcm1x80_bcm1x55(void) break; } - return ret; + return 0; } /* Setup code likely to be common to all SiByte platforms */ diff --git a/arch/mips/tools/loongson3-llsc-check.c b/arch/mips/tools/loongson3-llsc-check.c index bdbc7b4324ecdc6bccc383542df53c7325e3d557..5f68a4fa8a7ee9591bf2360807e1e8ea1b61e9e8 100644 --- a/arch/mips/tools/loongson3-llsc-check.c +++ b/arch/mips/tools/loongson3-llsc-check.c @@ -217,7 +217,7 @@ static int check_code(uint64_t pc, uint32_t *code, size_t sz) ) /* - * Skip the first instructionm allowing check_ll to look backwards + * Skip the first instruction, allowing check_ll to look backwards * unconditionally. */ advance(); diff --git a/arch/mips/txx9/generic/pci.c b/arch/mips/txx9/generic/pci.c index fb998726bd5d58b31e520d8ac4f8290835db473a..e98845543b772fa0090a1755d57fe358abbe74b3 100644 --- a/arch/mips/txx9/generic/pci.c +++ b/arch/mips/txx9/generic/pci.c @@ -225,7 +225,7 @@ txx9_alloc_pci_controller(struct pci_controller *pcic, static int __init txx9_arch_pci_init(void) { - PCIBIOS_MIN_IO = 0x8000; /* reseve legacy I/O space */ + PCIBIOS_MIN_IO = 0x8000; /* reserve legacy I/O space */ return 0; } arch_initcall(txx9_arch_pci_init); diff --git a/arch/mips/vr41xx/common/cmu.c b/arch/mips/vr41xx/common/cmu.c index b59ee54793137b49179aa5ce401550b49d51fb12..e4cbe116b26dbcfb00802bbd1f807032c7e27e92 100644 --- a/arch/mips/vr41xx/common/cmu.c +++ b/arch/mips/vr41xx/common/cmu.c @@ -236,8 +236,6 @@ static int __init vr41xx_cmu_init(void) if (current_cpu_type() == CPU_VR4133) cmuclkmsk2 = cmu_read(CMUCLKMSK2); - spin_lock_init(&cmu_lock); - return 0; } diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig index bd22578859d0024c72ba913bc88614c4d0fa7b72..5f2448dc5a2b2ee77e08f7b3b470273eff388cf4 100644 --- a/arch/parisc/Kconfig +++ b/arch/parisc/Kconfig @@ -332,10 +332,6 @@ config COMPAT def_bool y depends on 64BIT -config SYSVIPC_COMPAT - def_bool y - depends on COMPAT && SYSVIPC - config AUDIT_ARCH def_bool y diff --git a/arch/parisc/include/asm/assembly.h b/arch/parisc/include/asm/assembly.h index ea0cb318b13d23ad11aa42cef988a4098ce36451..0f0d4a496fef0ed5c4f54aae6fc1f75dbc2cb8a7 100644 --- a/arch/parisc/include/asm/assembly.h +++ b/arch/parisc/include/asm/assembly.h @@ -143,7 +143,7 @@ depd,z \r, 63-(\sa), 64-(\sa), \t .endm - /* Shift Right - note the r and t can NOT be the same! */ + /* Shift Right for 32-bit. Clobbers upper 32-bit on PA2.0. */ .macro shr r, sa, t extru \r, 31-(\sa), 32-(\sa), \t .endm @@ -174,6 +174,16 @@ #endif .endm + /* The depw instruction leaves the most significant 32 bits of the + * target register in an undefined state on PA 2.0 systems. */ + .macro dep_safe i, p, len, t +#ifdef CONFIG_64BIT + depd \i, 32+(\p), \len, \t +#else + depw \i, \p, \len, \t +#endif + .endm + /* load 32-bit 'value' into 'reg' compensating for the ldil * sign-extension when running in wide mode. * WARNING!! neither 'value' nor 'reg' can be expressions diff --git a/arch/parisc/include/asm/cache.h b/arch/parisc/include/asm/cache.h index 5032e758594e937cda158711ec49ef5931e8866a..e23d06b51a2044016cab18b1704953fb49641826 100644 --- a/arch/parisc/include/asm/cache.h +++ b/arch/parisc/include/asm/cache.h @@ -54,6 +54,7 @@ void parisc_setup_cache_timing(void); #define asm_io_sync() asm volatile("sync" \ ALTERNATIVE(ALT_COND_NO_DCACHE, INSN_NOP) \ ALTERNATIVE(ALT_COND_NO_IOC_FDC, INSN_NOP) :::"memory") +#define asm_syncdma() asm volatile("syncdma" :::"memory") #endif /* ! __ASSEMBLY__ */ diff --git a/arch/parisc/include/asm/compat.h b/arch/parisc/include/asm/compat.h index c04f5a637c390b9d84939f1476e497fd0a7d3649..339d1b833fa7e7addc6e82114f5455cfb63ff5f4 100644 --- a/arch/parisc/include/asm/compat.h +++ b/arch/parisc/include/asm/compat.h @@ -11,16 +11,16 @@ #define compat_mode_t compat_mode_t typedef u16 compat_mode_t; +#define compat_ipc_pid_t compat_ipc_pid_t +typedef u16 compat_ipc_pid_t; + +#define compat_ipc64_perm compat_ipc64_perm + #include -#define COMPAT_USER_HZ 100 #define COMPAT_UTS_MACHINE "parisc\0\0" -typedef u32 __compat_uid_t; -typedef u32 __compat_gid_t; -typedef u32 compat_dev_t; typedef u16 compat_nlink_t; -typedef u16 compat_ipc_pid_t; struct compat_stat { compat_dev_t st_dev; /* dev_t is 32 bits on parisc */ @@ -53,37 +53,6 @@ struct compat_stat { u32 st_spare4[3]; }; -struct compat_flock { - short l_type; - short l_whence; - compat_off_t l_start; - compat_off_t l_len; - compat_pid_t l_pid; -}; - -struct compat_flock64 { - short l_type; - short l_whence; - compat_loff_t l_start; - compat_loff_t l_len; - compat_pid_t l_pid; -}; - -struct compat_statfs { - s32 f_type; - s32 f_bsize; - s32 f_blocks; - s32 f_bfree; - s32 f_bavail; - s32 f_files; - s32 f_ffree; - __kernel_fsid_t f_fsid; - s32 f_namelen; - s32 f_frsize; - s32 f_flags; - s32 f_spare[4]; -}; - struct compat_sigcontext { compat_int_t sc_flags; compat_int_t sc_gr[32]; /* PSW in sc_gr[0] */ @@ -93,10 +62,6 @@ struct compat_sigcontext { compat_int_t sc_sar; /* cr11 */ }; -#define COMPAT_RLIM_INFINITY 0xffffffff - -#define COMPAT_OFF_T_MAX 0x7fffffff - struct compat_ipc64_perm { compat_key_t key; __compat_uid_t uid; diff --git a/arch/parisc/include/asm/fixmap.h b/arch/parisc/include/asm/fixmap.h index e480b2c054078eb9a0f72ff809b2aa3363c27a67..5cd80ce1163a82d0d20b8453fa3b1c95dbf4f357 100644 --- a/arch/parisc/include/asm/fixmap.h +++ b/arch/parisc/include/asm/fixmap.h @@ -9,12 +9,27 @@ * * All of the values in this file must be <4GB (because of assembly * loading restrictions). If you place this region anywhere above - * __PAGE_OFFSET, you must adjust the memory map accordingly */ + * __PAGE_OFFSET, you must adjust the memory map accordingly + */ -/* The alias region is used in kernel space to do copy/clear to or - * from areas congruently mapped with user space. It is 8MB large - * and must be 16MB aligned */ -#define TMPALIAS_MAP_START ((__PAGE_OFFSET) - 16*1024*1024) +/* + * The tmpalias region is used in kernel space to copy/clear/flush data + * from pages congruently mapped with user space. It is comprised of + * a pair regions. The size of these regions is determined by the largest + * cache aliasing boundary for machines that support equivalent aliasing. + * + * The c3750 with PA8700 processor returns an alias value of 11. This + * indicates that it has an alias boundary of 4 MB. It also supports + * non-equivalent aliasing without a performance penalty. + * + * Machines with PA8800/PA8900 processors return an alias value of 0. + * This indicates the alias boundary is unknown and may be larger than + * 16 MB. Non-equivalent aliasing is not supported. + * + * Here we assume the maximum alias boundary is 4 MB. + */ +#define TMPALIAS_SIZE_BITS 22 /* 4 MB */ +#define TMPALIAS_MAP_START ((__PAGE_OFFSET) - (2 << TMPALIAS_SIZE_BITS)) #define FIXMAP_SIZE (FIX_BITMAP_COUNT << PAGE_SHIFT) #define FIXMAP_START (TMPALIAS_MAP_START - FIXMAP_SIZE) diff --git a/arch/parisc/include/asm/unistd.h b/arch/parisc/include/asm/unistd.h index 7708a5806f09bd4a58796417520b73398e7cbc4c..e38f9a90ac154c2d7296ed2a75d2e9ed6b3d7453 100644 --- a/arch/parisc/include/asm/unistd.h +++ b/arch/parisc/include/asm/unistd.h @@ -142,7 +142,6 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) \ } #define __ARCH_WANT_NEW_STAT -#define __ARCH_WANT_OLD_READDIR #define __ARCH_WANT_STAT64 #define __ARCH_WANT_SYS_ALARM #define __ARCH_WANT_SYS_GETHOSTNAME @@ -156,7 +155,6 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) \ #define __ARCH_WANT_SYS_FADVISE64 #define __ARCH_WANT_SYS_GETPGRP #define __ARCH_WANT_SYS_NICE -#define __ARCH_WANT_SYS_OLDUMOUNT #define __ARCH_WANT_SYS_SIGPENDING #define __ARCH_WANT_SYS_SIGPROCMASK #define __ARCH_WANT_SYS_FORK @@ -164,6 +162,7 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) \ #define __ARCH_WANT_SYS_CLONE #define __ARCH_WANT_SYS_CLONE3 #define __ARCH_WANT_COMPAT_SYS_SENDFILE +#define __ARCH_WANT_COMPAT_STAT #ifdef CONFIG_64BIT #define __ARCH_WANT_SYS_TIME diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c index 0fd04073d4b685e5fea2b2ef8389f722db5c6793..c8a11fcecf4c67b8df5ffadfb403e5d71e1c0d9f 100644 --- a/arch/parisc/kernel/cache.c +++ b/arch/parisc/kernel/cache.c @@ -754,6 +754,9 @@ void invalidate_kernel_vmap_range(void *vaddr, int size) unsigned long start = (unsigned long)vaddr; unsigned long end = start + size; + /* Ensure DMA is complete */ + asm_syncdma(); + if ((!IS_ENABLED(CONFIG_SMP) || !arch_irqs_disabled()) && (unsigned long)size >= parisc_cache_flush_threshold) { flush_tlb_kernel_range(start, end); diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S index ecf50159359e3a824f8ff9c3de9e280423b27283..df8102fb435fced706266fe9786c7d46f24e9ccd 100644 --- a/arch/parisc/kernel/entry.S +++ b/arch/parisc/kernel/entry.S @@ -554,8 +554,9 @@ extrd,s \pte,63,25,\pte .endm - /* The alias region is an 8MB aligned 16MB to do clear and - * copy user pages at addresses congruent with the user + /* The alias region is comprised of a pair of 4 MB regions + * aligned to 8 MB. It is used to clear/copy/flush user pages + * using kernel virtual addresses congruent with the user * virtual address. * * To use the alias page, you set %r26 up with the to TLB @@ -565,13 +566,8 @@ .macro do_alias spc,tmp,tmp1,va,pte,prot,fault,patype cmpib,COND(<>),n 0,\spc,\fault ldil L%(TMPALIAS_MAP_START),\tmp -#if defined(CONFIG_64BIT) && (TMPALIAS_MAP_START >= 0x80000000) - /* on LP64, ldi will sign extend into the upper 32 bits, - * which is behaviour we don't want */ - depdi 0,31,32,\tmp -#endif copy \va,\tmp1 - depi 0,31,23,\tmp1 + depi_safe 0,31,TMPALIAS_SIZE_BITS+1,\tmp1 cmpb,COND(<>),n \tmp,\tmp1,\fault mfctl %cr19,\tmp /* iir */ /* get the opcode (first six bits) into \tmp */ @@ -604,13 +600,13 @@ * OK, it is in the temp alias region, check whether "from" or "to". * Check "subtle" note in pacache.S re: r23/r26. */ -#ifdef CONFIG_64BIT - extrd,u,*= \va,41,1,%r0 -#else - extrw,u,= \va,9,1,%r0 -#endif + extrw,u,= \va,31-TMPALIAS_SIZE_BITS,1,%r0 or,COND(tr) %r23,%r0,\pte or %r26,%r0,\pte + + /* convert phys addr in \pte (from r23 or r26) to tlb insert format */ + SHRREG \pte,PAGE_SHIFT+PAGE_ADD_SHIFT-5, \pte + depi_safe _PAGE_SIZE_ENCODING_DEFAULT, 31,5, \pte .endm diff --git a/arch/parisc/kernel/pacache.S b/arch/parisc/kernel/pacache.S index b4c3f01e2399b31b57a291beae1053cf2ee682be..9a0018f1f42cba9bb3e0e7dfd5c59ef2b6af70b0 100644 --- a/arch/parisc/kernel/pacache.S +++ b/arch/parisc/kernel/pacache.S @@ -300,7 +300,6 @@ fdoneloop2: fdce,m %arg1(%sr1, %arg0) /* Fdce for one loop */ fdsync: - syncdma sync mtsm %r22 /* restore I-bit */ 89: ALTERNATIVE(88b, 89b, ALT_COND_NO_DCACHE, INSN_NOP) @@ -488,6 +487,8 @@ ENDPROC_CFI(copy_page_asm) * parisc chip designers that there will not ever be a parisc * chip with a larger alias boundary (Never say never :-) ). * + * Yah, what about the PA8800 and PA8900 processors? + * * Subtle: the dtlb miss handlers support the temp alias region by * "knowing" that if a dtlb miss happens within the temp alias * region it must have occurred while in clear_user_page. Since @@ -499,19 +500,10 @@ ENDPROC_CFI(copy_page_asm) * miss on the translation, the dtlb miss handler inserts the * translation into the tlb using these values: * - * %r26 physical page (shifted for tlb insert) of "to" translation - * %r23 physical page (shifted for tlb insert) of "from" translation + * %r26 physical address of "to" translation + * %r23 physical address of "from" translation */ - /* Drop prot bits and convert to page addr for iitlbt and idtlbt */ - #define PAGE_ADD_SHIFT (PAGE_SHIFT-12) - .macro convert_phys_for_tlb_insert20 phys - extrd,u \phys, 56-PAGE_ADD_SHIFT, 32-PAGE_ADD_SHIFT, \phys -#if _PAGE_SIZE_ENCODING_DEFAULT - depdi _PAGE_SIZE_ENCODING_DEFAULT, 63, (63-58), \phys -#endif - .endm - /* * copy_user_page_asm() performs a page copy using mappings * equivalent to the user page mappings. It can be used to @@ -540,24 +532,10 @@ ENTRY_CFI(copy_user_page_asm) sub %r25, %r1, %r23 ldil L%(TMPALIAS_MAP_START), %r28 -#ifdef CONFIG_64BIT -#if (TMPALIAS_MAP_START >= 0x80000000) - depdi 0, 31,32, %r28 /* clear any sign extension */ -#endif - convert_phys_for_tlb_insert20 %r26 /* convert phys addr to tlb insert format */ - convert_phys_for_tlb_insert20 %r23 /* convert phys addr to tlb insert format */ - depd %r24,63,22, %r28 /* Form aliased virtual address 'to' */ - depdi 0, 63,PAGE_SHIFT, %r28 /* Clear any offset bits */ - copy %r28, %r29 - depdi 1, 41,1, %r29 /* Form aliased virtual address 'from' */ -#else - extrw,u %r26, 24,25, %r26 /* convert phys addr to tlb insert format */ - extrw,u %r23, 24,25, %r23 /* convert phys addr to tlb insert format */ - depw %r24, 31,22, %r28 /* Form aliased virtual address 'to' */ - depwi 0, 31,PAGE_SHIFT, %r28 /* Clear any offset bits */ + dep_safe %r24, 31,TMPALIAS_SIZE_BITS, %r28 /* Form aliased virtual address 'to' */ + depi_safe 0, 31,PAGE_SHIFT, %r28 /* Clear any offset bits */ copy %r28, %r29 - depwi 1, 9,1, %r29 /* Form aliased virtual address 'from' */ -#endif + depi_safe 1, 31-TMPALIAS_SIZE_BITS,1, %r29 /* Form aliased virtual address 'from' */ /* Purge any old translations */ @@ -687,18 +665,8 @@ ENTRY_CFI(clear_user_page_asm) tophys_r1 %r26 ldil L%(TMPALIAS_MAP_START), %r28 -#ifdef CONFIG_64BIT -#if (TMPALIAS_MAP_START >= 0x80000000) - depdi 0, 31,32, %r28 /* clear any sign extension */ -#endif - convert_phys_for_tlb_insert20 %r26 /* convert phys addr to tlb insert format */ - depd %r25, 63,22, %r28 /* Form aliased virtual address 'to' */ - depdi 0, 63,PAGE_SHIFT, %r28 /* Clear any offset bits */ -#else - extrw,u %r26, 24,25, %r26 /* convert phys addr to tlb insert format */ - depw %r25, 31,22, %r28 /* Form aliased virtual address 'to' */ - depwi 0, 31,PAGE_SHIFT, %r28 /* Clear any offset bits */ -#endif + dep_safe %r25, 31,TMPALIAS_SIZE_BITS, %r28 /* Form aliased virtual address 'to' */ + depi_safe 0, 31,PAGE_SHIFT, %r28 /* Clear any offset bits */ /* Purge any old translation */ @@ -763,18 +731,8 @@ ENDPROC_CFI(clear_user_page_asm) ENTRY_CFI(flush_dcache_page_asm) ldil L%(TMPALIAS_MAP_START), %r28 -#ifdef CONFIG_64BIT -#if (TMPALIAS_MAP_START >= 0x80000000) - depdi 0, 31,32, %r28 /* clear any sign extension */ -#endif - convert_phys_for_tlb_insert20 %r26 /* convert phys addr to tlb insert format */ - depd %r25, 63,22, %r28 /* Form aliased virtual address 'to' */ - depdi 0, 63,PAGE_SHIFT, %r28 /* Clear any offset bits */ -#else - extrw,u %r26, 24,25, %r26 /* convert phys addr to tlb insert format */ - depw %r25, 31,22, %r28 /* Form aliased virtual address 'to' */ - depwi 0, 31,PAGE_SHIFT, %r28 /* Clear any offset bits */ -#endif + dep_safe %r25, 31,TMPALIAS_SIZE_BITS, %r28 /* Form aliased virtual address 'to' */ + depi_safe 0, 31,PAGE_SHIFT, %r28 /* Clear any offset bits */ /* Purge any old translation */ @@ -822,18 +780,8 @@ ENDPROC_CFI(flush_dcache_page_asm) ENTRY_CFI(purge_dcache_page_asm) ldil L%(TMPALIAS_MAP_START), %r28 -#ifdef CONFIG_64BIT -#if (TMPALIAS_MAP_START >= 0x80000000) - depdi 0, 31,32, %r28 /* clear any sign extension */ -#endif - convert_phys_for_tlb_insert20 %r26 /* convert phys addr to tlb insert format */ - depd %r25, 63,22, %r28 /* Form aliased virtual address 'to' */ - depdi 0, 63,PAGE_SHIFT, %r28 /* Clear any offset bits */ -#else - extrw,u %r26, 24,25, %r26 /* convert phys addr to tlb insert format */ - depw %r25, 31,22, %r28 /* Form aliased virtual address 'to' */ - depwi 0, 31,PAGE_SHIFT, %r28 /* Clear any offset bits */ -#endif + dep_safe %r25, 31,TMPALIAS_SIZE_BITS, %r28 /* Form aliased virtual address 'to' */ + depi_safe 0, 31,PAGE_SHIFT, %r28 /* Clear any offset bits */ /* Purge any old translation */ @@ -881,18 +829,8 @@ ENDPROC_CFI(purge_dcache_page_asm) ENTRY_CFI(flush_icache_page_asm) ldil L%(TMPALIAS_MAP_START), %r28 -#ifdef CONFIG_64BIT -#if (TMPALIAS_MAP_START >= 0x80000000) - depdi 0, 31,32, %r28 /* clear any sign extension */ -#endif - convert_phys_for_tlb_insert20 %r26 /* convert phys addr to tlb insert format */ - depd %r25, 63,22, %r28 /* Form aliased virtual address 'to' */ - depdi 0, 63,PAGE_SHIFT, %r28 /* Clear any offset bits */ -#else - extrw,u %r26, 24,25, %r26 /* convert phys addr to tlb insert format */ - depw %r25, 31,22, %r28 /* Form aliased virtual address 'to' */ - depwi 0, 31,PAGE_SHIFT, %r28 /* Clear any offset bits */ -#endif + dep_safe %r25, 31,TMPALIAS_SIZE_BITS, %r28 /* Form aliased virtual address 'to' */ + depi_safe 0, 31,PAGE_SHIFT, %r28 /* Clear any offset bits */ /* Purge any old translation. Note that the FIC instruction * may use either the instruction or data TLB. Given that we @@ -1098,7 +1036,6 @@ ENTRY_CFI(flush_kernel_dcache_range_asm) sync 89: ALTERNATIVE(88b, 89b, ALT_COND_NO_DCACHE, INSN_NOP) - syncdma bv %r0(%r2) nop ENDPROC_CFI(flush_kernel_dcache_range_asm) @@ -1140,7 +1077,6 @@ ENTRY_CFI(purge_kernel_dcache_range_asm) sync 89: ALTERNATIVE(88b, 89b, ALT_COND_NO_DCACHE, INSN_NOP) - syncdma bv %r0(%r2) nop ENDPROC_CFI(purge_kernel_dcache_range_asm) diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c index 28b6a2a5574c614d20af12cae29eedb05c6664c6..d145184696ea5a2b5c87dfdd4e612d261c3098c8 100644 --- a/arch/parisc/kernel/process.c +++ b/arch/parisc/kernel/process.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -116,8 +117,7 @@ void machine_power_off(void) pdc_chassis_send_status(PDC_CHASSIS_DIRECT_SHUTDOWN); /* ipmi_poweroff may have been installed. */ - if (pm_power_off) - pm_power_off(); + do_kernel_power_off(); /* It seems we have no way to power the system off via * software. The user has to press the button himself. */ diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c index 1dc2e88e7b04fc60eb80c65bc99887e415d2cec0..0a81499dd35e2b49a66f6addf00e9c554b7076de 100644 --- a/arch/parisc/mm/init.c +++ b/arch/parisc/mm/init.c @@ -555,6 +555,12 @@ void __init mem_init(void) BUILD_BUG_ON(PT_INITIAL > PTRS_PER_PGD); #endif +#ifdef CONFIG_64BIT + /* avoid ldil_%L() asm statements to sign-extend into upper 32-bits */ + BUILD_BUG_ON(__PAGE_OFFSET >= 0x80000000); + BUILD_BUG_ON(TMPALIAS_MAP_START >= 0x80000000); +#endif + high_memory = __va((max_pfn << PAGE_SHIFT)); set_max_mapnr(max_low_pfn); memblock_free_all(); diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 22e2f1113c4c3815f111068dc10ab1029f2cf989..be68c1f02b794b169da802fb7be41395e07df655 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -109,6 +109,7 @@ config PPC # Please keep this list sorted alphabetically. # select ARCH_32BIT_OFF_T if PPC32 + select ARCH_DISABLE_KASAN_INLINE if PPC_RADIX_MMU select ARCH_ENABLE_MEMORY_HOTPLUG select ARCH_ENABLE_MEMORY_HOTREMOVE select ARCH_HAS_COPY_MC if PPC64 @@ -118,7 +119,6 @@ config PPC select ARCH_HAS_DEBUG_WX if STRICT_KERNEL_RWX select ARCH_HAS_DEVMEM_IS_ALLOWED select ARCH_HAS_DMA_MAP_DIRECT if PPC_PSERIES - select ARCH_HAS_ELF_RANDOMIZE select ARCH_HAS_FORTIFY_SOURCE select ARCH_HAS_GCOV_PROFILE_ALL select ARCH_HAS_HUGEPD if HUGETLB_PAGE @@ -155,10 +155,12 @@ config PPC select ARCH_USE_MEMTEST select ARCH_USE_QUEUED_RWLOCKS if PPC_QUEUED_SPINLOCKS select ARCH_USE_QUEUED_SPINLOCKS if PPC_QUEUED_SPINLOCKS + select ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT select ARCH_WANT_IPC_PARSE_VERSION select ARCH_WANT_IRQS_OFF_ACTIVATE_MM select ARCH_WANT_LD_ORPHAN_WARN select ARCH_WANTS_MODULES_DATA_IN_VMALLOC if PPC_BOOK3S_32 || PPC_8xx + select ARCH_WANTS_NO_INSTR select ARCH_WEAK_RELEASE_ACQUIRE select BINFMT_ELF select BUILDTIME_TABLE_SORT @@ -190,7 +192,8 @@ config PPC select HAVE_ARCH_JUMP_LABEL select HAVE_ARCH_JUMP_LABEL_RELATIVE select HAVE_ARCH_KASAN if PPC32 && PPC_PAGE_SHIFT <= 14 - select HAVE_ARCH_KASAN_VMALLOC if PPC32 && PPC_PAGE_SHIFT <= 14 + select HAVE_ARCH_KASAN if PPC_RADIX_MMU + select HAVE_ARCH_KASAN_VMALLOC if HAVE_ARCH_KASAN select HAVE_ARCH_KFENCE if PPC_BOOK3S_32 || PPC_8xx || 40x select HAVE_ARCH_KGDB select HAVE_ARCH_MMAP_RND_BITS @@ -210,7 +213,7 @@ config PPC select HAVE_EFFICIENT_UNALIGNED_ACCESS if !(CPU_LITTLE_ENDIAN && POWER7_CPU) select HAVE_FAST_GUP select HAVE_FTRACE_MCOUNT_RECORD - select HAVE_FUNCTION_DESCRIPTORS if PPC64 && !CPU_LITTLE_ENDIAN + select HAVE_FUNCTION_DESCRIPTORS if PPC64_ELF_ABI_V1 select HAVE_FUNCTION_ERROR_INJECTION select HAVE_FUNCTION_GRAPH_TRACER select HAVE_FUNCTION_TRACER @@ -300,11 +303,6 @@ config COMPAT select ARCH_WANT_OLD_COMPAT_IPC select COMPAT_OLD_SIGACTION -config SYSVIPC_COMPAT - bool - depends on COMPAT && SYSVIPC - default y - config SCHED_OMIT_FRAME_POINTER bool default y @@ -760,6 +758,22 @@ config PPC_256K_PAGES endchoice +config PAGE_SIZE_4KB + def_bool y + depends on PPC_4K_PAGES + +config PAGE_SIZE_16KB + def_bool y + depends on PPC_16K_PAGES + +config PAGE_SIZE_64KB + def_bool y + depends on PPC_64K_PAGES + +config PAGE_SIZE_256KB + def_bool y + depends on PPC_256K_PAGES + config PPC_PAGE_SHIFT int default 18 if PPC_256K_PAGES diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug index 192f0ed0097ff0445c7ad131e4f7dbc91fcda0d1..9f363c143d863b03b041cb80f1a4b3d7b3b90bd5 100644 --- a/arch/powerpc/Kconfig.debug +++ b/arch/powerpc/Kconfig.debug @@ -374,4 +374,5 @@ config PPC_FAST_ENDIAN_SWITCH config KASAN_SHADOW_OFFSET hex depends on KASAN - default 0xe0000000 + default 0xe0000000 if PPC32 + default 0xa80e000000000000 if PPC64 diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile index 45a9caa37b4e3f4e46ba534903d8898b47e6c885..a0cd707120619daf5c6c878fcaa02a6d26b330a2 100644 --- a/arch/powerpc/Makefile +++ b/arch/powerpc/Makefile @@ -89,10 +89,10 @@ endif ifdef CONFIG_PPC64 ifndef CONFIG_CC_IS_CLANG -cflags-$(CONFIG_CPU_BIG_ENDIAN) += $(call cc-option,-mabi=elfv1) -cflags-$(CONFIG_CPU_BIG_ENDIAN) += $(call cc-option,-mcall-aixdesc) -aflags-$(CONFIG_CPU_BIG_ENDIAN) += $(call cc-option,-mabi=elfv1) -aflags-$(CONFIG_CPU_LITTLE_ENDIAN) += -mabi=elfv2 +cflags-$(CONFIG_PPC64_ELF_ABI_V1) += $(call cc-option,-mabi=elfv1) +cflags-$(CONFIG_PPC64_ELF_ABI_V1) += $(call cc-option,-mcall-aixdesc) +aflags-$(CONFIG_PPC64_ELF_ABI_V1) += $(call cc-option,-mabi=elfv1) +aflags-$(CONFIG_PPC64_ELF_ABI_V2) += -mabi=elfv2 endif endif @@ -141,7 +141,7 @@ endif CFLAGS-$(CONFIG_PPC64) := $(call cc-option,-mtraceback=no) ifndef CONFIG_CC_IS_CLANG -ifdef CONFIG_CPU_LITTLE_ENDIAN +ifdef CONFIG_PPC64_ELF_ABI_V2 CFLAGS-$(CONFIG_PPC64) += $(call cc-option,-mabi=elfv2,$(call cc-option,-mcall-aixdesc)) AFLAGS-$(CONFIG_PPC64) += $(call cc-option,-mabi=elfv2) else @@ -213,7 +213,7 @@ CHECKFLAGS += -m$(BITS) -D__powerpc__ -D__powerpc$(BITS)__ ifdef CONFIG_CPU_BIG_ENDIAN CHECKFLAGS += -D__BIG_ENDIAN__ else -CHECKFLAGS += -D__LITTLE_ENDIAN__ -D_CALL_ELF=2 +CHECKFLAGS += -D__LITTLE_ENDIAN__ endif ifdef CONFIG_476FPE_ERR46 diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile index 008bf0bff1863a5374cf5b53f34776d87143f4c0..a9cd2ea4a8617dd86d74a1d32b2715ab89386a5e 100644 --- a/arch/powerpc/boot/Makefile +++ b/arch/powerpc/boot/Makefile @@ -38,9 +38,13 @@ BOOTCFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \ $(LINUXINCLUDE) ifdef CONFIG_PPC64_BOOT_WRAPPER -BOOTCFLAGS += -m64 +ifdef CONFIG_CPU_LITTLE_ENDIAN +BOOTCFLAGS += -m64 -mcpu=powerpc64le else -BOOTCFLAGS += -m32 +BOOTCFLAGS += -m64 -mcpu=powerpc64 +endif +else +BOOTCFLAGS += -m32 -mcpu=powerpc endif BOOTCFLAGS += -isystem $(shell $(BOOTCC) -print-file-name=include) @@ -49,6 +53,8 @@ ifdef CONFIG_CPU_BIG_ENDIAN BOOTCFLAGS += -mbig-endian else BOOTCFLAGS += -mlittle-endian +endif +ifdef CONFIG_PPC64_ELF_ABI_V2 BOOTCFLAGS += $(call cc-option,-mabi=elfv2) endif diff --git a/arch/powerpc/boot/crt0.S b/arch/powerpc/boot/crt0.S index feadee18e27152f1187055ab8b54c0bae8a0a0d6..44544720daae9fd1f56ec172956670685a8bea73 100644 --- a/arch/powerpc/boot/crt0.S +++ b/arch/powerpc/boot/crt0.S @@ -8,7 +8,8 @@ #include "ppc_asm.h" RELA = 7 -RELACOUNT = 0x6ffffff9 +RELASZ = 8 +RELAENT = 9 .data /* A procedure descriptor used when booting this as a COFF file. @@ -75,34 +76,39 @@ p_base: mflr r10 /* r10 now points to runtime addr of p_base */ bne 11f lwz r9,4(r12) /* get RELA pointer in r9 */ b 12f -11: addis r8,r8,(-RELACOUNT)@ha - cmpwi r8,RELACOUNT@l +11: cmpwi r8,RELASZ + bne .Lcheck_for_relaent + lwz r0,4(r12) /* get RELASZ value in r0 */ + b 12f +.Lcheck_for_relaent: + cmpwi r8,RELAENT bne 12f - lwz r0,4(r12) /* get RELACOUNT value in r0 */ + lwz r14,4(r12) /* get RELAENT value in r14 */ 12: addi r12,r12,8 b 9b /* The relocation section contains a list of relocations. * We now do the R_PPC_RELATIVE ones, which point to words - * which need to be initialized with addend + offset. - * The R_PPC_RELATIVE ones come first and there are RELACOUNT - * of them. */ + * which need to be initialized with addend + offset */ 10: /* skip relocation if we don't have both */ cmpwi r0,0 beq 3f cmpwi r9,0 beq 3f + cmpwi r14,0 + beq 3f add r9,r9,r11 /* Relocate RELA pointer */ + divwu r0,r0,r14 /* RELASZ / RELAENT */ mtctr r0 2: lbz r0,4+3(r9) /* ELF32_R_INFO(reloc->r_info) */ cmpwi r0,22 /* R_PPC_RELATIVE */ - bne 3f + bne .Lnext lwz r12,0(r9) /* reloc->r_offset */ lwz r0,8(r9) /* reloc->r_addend */ add r0,r0,r11 stwx r0,r11,r12 - addi r9,r9,12 +.Lnext: add r9,r9,r14 bdnz 2b /* Do a cache flush for our text, in case the loader didn't */ @@ -160,32 +166,39 @@ p_base: mflr r10 /* r10 now points to runtime addr of p_base */ bne 10f ld r13,8(r11) /* get RELA pointer in r13 */ b 11f -10: addis r12,r12,(-RELACOUNT)@ha - cmpdi r12,RELACOUNT@l - bne 11f - ld r8,8(r11) /* get RELACOUNT value in r8 */ +10: cmpwi r12,RELASZ + bne .Lcheck_for_relaent + lwz r8,8(r11) /* get RELASZ pointer in r8 */ + b 11f +.Lcheck_for_relaent: + cmpwi r12,RELAENT + bne 11f + lwz r14,8(r11) /* get RELAENT pointer in r14 */ 11: addi r11,r11,16 b 9b 12: - cmpdi r13,0 /* check we have both RELA and RELACOUNT */ + cmpdi r13,0 /* check we have both RELA, RELASZ, RELAENT*/ cmpdi cr1,r8,0 beq 3f beq cr1,3f + cmpdi r14,0 + beq 3f /* Calcuate the runtime offset. */ subf r13,r13,r9 /* Run through the list of relocations and process the * R_PPC64_RELATIVE ones. */ + divdu r8,r8,r14 /* RELASZ / RELAENT */ mtctr r8 13: ld r0,8(r9) /* ELF64_R_TYPE(reloc->r_info) */ cmpdi r0,22 /* R_PPC64_RELATIVE */ - bne 3f + bne .Lnext ld r12,0(r9) /* reloc->r_offset */ ld r0,16(r9) /* reloc->r_addend */ add r0,r0,r13 stdx r0,r13,r12 - addi r9,r9,24 +.Lnext: add r9,r9,r14 bdnz 13b /* Do a cache flush for our text, in case the loader didn't */ diff --git a/arch/powerpc/boot/cuboot-hotfoot.c b/arch/powerpc/boot/cuboot-hotfoot.c index 888a6b9bfead2169b657119626874dac0c60e5d0..0e5532f855d619266cc935e14e54b763bc462d1c 100644 --- a/arch/powerpc/boot/cuboot-hotfoot.c +++ b/arch/powerpc/boot/cuboot-hotfoot.c @@ -70,7 +70,7 @@ static void hotfoot_fixups(void) printf("Fixing devtree for 4M Flash\n"); - /* First fix up the base addresse */ + /* First fix up the base address */ getprop(devp, "reg", regs, sizeof(regs)); regs[0] = 0; regs[1] = 0xffc00000; diff --git a/arch/powerpc/boot/dts/fsl/p2020si-post.dtsi b/arch/powerpc/boot/dts/fsl/p2020si-post.dtsi index 884e01bcb2432e4af7f0ad57f80d182d505a76b0..7a590c92fe56a34468afd3cfe30b3a8d0362796f 100644 --- a/arch/powerpc/boot/dts/fsl/p2020si-post.dtsi +++ b/arch/powerpc/boot/dts/fsl/p2020si-post.dtsi @@ -198,4 +198,9 @@ reg = <0xe0000 0x1000>; fsl,has-rstcr; }; + + pmc: power@e0070 { + compatible = "fsl,mpc8548-pmc"; + reg = <0xe0070 0x20>; + }; }; diff --git a/arch/powerpc/boot/dts/microwatt.dts b/arch/powerpc/boot/dts/microwatt.dts index 65b270a90f9450cf2c330bacc558cb559b83ce4f..b69db1d275cd60f1db0950b578e6508a5d4b8d56 100644 --- a/arch/powerpc/boot/dts/microwatt.dts +++ b/arch/powerpc/boot/dts/microwatt.dts @@ -90,6 +90,8 @@ 64-bit; d-cache-size = <0x1000>; ibm,chip-id = <0>; + ibm,mmu-lpid-bits = <12>; + ibm,mmu-pid-bits = <20>; }; }; diff --git a/arch/powerpc/boot/ops.h b/arch/powerpc/boot/ops.h index 6455fc9a244f821f74ae37e1c465b5b9658f5738..8334bc3cbe499a166edcfaa74e59d91f69bf5051 100644 --- a/arch/powerpc/boot/ops.h +++ b/arch/powerpc/boot/ops.h @@ -200,12 +200,6 @@ void __dt_fixup_mac_addresses(u32 startindex, ...); __dt_fixup_mac_addresses(0, __VA_ARGS__, NULL) -static inline void *find_node_by_linuxphandle(const u32 linuxphandle) -{ - return find_node_by_prop_value(NULL, "linux,phandle", - (char *)&linuxphandle, sizeof(u32)); -} - static inline char *get_path(const void *phandle, char *buf, int len) { if (dt_ops.get_path) diff --git a/arch/powerpc/boot/wrapper b/arch/powerpc/boot/wrapper index 9184eda780fdc80b8eb125bb253c3b3469860933..55978f32fa7751373b24868e93603d57ad916d00 100755 --- a/arch/powerpc/boot/wrapper +++ b/arch/powerpc/boot/wrapper @@ -162,7 +162,7 @@ while [ "$#" -gt 0 ]; do fi ;; --no-gzip) - # a "feature" of the the wrapper script is that it can be used outside + # a "feature" of the wrapper script is that it can be used outside # the kernel tree. So keeping this around for backwards compatibility. compression= uboot_comp=none diff --git a/arch/powerpc/crypto/aes-spe-glue.c b/arch/powerpc/crypto/aes-spe-glue.c index c2b23b69d7b1dadf90936629cb39c18e7519c533..e8dfe9fb0266896a548899b71ae2e770b3da95b2 100644 --- a/arch/powerpc/crypto/aes-spe-glue.c +++ b/arch/powerpc/crypto/aes-spe-glue.c @@ -404,7 +404,7 @@ static int ppc_xts_decrypt(struct skcipher_request *req) /* * Algorithm definitions. Disabling alignment (cra_alignmask=0) was chosen - * because the e500 platform can handle unaligned reads/writes very efficently. + * because the e500 platform can handle unaligned reads/writes very efficiently. * This improves IPsec thoughput by another few percent. Additionally we assume * that AES context is always aligned to at least 8 bytes because it is created * with kmalloc() in the crypto infrastructure diff --git a/arch/powerpc/include/asm/book3s/64/hash.h b/arch/powerpc/include/asm/book3s/64/hash.h index a7a0572f38465ced214c446163cc028e52ec3884..17e7a778c856c3bd6b33bd500db88f80f6d4b7b0 100644 --- a/arch/powerpc/include/asm/book3s/64/hash.h +++ b/arch/powerpc/include/asm/book3s/64/hash.h @@ -18,6 +18,10 @@ #include #endif +#define H_PTRS_PER_PTE (1 << H_PTE_INDEX_SIZE) +#define H_PTRS_PER_PMD (1 << H_PMD_INDEX_SIZE) +#define H_PTRS_PER_PUD (1 << H_PUD_INDEX_SIZE) + /* Bits to set in a PMD/PUD/PGD entry valid bit*/ #define HASH_PMD_VAL_BITS (0x8000000000000000UL) #define HASH_PUD_VAL_BITS (0x8000000000000000UL) diff --git a/arch/powerpc/include/asm/book3s/64/hugetlb.h b/arch/powerpc/include/asm/book3s/64/hugetlb.h index 12e150e615b7756d040f256bd841bfb60c41e072..b37a28f62cf6c2a7dc7de68c337d1ef166783829 100644 --- a/arch/powerpc/include/asm/book3s/64/hugetlb.h +++ b/arch/powerpc/include/asm/book3s/64/hugetlb.h @@ -8,10 +8,6 @@ */ void radix__flush_hugetlb_page(struct vm_area_struct *vma, unsigned long vmaddr); void radix__local_flush_hugetlb_page(struct vm_area_struct *vma, unsigned long vmaddr); -extern unsigned long -radix__hugetlb_get_unmapped_area(struct file *file, unsigned long addr, - unsigned long len, unsigned long pgoff, - unsigned long flags); extern void radix__huge_ptep_modify_prot_commit(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep, diff --git a/arch/powerpc/include/asm/book3s/64/mmu-hash.h b/arch/powerpc/include/asm/book3s/64/mmu-hash.h index 21f7809429115b19216b6bba9a7777a1ab2bc739..1c4eebbc69c94b9d76187de65ee2796a78f8954a 100644 --- a/arch/powerpc/include/asm/book3s/64/mmu-hash.h +++ b/arch/powerpc/include/asm/book3s/64/mmu-hash.h @@ -18,6 +18,7 @@ * complete pgtable.h but only a portion of it. */ #include +#include #include #include diff --git a/arch/powerpc/include/asm/book3s/64/mmu.h b/arch/powerpc/include/asm/book3s/64/mmu.h index 006cbec70ffe5d3c553586b805a64d33ae25bb22..570a4960cf1790e00e1465979cd74bdf143b9955 100644 --- a/arch/powerpc/include/asm/book3s/64/mmu.h +++ b/arch/powerpc/include/asm/book3s/64/mmu.h @@ -4,12 +4,6 @@ #include -#ifdef CONFIG_HUGETLB_PAGE -#define HAVE_ARCH_HUGETLB_UNMAPPED_AREA -#endif -#define HAVE_ARCH_UNMAPPED_AREA -#define HAVE_ARCH_UNMAPPED_AREA_TOPDOWN - #ifndef __ASSEMBLY__ /* * Page size definition diff --git a/arch/powerpc/include/asm/book3s/64/pgtable.h b/arch/powerpc/include/asm/book3s/64/pgtable.h index eecff203686988f79b6915e4050ae14fa410d73a..cb9d5fd39d7f3b00449d430d4781f4da24d66d80 100644 --- a/arch/powerpc/include/asm/book3s/64/pgtable.h +++ b/arch/powerpc/include/asm/book3s/64/pgtable.h @@ -231,6 +231,9 @@ extern unsigned long __pmd_frag_size_shift; #define PTRS_PER_PUD (1 << PUD_INDEX_SIZE) #define PTRS_PER_PGD (1 << PGD_INDEX_SIZE) +#define MAX_PTRS_PER_PTE ((H_PTRS_PER_PTE > R_PTRS_PER_PTE) ? H_PTRS_PER_PTE : R_PTRS_PER_PTE) +#define MAX_PTRS_PER_PMD ((H_PTRS_PER_PMD > R_PTRS_PER_PMD) ? H_PTRS_PER_PMD : R_PTRS_PER_PMD) +#define MAX_PTRS_PER_PUD ((H_PTRS_PER_PUD > R_PTRS_PER_PUD) ? H_PTRS_PER_PUD : R_PTRS_PER_PUD) #define MAX_PTRS_PER_PGD (1 << (H_PGD_INDEX_SIZE > RADIX_PGD_INDEX_SIZE ? \ H_PGD_INDEX_SIZE : RADIX_PGD_INDEX_SIZE)) diff --git a/arch/powerpc/include/asm/book3s/64/radix.h b/arch/powerpc/include/asm/book3s/64/radix.h index d090d961234885a7aeb0aac0cc479f689a5cf48e..686001eda93663dc1238f774fe0e9a2b1bce78eb 100644 --- a/arch/powerpc/include/asm/book3s/64/radix.h +++ b/arch/powerpc/include/asm/book3s/64/radix.h @@ -35,6 +35,11 @@ #define RADIX_PMD_SHIFT (PAGE_SHIFT + RADIX_PTE_INDEX_SIZE) #define RADIX_PUD_SHIFT (RADIX_PMD_SHIFT + RADIX_PMD_INDEX_SIZE) #define RADIX_PGD_SHIFT (RADIX_PUD_SHIFT + RADIX_PUD_INDEX_SIZE) + +#define R_PTRS_PER_PTE (1 << RADIX_PTE_INDEX_SIZE) +#define R_PTRS_PER_PMD (1 << RADIX_PMD_INDEX_SIZE) +#define R_PTRS_PER_PUD (1 << RADIX_PUD_INDEX_SIZE) + /* * Size of EA range mapped by our pagetables. */ @@ -68,11 +73,11 @@ * * * 3rd quadrant expanded: - * +------------------------------+ - * | | + * +------------------------------+ Highest address (0xc010000000000000) + * +------------------------------+ KASAN shadow end (0xc00fc00000000000) * | | * | | - * +------------------------------+ Kernel vmemmap end (0xc010000000000000) + * +------------------------------+ Kernel vmemmap end/shadow start (0xc00e000000000000) * | | * | 512TB | * | | @@ -91,6 +96,7 @@ * +------------------------------+ Kernel linear (0xc.....) */ +/* For the sizes of the shadow area, see kasan.h */ /* * If we store section details in page->flags we can't increase the MAX_PHYSMEM_BITS diff --git a/arch/powerpc/include/asm/book3s/64/slice.h b/arch/powerpc/include/asm/book3s/64/slice.h index f0d3194ba41bda2d5fd0a2c545c08d0393c90f78..5fbe18544cbd1b629640cd4d537739b1dd39d2e7 100644 --- a/arch/powerpc/include/asm/book3s/64/slice.h +++ b/arch/powerpc/include/asm/book3s/64/slice.h @@ -2,6 +2,16 @@ #ifndef _ASM_POWERPC_BOOK3S_64_SLICE_H #define _ASM_POWERPC_BOOK3S_64_SLICE_H +#ifndef __ASSEMBLY__ + +#ifdef CONFIG_PPC_64S_HASH_MMU +#ifdef CONFIG_HUGETLB_PAGE +#define HAVE_ARCH_HUGETLB_UNMAPPED_AREA +#endif +#define HAVE_ARCH_UNMAPPED_AREA +#define HAVE_ARCH_UNMAPPED_AREA_TOPDOWN +#endif + #define SLICE_LOW_SHIFT 28 #define SLICE_LOW_TOP (0x100000000ul) #define SLICE_NUM_LOW (SLICE_LOW_TOP >> SLICE_LOW_SHIFT) @@ -13,4 +23,20 @@ #define SLB_ADDR_LIMIT_DEFAULT DEFAULT_MAP_WINDOW_USER64 +struct mm_struct; + +unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len, + unsigned long flags, unsigned int psize, + int topdown); + +unsigned int get_slice_psize(struct mm_struct *mm, unsigned long addr); + +void slice_set_range_psize(struct mm_struct *mm, unsigned long start, + unsigned long len, unsigned int psize); + +void slice_init_new_context_exec(struct mm_struct *mm); +void slice_setup_new_exec(void); + +#endif /* __ASSEMBLY__ */ + #endif /* _ASM_POWERPC_BOOK3S_64_SLICE_H */ diff --git a/arch/powerpc/include/asm/checksum.h b/arch/powerpc/include/asm/checksum.h index ab3832b93f0a91045b13538f71514c10766ed347..4b573a3b7e176e3092c76607d7d440b7c4d0f3bb 100644 --- a/arch/powerpc/include/asm/checksum.h +++ b/arch/powerpc/include/asm/checksum.h @@ -38,14 +38,15 @@ extern __wsum csum_and_copy_to_user(const void *src, void __user *dst, */ static inline __sum16 csum_fold(__wsum sum) { - unsigned int tmp; - - /* swap the two 16-bit halves of sum */ - __asm__("rlwinm %0,%1,16,0,31" : "=r" (tmp) : "r" (sum)); - /* if there is a carry from adding the two 16-bit halves, - it will carry from the lower half into the upper half, - giving us the correct sum in the upper half. */ - return (__force __sum16)(~((__force u32)sum + tmp) >> 16); + u32 tmp = (__force u32)sum; + + /* + * swap the two 16-bit halves of sum + * if there is a carry from adding the two 16-bit halves, + * it will carry from the lower half into the upper half, + * giving us the correct sum in the upper half. + */ + return (__force __sum16)(~(tmp + rol32(tmp, 16)) >> 16); } static inline u32 from64to32(u64 x) @@ -95,16 +96,15 @@ static __always_inline __wsum csum_add(__wsum csum, __wsum addend) { #ifdef __powerpc64__ u64 res = (__force u64)csum; -#endif + + res += (__force u64)addend; + return (__force __wsum)((u32)res + (res >> 32)); +#else if (__builtin_constant_p(csum) && csum == 0) return addend; if (__builtin_constant_p(addend) && addend == 0) return csum; -#ifdef __powerpc64__ - res += (__force u64)addend; - return (__force __wsum)((u32)res + (res >> 32)); -#else asm("addc %0,%0,%1;" "addze %0,%0;" : "+r" (csum) : "r" (addend) : "xer"); diff --git a/arch/powerpc/include/asm/code-patching.h b/arch/powerpc/include/asm/code-patching.h index 409483b2d0ceec15fb6a009e5bd2922a6cea99ac..1c6316ec4b74f9bdc9722bfd03d9e1cbf39be6cf 100644 --- a/arch/powerpc/include/asm/code-patching.h +++ b/arch/powerpc/include/asm/code-patching.h @@ -22,10 +22,55 @@ #define BRANCH_SET_LINK 0x1 #define BRANCH_ABSOLUTE 0x2 -bool is_offset_in_branch_range(long offset); -bool is_offset_in_cond_branch_range(long offset); -int create_branch(ppc_inst_t *instr, const u32 *addr, - unsigned long target, int flags); +DECLARE_STATIC_KEY_FALSE(init_mem_is_free); + +/* + * Powerpc branch instruction is : + * + * 0 6 30 31 + * +---------+----------------+---+---+ + * | opcode | LI |AA |LK | + * +---------+----------------+---+---+ + * Where AA = 0 and LK = 0 + * + * LI is a signed 24 bits integer. The real branch offset is computed + * by: imm32 = SignExtend(LI:'0b00', 32); + * + * So the maximum forward branch should be: + * (0x007fffff << 2) = 0x01fffffc = 0x1fffffc + * The maximum backward branch should be: + * (0xff800000 << 2) = 0xfe000000 = -0x2000000 + */ +static inline bool is_offset_in_branch_range(long offset) +{ + return (offset >= -0x2000000 && offset <= 0x1fffffc && !(offset & 0x3)); +} + +static inline bool is_offset_in_cond_branch_range(long offset) +{ + return offset >= -0x8000 && offset <= 0x7fff && !(offset & 0x3); +} + +static inline int create_branch(ppc_inst_t *instr, const u32 *addr, + unsigned long target, int flags) +{ + long offset; + + *instr = ppc_inst(0); + offset = target; + if (! (flags & BRANCH_ABSOLUTE)) + offset = offset - (unsigned long)addr; + + /* Check we can represent the target in the instruction format */ + if (!is_offset_in_branch_range(offset)) + return 1; + + /* Mask out the flags and target, so they don't step on each other. */ + *instr = ppc_inst(0x48000000 | (flags & 0x3) | (offset & 0x03FFFFFC)); + + return 0; +} + int create_cond_branch(ppc_inst_t *instr, const u32 *addr, unsigned long target, int flags); int patch_branch(u32 *addr, unsigned long target, int flags); @@ -87,7 +132,7 @@ bool is_conditional_branch(ppc_inst_t instr); static inline unsigned long ppc_function_entry(void *func) { -#ifdef PPC64_ELF_ABI_v2 +#ifdef CONFIG_PPC64_ELF_ABI_V2 u32 *insn = func; /* @@ -112,7 +157,7 @@ static inline unsigned long ppc_function_entry(void *func) return (unsigned long)(insn + 2); else return (unsigned long)func; -#elif defined(PPC64_ELF_ABI_v1) +#elif defined(CONFIG_PPC64_ELF_ABI_V1) /* * On PPC64 ABIv1 the function pointer actually points to the * function's descriptor. The first entry in the descriptor is the @@ -126,7 +171,7 @@ static inline unsigned long ppc_function_entry(void *func) static inline unsigned long ppc_global_function_entry(void *func) { -#ifdef PPC64_ELF_ABI_v2 +#ifdef CONFIG_PPC64_ELF_ABI_V2 /* PPC64 ABIv2 the global entry point is at the address */ return (unsigned long)func; #else @@ -143,7 +188,7 @@ static inline unsigned long ppc_global_function_entry(void *func) static inline unsigned long ppc_kallsyms_lookup_name(const char *name) { unsigned long addr; -#ifdef PPC64_ELF_ABI_v1 +#ifdef CONFIG_PPC64_ELF_ABI_V1 /* check for dot variant */ char dot_name[1 + KSYM_NAME_LEN]; bool dot_appended = false; @@ -164,7 +209,7 @@ static inline unsigned long ppc_kallsyms_lookup_name(const char *name) if (!addr && dot_appended) /* Let's try the original non-dot symbol lookup */ addr = kallsyms_lookup_name(name); -#elif defined(PPC64_ELF_ABI_v2) +#elif defined(CONFIG_PPC64_ELF_ABI_V2) addr = kallsyms_lookup_name(name); if (addr) addr = ppc_function_entry((void *)addr); @@ -174,14 +219,13 @@ static inline unsigned long ppc_kallsyms_lookup_name(const char *name) return addr; } -#ifdef CONFIG_PPC64 /* * Some instruction encodings commonly used in dynamic ftracing * and function live patching. */ /* This must match the definition of STK_GOT in */ -#ifdef PPC64_ELF_ABI_v2 +#ifdef CONFIG_PPC64_ELF_ABI_V2 #define R2_STACK_OFFSET 24 #else #define R2_STACK_OFFSET 40 @@ -191,6 +235,5 @@ static inline unsigned long ppc_kallsyms_lookup_name(const char *name) /* usually preceded by a mflr r0 */ #define PPC_INST_STD_LR PPC_RAW_STD(_R0, _R1, PPC_LR_STKOFF) -#endif /* CONFIG_PPC64 */ #endif /* _ASM_POWERPC_CODE_PATCHING_H */ diff --git a/arch/powerpc/include/asm/compat.h b/arch/powerpc/include/asm/compat.h index 7afc96fb6524b339e372cc0327658c5e6460b10c..dda4091fd0123618ecc769b9be80c33d13c41d73 100644 --- a/arch/powerpc/include/asm/compat.h +++ b/arch/powerpc/include/asm/compat.h @@ -8,21 +8,20 @@ #include #include +#define compat_ipc_pid_t compat_ipc_pid_t +typedef u16 compat_ipc_pid_t; + +#define compat_ipc64_perm compat_ipc64_perm + #include -#define COMPAT_USER_HZ 100 #ifdef __BIG_ENDIAN__ #define COMPAT_UTS_MACHINE "ppc\0\0" #else #define COMPAT_UTS_MACHINE "ppcle\0\0" #endif -typedef u32 __compat_uid_t; -typedef u32 __compat_gid_t; -typedef u32 compat_dev_t; typedef s16 compat_nlink_t; -typedef u16 compat_ipc_pid_t; -typedef __kernel_fsid_t compat_fsid_t; struct compat_stat { compat_dev_t st_dev; @@ -44,45 +43,6 @@ struct compat_stat { u32 __unused4[2]; }; -struct compat_flock { - short l_type; - short l_whence; - compat_off_t l_start; - compat_off_t l_len; - compat_pid_t l_pid; -}; - -#define F_GETLK64 12 /* using 'struct flock64' */ -#define F_SETLK64 13 -#define F_SETLKW64 14 - -struct compat_flock64 { - short l_type; - short l_whence; - compat_loff_t l_start; - compat_loff_t l_len; - compat_pid_t l_pid; -}; - -struct compat_statfs { - int f_type; - int f_bsize; - int f_blocks; - int f_bfree; - int f_bavail; - int f_files; - int f_ffree; - compat_fsid_t f_fsid; - int f_namelen; /* SunOS ignores this field. */ - int f_frsize; - int f_flags; - int f_spare[4]; -}; - -#define COMPAT_RLIM_INFINITY 0xffffffff - -#define COMPAT_OFF_T_MAX 0x7fffffff - /* * ipc64_perm is actually 32/64bit clean but since the compat layer refers to * it we may as well define it. diff --git a/arch/powerpc/include/asm/cputable.h b/arch/powerpc/include/asm/cputable.h index e85c849214a2f12f3ccce43af6cd9d16b02300c9..549eb6dd146f1d600516bee9235fdfe8bf5525f2 100644 --- a/arch/powerpc/include/asm/cputable.h +++ b/arch/powerpc/include/asm/cputable.h @@ -440,6 +440,10 @@ static inline void cpu_feature_keys_init(void) { } #define CPU_FTRS_POWER9_DD2_2 (CPU_FTRS_POWER9 | CPU_FTR_POWER9_DD2_1 | \ CPU_FTR_P9_TM_HV_ASSIST | \ CPU_FTR_P9_TM_XER_SO_BUG) +#define CPU_FTRS_POWER9_DD2_3 (CPU_FTRS_POWER9 | CPU_FTR_POWER9_DD2_1 | \ + CPU_FTR_P9_TM_HV_ASSIST | \ + CPU_FTR_P9_TM_XER_SO_BUG | \ + CPU_FTR_DAWR) #define CPU_FTRS_POWER10 (CPU_FTR_LWSYNC | \ CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | CPU_FTR_ARCH_206 |\ CPU_FTR_MMCRA | CPU_FTR_SMT | \ @@ -469,14 +473,16 @@ static inline void cpu_feature_keys_init(void) { } #define CPU_FTRS_POSSIBLE \ (CPU_FTRS_POWER7 | CPU_FTRS_POWER8E | CPU_FTRS_POWER8 | \ CPU_FTR_ALTIVEC_COMP | CPU_FTR_VSX_COMP | CPU_FTRS_POWER9 | \ - CPU_FTRS_POWER9_DD2_1 | CPU_FTRS_POWER9_DD2_2 | CPU_FTRS_POWER10) + CPU_FTRS_POWER9_DD2_1 | CPU_FTRS_POWER9_DD2_2 | \ + CPU_FTRS_POWER9_DD2_3 | CPU_FTRS_POWER10) #else #define CPU_FTRS_POSSIBLE \ (CPU_FTRS_PPC970 | CPU_FTRS_POWER5 | \ CPU_FTRS_POWER6 | CPU_FTRS_POWER7 | CPU_FTRS_POWER8E | \ CPU_FTRS_POWER8 | CPU_FTRS_CELL | CPU_FTRS_PA6T | \ CPU_FTR_VSX_COMP | CPU_FTR_ALTIVEC_COMP | CPU_FTRS_POWER9 | \ - CPU_FTRS_POWER9_DD2_1 | CPU_FTRS_POWER9_DD2_2 | CPU_FTRS_POWER10) + CPU_FTRS_POWER9_DD2_1 | CPU_FTRS_POWER9_DD2_2 | \ + CPU_FTRS_POWER9_DD2_3 | CPU_FTRS_POWER10) #endif /* CONFIG_CPU_LITTLE_ENDIAN */ #endif #else @@ -541,14 +547,16 @@ enum { #define CPU_FTRS_ALWAYS \ (CPU_FTRS_POSSIBLE & ~CPU_FTR_HVMODE & CPU_FTRS_POWER7 & \ CPU_FTRS_POWER8E & CPU_FTRS_POWER8 & CPU_FTRS_POWER9 & \ - CPU_FTRS_POWER9_DD2_1 & CPU_FTRS_DT_CPU_BASE) + CPU_FTRS_POWER9_DD2_1 & CPU_FTRS_POWER9_DD2_2 & \ + CPU_FTRS_POWER10 & CPU_FTRS_DT_CPU_BASE) #else #define CPU_FTRS_ALWAYS \ (CPU_FTRS_PPC970 & CPU_FTRS_POWER5 & \ CPU_FTRS_POWER6 & CPU_FTRS_POWER7 & CPU_FTRS_CELL & \ CPU_FTRS_PA6T & CPU_FTRS_POWER8 & CPU_FTRS_POWER8E & \ ~CPU_FTR_HVMODE & CPU_FTRS_POSSIBLE & CPU_FTRS_POWER9 & \ - CPU_FTRS_POWER9_DD2_1 & CPU_FTRS_DT_CPU_BASE) + CPU_FTRS_POWER9_DD2_1 & CPU_FTRS_POWER9_DD2_2 & \ + CPU_FTRS_POWER10 & CPU_FTRS_DT_CPU_BASE) #endif /* CONFIG_CPU_LITTLE_ENDIAN */ #endif #else diff --git a/arch/powerpc/include/asm/drmem.h b/arch/powerpc/include/asm/drmem.h index 4265d5e95c2c0a620912316eed5341beaf5e7190..13bf6dee8e2d478b61bacbadb55e1b2b215f8e2a 100644 --- a/arch/powerpc/include/asm/drmem.h +++ b/arch/powerpc/include/asm/drmem.h @@ -23,6 +23,9 @@ struct drmem_lmb_info { u64 lmb_size; }; +struct device_node; +struct property; + extern struct drmem_lmb_info *drmem_info; static inline struct drmem_lmb *drmem_lmb_next(struct drmem_lmb *lmb, diff --git a/arch/powerpc/include/asm/eeh.h b/arch/powerpc/include/asm/eeh.h index bd513fd49be990e171006a8dd484185d0c787984..514dd056c2c84b58cec5a2353c87ebc1917eb2fd 100644 --- a/arch/powerpc/include/asm/eeh.h +++ b/arch/powerpc/include/asm/eeh.h @@ -333,8 +333,6 @@ static inline bool eeh_enabled(void) static inline void eeh_show_enabled(void) { } -static inline void eeh_dev_phb_init_dynamic(struct pci_controller *phb) { } - static inline int eeh_check_failure(const volatile void __iomem *token) { return 0; @@ -354,11 +352,7 @@ static inline int eeh_phb_pe_create(struct pci_controller *phb) { return 0; } #endif /* CONFIG_EEH */ #if defined(CONFIG_PPC_PSERIES) && defined(CONFIG_EEH) -void pseries_eeh_init_edev(struct pci_dn *pdn); void pseries_eeh_init_edev_recursive(struct pci_dn *pdn); -#else -static inline void pseries_eeh_add_device_early(struct pci_dn *pdn) { } -static inline void pseries_eeh_add_device_tree_early(struct pci_dn *pdn) { } #endif #ifdef CONFIG_PPC64 diff --git a/arch/powerpc/include/asm/elf.h b/arch/powerpc/include/asm/elf.h index 971589a21bc033ee95857817f563b123bb10d90c..79f1c480b5eb2fe6e3266c46fe8c232226693ddd 100644 --- a/arch/powerpc/include/asm/elf.h +++ b/arch/powerpc/include/asm/elf.h @@ -160,7 +160,7 @@ extern int arch_setup_additional_pages(struct linux_binprm *bprm, * even if DLINFO_ARCH_ITEMS goes to zero or is undefined. * update AT_VECTOR_SIZE_ARCH if the number of NEW_AUX_ENT entries changes */ -#define ARCH_DLINFO \ +#define COMMON_ARCH_DLINFO \ do { \ /* Handle glibc compatibility. */ \ NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC); \ @@ -173,6 +173,18 @@ do { \ ARCH_DLINFO_CACHE_GEOMETRY; \ } while (0) +#define ARCH_DLINFO \ +do { \ + COMMON_ARCH_DLINFO; \ + NEW_AUX_ENT(AT_MINSIGSTKSZ, get_min_sigframe_size()); \ +} while (0) + +#define COMPAT_ARCH_DLINFO \ +do { \ + COMMON_ARCH_DLINFO; \ + NEW_AUX_ENT(AT_MINSIGSTKSZ, get_min_sigframe_size_compat()); \ +} while (0) + /* Relocate the kernel image to @final_address */ void relocate(unsigned long final_address); diff --git a/arch/powerpc/include/asm/fadump-internal.h b/arch/powerpc/include/asm/fadump-internal.h index 81bcb9abb3718fdf3cfa9898efd52b5c1656c384..27f9e11eda28cd2c9254b52e9fdafe1eac820003 100644 --- a/arch/powerpc/include/asm/fadump-internal.h +++ b/arch/powerpc/include/asm/fadump-internal.h @@ -50,7 +50,7 @@ struct fadump_crash_info_header { u64 elfcorehdr_addr; u32 crashing_cpu; struct pt_regs regs; - struct cpumask online_mask; + struct cpumask cpu_mask; }; struct fadump_memory_range { diff --git a/arch/powerpc/include/asm/fsl_85xx_cache_sram.h b/arch/powerpc/include/asm/fsl_85xx_cache_sram.h deleted file mode 100644 index 0235a0447baa465e1ac852b5864559c64b7ee88a..0000000000000000000000000000000000000000 --- a/arch/powerpc/include/asm/fsl_85xx_cache_sram.h +++ /dev/null @@ -1,35 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Copyright 2009 Freescale Semiconductor, Inc. - * - * Cache SRAM handling for QorIQ platform - * - * Author: Vivek Mahajan - - * This file is derived from the original work done - * by Sylvain Munaut for the Bestcomm SRAM allocator. - */ - -#ifndef __ASM_POWERPC_FSL_85XX_CACHE_SRAM_H__ -#define __ASM_POWERPC_FSL_85XX_CACHE_SRAM_H__ - -#include -#include - -/* - * Cache-SRAM - */ - -struct mpc85xx_cache_sram { - phys_addr_t base_phys; - void *base_virt; - unsigned int size; - rh_info_t *rh; - spinlock_t lock; -}; - -extern void mpc85xx_cache_sram_free(void *ptr); -extern void *mpc85xx_cache_sram_alloc(unsigned int size, - phys_addr_t *phys, unsigned int align); - -#endif /* __AMS_POWERPC_FSL_85XX_CACHE_SRAM_H__ */ diff --git a/arch/powerpc/include/asm/ftrace.h b/arch/powerpc/include/asm/ftrace.h index d83758acd1c7c35bec3372ac73ce666e1aeea7e2..3cee7115441b41cb92bbe6230bb5f936edda45c0 100644 --- a/arch/powerpc/include/asm/ftrace.h +++ b/arch/powerpc/include/asm/ftrace.h @@ -64,7 +64,7 @@ void ftrace_graph_func(unsigned long ip, unsigned long parent_ip, * those. */ #define ARCH_HAS_SYSCALL_MATCH_SYM_NAME -#ifdef PPC64_ELF_ABI_v1 +#ifdef CONFIG_PPC64_ELF_ABI_V1 static inline bool arch_syscall_match_sym_name(const char *sym, const char *name) { /* We need to skip past the initial dot, and the __se_sys alias */ @@ -83,10 +83,10 @@ static inline bool arch_syscall_match_sym_name(const char *sym, const char *name (!strncmp(sym, "ppc32_", 6) && !strcmp(sym + 6, name + 4)) || (!strncmp(sym, "ppc64_", 6) && !strcmp(sym + 6, name + 4)); } -#endif /* PPC64_ELF_ABI_v1 */ +#endif /* CONFIG_PPC64_ELF_ABI_V1 */ #endif /* CONFIG_FTRACE_SYSCALLS */ -#ifdef CONFIG_PPC64 +#if defined(CONFIG_PPC64) && defined(CONFIG_FUNCTION_TRACER) #include static inline void this_cpu_disable_ftrace(void) @@ -110,11 +110,13 @@ static inline u8 this_cpu_get_ftrace_enabled(void) return get_paca()->ftrace_enabled; } +void ftrace_free_init_tramp(void); #else /* CONFIG_PPC64 */ static inline void this_cpu_disable_ftrace(void) { } static inline void this_cpu_enable_ftrace(void) { } static inline void this_cpu_set_ftrace_enabled(u8 ftrace_enabled) { } static inline u8 this_cpu_get_ftrace_enabled(void) { return 1; } +static inline void ftrace_free_init_tramp(void) { } #endif /* CONFIG_PPC64 */ #endif /* !__ASSEMBLY__ */ diff --git a/arch/powerpc/include/asm/hugetlb.h b/arch/powerpc/include/asm/hugetlb.h index 8a5674fd120d9e8b700cfdaea6fa7b2dc6624bc9..32ce0fb7548f83712fe4a6b7fcc7be5e06c51f67 100644 --- a/arch/powerpc/include/asm/hugetlb.h +++ b/arch/powerpc/include/asm/hugetlb.h @@ -24,7 +24,7 @@ static inline int is_hugepage_only_range(struct mm_struct *mm, unsigned long addr, unsigned long len) { - if (IS_ENABLED(CONFIG_PPC_MM_SLICES) && !radix_enabled()) + if (IS_ENABLED(CONFIG_PPC_64S_HASH_MMU) && !radix_enabled()) return slice_is_hugepage_only_range(mm, addr, len); return 0; } diff --git a/arch/powerpc/include/asm/inst.h b/arch/powerpc/include/asm/inst.h index 80b6d74146c6fe59a44743cf17d235ae000dcb2b..b49aae9f6f27b0d0ddafed047e9ea55d54d353b5 100644 --- a/arch/powerpc/include/asm/inst.h +++ b/arch/powerpc/include/asm/inst.h @@ -158,13 +158,10 @@ static inline char *__ppc_inst_as_str(char str[PPC_INST_STR_LEN], ppc_inst_t x) __str; \ }) -static inline int copy_inst_from_kernel_nofault(ppc_inst_t *inst, u32 *src) +static inline int __copy_inst_from_kernel_nofault(ppc_inst_t *inst, u32 *src) { unsigned int val, suffix; - if (unlikely(!is_kernel_addr((unsigned long)src))) - return -ERANGE; - /* See https://github.com/ClangBuiltLinux/linux/issues/1521 */ #if defined(CONFIG_CC_IS_CLANG) && CONFIG_CLANG_VERSION < 140000 val = suffix = 0; @@ -181,4 +178,12 @@ Efault: return -EFAULT; } +static inline int copy_inst_from_kernel_nofault(ppc_inst_t *inst, u32 *src) +{ + if (unlikely(!is_kernel_addr((unsigned long)src))) + return -ERANGE; + + return __copy_inst_from_kernel_nofault(inst, src); +} + #endif /* _ASM_POWERPC_INST_H */ diff --git a/arch/powerpc/include/asm/interrupt.h b/arch/powerpc/include/asm/interrupt.h index f964ef5c57d80d85779aa69410861a17e0f4484d..b14f54d789d2cff9544d33733c4d1ee1de022ba9 100644 --- a/arch/powerpc/include/asm/interrupt.h +++ b/arch/powerpc/include/asm/interrupt.h @@ -324,22 +324,46 @@ static inline void interrupt_nmi_enter_prepare(struct pt_regs *regs, struct inte } #endif + /* If data relocations are enabled, it's safe to use nmi_enter() */ + if (mfmsr() & MSR_DR) { + nmi_enter(); + return; + } + /* - * Do not use nmi_enter() for pseries hash guest taking a real-mode + * But do not use nmi_enter() for pseries hash guest taking a real-mode * NMI because not everything it touches is within the RMA limit. */ - if (!IS_ENABLED(CONFIG_PPC_BOOK3S_64) || - !firmware_has_feature(FW_FEATURE_LPAR) || - radix_enabled() || (mfmsr() & MSR_DR)) - nmi_enter(); + if (IS_ENABLED(CONFIG_PPC_BOOK3S_64) && + firmware_has_feature(FW_FEATURE_LPAR) && + !radix_enabled()) + return; + + /* + * Likewise, don't use it if we have some form of instrumentation (like + * KASAN shadow) that is not safe to access in real mode (even on radix) + */ + if (IS_ENABLED(CONFIG_KASAN)) + return; + + /* Otherwise, it should be safe to call it */ + nmi_enter(); } static inline void interrupt_nmi_exit_prepare(struct pt_regs *regs, struct interrupt_nmi_state *state) { - if (!IS_ENABLED(CONFIG_PPC_BOOK3S_64) || - !firmware_has_feature(FW_FEATURE_LPAR) || - radix_enabled() || (mfmsr() & MSR_DR)) + if (mfmsr() & MSR_DR) { + // nmi_exit if relocations are on nmi_exit(); + } else if (IS_ENABLED(CONFIG_PPC_BOOK3S_64) && + firmware_has_feature(FW_FEATURE_LPAR) && + !radix_enabled()) { + // no nmi_exit for a pseries hash guest taking a real mode exception + } else if (IS_ENABLED(CONFIG_KASAN)) { + // no nmi_exit for KASAN in real mode + } else { + nmi_exit(); + } /* * nmi does not call nap_adjust_return because nmi should not create @@ -407,7 +431,8 @@ static inline void interrupt_nmi_exit_prepare(struct pt_regs *regs, struct inter * Specific handlers may have additional restrictions. */ #define DEFINE_INTERRUPT_HANDLER_RAW(func) \ -static __always_inline long ____##func(struct pt_regs *regs); \ +static __always_inline __no_sanitize_address __no_kcsan long \ +____##func(struct pt_regs *regs); \ \ interrupt_handler long func(struct pt_regs *regs) \ { \ @@ -421,7 +446,8 @@ interrupt_handler long func(struct pt_regs *regs) \ } \ NOKPROBE_SYMBOL(func); \ \ -static __always_inline long ____##func(struct pt_regs *regs) +static __always_inline __no_sanitize_address __no_kcsan long \ +____##func(struct pt_regs *regs) /** * DECLARE_INTERRUPT_HANDLER - Declare synchronous interrupt handler function @@ -541,7 +567,8 @@ static __always_inline void ____##func(struct pt_regs *regs) * body with a pair of curly brackets. */ #define DEFINE_INTERRUPT_HANDLER_NMI(func) \ -static __always_inline long ____##func(struct pt_regs *regs); \ +static __always_inline __no_sanitize_address __no_kcsan long \ +____##func(struct pt_regs *regs); \ \ interrupt_handler long func(struct pt_regs *regs) \ { \ @@ -558,7 +585,8 @@ interrupt_handler long func(struct pt_regs *regs) \ } \ NOKPROBE_SYMBOL(func); \ \ -static __always_inline long ____##func(struct pt_regs *regs) +static __always_inline __no_sanitize_address __no_kcsan long \ +____##func(struct pt_regs *regs) /* Interrupt handlers */ diff --git a/arch/powerpc/include/asm/io.h b/arch/powerpc/include/asm/io.h index fee979d3a1aa4388c26c47007d59d8eb4f9d7093..c5a5f7c9b231d6aff9c9c163f5f0e2a87fcb6d79 100644 --- a/arch/powerpc/include/asm/io.h +++ b/arch/powerpc/include/asm/io.h @@ -38,8 +38,6 @@ extern struct pci_dev *isa_bridge_pcidev; #define SIO_CONFIG_RA 0x398 #define SIO_CONFIG_RD 0x399 -#define SLOW_DOWN_IO - /* 32 bits uses slightly different variables for the various IO * bases. Most of this file only uses _IO_BASE though which we * define properly based on the platform diff --git a/arch/powerpc/include/asm/iommu.h b/arch/powerpc/include/asm/iommu.h index d7912b66c874829d2f958e7312d82eae5d75a6e0..7e29c73e3dd48d72a9f6d1d107aa1258134c01a2 100644 --- a/arch/powerpc/include/asm/iommu.h +++ b/arch/powerpc/include/asm/iommu.h @@ -51,13 +51,11 @@ struct iommu_table_ops { int (*xchg_no_kill)(struct iommu_table *tbl, long index, unsigned long *hpa, - enum dma_data_direction *direction, - bool realmode); + enum dma_data_direction *direction); void (*tce_kill)(struct iommu_table *tbl, unsigned long index, - unsigned long pages, - bool realmode); + unsigned long pages); __be64 *(*useraddrptr)(struct iommu_table *tbl, long index, bool alloc); #endif diff --git a/arch/powerpc/include/asm/kasan.h b/arch/powerpc/include/asm/kasan.h index 3c478e5ef24c2a4488bf6afaefb8099b05c445b4..a6be4025cba2386c73a891b0d36ced06bfd1d272 100644 --- a/arch/powerpc/include/asm/kasan.h +++ b/arch/powerpc/include/asm/kasan.h @@ -30,9 +30,31 @@ #define KASAN_SHADOW_OFFSET ASM_CONST(CONFIG_KASAN_SHADOW_OFFSET) +#ifdef CONFIG_PPC32 #define KASAN_SHADOW_END (-(-KASAN_SHADOW_START >> KASAN_SHADOW_SCALE_SHIFT)) +#elif defined(CONFIG_PPC_BOOK3S_64) +/* + * The shadow ends before the highest accessible address + * because we don't need a shadow for the shadow. Instead: + * c00e000000000000 << 3 + a80e000000000000 = c00fc00000000000 + */ +#define KASAN_SHADOW_END 0xc00fc00000000000UL +#endif #ifdef CONFIG_KASAN +#ifdef CONFIG_PPC_BOOK3S_64 +DECLARE_STATIC_KEY_FALSE(powerpc_kasan_enabled_key); + +static __always_inline bool kasan_arch_is_ready(void) +{ + if (static_branch_likely(&powerpc_kasan_enabled_key)) + return true; + return false; +} + +#define kasan_arch_is_ready kasan_arch_is_ready +#endif + void kasan_early_init(void); void kasan_mmu_init(void); void kasan_init(void); diff --git a/arch/powerpc/include/asm/kup.h b/arch/powerpc/include/asm/kup.h index fb2237809d63b46bf4040c7032cf41a0190c0787..d751ddd081108176c9793c5e7b92eee0f252fda0 100644 --- a/arch/powerpc/include/asm/kup.h +++ b/arch/powerpc/include/asm/kup.h @@ -52,7 +52,6 @@ __bad_kuap_fault(struct pt_regs *regs, unsigned long address, bool is_write) return false; } -static inline void __kuap_assert_locked(void) { } static inline void __kuap_lock(void) { } static inline void __kuap_save_and_lock(struct pt_regs *regs) { } static inline void kuap_user_restore(struct pt_regs *regs) { } diff --git a/arch/powerpc/include/asm/kvm_book3s_asm.h b/arch/powerpc/include/asm/kvm_book3s_asm.h index b6d31bff5209f5f1612d53e34b6c91112358b0fc..c8882d9b86c27c5118c1b09ff6f8fc15bed32dfb 100644 --- a/arch/powerpc/include/asm/kvm_book3s_asm.h +++ b/arch/powerpc/include/asm/kvm_book3s_asm.h @@ -14,9 +14,6 @@ #define XICS_MFRR 0xc #define XICS_IPI 2 /* interrupt source # for IPIs */ -/* LPIDs we support with this build -- runtime limit may be lower */ -#define KVMPPC_NR_LPIDS (LPID_RSVD + 1) - /* Maximum number of threads per physical core */ #define MAX_SMT_THREADS 8 diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h index faf301d0dec0164c7420644e9a64c916fa1442d0..2909a88acd163b3633626390e0eb36f0dcfd19f1 100644 --- a/arch/powerpc/include/asm/kvm_host.h +++ b/arch/powerpc/include/asm/kvm_host.h @@ -36,7 +36,12 @@ #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE #include /* for MAX_SMT_THREADS */ #define KVM_MAX_VCPU_IDS (MAX_SMT_THREADS * KVM_MAX_VCORES) -#define KVM_MAX_NESTED_GUESTS KVMPPC_NR_LPIDS + +/* + * Limit the nested partition table to 4096 entries (because that's what + * hardware supports). Both guest and host use this value. + */ +#define KVM_MAX_NESTED_GUESTS_SHIFT 12 #else #define KVM_MAX_VCPU_IDS KVM_MAX_VCPUS @@ -327,8 +332,7 @@ struct kvm_arch { struct list_head uvmem_pfns; struct mutex mmu_setup_lock; /* nests inside vcpu mutexes */ u64 l1_ptcr; - int max_nested_lpid; - struct kvm_nested_guest *nested_guests[KVM_MAX_NESTED_GUESTS]; + struct idr kvm_nested_guest_idr; /* This array can grow quite large, keep it at the end */ struct kvmppc_vcore *vcores[KVM_MAX_VCORES]; #endif diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h index 838d4cb460b7edf6b9a820a509e763e63298b0fe..9f625af3b65b53227c5e1702d6ed9bcbebec6175 100644 --- a/arch/powerpc/include/asm/kvm_ppc.h +++ b/arch/powerpc/include/asm/kvm_ppc.h @@ -177,8 +177,6 @@ extern void kvmppc_setup_partition_table(struct kvm *kvm); extern long kvm_vm_ioctl_create_spapr_tce(struct kvm *kvm, struct kvm_create_spapr_tce_64 *args); -extern struct kvmppc_spapr_tce_table *kvmppc_find_table( - struct kvm *kvm, unsigned long liobn); #define kvmppc_ioba_validate(stt, ioba, npages) \ (iommu_tce_check_ioba((stt)->page_shift, (stt)->offset, \ (stt)->size, (ioba), (npages)) ? \ @@ -685,7 +683,7 @@ extern int kvmppc_xive_set_irq(struct kvm *kvm, int irq_source_id, u32 irq, int level, bool line_status); extern void kvmppc_xive_push_vcpu(struct kvm_vcpu *vcpu); extern void kvmppc_xive_pull_vcpu(struct kvm_vcpu *vcpu); -extern void kvmppc_xive_rearm_escalation(struct kvm_vcpu *vcpu); +extern bool kvmppc_xive_rearm_escalation(struct kvm_vcpu *vcpu); static inline int kvmppc_xive_enabled(struct kvm_vcpu *vcpu) { @@ -723,7 +721,7 @@ static inline int kvmppc_xive_set_irq(struct kvm *kvm, int irq_source_id, u32 ir int level, bool line_status) { return -ENODEV; } static inline void kvmppc_xive_push_vcpu(struct kvm_vcpu *vcpu) { } static inline void kvmppc_xive_pull_vcpu(struct kvm_vcpu *vcpu) { } -static inline void kvmppc_xive_rearm_escalation(struct kvm_vcpu *vcpu) { } +static inline bool kvmppc_xive_rearm_escalation(struct kvm_vcpu *vcpu) { return true; } static inline int kvmppc_xive_enabled(struct kvm_vcpu *vcpu) { return 0; } @@ -789,13 +787,6 @@ long kvmppc_rm_h_page_init(struct kvm_vcpu *vcpu, unsigned long flags, unsigned long dest, unsigned long src); long kvmppc_hpte_hv_fault(struct kvm_vcpu *vcpu, unsigned long addr, unsigned long slb_v, unsigned int status, bool data); -unsigned long kvmppc_rm_h_xirr(struct kvm_vcpu *vcpu); -unsigned long kvmppc_rm_h_xirr_x(struct kvm_vcpu *vcpu); -unsigned long kvmppc_rm_h_ipoll(struct kvm_vcpu *vcpu, unsigned long server); -int kvmppc_rm_h_ipi(struct kvm_vcpu *vcpu, unsigned long server, - unsigned long mfrr); -int kvmppc_rm_h_cppr(struct kvm_vcpu *vcpu, unsigned long cppr); -int kvmppc_rm_h_eoi(struct kvm_vcpu *vcpu, unsigned long xirr); void kvmppc_guest_entry_inject_int(struct kvm_vcpu *vcpu); /* @@ -877,7 +868,6 @@ int kvm_vcpu_ioctl_dirty_tlb(struct kvm_vcpu *vcpu, struct kvm_dirty_tlb *cfg); long kvmppc_alloc_lpid(void); -void kvmppc_claim_lpid(long lpid); void kvmppc_free_lpid(long lpid); void kvmppc_init_lpid(unsigned long nr_lpids); diff --git a/arch/powerpc/include/asm/linkage.h b/arch/powerpc/include/asm/linkage.h index 1f00d2891d69171ac1e89673223ce1d6fadc7111..b71b9582e7546864fcef9947eed506cb5e47ca8f 100644 --- a/arch/powerpc/include/asm/linkage.h +++ b/arch/powerpc/include/asm/linkage.h @@ -4,7 +4,7 @@ #include -#ifdef PPC64_ELF_ABI_v1 +#ifdef CONFIG_PPC64_ELF_ABI_V1 #define cond_syscall(x) \ asm ("\t.weak " #x "\n\t.set " #x ", sys_ni_syscall\n" \ "\t.weak ." #x "\n\t.set ." #x ", .sys_ni_syscall\n") diff --git a/arch/powerpc/include/asm/mmu_context.h b/arch/powerpc/include/asm/mmu_context.h index b8527a74bd4df6d7d6d06c40ec1f7661a513aa3a..3f25bd3e14eb8419847f750e5b44a6ac397f0671 100644 --- a/arch/powerpc/include/asm/mmu_context.h +++ b/arch/powerpc/include/asm/mmu_context.h @@ -34,15 +34,10 @@ extern void mm_iommu_init(struct mm_struct *mm); extern void mm_iommu_cleanup(struct mm_struct *mm); extern struct mm_iommu_table_group_mem_t *mm_iommu_lookup(struct mm_struct *mm, unsigned long ua, unsigned long size); -extern struct mm_iommu_table_group_mem_t *mm_iommu_lookup_rm( - struct mm_struct *mm, unsigned long ua, unsigned long size); extern struct mm_iommu_table_group_mem_t *mm_iommu_get(struct mm_struct *mm, unsigned long ua, unsigned long entries); extern long mm_iommu_ua_to_hpa(struct mm_iommu_table_group_mem_t *mem, unsigned long ua, unsigned int pageshift, unsigned long *hpa); -extern long mm_iommu_ua_to_hpa_rm(struct mm_iommu_table_group_mem_t *mem, - unsigned long ua, unsigned int pageshift, unsigned long *hpa); -extern void mm_iommu_ua_mark_dirty_rm(struct mm_struct *mm, unsigned long ua); extern bool mm_iommu_is_devmem(struct mm_struct *mm, unsigned long hpa, unsigned int pageshift, unsigned long *size); extern long mm_iommu_mapped_inc(struct mm_iommu_table_group_mem_t *mem); diff --git a/arch/powerpc/include/asm/module.h b/arch/powerpc/include/asm/module.h index 857d9ff2429543a992afc9db2c9f9c1b0bca552d..09e2ffd360bbec28b87921064beee5535223defe 100644 --- a/arch/powerpc/include/asm/module.h +++ b/arch/powerpc/include/asm/module.h @@ -41,9 +41,7 @@ struct mod_arch_specific { #ifdef CONFIG_DYNAMIC_FTRACE unsigned long tramp; -#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS unsigned long tramp_regs; -#endif #endif /* List of BUG addresses, source line numbers and filenames */ diff --git a/arch/powerpc/include/asm/nohash/tlbflush.h b/arch/powerpc/include/asm/nohash/tlbflush.h index c08d25e3e62679ebe9206a107e8d834b3b5adc73..698935d4f72dddd59f1681f142a74e766820c22e 100644 --- a/arch/powerpc/include/asm/nohash/tlbflush.h +++ b/arch/powerpc/include/asm/nohash/tlbflush.h @@ -30,7 +30,6 @@ struct mm_struct; extern void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, unsigned long end); -extern void flush_tlb_kernel_range(unsigned long start, unsigned long end); #ifdef CONFIG_PPC_8xx static inline void local_flush_tlb_mm(struct mm_struct *mm) @@ -45,7 +44,18 @@ static inline void local_flush_tlb_page(struct vm_area_struct *vma, unsigned lon { asm volatile ("tlbie %0; sync" : : "r" (vmaddr) : "memory"); } + +static inline void flush_tlb_kernel_range(unsigned long start, unsigned long end) +{ + start &= PAGE_MASK; + + if (end - start <= PAGE_SIZE) + asm volatile ("tlbie %0; sync" : : "r" (start) : "memory"); + else + asm volatile ("sync; tlbia; isync" : : : "memory"); +} #else +extern void flush_tlb_kernel_range(unsigned long start, unsigned long end); extern void local_flush_tlb_mm(struct mm_struct *mm); extern void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr); diff --git a/arch/powerpc/include/asm/paca.h b/arch/powerpc/include/asm/paca.h index 8330968ca346cdf2588c9a64d63838355bb89174..4d7aaab8270232446fd6715d3fde0a3d1596294c 100644 --- a/arch/powerpc/include/asm/paca.h +++ b/arch/powerpc/include/asm/paca.h @@ -12,6 +12,7 @@ #ifdef CONFIG_PPC64 +#include #include #include #include @@ -152,16 +153,9 @@ struct paca_struct { struct tlb_core_data tcd; #endif /* CONFIG_PPC_BOOK3E */ -#ifdef CONFIG_PPC_BOOK3S #ifdef CONFIG_PPC_64S_HASH_MMU -#ifdef CONFIG_PPC_MM_SLICES unsigned char mm_ctx_low_slices_psize[BITS_PER_LONG / BITS_PER_BYTE]; unsigned char mm_ctx_high_slices_psize[SLICE_ARRAY_SIZE]; -#else - u16 mm_ctx_user_psize; - u16 mm_ctx_sllp; -#endif -#endif #endif /* diff --git a/arch/powerpc/include/asm/page.h b/arch/powerpc/include/asm/page.h index f2c5c26869f1a43888681bdee0633aab3cbf3784..e5f75c70eda8366c79f3f3fc821c3ed406f23408 100644 --- a/arch/powerpc/include/asm/page.h +++ b/arch/powerpc/include/asm/page.h @@ -216,6 +216,9 @@ static inline bool pfn_valid(unsigned long pfn) #define __pa(x) ((phys_addr_t)(unsigned long)(x) - VIRT_PHYS_OFFSET) #else #ifdef CONFIG_PPC64 + +#define VIRTUAL_WARN_ON(x) WARN_ON(IS_ENABLED(CONFIG_DEBUG_VIRTUAL) && (x)) + /* * gcc miscompiles (unsigned long)(&static_var) - PAGE_OFFSET * with -mcmodel=medium, so we use & and | instead of - and + on 64-bit. @@ -223,13 +226,13 @@ static inline bool pfn_valid(unsigned long pfn) */ #define __va(x) \ ({ \ - VIRTUAL_BUG_ON((unsigned long)(x) >= PAGE_OFFSET); \ + VIRTUAL_WARN_ON((unsigned long)(x) >= PAGE_OFFSET); \ (void *)(unsigned long)((phys_addr_t)(x) | PAGE_OFFSET); \ }) #define __pa(x) \ ({ \ - VIRTUAL_BUG_ON((unsigned long)(x) < PAGE_OFFSET); \ + VIRTUAL_WARN_ON((unsigned long)(x) < PAGE_OFFSET); \ (unsigned long)(x) & 0x0fffffffffffffffUL; \ }) @@ -333,6 +336,5 @@ static inline unsigned long kaslr_offset(void) #include #endif /* __ASSEMBLY__ */ -#include #endif /* _ASM_POWERPC_PAGE_H */ diff --git a/arch/powerpc/include/asm/parport.h b/arch/powerpc/include/asm/parport.h index 8abfb8f7c33dbe0c81ecc48496735b264afbec23..42cc321ed7544870b6a3487f17b185f2e3d09df2 100644 --- a/arch/powerpc/include/asm/parport.h +++ b/arch/powerpc/include/asm/parport.h @@ -11,7 +11,7 @@ #define _ASM_POWERPC_PARPORT_H #ifdef __KERNEL__ -#include +#include static int parport_pc_find_nonpci_ports (int autoirq, int autodma) { diff --git a/arch/powerpc/include/asm/pci-bridge.h b/arch/powerpc/include/asm/pci-bridge.h index 90f488fa4c175c0376c12ccfabdd939ebebcb05c..c85f901227c976523d3a869e30e4fe17ff8bbc1f 100644 --- a/arch/powerpc/include/asm/pci-bridge.h +++ b/arch/powerpc/include/asm/pci-bridge.h @@ -170,10 +170,10 @@ static inline struct pci_controller *pci_bus_to_host(const struct pci_bus *bus) return bus->sysdata; } -#ifndef CONFIG_PPC64 - extern int pci_device_from_OF_node(struct device_node *node, u8 *bus, u8 *devfn); +#ifndef CONFIG_PPC64 + extern void pci_create_OF_bus_map(void); #else /* CONFIG_PPC64 */ @@ -235,16 +235,6 @@ struct pci_dn *add_sriov_vf_pdns(struct pci_dev *pdev); void remove_sriov_vf_pdns(struct pci_dev *pdev); #endif -static inline int pci_device_from_OF_node(struct device_node *np, - u8 *bus, u8 *devfn) -{ - if (!PCI_DN(np)) - return -ENODEV; - *bus = PCI_DN(np)->busno; - *devfn = PCI_DN(np)->devfn; - return 0; -} - #if defined(CONFIG_EEH) static inline struct eeh_dev *pdn_to_eeh_dev(struct pci_dn *pdn) { diff --git a/arch/powerpc/include/asm/pnv-pci.h b/arch/powerpc/include/asm/pnv-pci.h index b3f4807993525de29dac643197ada297492be7c8..8afc92860dbbff0eb50205f32aefdacf32f6fcea 100644 --- a/arch/powerpc/include/asm/pnv-pci.h +++ b/arch/powerpc/include/asm/pnv-pci.h @@ -9,6 +9,7 @@ #include #include #include +#include #include #include diff --git a/arch/powerpc/include/asm/ppc-opcode.h b/arch/powerpc/include/asm/ppc-opcode.h index 82f1f0041c6f794e9eea6eee5862d7214763a292..89beabf5325cfee3bb2c19a65f9e9479e8eeabb1 100644 --- a/arch/powerpc/include/asm/ppc-opcode.h +++ b/arch/powerpc/include/asm/ppc-opcode.h @@ -127,8 +127,53 @@ /* opcode and xopcode for instructions */ -#define OP_TRAP 3 -#define OP_TRAP_64 2 +#define OP_PREFIX 1 +#define OP_TRAP_64 2 +#define OP_TRAP 3 +#define OP_SC 17 +#define OP_19 19 +#define OP_31 31 +#define OP_LWZ 32 +#define OP_LWZU 33 +#define OP_LBZ 34 +#define OP_LBZU 35 +#define OP_STW 36 +#define OP_STWU 37 +#define OP_STB 38 +#define OP_STBU 39 +#define OP_LHZ 40 +#define OP_LHZU 41 +#define OP_LHA 42 +#define OP_LHAU 43 +#define OP_STH 44 +#define OP_STHU 45 +#define OP_LMW 46 +#define OP_STMW 47 +#define OP_LFS 48 +#define OP_LFSU 49 +#define OP_LFD 50 +#define OP_LFDU 51 +#define OP_STFS 52 +#define OP_STFSU 53 +#define OP_STFD 54 +#define OP_STFDU 55 +#define OP_LQ 56 +#define OP_LD 58 +#define OP_STD 62 + +#define OP_19_XOP_RFID 18 +#define OP_19_XOP_RFMCI 38 +#define OP_19_XOP_RFDI 39 +#define OP_19_XOP_RFI 50 +#define OP_19_XOP_RFCI 51 +#define OP_19_XOP_RFSCV 82 +#define OP_19_XOP_HRFID 274 +#define OP_19_XOP_URFID 306 +#define OP_19_XOP_STOP 370 +#define OP_19_XOP_DOZE 402 +#define OP_19_XOP_NAP 434 +#define OP_19_XOP_SLEEP 466 +#define OP_19_XOP_RVWINKLE 498 #define OP_31_XOP_TRAP 4 #define OP_31_XOP_LDX 21 @@ -150,6 +195,8 @@ #define OP_31_XOP_LHZUX 311 #define OP_31_XOP_MSGSNDP 142 #define OP_31_XOP_MSGCLRP 174 +#define OP_31_XOP_MTMSR 146 +#define OP_31_XOP_MTMSRD 178 #define OP_31_XOP_TLBIE 306 #define OP_31_XOP_MFSPR 339 #define OP_31_XOP_LWAX 341 @@ -208,42 +255,6 @@ /* VMX Vector Store Instructions */ #define OP_31_XOP_STVX 231 -/* Prefixed Instructions */ -#define OP_PREFIX 1 - -#define OP_31 31 -#define OP_LWZ 32 -#define OP_STFS 52 -#define OP_STFSU 53 -#define OP_STFD 54 -#define OP_STFDU 55 -#define OP_LD 58 -#define OP_LWZU 33 -#define OP_LBZ 34 -#define OP_LBZU 35 -#define OP_STW 36 -#define OP_STWU 37 -#define OP_STD 62 -#define OP_STB 38 -#define OP_STBU 39 -#define OP_LHZ 40 -#define OP_LHZU 41 -#define OP_LHA 42 -#define OP_LHAU 43 -#define OP_STH 44 -#define OP_STHU 45 -#define OP_LMW 46 -#define OP_STMW 47 -#define OP_LFS 48 -#define OP_LFSU 49 -#define OP_LFD 50 -#define OP_LFDU 51 -#define OP_STFS 52 -#define OP_STFSU 53 -#define OP_STFD 54 -#define OP_STFDU 55 -#define OP_LQ 56 - /* sorted alphabetically */ #define PPC_INST_BCCTR_FLUSH 0x4c400420 #define PPC_INST_COPY 0x7c20060c @@ -285,13 +296,6 @@ #define PPC_INST_TRECHKPT 0x7c0007dd #define PPC_INST_TRECLAIM 0x7c00075d #define PPC_INST_TSR 0x7c0005dd -#define PPC_INST_LD 0xe8000000 -#define PPC_INST_STD 0xf8000000 -#define PPC_INST_ADDIS 0x3c000000 -#define PPC_INST_ADD 0x7c000214 -#define PPC_INST_DIVD 0x7c0003d2 -#define PPC_INST_BRANCH 0x48000000 -#define PPC_INST_BL 0x48000001 #define PPC_INST_BRANCH_COND 0x40800000 /* Prefixes */ @@ -352,6 +356,10 @@ #define PPC_HIGHER(v) (((v) >> 32) & 0xffff) #define PPC_HIGHEST(v) (((v) >> 48) & 0xffff) +/* LI Field */ +#define PPC_LI_MASK 0x03fffffc +#define PPC_LI(v) ((v) & PPC_LI_MASK) + /* * Only use the larx hint bit on 64bit CPUs. e500v1/v2 based CPUs will treat a * larx with EH set as an illegal instruction. @@ -460,10 +468,10 @@ (0x100000c7 | ___PPC_RT(vrt) | ___PPC_RA(vra) | ___PPC_RB(vrb) | __PPC_RC21) #define PPC_RAW_VCMPEQUB_RC(vrt, vra, vrb) \ (0x10000006 | ___PPC_RT(vrt) | ___PPC_RA(vra) | ___PPC_RB(vrb) | __PPC_RC21) -#define PPC_RAW_LD(r, base, i) (PPC_INST_LD | ___PPC_RT(r) | ___PPC_RA(base) | IMM_DS(i)) +#define PPC_RAW_LD(r, base, i) (0xe8000000 | ___PPC_RT(r) | ___PPC_RA(base) | IMM_DS(i)) #define PPC_RAW_LWZ(r, base, i) (0x80000000 | ___PPC_RT(r) | ___PPC_RA(base) | IMM_L(i)) #define PPC_RAW_LWZX(t, a, b) (0x7c00002e | ___PPC_RT(t) | ___PPC_RA(a) | ___PPC_RB(b)) -#define PPC_RAW_STD(r, base, i) (PPC_INST_STD | ___PPC_RS(r) | ___PPC_RA(base) | IMM_DS(i)) +#define PPC_RAW_STD(r, base, i) (0xf8000000 | ___PPC_RS(r) | ___PPC_RA(base) | IMM_DS(i)) #define PPC_RAW_STDCX(s, a, b) (0x7c0001ad | ___PPC_RS(s) | ___PPC_RA(a) | ___PPC_RB(b)) #define PPC_RAW_LFSX(t, a, b) (0x7c00042e | ___PPC_RT(t) | ___PPC_RA(a) | ___PPC_RB(b)) #define PPC_RAW_STFSX(s, a, b) (0x7c00052e | ___PPC_RS(s) | ___PPC_RA(a) | ___PPC_RB(b)) @@ -474,8 +482,8 @@ #define PPC_RAW_ADDE(t, a, b) (0x7c000114 | ___PPC_RT(t) | ___PPC_RA(a) | ___PPC_RB(b)) #define PPC_RAW_ADDZE(t, a) (0x7c000194 | ___PPC_RT(t) | ___PPC_RA(a)) #define PPC_RAW_ADDME(t, a) (0x7c0001d4 | ___PPC_RT(t) | ___PPC_RA(a)) -#define PPC_RAW_ADD(t, a, b) (PPC_INST_ADD | ___PPC_RT(t) | ___PPC_RA(a) | ___PPC_RB(b)) -#define PPC_RAW_ADD_DOT(t, a, b) (PPC_INST_ADD | ___PPC_RT(t) | ___PPC_RA(a) | ___PPC_RB(b) | 0x1) +#define PPC_RAW_ADD(t, a, b) (0x7c000214 | ___PPC_RT(t) | ___PPC_RA(a) | ___PPC_RB(b)) +#define PPC_RAW_ADD_DOT(t, a, b) (0x7c000214 | ___PPC_RT(t) | ___PPC_RA(a) | ___PPC_RB(b) | 0x1) #define PPC_RAW_ADDC(t, a, b) (0x7c000014 | ___PPC_RT(t) | ___PPC_RA(a) | ___PPC_RB(b)) #define PPC_RAW_ADDC_DOT(t, a, b) (0x7c000014 | ___PPC_RT(t) | ___PPC_RA(a) | ___PPC_RB(b) | 0x1) #define PPC_RAW_NOP() PPC_RAW_ORI(0, 0, 0) @@ -571,7 +579,8 @@ #define PPC_RAW_MTSPR(spr, d) (0x7c0003a6 | ___PPC_RS(d) | __PPC_SPR(spr)) #define PPC_RAW_EIEIO() (0x7c0006ac) -#define PPC_RAW_BRANCH(addr) (PPC_INST_BRANCH | ((addr) & 0x03fffffc)) +#define PPC_RAW_BRANCH(offset) (0x48000000 | PPC_LI(offset)) +#define PPC_RAW_BL(offset) (0x48000001 | PPC_LI(offset)) /* Deal with instructions that older assemblers aren't aware of */ #define PPC_BCCTR_FLUSH stringify_in_c(.long PPC_INST_BCCTR_FLUSH) diff --git a/arch/powerpc/include/asm/ppc_asm.h b/arch/powerpc/include/asm/ppc_asm.h index 4dea2d963738e3569d3110d399f19079a9c30fc0..83c02f5a7f2ab11d056f4e5c114172563ac2462d 100644 --- a/arch/powerpc/include/asm/ppc_asm.h +++ b/arch/powerpc/include/asm/ppc_asm.h @@ -149,7 +149,7 @@ #define __STK_REG(i) (112 + ((i)-14)*8) #define STK_REG(i) __STK_REG(__REG_##i) -#ifdef PPC64_ELF_ABI_v2 +#ifdef CONFIG_PPC64_ELF_ABI_V2 #define STK_GOT 24 #define __STK_PARAM(i) (32 + ((i)-3)*8) #else @@ -158,7 +158,7 @@ #endif #define STK_PARAM(i) __STK_PARAM(__REG_##i) -#ifdef PPC64_ELF_ABI_v2 +#ifdef CONFIG_PPC64_ELF_ABI_V2 #define _GLOBAL(name) \ .align 2 ; \ diff --git a/arch/powerpc/include/asm/probes.h b/arch/powerpc/include/asm/probes.h index c5d984700d241a976e9d1039d16a410de9875293..6f66e358aa37805cd7169b3c4d329bcd40375842 100644 --- a/arch/powerpc/include/asm/probes.h +++ b/arch/powerpc/include/asm/probes.h @@ -8,6 +8,7 @@ * Copyright IBM Corporation, 2012 */ #include +#include typedef u32 ppc_opcode_t; #define BREAKPOINT_INSTRUCTION 0x7fe00008 /* trap */ @@ -31,6 +32,41 @@ typedef u32 ppc_opcode_t; #define MSR_SINGLESTEP (MSR_SE) #endif +static inline bool can_single_step(u32 inst) +{ + switch (get_op(inst)) { + case OP_TRAP_64: return false; + case OP_TRAP: return false; + case OP_SC: return false; + case OP_19: + switch (get_xop(inst)) { + case OP_19_XOP_RFID: return false; + case OP_19_XOP_RFMCI: return false; + case OP_19_XOP_RFDI: return false; + case OP_19_XOP_RFI: return false; + case OP_19_XOP_RFCI: return false; + case OP_19_XOP_RFSCV: return false; + case OP_19_XOP_HRFID: return false; + case OP_19_XOP_URFID: return false; + case OP_19_XOP_STOP: return false; + case OP_19_XOP_DOZE: return false; + case OP_19_XOP_NAP: return false; + case OP_19_XOP_SLEEP: return false; + case OP_19_XOP_RVWINKLE: return false; + } + break; + case OP_31: + switch (get_xop(inst)) { + case OP_31_XOP_TRAP: return false; + case OP_31_XOP_TRAP_64: return false; + case OP_31_XOP_MTMSR: return false; + case OP_31_XOP_MTMSRD: return false; + } + break; + } + return true; +} + /* Enable single stepping for the current task */ static inline void enable_single_step(struct pt_regs *regs) { diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h index 39c25021030f7b0ac042e38a83d709bcaa4d36ef..fdfaae194ddd5c17a978425db9501916ac02f3b8 100644 --- a/arch/powerpc/include/asm/processor.h +++ b/arch/powerpc/include/asm/processor.h @@ -392,8 +392,6 @@ static inline void prefetchw(const void *x) #define spin_lock_prefetch(x) prefetchw(x) -#define HAVE_ARCH_PICK_MMAP_LAYOUT - /* asm stubs */ extern unsigned long isa300_idle_stop_noloss(unsigned long psscr_val); extern unsigned long isa300_idle_stop_mayloss(unsigned long psscr_val); diff --git a/arch/powerpc/include/asm/ptrace.h b/arch/powerpc/include/asm/ptrace.h index 42f89e2d8f04f76a98679be6c634b9dba3a4a4c8..a03403695cd4ee6f266a0ad307b43f7d53e8bd65 100644 --- a/arch/powerpc/include/asm/ptrace.h +++ b/arch/powerpc/include/asm/ptrace.h @@ -120,7 +120,7 @@ struct pt_regs STACK_FRAME_OVERHEAD + KERNEL_REDZONE_SIZE) #define STACK_FRAME_MARKER 12 -#ifdef PPC64_ELF_ABI_v2 +#ifdef CONFIG_PPC64_ELF_ABI_V2 #define STACK_FRAME_MIN_SIZE 32 #else #define STACK_FRAME_MIN_SIZE STACK_FRAME_OVERHEAD diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h index 2835f636322827849840789587f052207d25ba09..1e8b2e04e626a125e48e60d5d4ac4c7758670cdf 100644 --- a/arch/powerpc/include/asm/reg.h +++ b/arch/powerpc/include/asm/reg.h @@ -417,7 +417,6 @@ #define FSCR_DSCR __MASK(FSCR_DSCR_LG) #define FSCR_INTR_CAUSE (ASM_CONST(0xFF) << 56) /* interrupt cause */ #define SPRN_HFSCR 0xbe /* HV=1 Facility Status & Control Register */ -#define HFSCR_PREFIX __MASK(FSCR_PREFIX_LG) #define HFSCR_MSGP __MASK(FSCR_MSGP_LG) #define HFSCR_TAR __MASK(FSCR_TAR_LG) #define HFSCR_EBB __MASK(FSCR_EBB_LG) @@ -474,8 +473,6 @@ #ifndef SPRN_LPID #define SPRN_LPID 0x13F /* Logical Partition Identifier */ #endif -#define LPID_RSVD_POWER7 0x3ff /* Reserved LPID for partn switching */ -#define LPID_RSVD 0xfff /* Reserved LPID for partn switching */ #define SPRN_HMER 0x150 /* Hypervisor maintenance exception reg */ #define HMER_DEBUG_TRIG (1ul << (63 - 17)) /* Debug trigger */ #define SPRN_HMEER 0x151 /* Hyp maintenance exception enable reg */ diff --git a/arch/powerpc/include/asm/signal.h b/arch/powerpc/include/asm/signal.h index 99e1c6de27bc167d01b57d24588ac6eefcdeac4d..922d43700fb41f05ec58721090d2187165891108 100644 --- a/arch/powerpc/include/asm/signal.h +++ b/arch/powerpc/include/asm/signal.h @@ -9,4 +9,9 @@ struct pt_regs; void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags); +unsigned long get_min_sigframe_size_32(void); +unsigned long get_min_sigframe_size_64(void); +unsigned long get_min_sigframe_size(void); +unsigned long get_min_sigframe_size_compat(void); + #endif /* _ASM_POWERPC_SIGNAL_H */ diff --git a/arch/powerpc/include/asm/slice.h b/arch/powerpc/include/asm/slice.h deleted file mode 100644 index 0bdd9c62eca0d07a40123b6fd072fb6154e794be..0000000000000000000000000000000000000000 --- a/arch/powerpc/include/asm/slice.h +++ /dev/null @@ -1,46 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _ASM_POWERPC_SLICE_H -#define _ASM_POWERPC_SLICE_H - -#ifdef CONFIG_PPC_BOOK3S_64 -#include -#endif - -#ifndef __ASSEMBLY__ - -struct mm_struct; - -#ifdef CONFIG_PPC_MM_SLICES - -#ifdef CONFIG_HUGETLB_PAGE -#define HAVE_ARCH_HUGETLB_UNMAPPED_AREA -#endif -#define HAVE_ARCH_UNMAPPED_AREA -#define HAVE_ARCH_UNMAPPED_AREA_TOPDOWN - -unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len, - unsigned long flags, unsigned int psize, - int topdown); - -unsigned int get_slice_psize(struct mm_struct *mm, unsigned long addr); - -void slice_set_range_psize(struct mm_struct *mm, unsigned long start, - unsigned long len, unsigned int psize); - -void slice_init_new_context_exec(struct mm_struct *mm); -void slice_setup_new_exec(void); - -#else /* CONFIG_PPC_MM_SLICES */ - -static inline void slice_init_new_context_exec(struct mm_struct *mm) {} - -static inline unsigned int get_slice_psize(struct mm_struct *mm, unsigned long addr) -{ - return 0; -} - -#endif /* CONFIG_PPC_MM_SLICES */ - -#endif /* __ASSEMBLY__ */ - -#endif /* _ASM_POWERPC_SLICE_H */ diff --git a/arch/powerpc/include/asm/smp.h b/arch/powerpc/include/asm/smp.h index 60ab739a5e3b52439fd1b227aeba4d7693f65867..f63505d74932bf89eb6d657a60bf3356aff47e72 100644 --- a/arch/powerpc/include/asm/smp.h +++ b/arch/powerpc/include/asm/smp.h @@ -189,8 +189,6 @@ extern void __cpu_die(unsigned int cpu); #define smp_setup_cpu_maps() #define thread_group_shares_l2 0 #define thread_group_shares_l3 0 -static inline void inhibit_secondary_onlining(void) {} -static inline void uninhibit_secondary_onlining(void) {} static inline const struct cpumask *cpu_sibling_mask(int cpu) { return cpumask_of(cpu); diff --git a/arch/powerpc/include/asm/svm.h b/arch/powerpc/include/asm/svm.h index 85580b30aba482852a06f04a2b257a70f7897e5c..a02bd54b894801e1d1c1f20d271658a61c6c2f2d 100644 --- a/arch/powerpc/include/asm/svm.h +++ b/arch/powerpc/include/asm/svm.h @@ -10,6 +10,8 @@ #ifdef CONFIG_PPC_SVM +#include + static inline bool is_secure_guest(void) { return mfmsr() & MSR_S; diff --git a/arch/powerpc/include/asm/switch_to.h b/arch/powerpc/include/asm/switch_to.h index 1f43ef6960339f7dfa207addd41d862951bd7513..aee25e3ebf96017a108fefa46ab95761901ccabc 100644 --- a/arch/powerpc/include/asm/switch_to.h +++ b/arch/powerpc/include/asm/switch_to.h @@ -62,6 +62,15 @@ static inline void disable_kernel_altivec(void) #else static inline void save_altivec(struct task_struct *t) { } static inline void __giveup_altivec(struct task_struct *t) { } +static inline void enable_kernel_altivec(void) +{ + BUILD_BUG(); +} + +static inline void disable_kernel_altivec(void) +{ + BUILD_BUG(); +} #endif #ifdef CONFIG_VSX diff --git a/arch/powerpc/include/asm/task_size_64.h b/arch/powerpc/include/asm/task_size_64.h index 38fdf8041d121637a202d48922bedddbb6a1ef4e..5a709951c90195417313548050274ef6d01b71aa 100644 --- a/arch/powerpc/include/asm/task_size_64.h +++ b/arch/powerpc/include/asm/task_size_64.h @@ -72,4 +72,12 @@ #define STACK_TOP_MAX TASK_SIZE_USER64 #define STACK_TOP (is_32bit_task() ? STACK_TOP_USER32 : STACK_TOP_USER64) +#define arch_get_mmap_base(addr, base) \ + (((addr) > DEFAULT_MAP_WINDOW) ? (base) + TASK_SIZE - DEFAULT_MAP_WINDOW : (base)) + +#define arch_get_mmap_end(addr, len, flags) \ + (((addr) > DEFAULT_MAP_WINDOW) || \ + (((flags) & MAP_FIXED) && ((addr) + (len) > DEFAULT_MAP_WINDOW)) ? TASK_SIZE : \ + DEFAULT_MAP_WINDOW) + #endif /* _ASM_POWERPC_TASK_SIZE_64_H */ diff --git a/arch/powerpc/include/asm/time.h b/arch/powerpc/include/asm/time.h index 924b2157882fad9037e388bd795365c6d03ad436..1e5643a9b1f2eb4cefc432810f5946b206d0440b 100644 --- a/arch/powerpc/include/asm/time.h +++ b/arch/powerpc/include/asm/time.h @@ -24,6 +24,7 @@ extern unsigned long tb_ticks_per_jiffy; extern unsigned long tb_ticks_per_usec; extern unsigned long tb_ticks_per_sec; extern struct clock_event_device decrementer_clockevent; +extern u64 decrementer_max; extern void generic_calibrate_decr(void); diff --git a/arch/powerpc/include/asm/topology.h b/arch/powerpc/include/asm/topology.h index 36fcafb1fd6d1ba7fe7f337a997f5d02b191201c..8a4d4f4d974959383439cbb1640d247ce5453f7a 100644 --- a/arch/powerpc/include/asm/topology.h +++ b/arch/powerpc/include/asm/topology.h @@ -111,14 +111,10 @@ static inline void unmap_cpu_from_node(unsigned long cpu) {} #endif /* CONFIG_NUMA */ #if defined(CONFIG_NUMA) && defined(CONFIG_PPC_SPLPAR) -extern int find_and_online_cpu_nid(int cpu); +void find_and_update_cpu_nid(int cpu); extern int cpu_to_coregroup_id(int cpu); #else -static inline int find_and_online_cpu_nid(int cpu) -{ - return 0; -} - +static inline void find_and_update_cpu_nid(int cpu) {} static inline int cpu_to_coregroup_id(int cpu) { #ifdef CONFIG_SMP diff --git a/arch/powerpc/include/asm/types.h b/arch/powerpc/include/asm/types.h index 84078c28c1a2c1278d721819f5ab6a961e0ae96a..93157a661dcc75fd2165918051c04c0efd9559ae 100644 --- a/arch/powerpc/include/asm/types.h +++ b/arch/powerpc/include/asm/types.h @@ -11,14 +11,6 @@ #include -#ifdef __powerpc64__ -#if defined(_CALL_ELF) && _CALL_ELF == 2 -#define PPC64_ELF_ABI_v2 1 -#else -#define PPC64_ELF_ABI_v1 1 -#endif -#endif /* __powerpc64__ */ - #ifndef __ASSEMBLY__ typedef __vector128 vector128; diff --git a/arch/powerpc/include/asm/unistd.h b/arch/powerpc/include/asm/unistd.h index 5eb462af6766438621c287a0e46db677e4eee31a..b1129b4ef57d90c2ca06c0f4fb87c008b715e193 100644 --- a/arch/powerpc/include/asm/unistd.h +++ b/arch/powerpc/include/asm/unistd.h @@ -44,6 +44,7 @@ #define __ARCH_WANT_SYS_TIME #define __ARCH_WANT_SYS_UTIME #define __ARCH_WANT_SYS_NEWFSTATAT +#define __ARCH_WANT_COMPAT_STAT #define __ARCH_WANT_COMPAT_SYS_SENDFILE #endif #define __ARCH_WANT_SYS_FORK diff --git a/arch/powerpc/include/asm/vas.h b/arch/powerpc/include/asm/vas.h index 83afcb6c194b5cb2a61b834f193388cc1aceb24d..c36f71e01c0f01a85f364a46c5930861ee740292 100644 --- a/arch/powerpc/include/asm/vas.h +++ b/arch/powerpc/include/asm/vas.h @@ -126,7 +126,7 @@ static inline void vas_user_win_add_mm_context(struct vas_user_win_ref *ref) * Receive window attributes specified by the (in-kernel) owner of window. */ struct vas_rx_win_attr { - void *rx_fifo; + u64 rx_fifo; int rx_fifo_size; int wcreds_max; diff --git a/arch/powerpc/include/uapi/asm/auxvec.h b/arch/powerpc/include/uapi/asm/auxvec.h index 7af21dc0e32094a05a07481891835c4f43f74b2e..aa7c162154538e3b897ad29a337d3423a7a0c3e0 100644 --- a/arch/powerpc/include/uapi/asm/auxvec.h +++ b/arch/powerpc/include/uapi/asm/auxvec.h @@ -48,6 +48,8 @@ #define AT_L3_CACHESIZE 46 #define AT_L3_CACHEGEOMETRY 47 -#define AT_VECTOR_SIZE_ARCH 14 /* entries in ARCH_DLINFO */ +#define AT_MINSIGSTKSZ 51 /* stack needed for signal delivery */ + +#define AT_VECTOR_SIZE_ARCH 15 /* entries in ARCH_DLINFO */ #endif diff --git a/arch/powerpc/include/uapi/asm/signal.h b/arch/powerpc/include/uapi/asm/signal.h index 37d41d87c45bffacaaebc61ee497015e9417a322..a5dfe84f50ab6168360b80442c36fd7c7d68e876 100644 --- a/arch/powerpc/include/uapi/asm/signal.h +++ b/arch/powerpc/include/uapi/asm/signal.h @@ -62,8 +62,13 @@ typedef struct { #define SA_RESTORER 0x04000000U +#ifdef __powerpc64__ +#define MINSIGSTKSZ 8192 +#define SIGSTKSZ 32768 +#else #define MINSIGSTKSZ 2048 #define SIGSTKSZ 8192 +#endif #include diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index 4ddd161aef324da5122b7d443af1a75ae04a7704..2e2a2a9bcf43f09ef4d9025c1f308d93c6c7ffe6 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile @@ -33,6 +33,17 @@ KASAN_SANITIZE_early_32.o := n KASAN_SANITIZE_cputable.o := n KASAN_SANITIZE_prom_init.o := n KASAN_SANITIZE_btext.o := n +KASAN_SANITIZE_paca.o := n +KASAN_SANITIZE_setup_64.o := n +KASAN_SANITIZE_mce.o := n +KASAN_SANITIZE_mce_power.o := n + +# we have to be particularly careful in ppc64 to exclude code that +# runs with translations off, as we cannot access the shadow with +# translations off. However, ppc32 can sanitize this. +ifdef CONFIG_PPC64 +KASAN_SANITIZE_traps.o := n +endif ifdef CONFIG_KASAN CFLAGS_early_32.o += -DDISABLE_BRANCH_PROFILING @@ -68,7 +79,7 @@ obj-$(CONFIG_PPC_BOOK3S_IDLE) += idle_book3s.o procfs-y := proc_powerpc.o obj-$(CONFIG_PROC_FS) += $(procfs-y) rtaspci-$(CONFIG_PPC64)-$(CONFIG_PCI) := rtas_pci.o -obj-$(CONFIG_PPC_RTAS) += rtas.o rtas-rtc.o $(rtaspci-y-y) +obj-$(CONFIG_PPC_RTAS) += rtas_entry.o rtas.o rtas-rtc.o $(rtaspci-y-y) obj-$(CONFIG_PPC_RTAS_DAEMON) += rtasd.o obj-$(CONFIG_RTAS_FLASH) += rtas_flash.o obj-$(CONFIG_RTAS_PROC) += rtas-proc.o diff --git a/arch/powerpc/kernel/btext.c b/arch/powerpc/kernel/btext.c index 9d9d56b574cceac4aec8d70d10e5f576a2116d17..8f69bb07e5002b0e020ad0b237e7a7adfdc7e5f4 100644 --- a/arch/powerpc/kernel/btext.c +++ b/arch/powerpc/kernel/btext.c @@ -10,9 +10,9 @@ #include #include #include +#include #include -#include #include #include #include @@ -45,8 +45,7 @@ unsigned long disp_BAT[2] __initdata = {0, 0}; static unsigned char vga_font[cmapsz]; -int boot_text_mapped __force_data = 0; -int force_printk_to_btext = 0; +static int boot_text_mapped __force_data; extern void rmci_on(void); extern void rmci_off(void); diff --git a/arch/powerpc/kernel/cacheinfo.c b/arch/powerpc/kernel/cacheinfo.c index 00b0992be3e70597179aa755a2ae4c3c74566005..f502337dd37d64c56ec67fd16a6879323e5585b2 100644 --- a/arch/powerpc/kernel/cacheinfo.c +++ b/arch/powerpc/kernel/cacheinfo.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index ae0fdef0ac1156c120c40ebc591c90898a13043f..a5dbfccd2047915c068f3c8bcded0ca0048d7b54 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c @@ -12,9 +12,9 @@ #include #include #include +#include #include -#include /* for PTRRELOC on ARCH=ppc */ #include #include #include @@ -487,11 +487,29 @@ static struct cpu_spec __initdata cpu_specs[] = { .machine_check_early = __machine_check_early_realmode_p9, .platform = "power9", }, - { /* Power9 DD2.2 or later */ + { /* Power9 DD2.2 */ + .pvr_mask = 0xffffefff, + .pvr_value = 0x004e0202, + .cpu_name = "POWER9 (raw)", + .cpu_features = CPU_FTRS_POWER9_DD2_2, + .cpu_user_features = COMMON_USER_POWER9, + .cpu_user_features2 = COMMON_USER2_POWER9, + .mmu_features = MMU_FTRS_POWER9, + .icache_bsize = 128, + .dcache_bsize = 128, + .num_pmcs = 6, + .pmc_type = PPC_PMC_IBM, + .oprofile_cpu_type = "ppc64/power9", + .cpu_setup = __setup_cpu_power9, + .cpu_restore = __restore_cpu_power9, + .machine_check_early = __machine_check_early_realmode_p9, + .platform = "power9", + }, + { /* Power9 DD2.3 or later */ .pvr_mask = 0xffff0000, .pvr_value = 0x004e0000, .cpu_name = "POWER9 (raw)", - .cpu_features = CPU_FTRS_POWER9_DD2_2, + .cpu_features = CPU_FTRS_POWER9_DD2_3, .cpu_user_features = COMMON_USER_POWER9, .cpu_user_features2 = COMMON_USER2_POWER9, .mmu_features = MMU_FTRS_POWER9, @@ -2025,7 +2043,7 @@ static struct cpu_spec * __init setup_cpu_spec(unsigned long offset, * oprofile_cpu_type already has a value, then we are * possibly overriding a real PVR with a logical one, * and, in that case, keep the current value for - * oprofile_cpu_type. Futhermore, let's ensure that the + * oprofile_cpu_type. Furthermore, let's ensure that the * fix for the PMAO bug is enabled on compatibility mode. */ if (old.oprofile_cpu_type != NULL) { @@ -2119,7 +2137,7 @@ void __init cpu_feature_keys_init(void) struct static_key_true mmu_feature_keys[NUM_MMU_FTR_KEYS] = { [0 ... NUM_MMU_FTR_KEYS - 1] = STATIC_KEY_TRUE_INIT }; -EXPORT_SYMBOL_GPL(mmu_feature_keys); +EXPORT_SYMBOL(mmu_feature_keys); void __init mmu_feature_keys_init(void) { diff --git a/arch/powerpc/kernel/crash_dump.c b/arch/powerpc/kernel/crash_dump.c index 32b4a97f1b79bb2aae51f0a9cee46ca6e6a65a39..9a3b85bfc83f7b72e5356a7353805d79d8b64622 100644 --- a/arch/powerpc/kernel/crash_dump.c +++ b/arch/powerpc/kernel/crash_dump.c @@ -12,9 +12,9 @@ #include #include #include +#include #include #include -#include #include #include #include diff --git a/arch/powerpc/kernel/dawr.c b/arch/powerpc/kernel/dawr.c index 64e423d2fe0f113aa19d125c09da075c6cde21f4..30d4eca88d174d25743fed5198194b17c0e09ae2 100644 --- a/arch/powerpc/kernel/dawr.c +++ b/arch/powerpc/kernel/dawr.c @@ -27,7 +27,7 @@ int set_dawr(int nr, struct arch_hw_breakpoint *brk) dawrx |= (brk->type & (HW_BRK_TYPE_PRIV_ALL)) >> 3; /* * DAWR length is stored in field MDR bits 48:53. Matches range in - * doublewords (64 bits) baised by -1 eg. 0b000000=1DW and + * doublewords (64 bits) biased by -1 eg. 0b000000=1DW and * 0b111111=64DW. * brk->hw_len is in bytes. * This aligns up to double word size, shifts and does the bias. diff --git a/arch/powerpc/kernel/dt_cpu_ftrs.c b/arch/powerpc/kernel/dt_cpu_ftrs.c index 7d1b2c4a4891142a273e7a04994fcf1e99f2fa19..2ad365c21afa8af428488e4e66e83d009001c82f 100644 --- a/arch/powerpc/kernel/dt_cpu_ftrs.c +++ b/arch/powerpc/kernel/dt_cpu_ftrs.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -19,7 +20,6 @@ #include #include #include -#include #include @@ -774,20 +774,26 @@ static __init void cpufeatures_cpu_quirks(void) if ((version & 0xffffefff) == 0x004e0200) { /* DD2.0 has no feature flag */ cur_cpu_spec->cpu_features |= CPU_FTR_P9_RADIX_PREFETCH_BUG; + cur_cpu_spec->cpu_features &= ~(CPU_FTR_DAWR); } else if ((version & 0xffffefff) == 0x004e0201) { cur_cpu_spec->cpu_features |= CPU_FTR_POWER9_DD2_1; cur_cpu_spec->cpu_features |= CPU_FTR_P9_RADIX_PREFETCH_BUG; + cur_cpu_spec->cpu_features &= ~(CPU_FTR_DAWR); } else if ((version & 0xffffefff) == 0x004e0202) { cur_cpu_spec->cpu_features |= CPU_FTR_P9_TM_HV_ASSIST; cur_cpu_spec->cpu_features |= CPU_FTR_P9_TM_XER_SO_BUG; cur_cpu_spec->cpu_features |= CPU_FTR_POWER9_DD2_1; + cur_cpu_spec->cpu_features &= ~(CPU_FTR_DAWR); + } else if ((version & 0xffffefff) == 0x004e0203) { + cur_cpu_spec->cpu_features |= CPU_FTR_P9_TM_HV_ASSIST; + cur_cpu_spec->cpu_features |= CPU_FTR_P9_TM_XER_SO_BUG; + cur_cpu_spec->cpu_features |= CPU_FTR_POWER9_DD2_1; } else if ((version & 0xffff0000) == 0x004e0000) { /* DD2.1 and up have DD2_1 */ cur_cpu_spec->cpu_features |= CPU_FTR_POWER9_DD2_1; } if ((version & 0xffff0000) == 0x004e0000) { - cur_cpu_spec->cpu_features &= ~(CPU_FTR_DAWR); cur_cpu_spec->cpu_features |= CPU_FTR_P9_TIDR; } diff --git a/arch/powerpc/kernel/eeh.c b/arch/powerpc/kernel/eeh.c index 28bb1e7263a6c6a3c8fffb9f285f5c0cdf881fae..ab316e155ea9f5f16b05cb9c6bab16c65057d317 100644 --- a/arch/powerpc/kernel/eeh.c +++ b/arch/powerpc/kernel/eeh.c @@ -1329,7 +1329,7 @@ int eeh_pe_set_option(struct eeh_pe *pe, int option) /* * EEH functionality could possibly be disabled, just - * return error for the case. And the EEH functinality + * return error for the case. And the EEH functionality * isn't expected to be disabled on one specific PE. */ switch (option) { @@ -1804,7 +1804,7 @@ static int eeh_debugfs_break_device(struct pci_dev *pdev) * PE freeze. Using the in_8() accessor skips the eeh detection hook * so the freeze hook so the EEH Detection machinery won't be * triggered here. This is to match the usual behaviour of EEH - * where the HW will asyncronously freeze a PE and it's up to + * where the HW will asynchronously freeze a PE and it's up to * the kernel to notice and deal with it. * * 3. Turn Memory space back on. This is more important for VFs diff --git a/arch/powerpc/kernel/eeh_driver.c b/arch/powerpc/kernel/eeh_driver.c index 422f80b5b27bc8e233a3115b4dad6cf7c55234a1..260273e564312652eeae180aa3ef9ba43ddea141 100644 --- a/arch/powerpc/kernel/eeh_driver.c +++ b/arch/powerpc/kernel/eeh_driver.c @@ -16,7 +16,6 @@ #include #include #include -#include #include struct eeh_rmv_data { diff --git a/arch/powerpc/kernel/eeh_event.c b/arch/powerpc/kernel/eeh_event.c index a7a8dc182efb98e741d90443f75bd53da15fac71..c23a454af08a8593d4bcd0101e4d9b1f3c25db45 100644 --- a/arch/powerpc/kernel/eeh_event.c +++ b/arch/powerpc/kernel/eeh_event.c @@ -143,7 +143,7 @@ int __eeh_send_failure_event(struct eeh_pe *pe) int eeh_send_failure_event(struct eeh_pe *pe) { /* - * If we've manually supressed recovery events via debugfs + * If we've manually suppressed recovery events via debugfs * then just drop it on the floor. */ if (eeh_debugfs_no_recover) { diff --git a/arch/powerpc/kernel/eeh_pe.c b/arch/powerpc/kernel/eeh_pe.c index 845e024321d4718b48293a9aff2025bc3cf541c1..d2873d17d2b1504384fdb74da53bd66bd5e12f76 100644 --- a/arch/powerpc/kernel/eeh_pe.c +++ b/arch/powerpc/kernel/eeh_pe.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -301,7 +302,7 @@ struct eeh_pe *eeh_pe_get(struct pci_controller *phb, int pe_no) * @new_pe_parent. * * If @new_pe_parent is NULL then the new PE will be inserted under - * directly under the the PHB. + * directly under the PHB. */ int eeh_pe_tree_insert(struct eeh_dev *edev, struct eeh_pe *new_pe_parent) { diff --git a/arch/powerpc/kernel/eeh_sysfs.c b/arch/powerpc/kernel/eeh_sysfs.c index 429620da73baa5af302d1221f32eb0c5d3a8d372..706e1eb95efe6d45d942d6165c8b2fa8bcf8eb12 100644 --- a/arch/powerpc/kernel/eeh_sysfs.c +++ b/arch/powerpc/kernel/eeh_sysfs.c @@ -6,6 +6,7 @@ * * Send comments and feedback to Linas Vepstas */ +#include #include #include #include diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S index 7748c278d13c81729aff32ba9e947cfdbf039da0..1d599df6f16906054531c6b54d6a9d50a432796c 100644 --- a/arch/powerpc/kernel/entry_32.S +++ b/arch/powerpc/kernel/entry_32.S @@ -555,52 +555,3 @@ ret_from_mcheck_exc: _ASM_NOKPROBE_SYMBOL(ret_from_mcheck_exc) #endif /* CONFIG_BOOKE */ #endif /* !(CONFIG_4xx || CONFIG_BOOKE) */ - -/* - * PROM code for specific machines follows. Put it - * here so it's easy to add arch-specific sections later. - * -- Cort - */ -#ifdef CONFIG_PPC_RTAS -/* - * On CHRP, the Run-Time Abstraction Services (RTAS) have to be - * called with the MMU off. - */ -_GLOBAL(enter_rtas) - stwu r1,-INT_FRAME_SIZE(r1) - mflr r0 - stw r0,INT_FRAME_SIZE+4(r1) - LOAD_REG_ADDR(r4, rtas) - lis r6,1f@ha /* physical return address for rtas */ - addi r6,r6,1f@l - tophys(r6,r6) - lwz r8,RTASENTRY(r4) - lwz r4,RTASBASE(r4) - mfmsr r9 - stw r9,8(r1) - LOAD_REG_IMMEDIATE(r0,MSR_KERNEL) - mtmsr r0 /* disable interrupts so SRR0/1 don't get trashed */ - li r9,MSR_KERNEL & ~(MSR_IR|MSR_DR) - mtlr r6 - stw r1, THREAD + RTAS_SP(r2) - mtspr SPRN_SRR0,r8 - mtspr SPRN_SRR1,r9 - rfi -1: - lis r8, 1f@h - ori r8, r8, 1f@l - LOAD_REG_IMMEDIATE(r9,MSR_KERNEL) - mtspr SPRN_SRR0,r8 - mtspr SPRN_SRR1,r9 - rfi /* Reactivate MMU translation */ -1: - lwz r8,INT_FRAME_SIZE+4(r1) /* get return address */ - lwz r9,8(r1) /* original msr value */ - addi r1,r1,INT_FRAME_SIZE - li r0,0 - stw r0, THREAD + RTAS_SP(r2) - mtlr r8 - mtmsr r9 - blr /* return to caller */ -_ASM_NOKPROBE_SYMBOL(enter_rtas) -#endif /* CONFIG_PPC_RTAS */ diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index 9581906b5ee9c066adf96dab4322a55bd5dff918..01ace4c56104dcb8c613fcff810c167d12fcf05f 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S @@ -264,156 +264,6 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S) addi r1,r1,SWITCH_FRAME_SIZE blr -#ifdef CONFIG_PPC_RTAS -/* - * On CHRP, the Run-Time Abstraction Services (RTAS) have to be - * called with the MMU off. - * - * In addition, we need to be in 32b mode, at least for now. - * - * Note: r3 is an input parameter to rtas, so don't trash it... - */ -_GLOBAL(enter_rtas) - mflr r0 - std r0,16(r1) - stdu r1,-SWITCH_FRAME_SIZE(r1) /* Save SP and create stack space. */ - - /* Because RTAS is running in 32b mode, it clobbers the high order half - * of all registers that it saves. We therefore save those registers - * RTAS might touch to the stack. (r0, r3-r13 are caller saved) - */ - SAVE_GPR(2, r1) /* Save the TOC */ - SAVE_GPR(13, r1) /* Save paca */ - SAVE_NVGPRS(r1) /* Save the non-volatiles */ - - mfcr r4 - std r4,_CCR(r1) - mfctr r5 - std r5,_CTR(r1) - mfspr r6,SPRN_XER - std r6,_XER(r1) - mfdar r7 - std r7,_DAR(r1) - mfdsisr r8 - std r8,_DSISR(r1) - - /* Temporary workaround to clear CR until RTAS can be modified to - * ignore all bits. - */ - li r0,0 - mtcr r0 - -#ifdef CONFIG_BUG - /* There is no way it is acceptable to get here with interrupts enabled, - * check it with the asm equivalent of WARN_ON - */ - lbz r0,PACAIRQSOFTMASK(r13) -1: tdeqi r0,IRQS_ENABLED - EMIT_WARN_ENTRY 1b,__FILE__,__LINE__,BUGFLAG_WARNING -#endif - - /* Hard-disable interrupts */ - mfmsr r6 - rldicl r7,r6,48,1 - rotldi r7,r7,16 - mtmsrd r7,1 - - /* Unfortunately, the stack pointer and the MSR are also clobbered, - * so they are saved in the PACA which allows us to restore - * our original state after RTAS returns. - */ - std r1,PACAR1(r13) - std r6,PACASAVEDMSR(r13) - - /* Setup our real return addr */ - LOAD_REG_ADDR(r4,rtas_return_loc) - clrldi r4,r4,2 /* convert to realmode address */ - mtlr r4 - - li r0,0 - ori r0,r0,MSR_EE|MSR_SE|MSR_BE|MSR_RI - andc r0,r6,r0 - - li r9,1 - rldicr r9,r9,MSR_SF_LG,(63-MSR_SF_LG) - ori r9,r9,MSR_IR|MSR_DR|MSR_FE0|MSR_FE1|MSR_FP|MSR_RI|MSR_LE - andc r6,r0,r9 - -__enter_rtas: - sync /* disable interrupts so SRR0/1 */ - mtmsrd r0 /* don't get trashed */ - - LOAD_REG_ADDR(r4, rtas) - ld r5,RTASENTRY(r4) /* get the rtas->entry value */ - ld r4,RTASBASE(r4) /* get the rtas->base value */ - - mtspr SPRN_SRR0,r5 - mtspr SPRN_SRR1,r6 - RFI_TO_KERNEL - b . /* prevent speculative execution */ - -rtas_return_loc: - FIXUP_ENDIAN - - /* - * Clear RI and set SF before anything. - */ - mfmsr r6 - li r0,MSR_RI - andc r6,r6,r0 - sldi r0,r0,(MSR_SF_LG - MSR_RI_LG) - or r6,r6,r0 - sync - mtmsrd r6 - - /* relocation is off at this point */ - GET_PACA(r4) - clrldi r4,r4,2 /* convert to realmode address */ - - bcl 20,31,$+4 -0: mflr r3 - ld r3,(1f-0b)(r3) /* get &rtas_restore_regs */ - - ld r1,PACAR1(r4) /* Restore our SP */ - ld r4,PACASAVEDMSR(r4) /* Restore our MSR */ - - mtspr SPRN_SRR0,r3 - mtspr SPRN_SRR1,r4 - RFI_TO_KERNEL - b . /* prevent speculative execution */ -_ASM_NOKPROBE_SYMBOL(__enter_rtas) -_ASM_NOKPROBE_SYMBOL(rtas_return_loc) - - .align 3 -1: .8byte rtas_restore_regs - -rtas_restore_regs: - /* relocation is on at this point */ - REST_GPR(2, r1) /* Restore the TOC */ - REST_GPR(13, r1) /* Restore paca */ - REST_NVGPRS(r1) /* Restore the non-volatiles */ - - GET_PACA(r13) - - ld r4,_CCR(r1) - mtcr r4 - ld r5,_CTR(r1) - mtctr r5 - ld r6,_XER(r1) - mtspr SPRN_XER,r6 - ld r7,_DAR(r1) - mtdar r7 - ld r8,_DSISR(r1) - mtdsisr r8 - - addi r1,r1,SWITCH_FRAME_SIZE /* Unstack our frame */ - ld r0,16(r1) /* get return address */ - - mtlr r0 - blr /* return to caller */ - -#endif /* CONFIG_PPC_RTAS */ - _GLOBAL(enter_prom) mflr r0 std r0,16(r1) diff --git a/arch/powerpc/kernel/fadump.c b/arch/powerpc/kernel/fadump.c index 4c09c6688ac6685665ddfc82aef3376a52b366d9..ea0a073abd969b2b588b481826c5f4b34a205b01 100644 --- a/arch/powerpc/kernel/fadump.c +++ b/arch/powerpc/kernel/fadump.c @@ -25,9 +25,10 @@ #include #include #include +#include +#include #include -#include #include #include #include @@ -73,8 +74,8 @@ static struct cma *fadump_cma; * The total size of fadump reserved memory covers for boot memory size * + cpu data size + hpte size and metadata. * Initialize only the area equivalent to boot memory size for CMA use. - * The reamining portion of fadump reserved memory will be not given - * to CMA and pages for thoes will stay reserved. boot memory size is + * The remaining portion of fadump reserved memory will be not given + * to CMA and pages for those will stay reserved. boot memory size is * aligned per CMA requirement to satisy cma_init_reserved_mem() call. * But for some reason even if it fails we still have the memory reservation * with us and we can still continue doing fadump. @@ -365,6 +366,11 @@ static unsigned long __init get_fadump_area_size(void) size += fw_dump.cpu_state_data_size; size += fw_dump.hpte_region_size; + /* + * Account for pagesize alignment of boot memory area destination address. + * This faciliates in mmap reading of first kernel's memory. + */ + size = PAGE_ALIGN(size); size += fw_dump.boot_memory_size; size += sizeof(struct fadump_crash_info_header); size += sizeof(struct elfhdr); /* ELF core header.*/ @@ -728,7 +734,7 @@ void crash_fadump(struct pt_regs *regs, const char *str) else ppc_save_regs(&fdh->regs); - fdh->online_mask = *cpu_online_mask; + fdh->cpu_mask = *cpu_online_mask; /* * If we came in via system reset, wait a while for the secondary @@ -867,7 +873,6 @@ static int fadump_alloc_mem_ranges(struct fadump_mrange_info *mrange_info) sizeof(struct fadump_memory_range)); return 0; } - static inline int fadump_add_mem_range(struct fadump_mrange_info *mrange_info, u64 base, u64 end) { @@ -886,7 +891,12 @@ static inline int fadump_add_mem_range(struct fadump_mrange_info *mrange_info, start = mem_ranges[mrange_info->mem_range_cnt - 1].base; size = mem_ranges[mrange_info->mem_range_cnt - 1].size; - if ((start + size) == base) + /* + * Boot memory area needs separate PT_LOAD segment(s) as it + * is moved to a different location at the time of crash. + * So, fold only if the region is not boot memory area. + */ + if ((start + size) == base && start >= fw_dump.boot_mem_top) is_adjacent = true; } if (!is_adjacent) { @@ -968,11 +978,14 @@ static int fadump_init_elfcore_header(char *bufp) elf->e_entry = 0; elf->e_phoff = sizeof(struct elfhdr); elf->e_shoff = 0; -#if defined(_CALL_ELF) - elf->e_flags = _CALL_ELF; -#else - elf->e_flags = 0; -#endif + + if (IS_ENABLED(CONFIG_PPC64_ELF_ABI_V2)) + elf->e_flags = 2; + else if (IS_ENABLED(CONFIG_PPC64_ELF_ABI_V1)) + elf->e_flags = 1; + else + elf->e_flags = 0; + elf->e_ehsize = sizeof(struct elfhdr); elf->e_phentsize = sizeof(struct elf_phdr); elf->e_phnum = 0; @@ -1164,6 +1177,11 @@ static unsigned long init_fadump_header(unsigned long addr) fdh->elfcorehdr_addr = addr; /* We will set the crashing cpu id in crash_fadump() during crash. */ fdh->crashing_cpu = FADUMP_CPU_UNKNOWN; + /* + * When LPAR is terminated by PYHP, ensure all possible CPUs' + * register data is processed while exporting the vmcore. + */ + fdh->cpu_mask = *cpu_possible_mask; return addr; } @@ -1271,7 +1289,6 @@ static void fadump_release_reserved_area(u64 start, u64 end) static void sort_and_merge_mem_ranges(struct fadump_mrange_info *mrange_info) { struct fadump_memory_range *mem_ranges; - struct fadump_memory_range tmp_range; u64 base, size; int i, j, idx; @@ -1286,11 +1303,8 @@ static void sort_and_merge_mem_ranges(struct fadump_mrange_info *mrange_info) if (mem_ranges[idx].base > mem_ranges[j].base) idx = j; } - if (idx != i) { - tmp_range = mem_ranges[idx]; - mem_ranges[idx] = mem_ranges[i]; - mem_ranges[i] = tmp_range; - } + if (idx != i) + swap(mem_ranges[idx], mem_ranges[i]); } /* Merge adjacent reserved ranges */ @@ -1661,8 +1675,8 @@ int __init setup_fadump(void) } /* * Use subsys_initcall_sync() here because there is dependency with - * crash_save_vmcoreinfo_init(), which mush run first to ensure vmcoreinfo initialization - * is done before regisering with f/w. + * crash_save_vmcoreinfo_init(), which must run first to ensure vmcoreinfo initialization + * is done before registering with f/w. */ subsys_initcall_sync(setup_fadump); #else /* !CONFIG_PRESERVE_FA_DUMP */ diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index 5c5181e8d5f13168e9ab2d8a8be172818426f67f..d3eea633d11a85ce3e95b9977b4b42d4849ce761 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S @@ -111,7 +111,7 @@ __secondary_hold_acknowledge: #ifdef CONFIG_RELOCATABLE /* This flag is set to 1 by a loader if the kernel should run * at the loaded address instead of the linked address. This - * is used by kexec-tools to keep the the kdump kernel in the + * is used by kexec-tools to keep the kdump kernel in the * crash_kernel region. The loader is responsible for * observing the alignment requirement. */ @@ -435,7 +435,7 @@ generic_secondary_common_init: ld r12,CPU_SPEC_RESTORE(r23) cmpdi 0,r12,0 beq 3f -#ifdef PPC64_ELF_ABI_v1 +#ifdef CONFIG_PPC64_ELF_ABI_V1 ld r12,0(r12) #endif mtctr r12 diff --git a/arch/powerpc/kernel/idle.c b/arch/powerpc/kernel/idle.c index 4ad79eb638c62bce1db8d22b639a97cbb022d111..77cd4c5a2d631f1a716b5a3341d0ecca5ce261f3 100644 --- a/arch/powerpc/kernel/idle.c +++ b/arch/powerpc/kernel/idle.c @@ -37,7 +37,7 @@ static int __init powersave_off(char *arg) { ppc_md.power_save = NULL; cpuidle_disable = IDLE_POWERSAVE_OFF; - return 0; + return 1; } __setup("powersave=off", powersave_off); diff --git a/arch/powerpc/kernel/interrupt_64.S b/arch/powerpc/kernel/interrupt_64.S index 7bab2d7de372e0ab24a0f63d5293589762131dbf..ce25b28cf418ef6154fd46fad165c21c62c90b7b 100644 --- a/arch/powerpc/kernel/interrupt_64.S +++ b/arch/powerpc/kernel/interrupt_64.S @@ -219,16 +219,6 @@ system_call_vectored common 0x3000 */ system_call_vectored sigill 0x7ff0 - -/* - * Entered via kernel return set up by kernel/sstep.c, must match entry regs - */ - .globl system_call_vectored_emulate -system_call_vectored_emulate: -_ASM_NOKPROBE_SYMBOL(system_call_vectored_emulate) - li r10,IRQS_ALL_DISABLED - stb r10,PACAIRQSOFTMASK(r13) - b system_call_vectored_common #endif /* CONFIG_PPC_BOOK3S */ .balign IFETCH_ALIGN_BYTES @@ -721,7 +711,7 @@ _GLOBAL(ret_from_kernel_thread) REST_NVGPRS(r1) mtctr r14 mr r3,r15 -#ifdef PPC64_ELF_ABI_v2 +#ifdef CONFIG_PPC64_ELF_ABI_V2 mr r12,r14 #endif bctrl diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c index 07093b7cdcb9aa039215da604261354f16c86f3e..7e56ddb3e0b9432045ac7d5615b01ceeb8af44ac 100644 --- a/arch/powerpc/kernel/iommu.c +++ b/arch/powerpc/kernel/iommu.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include @@ -1065,7 +1064,7 @@ extern long iommu_tce_xchg_no_kill(struct mm_struct *mm, long ret; unsigned long size = 0; - ret = tbl->it_ops->xchg_no_kill(tbl, entry, hpa, direction, false); + ret = tbl->it_ops->xchg_no_kill(tbl, entry, hpa, direction); if (!ret && ((*direction == DMA_FROM_DEVICE) || (*direction == DMA_BIDIRECTIONAL)) && !mm_iommu_is_devmem(mm, *hpa, tbl->it_page_shift, @@ -1080,7 +1079,7 @@ void iommu_tce_kill(struct iommu_table *tbl, unsigned long entry, unsigned long pages) { if (tbl->it_ops->tce_kill) - tbl->it_ops->tce_kill(tbl, entry, pages, false); + tbl->it_ops->tce_kill(tbl, entry, pages); } EXPORT_SYMBOL_GPL(iommu_tce_kill); diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index 752fb182eacb43e44447d13f785744e4b0ebae14..ea38c13936c7e995e737ec6f7836090dbf65be77 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c @@ -52,13 +52,13 @@ #include #include #include +#include #include #include #include #include #include -#include #include #include #include @@ -217,7 +217,6 @@ static inline void replay_soft_interrupts_irqrestore(void) #define replay_soft_interrupts_irqrestore() replay_soft_interrupts() #endif -#ifdef CONFIG_CC_HAS_ASM_GOTO notrace void arch_local_irq_restore(unsigned long mask) { unsigned char irq_happened; @@ -313,82 +312,6 @@ happened: __hard_irq_enable(); preempt_enable(); } -#else -notrace void arch_local_irq_restore(unsigned long mask) -{ - unsigned char irq_happened; - - /* Write the new soft-enabled value */ - irq_soft_mask_set(mask); - if (mask) - return; - - if (IS_ENABLED(CONFIG_PPC_IRQ_SOFT_MASK_DEBUG)) - WARN_ON_ONCE(in_nmi() || in_hardirq()); - - /* - * From this point onward, we can take interrupts, preempt, - * etc... unless we got hard-disabled. We check if an event - * happened. If none happened, we know we can just return. - * - * We may have preempted before the check below, in which case - * we are checking the "new" CPU instead of the old one. This - * is only a problem if an event happened on the "old" CPU. - * - * External interrupt events will have caused interrupts to - * be hard-disabled, so there is no problem, we - * cannot have preempted. - */ - irq_happened = get_irq_happened(); - if (!irq_happened) { - if (IS_ENABLED(CONFIG_PPC_IRQ_SOFT_MASK_DEBUG)) - WARN_ON_ONCE(!(mfmsr() & MSR_EE)); - return; - } - - /* We need to hard disable to replay. */ - if (!(irq_happened & PACA_IRQ_HARD_DIS)) { - if (IS_ENABLED(CONFIG_PPC_IRQ_SOFT_MASK_DEBUG)) - WARN_ON_ONCE(!(mfmsr() & MSR_EE)); - __hard_irq_disable(); - local_paca->irq_happened |= PACA_IRQ_HARD_DIS; - } else { - /* - * We should already be hard disabled here. We had bugs - * where that wasn't the case so let's dbl check it and - * warn if we are wrong. Only do that when IRQ tracing - * is enabled as mfmsr() can be costly. - */ - if (IS_ENABLED(CONFIG_PPC_IRQ_SOFT_MASK_DEBUG)) { - if (WARN_ON_ONCE(mfmsr() & MSR_EE)) - __hard_irq_disable(); - } - - if (irq_happened == PACA_IRQ_HARD_DIS) { - local_paca->irq_happened = 0; - __hard_irq_enable(); - return; - } - } - - /* - * Disable preempt here, so that the below preempt_enable will - * perform resched if required (a replayed interrupt may set - * need_resched). - */ - preempt_disable(); - irq_soft_mask_set(IRQS_ALL_DISABLED); - trace_hardirqs_off(); - - replay_soft_interrupts_irqrestore(); - local_paca->irq_happened = 0; - - trace_hardirqs_on(); - irq_soft_mask_set(IRQS_ENABLED); - __hard_irq_enable(); - preempt_enable(); -} -#endif EXPORT_SYMBOL(arch_local_irq_restore); /* @@ -730,6 +653,8 @@ static __always_inline void call_do_irq(struct pt_regs *regs, void *sp) ); } +DEFINE_STATIC_CALL_RET0(ppc_get_irq, *ppc_md.get_irq); + void __do_irq(struct pt_regs *regs) { unsigned int irq; @@ -741,7 +666,7 @@ void __do_irq(struct pt_regs *regs) * * This will typically lower the interrupt line to the CPU */ - irq = ppc_md.get_irq(); + irq = static_call(ppc_get_irq)(); /* We can hard enable interrupts now to allow perf interrupts */ if (should_hard_irq_enable()) @@ -809,6 +734,9 @@ void __init init_IRQ(void) if (ppc_md.init_IRQ) ppc_md.init_IRQ(); + + if (!WARN_ON(!ppc_md.get_irq)) + static_call_update(ppc_get_irq, ppc_md.get_irq); } #ifdef CONFIG_BOOKE_OR_40x diff --git a/arch/powerpc/kernel/isa-bridge.c b/arch/powerpc/kernel/isa-bridge.c index 39c625737c092fc4594fb5db00ee959cf945ad14..dc746611ebc02f200abe346acff7207801a1f72e 100644 --- a/arch/powerpc/kernel/isa-bridge.c +++ b/arch/powerpc/kernel/isa-bridge.c @@ -18,11 +18,11 @@ #include #include #include +#include #include #include #include -#include #include #include #include diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c index 7dae0b01abfbd6ead362ed3eb1ec58d5b427e15c..1c97c0f177aed72a793cfeaebcae638995b0449f 100644 --- a/arch/powerpc/kernel/kprobes.c +++ b/arch/powerpc/kernel/kprobes.c @@ -45,7 +45,7 @@ kprobe_opcode_t *kprobe_lookup_name(const char *name, unsigned int offset) { kprobe_opcode_t *addr = NULL; -#ifdef PPC64_ELF_ABI_v2 +#ifdef CONFIG_PPC64_ELF_ABI_V2 /* PPC64 ABIv2 needs local entry point */ addr = (kprobe_opcode_t *)kallsyms_lookup_name(name); if (addr && !offset) { @@ -63,7 +63,7 @@ kprobe_opcode_t *kprobe_lookup_name(const char *name, unsigned int offset) #endif addr = (kprobe_opcode_t *)ppc_function_entry(addr); } -#elif defined(PPC64_ELF_ABI_v1) +#elif defined(CONFIG_PPC64_ELF_ABI_V1) /* * 64bit powerpc ABIv1 uses function descriptors: * - Check for the dot variant of the symbol first. @@ -107,7 +107,7 @@ kprobe_opcode_t *kprobe_lookup_name(const char *name, unsigned int offset) static bool arch_kprobe_on_func_entry(unsigned long offset) { -#ifdef PPC64_ELF_ABI_v2 +#ifdef CONFIG_PPC64_ELF_ABI_V2 #ifdef CONFIG_KPROBES_ON_FTRACE return offset <= 16; #else @@ -150,8 +150,8 @@ int arch_prepare_kprobe(struct kprobe *p) if ((unsigned long)p->addr & 0x03) { printk("Attempt to register kprobe at an unaligned address\n"); ret = -EINVAL; - } else if (IS_MTMSRD(insn) || IS_RFID(insn)) { - printk("Cannot register a kprobe on mtmsr[d]/rfi[d]\n"); + } else if (!can_single_step(ppc_inst_val(insn))) { + printk("Cannot register a kprobe on instructions that can't be single stepped\n"); ret = -EINVAL; } else if ((unsigned long)p->addr & ~PAGE_MASK && ppc_inst_prefixed(ppc_inst_read(p->addr - 1))) { diff --git a/arch/powerpc/kernel/legacy_serial.c b/arch/powerpc/kernel/legacy_serial.c index cfc03e016ff2d5f4f605f9cfae425b2fef34478c..5c58460b269ac3f6057cbd026e97dcb35053d707 100644 --- a/arch/powerpc/kernel/legacy_serial.c +++ b/arch/powerpc/kernel/legacy_serial.c @@ -7,10 +7,10 @@ #include #include #include +#include #include #include #include -#include #include #include #include diff --git a/arch/powerpc/kernel/misc_64.S b/arch/powerpc/kernel/misc_64.S index d38a019b38e108f8e0380aca515969f58bc3a6ef..fd6d8d3a548e0cc17cbbb5b70beea22275da6ffe 100644 --- a/arch/powerpc/kernel/misc_64.S +++ b/arch/powerpc/kernel/misc_64.S @@ -454,7 +454,7 @@ _GLOBAL(kexec_sequence) beq 1f /* clear out hardware hash page table and tlb */ -#ifdef PPC64_ELF_ABI_v1 +#ifdef CONFIG_PPC64_ELF_ABI_V1 ld r12,0(r27) /* deref function descriptor */ #else mr r12,r27 diff --git a/arch/powerpc/kernel/module.c b/arch/powerpc/kernel/module.c index 97a76a8619fbd47bac406a3f23830ce04a13723a..f6d6ae0a1692396a6b65458e9731cbb61ea443a6 100644 --- a/arch/powerpc/kernel/module.c +++ b/arch/powerpc/kernel/module.c @@ -64,13 +64,13 @@ int module_finalize(const Elf_Ehdr *hdr, (void *)sect->sh_addr + sect->sh_size); #endif /* CONFIG_PPC64 */ -#ifdef PPC64_ELF_ABI_v1 +#ifdef CONFIG_PPC64_ELF_ABI_V1 sect = find_section(hdr, sechdrs, ".opd"); if (sect != NULL) { me->arch.start_opd = sect->sh_addr; me->arch.end_opd = sect->sh_addr + sect->sh_size; } -#endif /* PPC64_ELF_ABI_v1 */ +#endif /* CONFIG_PPC64_ELF_ABI_V1 */ #ifdef CONFIG_PPC_BARRIER_NOSPEC sect = find_section(hdr, sechdrs, "__spec_barrier_fixup"); diff --git a/arch/powerpc/kernel/module_32.c b/arch/powerpc/kernel/module_32.c index a0432ef46967efadb2daa0509cebd46e2968ecbf..ea653617177818fe0998fc37616b112613f0d757 100644 --- a/arch/powerpc/kernel/module_32.c +++ b/arch/powerpc/kernel/module_32.c @@ -99,7 +99,7 @@ static unsigned long get_plt_size(const Elf32_Ehdr *hdr, /* Sort the relocation information based on a symbol and * addend key. This is a stable O(n*log n) complexity - * alogrithm but it will reduce the complexity of + * algorithm but it will reduce the complexity of * count_relocs() to linear complexity O(n) */ sort((void *)hdr + sechdrs[i].sh_offset, @@ -256,9 +256,8 @@ int apply_relocate_add(Elf32_Shdr *sechdrs, value, (uint32_t)location); pr_debug("Location before: %08X.\n", *(uint32_t *)location); - value = (*(uint32_t *)location & ~0x03fffffc) - | ((value - (uint32_t)location) - & 0x03fffffc); + value = (*(uint32_t *)location & ~PPC_LI_MASK) | + PPC_LI(value - (uint32_t)location); if (patch_instruction(location, ppc_inst(value))) return -EFAULT; @@ -266,10 +265,8 @@ int apply_relocate_add(Elf32_Shdr *sechdrs, pr_debug("Location after: %08X.\n", *(uint32_t *)location); pr_debug("ie. jump to %08X+%08X = %08X\n", - *(uint32_t *)location & 0x03fffffc, - (uint32_t)location, - (*(uint32_t *)location & 0x03fffffc) - + (uint32_t)location); + *(uint32_t *)PPC_LI((uint32_t)location), (uint32_t)location, + (*(uint32_t *)PPC_LI((uint32_t)location)) + (uint32_t)location); break; case R_PPC_REL32: @@ -289,23 +286,32 @@ int apply_relocate_add(Elf32_Shdr *sechdrs, } #ifdef CONFIG_DYNAMIC_FTRACE -int module_trampoline_target(struct module *mod, unsigned long addr, - unsigned long *target) +notrace int module_trampoline_target(struct module *mod, unsigned long addr, + unsigned long *target) { - unsigned int jmp[4]; + ppc_inst_t jmp[4]; /* Find where the trampoline jumps to */ - if (copy_from_kernel_nofault(jmp, (void *)addr, sizeof(jmp))) + if (copy_inst_from_kernel_nofault(jmp, (void *)addr)) + return -EFAULT; + if (__copy_inst_from_kernel_nofault(jmp + 1, (void *)addr + 4)) + return -EFAULT; + if (__copy_inst_from_kernel_nofault(jmp + 2, (void *)addr + 8)) + return -EFAULT; + if (__copy_inst_from_kernel_nofault(jmp + 3, (void *)addr + 12)) return -EFAULT; /* verify that this is what we expect it to be */ - if ((jmp[0] & 0xffff0000) != PPC_RAW_LIS(_R12, 0) || - (jmp[1] & 0xffff0000) != PPC_RAW_ADDI(_R12, _R12, 0) || - jmp[2] != PPC_RAW_MTCTR(_R12) || - jmp[3] != PPC_RAW_BCTR()) + if ((ppc_inst_val(jmp[0]) & 0xffff0000) != PPC_RAW_LIS(_R12, 0)) + return -EINVAL; + if ((ppc_inst_val(jmp[1]) & 0xffff0000) != PPC_RAW_ADDI(_R12, _R12, 0)) + return -EINVAL; + if (ppc_inst_val(jmp[2]) != PPC_RAW_MTCTR(_R12)) + return -EINVAL; + if (ppc_inst_val(jmp[3]) != PPC_RAW_BCTR()) return -EINVAL; - addr = (jmp[1] & 0xffff) | ((jmp[0] & 0xffff) << 16); + addr = (ppc_inst_val(jmp[1]) & 0xffff) | ((ppc_inst_val(jmp[0]) & 0xffff) << 16); if (addr & 0x8000) addr -= 0x10000; diff --git a/arch/powerpc/kernel/module_64.c b/arch/powerpc/kernel/module_64.c index 794720530442702f8bd0f6a46f6e40d755febf95..7e45dc98df8a136e08bf3b4af2b0f1d76086effa 100644 --- a/arch/powerpc/kernel/module_64.c +++ b/arch/powerpc/kernel/module_64.c @@ -31,7 +31,7 @@ this, and makes other things simpler. Anton? --RR. */ -#ifdef PPC64_ELF_ABI_v2 +#ifdef CONFIG_PPC64_ELF_ABI_V2 static func_desc_t func_desc(unsigned long addr) { @@ -122,7 +122,7 @@ static u32 ppc64_stub_insns[] = { /* Save current r2 value in magic place on the stack. */ PPC_RAW_STD(_R2, _R1, R2_STACK_OFFSET), PPC_RAW_LD(_R12, _R11, 32), -#ifdef PPC64_ELF_ABI_v1 +#ifdef CONFIG_PPC64_ELF_ABI_V1 /* Set up new r2 from function descriptor */ PPC_RAW_LD(_R2, _R11, 40), #endif @@ -194,7 +194,7 @@ static unsigned long get_stubs_size(const Elf64_Ehdr *hdr, /* Sort the relocation information based on a symbol and * addend key. This is a stable O(n*log n) complexity - * alogrithm but it will reduce the complexity of + * algorithm but it will reduce the complexity of * count_relocs() to linear complexity O(n) */ sort((void *)sechdrs[i].sh_addr, @@ -361,7 +361,7 @@ static inline int create_ftrace_stub(struct ppc64_stub_entry *entry, entry->jump[1] |= PPC_HA(reladdr); entry->jump[2] |= PPC_LO(reladdr); - /* Eventhough we don't use funcdata in the stub, it's needed elsewhere. */ + /* Even though we don't use funcdata in the stub, it's needed elsewhere. */ entry->funcdata = func_desc(addr); entry->magic = STUB_MAGIC; @@ -653,8 +653,7 @@ int apply_relocate_add(Elf64_Shdr *sechdrs, } /* Only replace bits 2 through 26 */ - value = (*(uint32_t *)location & ~0x03fffffc) - | (value & 0x03fffffc); + value = (*(uint32_t *)location & ~PPC_LI_MASK) | PPC_LI(value); if (patch_instruction((u32 *)location, ppc_inst(value))) return -EFAULT; diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c index 0d9f9cd41e135bbe7487aae5b0092a1fc7833c99..e385d3164648ce84461b09069a53845c903eb520 100644 --- a/arch/powerpc/kernel/nvram_64.c +++ b/arch/powerpc/kernel/nvram_64.c @@ -19,9 +19,9 @@ #include #include #include +#include #include #include -#include #include #undef DEBUG_NVRAM diff --git a/arch/powerpc/kernel/paca.c b/arch/powerpc/kernel/paca.c index 39da688a9455a2eabad8127519de8204d9885eed..ba593fd6012450b658ac66b210212705404cbe51 100644 --- a/arch/powerpc/kernel/paca.c +++ b/arch/powerpc/kernel/paca.c @@ -344,15 +344,10 @@ void copy_mm_to_paca(struct mm_struct *mm) { mm_context_t *context = &mm->context; -#ifdef CONFIG_PPC_MM_SLICES VM_BUG_ON(!mm_ctx_slb_addr_limit(context)); memcpy(&get_paca()->mm_ctx_low_slices_psize, mm_ctx_low_slices(context), LOW_SLICE_ARRAY_SZ); memcpy(&get_paca()->mm_ctx_high_slices_psize, mm_ctx_high_slices(context), TASK_SLICE_ARRAY_SZ(context)); -#else /* CONFIG_PPC_MM_SLICES */ - get_paca()->mm_ctx_user_psize = context->user_psize; - get_paca()->mm_ctx_sllp = context->sllp; -#endif } #endif /* CONFIG_PPC_64S_HASH_MMU */ diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c index 8bc9cf62cd93d55a2e78d8e3e2bbf41e5afbdd5b..068410cd54a3daab114122e8ae485f43226d1913 100644 --- a/arch/powerpc/kernel/pci-common.c +++ b/arch/powerpc/kernel/pci-common.c @@ -30,10 +30,10 @@ #include #include #include +#include #include #include -#include #include #include #include @@ -42,7 +42,7 @@ #include "../../../drivers/pci/pci.h" -/* hose_spinlock protects accesses to the the phb_bitmap. */ +/* hose_spinlock protects accesses to the phb_bitmap. */ static DEFINE_SPINLOCK(hose_spinlock); LIST_HEAD(hose_list); @@ -1688,7 +1688,7 @@ EXPORT_SYMBOL_GPL(pcibios_scan_phb); static void fixup_hide_host_resource_fsl(struct pci_dev *dev) { int i, class = dev->class >> 8; - /* When configured as agent, programing interface = 1 */ + /* When configured as agent, programming interface = 1 */ int prog_if = dev->class & 0xf; if ((class == PCI_CLASS_PROCESSOR_POWERPC || diff --git a/arch/powerpc/kernel/pci-hotplug.c b/arch/powerpc/kernel/pci-hotplug.c index 2fc12198ec071ca20973143d4df310ef48ca08b5..0fe251c6ac2ce7a4e7462ce9b8b6285c77cd3851 100644 --- a/arch/powerpc/kernel/pci-hotplug.c +++ b/arch/powerpc/kernel/pci-hotplug.c @@ -12,6 +12,7 @@ #include #include +#include #include #include #include diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c index 48537964fba122c033c623f13d0e93dc8065d193..5a174936c9a0e049ebf70cb335acc3679d324d10 100644 --- a/arch/powerpc/kernel/pci_32.c +++ b/arch/powerpc/kernel/pci_32.c @@ -21,7 +21,6 @@ #include #include -#include #include #include #include diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index 3fb7e572abedfa3214016ccab1481e0d1da39d42..19b03ddf563113421df759b9cb5d818f260f33e3 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c @@ -19,10 +19,10 @@ #include #include #include +#include #include #include -#include #include #include #include @@ -285,3 +285,12 @@ int pcibus_to_node(struct pci_bus *bus) } EXPORT_SYMBOL(pcibus_to_node); #endif + +int pci_device_from_OF_node(struct device_node *np, u8 *bus, u8 *devfn) +{ + if (!PCI_DN(np)) + return -ENODEV; + *bus = PCI_DN(np)->busno; + *devfn = PCI_DN(np)->devfn; + return 0; +} diff --git a/arch/powerpc/kernel/pci_dn.c b/arch/powerpc/kernel/pci_dn.c index 61571ae23953063ee5ae4e80589922b8102a8804..938ab8838ab546e2a3e13451559c2dc2d31da78d 100644 --- a/arch/powerpc/kernel/pci_dn.c +++ b/arch/powerpc/kernel/pci_dn.c @@ -12,9 +12,9 @@ #include #include #include +#include #include -#include #include #include #include diff --git a/arch/powerpc/kernel/pci_of_scan.c b/arch/powerpc/kernel/pci_of_scan.c index c3024f1047654c3a9ef774a2ab1395407032cf15..756043dd06e9ae0d0221221373f2395d51e60e40 100644 --- a/arch/powerpc/kernel/pci_of_scan.c +++ b/arch/powerpc/kernel/pci_of_scan.c @@ -13,8 +13,8 @@ #include #include +#include #include -#include /** * get_int_prop - Decode a u32 from a device tree property @@ -244,7 +244,7 @@ EXPORT_SYMBOL(of_create_pci_dev); * @dev: pci_dev structure for the bridge * * of_scan_bus() calls this routine for each PCI bridge that it finds, and - * this routine in turn call of_scan_bus() recusively to scan for more child + * this routine in turn call of_scan_bus() recursively to scan for more child * devices. */ void of_scan_pci_bridge(struct pci_dev *dev) diff --git a/arch/powerpc/kernel/proc_powerpc.c b/arch/powerpc/kernel/proc_powerpc.c index 6a029f2378e1833ed06406a4f16bfc95bf46d382..b109cd7b5d01fbe6870b60e60965effa86ecf3b6 100644 --- a/arch/powerpc/kernel/proc_powerpc.c +++ b/arch/powerpc/kernel/proc_powerpc.c @@ -7,12 +7,12 @@ #include #include #include +#include #include #include #include #include -#include #ifdef CONFIG_PPC64 diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 984813a4d5dc47283687e0cc7f38f7e5deaf19c9..d00b20c6596671f53db148f184a04ddb7fc6650d 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -34,10 +34,8 @@ #include #include #include -#include #include #include -#include #include #include @@ -45,7 +43,6 @@ #include #include #include -#include #include #include #include @@ -307,7 +304,7 @@ static void __giveup_vsx(struct task_struct *tsk) unsigned long msr = tsk->thread.regs->msr; /* - * We should never be ssetting MSR_VSX without also setting + * We should never be setting MSR_VSX without also setting * MSR_FP and MSR_VEC */ WARN_ON((msr & MSR_VSX) && !((msr & MSR_FP) && (msr & MSR_VEC))); @@ -645,7 +642,7 @@ static void do_break_handler(struct pt_regs *regs) return; } - /* Otherwise findout which DAWR caused exception and disable it. */ + /* Otherwise find out which DAWR caused exception and disable it. */ wp_get_instr_detail(regs, &instr, &type, &size, &ea); for (i = 0; i < nr_wp_slots(); i++) { @@ -2313,42 +2310,3 @@ unsigned long arch_align_stack(unsigned long sp) sp -= get_random_int() & ~PAGE_MASK; return sp & ~0xf; } - -static inline unsigned long brk_rnd(void) -{ - unsigned long rnd = 0; - - /* 8MB for 32bit, 1GB for 64bit */ - if (is_32bit_task()) - rnd = (get_random_long() % (1UL<<(23-PAGE_SHIFT))); - else - rnd = (get_random_long() % (1UL<<(30-PAGE_SHIFT))); - - return rnd << PAGE_SHIFT; -} - -unsigned long arch_randomize_brk(struct mm_struct *mm) -{ - unsigned long base = mm->brk; - unsigned long ret; - -#ifdef CONFIG_PPC_BOOK3S_64 - /* - * If we are using 1TB segments and we are allowed to randomise - * the heap, we can put it above 1TB so it is backed by a 1TB - * segment. Otherwise the heap will be in the bottom 1TB - * which always uses 256MB segments and this may result in a - * performance penalty. - */ - if (!radix_enabled() && !is_32bit_task() && (mmu_highuser_ssize == MMU_SEGSIZE_1T)) - base = max_t(unsigned long, mm->brk, 1UL << SID_SHIFT_1T); -#endif - - ret = PAGE_ALIGN(base + brk_rnd()); - - if (ret < mm->brk) - return mm->brk; - - return ret; -} - diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 86c4f009563d95b323175307a560f0531df5b6f1..feae8509b59c9b5260dfddef1c9da837f750cee0 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -31,7 +31,6 @@ #include #include -#include #include #include #include diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index 0ac5faacc909cac6497a7aa14c113bd9dbc7037b..04694ec423f6649a973e1f61e78e1bad2448600c 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c @@ -28,6 +28,8 @@ #include #include #include +#include +#include #include #include #include @@ -3416,7 +3418,7 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, * * PowerMacs use a different mechanism to spin CPUs * - * (This must be done after instanciating RTAS) + * (This must be done after instantiating RTAS) */ if (of_platform != PLATFORM_POWERMAC) prom_hold_cpus(); diff --git a/arch/powerpc/kernel/ptrace/ptrace-view.c b/arch/powerpc/kernel/ptrace/ptrace-view.c index f15bc78caf7188278eca0074b61f1053b9563086..076d867412c70d52bf7bdf7968b097ed94de9268 100644 --- a/arch/powerpc/kernel/ptrace/ptrace-view.c +++ b/arch/powerpc/kernel/ptrace/ptrace-view.c @@ -174,7 +174,7 @@ int ptrace_get_reg(struct task_struct *task, int regno, unsigned long *data) /* * softe copies paca->irq_soft_mask variable state. Since irq_soft_mask is - * no more used as a flag, lets force usr to alway see the softe value as 1 + * no more used as a flag, lets force usr to always see the softe value as 1 * which means interrupts are not soft disabled. */ if (IS_ENABLED(CONFIG_PPC64) && regno == PT_SOFTE) { diff --git a/arch/powerpc/kernel/ptrace/ptrace.c b/arch/powerpc/kernel/ptrace/ptrace.c index 6d5026a9db4fc6e05a14f0662a9166552ef7e739..4d2dc22d4a2d54637fb1c042da1b1b5326432bcd 100644 --- a/arch/powerpc/kernel/ptrace/ptrace.c +++ b/arch/powerpc/kernel/ptrace/ptrace.c @@ -444,10 +444,4 @@ void __init pt_regs_check(void) * real registers. */ BUILD_BUG_ON(PT_DSCR < sizeof(struct user_pt_regs) / sizeof(unsigned long)); - -#ifdef PPC64_ELF_ABI_v1 - BUILD_BUG_ON(!IS_ENABLED(CONFIG_HAVE_FUNCTION_DESCRIPTORS)); -#else - BUILD_BUG_ON(IS_ENABLED(CONFIG_HAVE_FUNCTION_DESCRIPTORS)); -#endif } diff --git a/arch/powerpc/kernel/rtas-proc.c b/arch/powerpc/kernel/rtas-proc.c index 6857a5b0a1c39c24208c253e96e56110b3fe5706..081b2b741a8c7fa91e21a7a403255714736618b5 100644 --- a/arch/powerpc/kernel/rtas-proc.c +++ b/arch/powerpc/kernel/rtas-proc.c @@ -24,11 +24,11 @@ #include #include #include +#include #include #include #include -#include #include #include /* for ppc_md */ #include @@ -259,7 +259,6 @@ __initcall(proc_rtas_init); static int parse_number(const char __user *p, size_t count, u64 *val) { char buf[40]; - char *end; if (count > 39) return -EINVAL; @@ -269,11 +268,7 @@ static int parse_number(const char __user *p, size_t count, u64 *val) buf[count] = 0; - *val = simple_strtoull(buf, &end, 10); - if (*end && *end != '\n') - return -EINVAL; - - return 0; + return kstrtoull(buf, 10, val); } /* ****************************************************************** */ diff --git a/arch/powerpc/kernel/rtas-rtc.c b/arch/powerpc/kernel/rtas-rtc.c index 33c07c8af6c8b379852cc8f8784b70b5381ccfd2..5a31d1829bcabf96d44f9e5a10dd3a4e945ee8c5 100644 --- a/arch/powerpc/kernel/rtas-rtc.c +++ b/arch/powerpc/kernel/rtas-rtc.c @@ -6,7 +6,6 @@ #include #include #include -#include #include #include diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index 1f42aabbbab3a05195b535b337066aa82f57cb50..9bb43aa53d43ec331299a2d378751b694bed609d 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c @@ -24,9 +24,10 @@ #include #include #include +#include +#include #include -#include #include #include #include @@ -49,6 +50,19 @@ void enter_rtas(unsigned long); static inline void do_enter_rtas(unsigned long args) { + unsigned long msr; + + /* + * Make sure MSR[RI] is currently enabled as it will be forced later + * in enter_rtas. + */ + msr = mfmsr(); + BUG_ON(!(msr & MSR_RI)); + + BUG_ON(!irqs_disabled()); + + hard_irq_disable(); /* Ensure MSR[EE] is disabled on PPC64 */ + enter_rtas(args); srr_regs_clobbered(); /* rtas uses SRRs, invalidate */ @@ -462,6 +476,11 @@ int rtas_call(int token, int nargs, int nret, int *outputs, ...) if (!rtas.entry || token == RTAS_UNKNOWN_SERVICE) return -1; + if ((mfmsr() & (MSR_IR|MSR_DR)) != (MSR_IR|MSR_DR)) { + WARN_ON_ONCE(1); + return -1; + } + s = lock_rtas(); /* We use the global rtas args buffer */ diff --git a/arch/powerpc/kernel/rtas_entry.S b/arch/powerpc/kernel/rtas_entry.S new file mode 100644 index 0000000000000000000000000000000000000000..9a434d42e660ac8ee8d13415b324a4da1bbf9142 --- /dev/null +++ b/arch/powerpc/kernel/rtas_entry.S @@ -0,0 +1,172 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include +#include +#include +#include + +/* + * RTAS is called with MSR IR, DR, EE disabled, and LR in the return address. + * + * Note: r3 is an input parameter to rtas, so don't trash it... + */ + +#ifdef CONFIG_PPC32 +_GLOBAL(enter_rtas) + stwu r1,-INT_FRAME_SIZE(r1) + mflr r0 + stw r0,INT_FRAME_SIZE+4(r1) + LOAD_REG_ADDR(r4, rtas) + lis r6,1f@ha /* physical return address for rtas */ + addi r6,r6,1f@l + tophys(r6,r6) + lwz r8,RTASENTRY(r4) + lwz r4,RTASBASE(r4) + mfmsr r9 + stw r9,8(r1) + li r9,MSR_KERNEL & ~(MSR_IR|MSR_DR) + mtlr r6 + stw r1, THREAD + RTAS_SP(r2) + mtspr SPRN_SRR0,r8 + mtspr SPRN_SRR1,r9 + rfi +1: + lis r8, 1f@h + ori r8, r8, 1f@l + LOAD_REG_IMMEDIATE(r9,MSR_KERNEL) + mtspr SPRN_SRR0,r8 + mtspr SPRN_SRR1,r9 + rfi /* Reactivate MMU translation */ +1: + lwz r8,INT_FRAME_SIZE+4(r1) /* get return address */ + lwz r9,8(r1) /* original msr value */ + addi r1,r1,INT_FRAME_SIZE + li r0,0 + stw r0, THREAD + RTAS_SP(r2) + mtlr r8 + mtmsr r9 + blr /* return to caller */ +_ASM_NOKPROBE_SYMBOL(enter_rtas) + +#else /* CONFIG_PPC32 */ +#include + +/* + * 32-bit rtas on 64-bit machines has the additional problem that RTAS may + * not preserve the upper parts of registers it uses. + */ +_GLOBAL(enter_rtas) + mflr r0 + std r0,16(r1) + stdu r1,-SWITCH_FRAME_SIZE(r1) /* Save SP and create stack space. */ + + /* Because RTAS is running in 32b mode, it clobbers the high order half + * of all registers that it saves. We therefore save those registers + * RTAS might touch to the stack. (r0, r3-r12 are caller saved) + */ + SAVE_GPR(2, r1) /* Save the TOC */ + SAVE_NVGPRS(r1) /* Save the non-volatiles */ + + mfcr r4 + std r4,_CCR(r1) + mfctr r5 + std r5,_CTR(r1) + mfspr r6,SPRN_XER + std r6,_XER(r1) + mfdar r7 + std r7,_DAR(r1) + mfdsisr r8 + std r8,_DSISR(r1) + + /* Temporary workaround to clear CR until RTAS can be modified to + * ignore all bits. + */ + li r0,0 + mtcr r0 + + mfmsr r6 + + /* Unfortunately, the stack pointer and the MSR are also clobbered, + * so they are saved in the PACA which allows us to restore + * our original state after RTAS returns. + */ + std r1,PACAR1(r13) + std r6,PACASAVEDMSR(r13) + + /* Setup our real return addr */ + LOAD_REG_ADDR(r4,rtas_return_loc) + clrldi r4,r4,2 /* convert to realmode address */ + mtlr r4 + +__enter_rtas: + LOAD_REG_ADDR(r4, rtas) + ld r5,RTASENTRY(r4) /* get the rtas->entry value */ + ld r4,RTASBASE(r4) /* get the rtas->base value */ + + /* + * RTAS runs in 32-bit big endian real mode, but leave MSR[RI] on as we + * may hit NMI (SRESET or MCE) while in RTAS. RTAS should disable RI in + * its critical regions (as specified in PAPR+ section 7.2.1). MSR[S] + * is not impacted by RFI_TO_KERNEL (only urfid can unset it). So if + * MSR[S] is set, it will remain when entering RTAS. + */ + LOAD_REG_IMMEDIATE(r6, MSR_ME | MSR_RI) + + li r0,0 + mtmsrd r0,1 /* disable RI before using SRR0/1 */ + + mtspr SPRN_SRR0,r5 + mtspr SPRN_SRR1,r6 + RFI_TO_KERNEL + b . /* prevent speculative execution */ +rtas_return_loc: + FIXUP_ENDIAN + + /* Set SF before anything. */ + LOAD_REG_IMMEDIATE(r6, MSR_KERNEL & ~(MSR_IR|MSR_DR)) + mtmsrd r6 + + /* relocation is off at this point */ + GET_PACA(r13) + + bcl 20,31,$+4 +0: mflr r3 + ld r3,(1f-0b)(r3) /* get &rtas_restore_regs */ + + ld r1,PACAR1(r13) /* Restore our SP */ + ld r4,PACASAVEDMSR(r13) /* Restore our MSR */ + + mtspr SPRN_SRR0,r3 + mtspr SPRN_SRR1,r4 + RFI_TO_KERNEL + b . /* prevent speculative execution */ +_ASM_NOKPROBE_SYMBOL(enter_rtas) +_ASM_NOKPROBE_SYMBOL(__enter_rtas) +_ASM_NOKPROBE_SYMBOL(rtas_return_loc) + + .align 3 +1: .8byte rtas_restore_regs + +rtas_restore_regs: + /* relocation is on at this point */ + REST_GPR(2, r1) /* Restore the TOC */ + REST_NVGPRS(r1) /* Restore the non-volatiles */ + + ld r4,_CCR(r1) + mtcr r4 + ld r5,_CTR(r1) + mtctr r5 + ld r6,_XER(r1) + mtspr SPRN_XER,r6 + ld r7,_DAR(r1) + mtdar r7 + ld r8,_DSISR(r1) + mtdsisr r8 + + addi r1,r1,SWITCH_FRAME_SIZE /* Unstack our frame */ + ld r0,16(r1) /* get return address */ + + mtlr r0 + blr /* return to caller */ + +#endif /* CONFIG_PPC32 */ diff --git a/arch/powerpc/kernel/rtas_flash.c b/arch/powerpc/kernel/rtas_flash.c index a99179d835382f1c1d6a3ea408cb593ef93f4a39..bc817a5619d6412c81832574f3b5062605b9e839 100644 --- a/arch/powerpc/kernel/rtas_flash.c +++ b/arch/powerpc/kernel/rtas_flash.c @@ -120,7 +120,7 @@ static struct kmem_cache *flash_block_cache = NULL; /* * Local copy of the flash block list. * - * The rtas_firmware_flash_list varable will be + * The rtas_firmware_flash_list variable will be * set once the data is fully read. * * For convenience as we build the list we use virtual addrs, diff --git a/arch/powerpc/kernel/rtas_pci.c b/arch/powerpc/kernel/rtas_pci.c index 781c1869902ef2f6caee36ebb4035e726e715b87..5a2f5ea3b054eb405629d3a75d044839bcbd790a 100644 --- a/arch/powerpc/kernel/rtas_pci.c +++ b/arch/powerpc/kernel/rtas_pci.c @@ -14,10 +14,11 @@ #include #include #include +#include +#include #include #include -#include #include #include #include diff --git a/arch/powerpc/kernel/rtasd.c b/arch/powerpc/kernel/rtasd.c index cf0f42909ddfaeafb54514c3629fbd9414e21fb8..5270b450bbde406f2f0258a39ccaf79ee609b0ee 100644 --- a/arch/powerpc/kernel/rtasd.c +++ b/arch/powerpc/kernel/rtasd.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c index 518ae5aa94109603c5943b2254b881baa7ec74ee..eb0077b302e24fe0024dfd76b8e3ac096f7ca784 100644 --- a/arch/powerpc/kernel/setup-common.c +++ b/arch/powerpc/kernel/setup-common.c @@ -23,19 +23,19 @@ #include #include #include -#include #include #include #include #include #include #include +#include +#include #include #include #include #include #include -#include #include #include #include @@ -161,9 +161,7 @@ void machine_restart(char *cmd) void machine_power_off(void) { machine_shutdown(); - if (pm_power_off) - pm_power_off(); - + do_kernel_power_off(); smp_send_stop(); machine_hang(); } @@ -279,7 +277,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) proc_freq / 1000000, proc_freq % 1000000); /* If we are a Freescale core do a simple check so - * we dont have to keep adding cases in the future */ + * we don't have to keep adding cases in the future */ if (PVR_VER(pvr) & 0x8000) { switch (PVR_VER(pvr)) { case 0x8000: /* 7441/7450/7451, Voyager */ @@ -680,8 +678,25 @@ int check_legacy_ioport(unsigned long base_port) } EXPORT_SYMBOL(check_legacy_ioport); -static int ppc_panic_event(struct notifier_block *this, - unsigned long event, void *ptr) +/* + * Panic notifiers setup + * + * We have 3 notifiers for powerpc, each one from a different "nature": + * + * - ppc_panic_fadump_handler() is a hypervisor notifier, which hard-disables + * IRQs and deal with the Firmware-Assisted dump, when it is configured; + * should run early in the panic path. + * + * - dump_kernel_offset() is an informative notifier, just showing the KASLR + * offset if we have RANDOMIZE_BASE set. + * + * - ppc_panic_platform_handler() is a low-level handler that's registered + * only if the platform wishes to perform final actions in the panic path, + * hence it should run late and might not even return. Currently, only + * pseries and ps3 platforms register callbacks. + */ +static int ppc_panic_fadump_handler(struct notifier_block *this, + unsigned long event, void *ptr) { /* * panic does a local_irq_disable, but we really @@ -691,45 +706,63 @@ static int ppc_panic_event(struct notifier_block *this, /* * If firmware-assisted dump has been registered then trigger - * firmware-assisted dump and let firmware handle everything else. + * its callback and let the firmware handles everything else. */ crash_fadump(NULL, ptr); - if (ppc_md.panic) - ppc_md.panic(ptr); /* May not return */ + return NOTIFY_DONE; } -static struct notifier_block ppc_panic_block = { - .notifier_call = ppc_panic_event, - .priority = INT_MIN /* may not return; must be done last */ -}; - -/* - * Dump out kernel offset information on panic. - */ static int dump_kernel_offset(struct notifier_block *self, unsigned long v, void *p) { pr_emerg("Kernel Offset: 0x%lx from 0x%lx\n", kaslr_offset(), KERNELBASE); - return 0; + return NOTIFY_DONE; } +static int ppc_panic_platform_handler(struct notifier_block *this, + unsigned long event, void *ptr) +{ + /* + * This handler is only registered if we have a panic callback + * on ppc_md, hence NULL check is not needed. + * Also, it may not return, so it runs really late on panic path. + */ + ppc_md.panic(ptr); + + return NOTIFY_DONE; +} + +static struct notifier_block ppc_fadump_block = { + .notifier_call = ppc_panic_fadump_handler, + .priority = INT_MAX, /* run early, to notify the firmware ASAP */ +}; + static struct notifier_block kernel_offset_notifier = { - .notifier_call = dump_kernel_offset + .notifier_call = dump_kernel_offset, +}; + +static struct notifier_block ppc_panic_block = { + .notifier_call = ppc_panic_platform_handler, + .priority = INT_MIN, /* may not return; must be done last */ }; void __init setup_panic(void) { + /* Hard-disables IRQs + deal with FW-assisted dump (fadump) */ + atomic_notifier_chain_register(&panic_notifier_list, + &ppc_fadump_block); + if (IS_ENABLED(CONFIG_RANDOMIZE_BASE) && kaslr_offset() > 0) atomic_notifier_chain_register(&panic_notifier_list, &kernel_offset_notifier); - /* PPC64 always does a hard irq disable in its panic handler */ - if (!IS_ENABLED(CONFIG_PPC64) && !ppc_md.panic) - return; - atomic_notifier_chain_register(&panic_notifier_list, &ppc_panic_block); + /* Low-level platform-specific routines that should run on panic */ + if (ppc_md.panic) + atomic_notifier_chain_register(&panic_notifier_list, + &ppc_panic_block); } #ifdef CONFIG_CHECK_CACHE_COHERENCY diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c index a6e9d36d7c0190fd541499acd3307bdd00aadd6b..8132617893035cfa04ae18b81e6399c691bf7740 100644 --- a/arch/powerpc/kernel/setup_32.c +++ b/arch/powerpc/kernel/setup_32.c @@ -20,9 +20,10 @@ #include #include #include +#include +#include #include -#include #include #include #include diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index a96f05063bc9108da0770877ad3b2b86291f8c90..0e8fc1cd1c558e1acd17ae1e14efd795e66c9318 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -31,11 +31,12 @@ #include #include #include +#include +#include #include #include #include -#include #include #include #include diff --git a/arch/powerpc/kernel/signal.c b/arch/powerpc/kernel/signal.c index f7f8620663c70fd523e1512dd1007e34330ec2ea..68a91e553e14cea211f3b7b7001842097bf227fc 100644 --- a/arch/powerpc/kernel/signal.c +++ b/arch/powerpc/kernel/signal.c @@ -141,6 +141,21 @@ unsigned long copy_ckvsx_from_user(struct task_struct *task, int show_unhandled_signals = 1; +unsigned long get_min_sigframe_size(void) +{ + if (IS_ENABLED(CONFIG_PPC64)) + return get_min_sigframe_size_64(); + else + return get_min_sigframe_size_32(); +} + +#ifdef CONFIG_COMPAT +unsigned long get_min_sigframe_size_compat(void) +{ + return get_min_sigframe_size_32(); +} +#endif + /* * Allocate space for the signal frame */ diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c index d84c434b2b78edf9988ba14ec4ffc7b9b143aaa1..157a7403e3eb3e3f39002c2f23e0927323fef6f9 100644 --- a/arch/powerpc/kernel/signal_32.c +++ b/arch/powerpc/kernel/signal_32.c @@ -233,6 +233,12 @@ struct rt_sigframe { int abigap[56]; }; +unsigned long get_min_sigframe_size_32(void) +{ + return max(sizeof(struct rt_sigframe) + __SIGNAL_FRAMESIZE + 16, + sizeof(struct sigframe) + __SIGNAL_FRAMESIZE); +} + /* * Save the current user registers on the user stack. * We only save the altivec/spe registers if the process has used diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c index 73d483b07ff39e9ba5f251a4be3cbb8e9d44db96..472596a109e2d592d628f21b000258bfe60791be 100644 --- a/arch/powerpc/kernel/signal_64.c +++ b/arch/powerpc/kernel/signal_64.c @@ -66,6 +66,11 @@ struct rt_sigframe { char abigap[USER_REDZONE_SIZE]; } __attribute__ ((aligned (16))); +unsigned long get_min_sigframe_size_64(void) +{ + return sizeof(struct rt_sigframe) + __SIGNAL_FRAMESIZE; +} + /* * This computes a quad word aligned pointer inside the vmx_reserve array * element. For historical reasons sigcontext might not be quad word aligned, @@ -123,7 +128,7 @@ static long notrace __unsafe_setup_sigcontext(struct sigcontext __user *sc, #endif struct pt_regs *regs = tsk->thread.regs; unsigned long msr = regs->msr; - /* Force usr to alway see softe as 1 (interrupts enabled) */ + /* Force usr to always see softe as 1 (interrupts enabled) */ unsigned long softe = 0x1; BUG_ON(tsk != current); diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index de0f6f09a5ddc947a8cddd2e1a1e9a1950b7cf9a..bcefab484ea61d28f1c163f386a539a17358d47e 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c @@ -43,7 +43,6 @@ #include #include #include -#include #include #include #include @@ -412,32 +411,32 @@ static struct cpumask nmi_ipi_pending_mask; static bool nmi_ipi_busy = false; static void (*nmi_ipi_function)(struct pt_regs *) = NULL; -static void nmi_ipi_lock_start(unsigned long *flags) +noinstr static void nmi_ipi_lock_start(unsigned long *flags) { raw_local_irq_save(*flags); hard_irq_disable(); - while (atomic_cmpxchg(&__nmi_ipi_lock, 0, 1) == 1) { + while (arch_atomic_cmpxchg(&__nmi_ipi_lock, 0, 1) == 1) { raw_local_irq_restore(*flags); - spin_until_cond(atomic_read(&__nmi_ipi_lock) == 0); + spin_until_cond(arch_atomic_read(&__nmi_ipi_lock) == 0); raw_local_irq_save(*flags); hard_irq_disable(); } } -static void nmi_ipi_lock(void) +noinstr static void nmi_ipi_lock(void) { - while (atomic_cmpxchg(&__nmi_ipi_lock, 0, 1) == 1) - spin_until_cond(atomic_read(&__nmi_ipi_lock) == 0); + while (arch_atomic_cmpxchg(&__nmi_ipi_lock, 0, 1) == 1) + spin_until_cond(arch_atomic_read(&__nmi_ipi_lock) == 0); } -static void nmi_ipi_unlock(void) +noinstr static void nmi_ipi_unlock(void) { smp_mb(); - WARN_ON(atomic_read(&__nmi_ipi_lock) != 1); - atomic_set(&__nmi_ipi_lock, 0); + WARN_ON(arch_atomic_read(&__nmi_ipi_lock) != 1); + arch_atomic_set(&__nmi_ipi_lock, 0); } -static void nmi_ipi_unlock_end(unsigned long *flags) +noinstr static void nmi_ipi_unlock_end(unsigned long *flags) { nmi_ipi_unlock(); raw_local_irq_restore(*flags); @@ -446,7 +445,7 @@ static void nmi_ipi_unlock_end(unsigned long *flags) /* * Platform NMI handler calls this to ack */ -int smp_handle_nmi_ipi(struct pt_regs *regs) +noinstr int smp_handle_nmi_ipi(struct pt_regs *regs) { void (*fn)(struct pt_regs *) = NULL; unsigned long flags; @@ -875,7 +874,7 @@ out_free: * @tg : The thread-group structure of the CPU node which @cpu belongs * to. * - * Returns the index to tg->thread_list that points to the the start + * Returns the index to tg->thread_list that points to the start * of the thread_group that @cpu belongs to. * * Returns -1 if cpu doesn't belong to any of the groups pointed to by @@ -1102,7 +1101,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus) DBG("smp_prepare_cpus\n"); /* - * setup_cpu may need to be called on the boot cpu. We havent + * setup_cpu may need to be called on the boot cpu. We haven't * spun any cpus up but lets be paranoid. */ BUG_ON(boot_cpuid != smp_processor_id()); diff --git a/arch/powerpc/kernel/syscalls.c b/arch/powerpc/kernel/syscalls.c index c4f5b4ce926f0efcafa17e292875788036375a79..fc999140bc27e94229856e80f0cac221f87c59b8 100644 --- a/arch/powerpc/kernel/syscalls.c +++ b/arch/powerpc/kernel/syscalls.c @@ -73,7 +73,7 @@ SYSCALL_DEFINE6(mmap, unsigned long, addr, size_t, len, int ppc_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp, struct __kernel_old_timeval __user *tvp) { - if ( (unsigned long)n >= 4096 ) + if ((unsigned long)n >= 4096) return sys_old_select((void __user *)n); return sys_select(n, inp, outp, exp, tvp); diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c index 2069bbb90a9a39fc41654a2daeb0b241eb930d6a..3a10cda9c05ec775787e7199ed5adc4b7ccc6ce7 100644 --- a/arch/powerpc/kernel/sysfs.c +++ b/arch/powerpc/kernel/sysfs.c @@ -9,12 +9,12 @@ #include #include #include +#include #include #include #include #include -#include #include #include #include diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index f80cce0e38994538dcef03bd2dec3f0e03ffa716..587adcc12860bd96f1867cea9e4121aff2b0c07c 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c @@ -54,8 +54,10 @@ #include #include #include -#include +#include +#include +#include #include #include #include @@ -63,7 +65,6 @@ #include #include #include -#include #include #include #include @@ -156,10 +157,6 @@ bool tb_invalid; u64 __cputime_usec_factor; EXPORT_SYMBOL(__cputime_usec_factor); -#ifdef CONFIG_PPC_SPLPAR -void (*dtl_consumer)(struct dtl_entry *, u64); -#endif - static void calc_cputime_factors(void) { struct div_result res; @@ -185,6 +182,8 @@ static inline unsigned long read_spurr(unsigned long tb) #include +void (*dtl_consumer)(struct dtl_entry *, u64); + /* * Scan the dispatch trace log and count up the stolen time. * Should be called with interrupts disabled. @@ -829,7 +828,7 @@ static void __read_persistent_clock(struct timespec64 *ts) static int first = 1; ts->tv_nsec = 0; - /* XXX this is a litle fragile but will work okay in the short term */ + /* XXX this is a little fragile but will work okay in the short term */ if (first) { first = 0; if (ppc_md.time_init) @@ -974,7 +973,7 @@ void secondary_cpu_time_init(void) */ start_cpu_decrementer(); - /* FIME: Should make unrelatred change to move snapshot_timebase + /* FIME: Should make unrelated change to move snapshot_timebase * call here ! */ register_decrementer_clockevent(smp_processor_id()); } diff --git a/arch/powerpc/kernel/trace/Makefile b/arch/powerpc/kernel/trace/Makefile index 542aa7a8b2b427672d1e20f9e77d97ea89bc8be5..af8527538fe4d574f511a06191f151cfce4cfd94 100644 --- a/arch/powerpc/kernel/trace/Makefile +++ b/arch/powerpc/kernel/trace/Makefile @@ -14,10 +14,7 @@ obj64-$(CONFIG_FUNCTION_TRACER) += ftrace_mprofile.o else obj64-$(CONFIG_FUNCTION_TRACER) += ftrace_64_pg.o endif -obj-$(CONFIG_FUNCTION_TRACER) += ftrace_low.o -obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o -obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o -obj-$(CONFIG_FTRACE_SYSCALLS) += ftrace.o +obj-$(CONFIG_FUNCTION_TRACER) += ftrace_low.o ftrace.o obj-$(CONFIG_TRACING) += trace_clock.o obj-$(CONFIG_PPC64) += $(obj64-y) diff --git a/arch/powerpc/kernel/trace/ftrace.c b/arch/powerpc/kernel/trace/ftrace.c index 4ee04aacf9f13c32f20f6b4eb39ea71e47a1cd66..2a893e06e4f1fbd35c21c6096c9445500e94d5d0 100644 --- a/arch/powerpc/kernel/trace/ftrace.c +++ b/arch/powerpc/kernel/trace/ftrace.c @@ -28,9 +28,6 @@ #include #include - -#ifdef CONFIG_DYNAMIC_FTRACE - /* * We generally only have a single long_branch tramp and at most 2 or 3 plt * tramps generated. But, we don't use the plt tramps currently. We also allot @@ -48,12 +45,12 @@ ftrace_call_replace(unsigned long ip, unsigned long addr, int link) addr = ppc_function_entry((void *)addr); /* if (link) set op to 'bl' else 'b' */ - create_branch(&op, (u32 *)ip, addr, link ? 1 : 0); + create_branch(&op, (u32 *)ip, addr, link ? BRANCH_SET_LINK : 0); return op; } -static int +static inline int ftrace_modify_code(unsigned long ip, ppc_inst_t old, ppc_inst_t new) { ppc_inst_t replaced; @@ -78,10 +75,7 @@ ftrace_modify_code(unsigned long ip, ppc_inst_t old, ppc_inst_t new) } /* replace the text with the new text */ - if (patch_instruction((u32 *)ip, new)) - return -EPERM; - - return 0; + return patch_instruction((u32 *)ip, new); } /* @@ -89,28 +83,26 @@ ftrace_modify_code(unsigned long ip, ppc_inst_t old, ppc_inst_t new) */ static int test_24bit_addr(unsigned long ip, unsigned long addr) { - ppc_inst_t op; addr = ppc_function_entry((void *)addr); - /* use the create_branch to verify that this offset can be branched */ - return create_branch(&op, (u32 *)ip, addr, 0) == 0; + return is_offset_in_branch_range(addr - ip); } static int is_bl_op(ppc_inst_t op) { - return (ppc_inst_val(op) & 0xfc000003) == 0x48000001; + return (ppc_inst_val(op) & ~PPC_LI_MASK) == PPC_RAW_BL(0); } static int is_b_op(ppc_inst_t op) { - return (ppc_inst_val(op) & 0xfc000003) == 0x48000000; + return (ppc_inst_val(op) & ~PPC_LI_MASK) == PPC_RAW_BRANCH(0); } static unsigned long find_bl_target(unsigned long ip, ppc_inst_t op) { int offset; - offset = (ppc_inst_val(op) & 0x03fffffc); + offset = PPC_LI(ppc_inst_val(op)); /* make it signed */ if (offset & 0x02000000) offset |= 0xfe000000; @@ -119,7 +111,6 @@ static unsigned long find_bl_target(unsigned long ip, ppc_inst_t op) } #ifdef CONFIG_MODULES -#ifdef CONFIG_PPC64 static int __ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec, unsigned long addr) @@ -159,25 +150,39 @@ __ftrace_make_nop(struct module *mod, return -EINVAL; } -#ifdef CONFIG_MPROFILE_KERNEL - /* When using -mkernel_profile there is no load to jump over */ - pop = ppc_inst(PPC_RAW_NOP()); + if (IS_ENABLED(CONFIG_MPROFILE_KERNEL)) { + if (copy_inst_from_kernel_nofault(&op, (void *)(ip - 4))) { + pr_err("Fetching instruction at %lx failed.\n", ip - 4); + return -EFAULT; + } - if (copy_inst_from_kernel_nofault(&op, (void *)(ip - 4))) { - pr_err("Fetching instruction at %lx failed.\n", ip - 4); - return -EFAULT; - } + /* We expect either a mflr r0, or a std r0, LRSAVE(r1) */ + if (!ppc_inst_equal(op, ppc_inst(PPC_RAW_MFLR(_R0))) && + !ppc_inst_equal(op, ppc_inst(PPC_INST_STD_LR))) { + pr_err("Unexpected instruction %s around bl _mcount\n", + ppc_inst_as_str(op)); + return -EINVAL; + } + } else if (IS_ENABLED(CONFIG_PPC64)) { + /* + * Check what is in the next instruction. We can see ld r2,40(r1), but + * on first pass after boot we will see mflr r0. + */ + if (copy_inst_from_kernel_nofault(&op, (void *)(ip + 4))) { + pr_err("Fetching op failed.\n"); + return -EFAULT; + } - /* We expect either a mflr r0, or a std r0, LRSAVE(r1) */ - if (!ppc_inst_equal(op, ppc_inst(PPC_RAW_MFLR(_R0))) && - !ppc_inst_equal(op, ppc_inst(PPC_INST_STD_LR))) { - pr_err("Unexpected instruction %s around bl _mcount\n", - ppc_inst_as_str(op)); - return -EINVAL; + if (!ppc_inst_equal(op, ppc_inst(PPC_INST_LD_TOC))) { + pr_err("Expected %08lx found %s\n", PPC_INST_LD_TOC, ppc_inst_as_str(op)); + return -EINVAL; + } } -#else + /* - * Our original call site looks like: + * When using -mprofile-kernel or PPC32 there is no load to jump over. + * + * Otherwise our original call site looks like: * * bl * ld r2,XX(r1) @@ -189,23 +194,10 @@ __ftrace_make_nop(struct module *mod, * * Use a b +8 to jump over the load. */ - - pop = ppc_inst(PPC_INST_BRANCH | 8); /* b +8 */ - - /* - * Check what is in the next instruction. We can see ld r2,40(r1), but - * on first pass after boot we will see mflr r0. - */ - if (copy_inst_from_kernel_nofault(&op, (void *)(ip + 4))) { - pr_err("Fetching op failed.\n"); - return -EFAULT; - } - - if (!ppc_inst_equal(op, ppc_inst(PPC_INST_LD_TOC))) { - pr_err("Expected %08lx found %s\n", PPC_INST_LD_TOC, ppc_inst_as_str(op)); - return -EINVAL; - } -#endif /* CONFIG_MPROFILE_KERNEL */ + if (IS_ENABLED(CONFIG_MPROFILE_KERNEL) || IS_ENABLED(CONFIG_PPC32)) + pop = ppc_inst(PPC_RAW_NOP()); + else + pop = ppc_inst(PPC_RAW_BRANCH(8)); /* b +8 */ if (patch_instruction((u32 *)ip, pop)) { pr_err("Patching NOP failed.\n"); @@ -214,54 +206,16 @@ __ftrace_make_nop(struct module *mod, return 0; } - -#else /* !PPC64 */ -static int -__ftrace_make_nop(struct module *mod, - struct dyn_ftrace *rec, unsigned long addr) +#else +static int __ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec, unsigned long addr) { - ppc_inst_t op; - unsigned long ip = rec->ip; - unsigned long tramp, ptr; - - if (copy_from_kernel_nofault(&op, (void *)ip, MCOUNT_INSN_SIZE)) - return -EFAULT; - - /* Make sure that that this is still a 24bit jump */ - if (!is_bl_op(op)) { - pr_err("Not expected bl: opcode is %s\n", ppc_inst_as_str(op)); - return -EINVAL; - } - - /* lets find where the pointer goes */ - tramp = find_bl_target(ip, op); - - /* Find where the trampoline jumps to */ - if (module_trampoline_target(mod, tramp, &ptr)) { - pr_err("Failed to get trampoline target\n"); - return -EFAULT; - } - - if (ptr != addr) { - pr_err("Trampoline location %08lx does not match addr\n", - tramp); - return -EINVAL; - } - - op = ppc_inst(PPC_RAW_NOP()); - - if (patch_instruction((u32 *)ip, op)) - return -EPERM; - return 0; } -#endif /* PPC64 */ #endif /* CONFIG_MODULES */ static unsigned long find_ftrace_tramp(unsigned long ip) { int i; - ppc_inst_t instr; /* * We have the compiler generated long_branch tramps at the end @@ -270,8 +224,7 @@ static unsigned long find_ftrace_tramp(unsigned long ip) for (i = NUM_FTRACE_TRAMPS - 1; i >= 0; i--) if (!ftrace_tramps[i]) continue; - else if (create_branch(&instr, (void *)ip, - ftrace_tramps[i], 0) == 0) + else if (is_offset_in_branch_range(ftrace_tramps[i] - ip)) return ftrace_tramps[i]; return 0; @@ -301,23 +254,12 @@ static int setup_mcount_compiler_tramp(unsigned long tramp) int i; ppc_inst_t op; unsigned long ptr; - ppc_inst_t instr; - static unsigned long ftrace_plt_tramps[NUM_FTRACE_TRAMPS]; /* Is this a known long jump tramp? */ for (i = 0; i < NUM_FTRACE_TRAMPS; i++) - if (!ftrace_tramps[i]) - break; - else if (ftrace_tramps[i] == tramp) + if (ftrace_tramps[i] == tramp) return 0; - /* Is this a known plt tramp? */ - for (i = 0; i < NUM_FTRACE_TRAMPS; i++) - if (!ftrace_plt_tramps[i]) - break; - else if (ftrace_plt_tramps[i] == tramp) - return -1; - /* New trampoline -- read where this goes */ if (copy_inst_from_kernel_nofault(&op, (void *)tramp)) { pr_debug("Fetching opcode failed.\n"); @@ -339,16 +281,10 @@ static int setup_mcount_compiler_tramp(unsigned long tramp) } /* Let's re-write the tramp to go to ftrace_[regs_]caller */ -#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS - ptr = ppc_global_function_entry((void *)ftrace_regs_caller); -#else - ptr = ppc_global_function_entry((void *)ftrace_caller); -#endif - if (create_branch(&instr, (void *)tramp, ptr, 0)) { - pr_debug("%ps is not reachable from existing mcount tramp\n", - (void *)ptr); - return -1; - } + if (IS_ENABLED(CONFIG_DYNAMIC_FTRACE_WITH_REGS)) + ptr = ppc_global_function_entry((void *)ftrace_regs_caller); + else + ptr = ppc_global_function_entry((void *)ftrace_caller); if (patch_branch((u32 *)tramp, ptr, 0)) { pr_debug("REL24 out of range!\n"); @@ -418,10 +354,12 @@ int ftrace_make_nop(struct module *mod, old = ftrace_call_replace(ip, addr, 1); new = ppc_inst(PPC_RAW_NOP()); return ftrace_modify_code(ip, old, new); - } else if (core_kernel_text(ip)) + } else if (core_kernel_text(ip)) { return __ftrace_make_nop_kernel(rec, addr); + } else if (!IS_ENABLED(CONFIG_MODULES)) { + return -EINVAL; + } -#ifdef CONFIG_MODULES /* * Out of range jumps are called from modules. * We should either already have a pointer to the module @@ -444,53 +382,27 @@ int ftrace_make_nop(struct module *mod, mod = rec->arch.mod; return __ftrace_make_nop(mod, rec, addr); -#else - /* We should not get here without modules */ - return -EINVAL; -#endif /* CONFIG_MODULES */ } #ifdef CONFIG_MODULES -#ifdef CONFIG_PPC64 /* * Examine the existing instructions for __ftrace_make_call. * They should effectively be a NOP, and follow formal constraints, * depending on the ABI. Return false if they don't. */ -#ifndef CONFIG_MPROFILE_KERNEL -static int -expected_nop_sequence(void *ip, ppc_inst_t op0, ppc_inst_t op1) +static bool expected_nop_sequence(void *ip, ppc_inst_t op0, ppc_inst_t op1) { - /* - * We expect to see: - * - * b +8 - * ld r2,XX(r1) - * - * The load offset is different depending on the ABI. For simplicity - * just mask it out when doing the compare. - */ - if (!ppc_inst_equal(op0, ppc_inst(0x48000008)) || - (ppc_inst_val(op1) & 0xffff0000) != 0xe8410000) - return 0; - return 1; -} -#else -static int -expected_nop_sequence(void *ip, ppc_inst_t op0, ppc_inst_t op1) -{ - /* look for patched "NOP" on ppc64 with -mprofile-kernel */ - if (!ppc_inst_equal(op0, ppc_inst(PPC_RAW_NOP()))) - return 0; - return 1; + if (IS_ENABLED(CONFIG_PPC64_ELF_ABI_V1)) + return ppc_inst_equal(op0, ppc_inst(PPC_RAW_BRANCH(8))) && + ppc_inst_equal(op1, ppc_inst(PPC_INST_LD_TOC)); + else + return ppc_inst_equal(op0, ppc_inst(PPC_RAW_NOP())); } -#endif static int __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) { ppc_inst_t op[2]; - ppc_inst_t instr; void *ip = (void *)rec->ip; unsigned long entry, ptr, tramp; struct module *mod = rec->arch.mod; @@ -499,7 +411,8 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) if (copy_inst_from_kernel_nofault(op, ip)) return -EFAULT; - if (copy_inst_from_kernel_nofault(op + 1, ip + 4)) + if (IS_ENABLED(CONFIG_PPC64_ELF_ABI_V1) && + copy_inst_from_kernel_nofault(op + 1, ip + 4)) return -EFAULT; if (!expected_nop_sequence(ip, op[0], op[1])) { @@ -509,20 +422,15 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) } /* If we never set up ftrace trampoline(s), then bail */ -#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS - if (!mod->arch.tramp || !mod->arch.tramp_regs) { -#else - if (!mod->arch.tramp) { -#endif + if (!mod->arch.tramp || + (IS_ENABLED(CONFIG_DYNAMIC_FTRACE_WITH_REGS) && !mod->arch.tramp_regs)) { pr_err("No ftrace trampoline\n"); return -EINVAL; } -#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS - if (rec->flags & FTRACE_FL_REGS) + if (IS_ENABLED(CONFIG_DYNAMIC_FTRACE_WITH_REGS) && rec->flags & FTRACE_FL_REGS) tramp = mod->arch.tramp_regs; else -#endif tramp = mod->arch.tramp; if (module_trampoline_target(mod, tramp, &ptr)) { @@ -539,12 +447,6 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) return -EINVAL; } - /* Ensure branch is within 24 bits */ - if (create_branch(&instr, ip, tramp, BRANCH_SET_LINK)) { - pr_err("Branch out of range\n"); - return -EINVAL; - } - if (patch_branch(ip, tramp, BRANCH_SET_LINK)) { pr_err("REL24 out of range!\n"); return -EINVAL; @@ -552,58 +454,11 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) return 0; } - -#else /* !CONFIG_PPC64: */ -static int -__ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) -{ - int err; - ppc_inst_t op; - u32 *ip = (u32 *)rec->ip; - struct module *mod = rec->arch.mod; - unsigned long tramp; - - /* read where this goes */ - if (copy_inst_from_kernel_nofault(&op, ip)) - return -EFAULT; - - /* It should be pointing to a nop */ - if (!ppc_inst_equal(op, ppc_inst(PPC_RAW_NOP()))) { - pr_err("Expected NOP but have %s\n", ppc_inst_as_str(op)); - return -EINVAL; - } - - /* If we never set up a trampoline to ftrace_caller, then bail */ -#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS - if (!mod->arch.tramp || !mod->arch.tramp_regs) { #else - if (!mod->arch.tramp) { -#endif - pr_err("No ftrace trampoline\n"); - return -EINVAL; - } - -#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS - if (rec->flags & FTRACE_FL_REGS) - tramp = mod->arch.tramp_regs; - else -#endif - tramp = mod->arch.tramp; - /* create the branch to the trampoline */ - err = create_branch(&op, ip, tramp, BRANCH_SET_LINK); - if (err) { - pr_err("REL24 out of range!\n"); - return -EINVAL; - } - - pr_devel("write to %lx\n", rec->ip); - - if (patch_instruction(ip, op)) - return -EPERM; - +static int __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) +{ return 0; } -#endif /* CONFIG_PPC64 */ #endif /* CONFIG_MODULES */ static int __ftrace_make_call_kernel(struct dyn_ftrace *rec, unsigned long addr) @@ -616,16 +471,12 @@ static int __ftrace_make_call_kernel(struct dyn_ftrace *rec, unsigned long addr) entry = ppc_global_function_entry((void *)ftrace_caller); ptr = ppc_global_function_entry((void *)addr); - if (ptr != entry) { -#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS + if (ptr != entry && IS_ENABLED(CONFIG_DYNAMIC_FTRACE_WITH_REGS)) entry = ppc_global_function_entry((void *)ftrace_regs_caller); - if (ptr != entry) { -#endif - pr_err("Unknown ftrace addr to patch: %ps\n", (void *)ptr); - return -EINVAL; -#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS - } -#endif + + if (ptr != entry) { + pr_err("Unknown ftrace addr to patch: %ps\n", (void *)ptr); + return -EINVAL; } /* Make sure we have a nop */ @@ -668,10 +519,13 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) old = ppc_inst(PPC_RAW_NOP()); new = ftrace_call_replace(ip, addr, 1); return ftrace_modify_code(ip, old, new); - } else if (core_kernel_text(ip)) + } else if (core_kernel_text(ip)) { return __ftrace_make_call_kernel(rec, addr); + } else if (!IS_ENABLED(CONFIG_MODULES)) { + /* We should not get here without modules */ + return -EINVAL; + } -#ifdef CONFIG_MODULES /* * Out of range jumps are called from modules. * Being that we are converting from nop, it had better @@ -683,10 +537,6 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) } return __ftrace_make_call(rec, addr); -#else - /* We should not get here without modules */ - return -EINVAL; -#endif /* CONFIG_MODULES */ } #ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS @@ -770,12 +620,6 @@ __ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr, return -EINVAL; } - /* Ensure branch is within 24 bits */ - if (create_branch(&op, (u32 *)ip, tramp, BRANCH_SET_LINK)) { - pr_err("Branch out of range\n"); - return -EINVAL; - } - if (patch_branch((u32 *)ip, tramp, BRANCH_SET_LINK)) { pr_err("REL24 out of range!\n"); return -EINVAL; @@ -783,6 +627,11 @@ __ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr, return 0; } +#else +static int __ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr, unsigned long addr) +{ + return 0; +} #endif int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr, @@ -807,9 +656,11 @@ int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr, * variant, so there is nothing to do here */ return 0; + } else if (!IS_ENABLED(CONFIG_MODULES)) { + /* We should not get here without modules */ + return -EINVAL; } -#ifdef CONFIG_MODULES /* * Out of range jumps are called from modules. */ @@ -819,10 +670,6 @@ int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr, } return __ftrace_modify_call(rec, old_addr, addr); -#else - /* We should not get here without modules */ - return -EINVAL; -#endif /* CONFIG_MODULES */ } #endif @@ -836,15 +683,13 @@ int ftrace_update_ftrace_func(ftrace_func_t func) new = ftrace_call_replace(ip, (unsigned long)func, 1); ret = ftrace_modify_code(ip, old, new); -#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS /* Also update the regs callback function */ - if (!ret) { + if (IS_ENABLED(CONFIG_DYNAMIC_FTRACE_WITH_REGS) && !ret) { ip = (unsigned long)(&ftrace_regs_call); old = ppc_inst_read((u32 *)&ftrace_regs_call); new = ftrace_call_replace(ip, (unsigned long)func, 1); ret = ftrace_modify_code(ip, old, new); } -#endif return ret; } @@ -863,25 +708,39 @@ void arch_ftrace_update_code(int command) extern unsigned int ftrace_tramp_text[], ftrace_tramp_init[]; +void ftrace_free_init_tramp(void) +{ + int i; + + for (i = 0; i < NUM_FTRACE_TRAMPS && ftrace_tramps[i]; i++) + if (ftrace_tramps[i] == (unsigned long)ftrace_tramp_init) { + ftrace_tramps[i] = 0; + return; + } +} + int __init ftrace_dyn_arch_init(void) { int i; unsigned int *tramp[] = { ftrace_tramp_text, ftrace_tramp_init }; u32 stub_insns[] = { - 0xe98d0000 | PACATOC, /* ld r12,PACATOC(r13) */ - 0x3d8c0000, /* addis r12,r12, */ - 0x398c0000, /* addi r12,r12, */ - 0x7d8903a6, /* mtctr r12 */ - 0x4e800420, /* bctr */ + PPC_RAW_LD(_R12, _R13, PACATOC), + PPC_RAW_ADDIS(_R12, _R12, 0), + PPC_RAW_ADDI(_R12, _R12, 0), + PPC_RAW_MTCTR(_R12), + PPC_RAW_BCTR() }; -#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS - unsigned long addr = ppc_global_function_entry((void *)ftrace_regs_caller); -#else - unsigned long addr = ppc_global_function_entry((void *)ftrace_caller); -#endif - long reladdr = addr - kernel_toc_addr(); + unsigned long addr; + long reladdr; + + if (IS_ENABLED(CONFIG_DYNAMIC_FTRACE_WITH_REGS)) + addr = ppc_global_function_entry((void *)ftrace_regs_caller); + else + addr = ppc_global_function_entry((void *)ftrace_caller); - if (reladdr > 0x7FFFFFFF || reladdr < -(0x80000000L)) { + reladdr = addr - kernel_toc_addr(); + + if (reladdr >= SZ_2G || reladdr < -(long)SZ_2G) { pr_err("Address of %ps out of range of kernel_toc.\n", (void *)addr); return -1; @@ -896,13 +755,7 @@ int __init ftrace_dyn_arch_init(void) return 0; } -#else -int __init ftrace_dyn_arch_init(void) -{ - return 0; -} #endif -#endif /* CONFIG_DYNAMIC_FTRACE */ #ifdef CONFIG_FUNCTION_GRAPH_TRACER @@ -939,8 +792,8 @@ int ftrace_disable_ftrace_graph_caller(void) * Hook the return address and push it in the stack of return addrs * in current thread info. Return the address we want to divert to. */ -unsigned long prepare_ftrace_return(unsigned long parent, unsigned long ip, - unsigned long sp) +static unsigned long +__prepare_ftrace_return(unsigned long parent, unsigned long ip, unsigned long sp) { unsigned long return_hooker; int bit; @@ -969,12 +822,18 @@ out: void ftrace_graph_func(unsigned long ip, unsigned long parent_ip, struct ftrace_ops *op, struct ftrace_regs *fregs) { - fregs->regs.link = prepare_ftrace_return(parent_ip, ip, fregs->regs.gpr[1]); + fregs->regs.link = __prepare_ftrace_return(parent_ip, ip, fregs->regs.gpr[1]); +} +#else +unsigned long prepare_ftrace_return(unsigned long parent, unsigned long ip, + unsigned long sp) +{ + return __prepare_ftrace_return(parent, ip, sp); } #endif #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ -#ifdef PPC64_ELF_ABI_v1 +#ifdef CONFIG_PPC64_ELF_ABI_V1 char *arch_ftrace_match_adjust(char *str, const char *search) { if (str[0] == '.' && search[0] != '.') @@ -982,4 +841,4 @@ char *arch_ftrace_match_adjust(char *str, const char *search) else return str; } -#endif /* PPC64_ELF_ABI_v1 */ +#endif /* CONFIG_PPC64_ELF_ABI_V1 */ diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index a08bb7cefdc545671627dcf1c45767e23cbacefa..3aaa50e5c72f2537a2c06758f1e926b1d177844b 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c @@ -393,7 +393,7 @@ void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr) * Builds that do not support KVM could take this second option to increase * the recoverability of NMIs. */ -void hv_nmi_check_nonrecoverable(struct pt_regs *regs) +noinstr void hv_nmi_check_nonrecoverable(struct pt_regs *regs) { #ifdef CONFIG_PPC_POWERNV unsigned long kbase = (unsigned long)_stext; @@ -433,7 +433,9 @@ void hv_nmi_check_nonrecoverable(struct pt_regs *regs) return; nonrecoverable: - regs_set_unrecoverable(regs); + regs->msr &= ~MSR_RI; + local_paca->hsrr_valid = 0; + local_paca->srr_valid = 0; #endif } DEFINE_INTERRUPT_HANDLER_NMI(system_reset_exception) diff --git a/arch/powerpc/kernel/uprobes.c b/arch/powerpc/kernel/uprobes.c index c6975467d9ffdcad81b9a56a7a96a75b9ca0c3c6..95a41ae9dfa75553ca4ee38a999570f210a52b20 100644 --- a/arch/powerpc/kernel/uprobes.c +++ b/arch/powerpc/kernel/uprobes.c @@ -48,6 +48,11 @@ int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, return -EINVAL; } + if (!can_single_step(ppc_inst_val(ppc_inst_read(auprobe->insn)))) { + pr_info_ratelimited("Cannot register a uprobe on instructions that can't be single stepped\n"); + return -ENOTSUPP; + } + return 0; } diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c index 717f2c9a7573cf395d41c338de1a99fb8d65fbf8..0da287544054f55000dc8df90a402be7d5615466 100644 --- a/arch/powerpc/kernel/vdso.c +++ b/arch/powerpc/kernel/vdso.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/powerpc/kernel/vdso/Makefile b/arch/powerpc/kernel/vdso/Makefile index 954974287ee7deccf4553cfee689ae0c95e956dc..096b0bf1335ffc7d73fc15bb4fe23adfc4acd68a 100644 --- a/arch/powerpc/kernel/vdso/Makefile +++ b/arch/powerpc/kernel/vdso/Makefile @@ -48,6 +48,7 @@ UBSAN_SANITIZE := n KASAN_SANITIZE := n ccflags-y := -shared -fno-common -fno-builtin -nostdlib -Wl,--hash-style=both +ccflags-$(CONFIG_LD_IS_LLD) += $(call cc-option,--ld-path=$(LD),-fuse-ld=lld) CC32FLAGS := -Wl,-soname=linux-vdso32.so.1 -m32 AS32FLAGS := -D__VDSO32__ -s diff --git a/arch/powerpc/kernel/vdso/vdso32.lds.S b/arch/powerpc/kernel/vdso/vdso32.lds.S index 58e0099f70f42e7c07a3e7c337f1ef2a55c3239b..e0d19d74455fd880c9f710b7572438d1fef0a4dc 100644 --- a/arch/powerpc/kernel/vdso/vdso32.lds.S +++ b/arch/powerpc/kernel/vdso/vdso32.lds.S @@ -13,7 +13,6 @@ OUTPUT_FORMAT("elf32-powerpcle", "elf32-powerpcle", "elf32-powerpcle") OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", "elf32-powerpc") #endif OUTPUT_ARCH(powerpc:common) -ENTRY(_start) SECTIONS { diff --git a/arch/powerpc/kernel/vdso/vdso64.lds.S b/arch/powerpc/kernel/vdso/vdso64.lds.S index 0288cad428b039da38c4e9bab23a781d79bb5eed..1a4a7bc4c8157fa468ebc7a1468ab47424ad0e30 100644 --- a/arch/powerpc/kernel/vdso/vdso64.lds.S +++ b/arch/powerpc/kernel/vdso/vdso64.lds.S @@ -13,7 +13,6 @@ OUTPUT_FORMAT("elf64-powerpcle", "elf64-powerpcle", "elf64-powerpcle") OUTPUT_FORMAT("elf64-powerpc", "elf64-powerpc", "elf64-powerpc") #endif OUTPUT_ARCH(powerpc:common64) -ENTRY(_start) SECTIONS { diff --git a/arch/powerpc/kernel/watchdog.c b/arch/powerpc/kernel/watchdog.c index bfc27496fe7e25dbf0ca4b92ebe7c46eab0a6ccd..7d28b95536540bae5f2271fb0c2b8c327ccaa633 100644 --- a/arch/powerpc/kernel/watchdog.c +++ b/arch/powerpc/kernel/watchdog.c @@ -56,7 +56,7 @@ * solved by also having a SMP watchdog where all CPUs check all other * CPUs heartbeat. * - * The SMP checker can detect lockups on other CPUs. A gobal "pending" + * The SMP checker can detect lockups on other CPUs. A global "pending" * cpumask is kept, containing all CPUs which enable the watchdog. Each * CPU clears their pending bit in their heartbeat timer. When the bitmask * becomes empty, the last CPU to clear its pending bit updates a global diff --git a/arch/powerpc/kexec/Makefile b/arch/powerpc/kexec/Makefile index b6c52608cb490c1bab84a92ddd6f6c6e2fd1dd70..0c2abe7f99087495098d37be69041ef698819dc2 100644 --- a/arch/powerpc/kexec/Makefile +++ b/arch/powerpc/kexec/Makefile @@ -13,3 +13,5 @@ obj-$(CONFIG_KEXEC_FILE) += file_load.o ranges.o file_load_$(BITS).o elf_$(BITS) GCOV_PROFILE_core_$(BITS).o := n KCOV_INSTRUMENT_core_$(BITS).o := n UBSAN_SANITIZE_core_$(BITS).o := n +KASAN_SANITIZE_core.o := n +KASAN_SANITIZE_core_$(BITS) := n diff --git a/arch/powerpc/kexec/core.c b/arch/powerpc/kexec/core.c index abf5897ae88c8b3849c79fe0f1a36ad5d57ff6b8..7ab4980fe13ab4dca3c8e59f13195a0fda43aa7c 100644 --- a/arch/powerpc/kexec/core.c +++ b/arch/powerpc/kexec/core.c @@ -18,7 +18,6 @@ #include #include #include -#include #include void machine_kexec_mask_interrupts(void) { diff --git a/arch/powerpc/kexec/core_64.c b/arch/powerpc/kexec/core_64.c index 6cc7793b8420c81255cd692c7eaaf468487fe496..c2bea9db1c1e145fbdaf2624137f209bb5cd2fe8 100644 --- a/arch/powerpc/kexec/core_64.c +++ b/arch/powerpc/kexec/core_64.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -25,7 +26,6 @@ #include #include #include /* _end */ -#include #include #include #include @@ -406,7 +406,7 @@ static int __init export_htab_values(void) if (!node) return -ENODEV; - /* remove any stale propertys so ours can be found */ + /* remove any stale properties so ours can be found */ of_remove_property(node, of_find_property(node, htab_base_prop.name, NULL)); of_remove_property(node, of_find_property(node, htab_size_prop.name, NULL)); diff --git a/arch/powerpc/kexec/crash.c b/arch/powerpc/kexec/crash.c index 22ceeeb705abdffbdd95872dc6fc1956b132c187..d85fa9fc6f3ca4a7f12681974961308ace4a78a8 100644 --- a/arch/powerpc/kexec/crash.c +++ b/arch/powerpc/kexec/crash.c @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/powerpc/kvm/Makefile b/arch/powerpc/kvm/Makefile index 9bdfc8b5089962a6a5a6d1d999f8c6cdad657da4..0cd23ce07d68da1fe1a5666dc4ff152a9dc136b1 100644 --- a/arch/powerpc/kvm/Makefile +++ b/arch/powerpc/kvm/Makefile @@ -37,9 +37,6 @@ kvm-e500mc-objs := \ e500_emulate.o kvm-objs-$(CONFIG_KVM_E500MC) := $(kvm-e500mc-objs) -kvm-book3s_64-builtin-objs-$(CONFIG_SPAPR_TCE_IOMMU) := \ - book3s_64_vio_hv.o - kvm-pr-y := \ fpu.o \ emulate.o \ @@ -76,7 +73,7 @@ kvm-hv-$(CONFIG_PPC_TRANSACTIONAL_MEM) += \ book3s_hv_tm.o kvm-book3s_64-builtin-xics-objs-$(CONFIG_KVM_XICS) := \ - book3s_hv_rm_xics.o book3s_hv_rm_xive.o + book3s_hv_rm_xics.o kvm-book3s_64-builtin-tm-objs-$(CONFIG_PPC_TRANSACTIONAL_MEM) += \ book3s_hv_tm_builtin.o @@ -134,3 +131,8 @@ obj-$(CONFIG_KVM_BOOK3S_64_PR) += kvm-pr.o obj-$(CONFIG_KVM_BOOK3S_64_HV) += kvm-hv.o obj-y += $(kvm-book3s_64-builtin-objs-y) + +# KVM does a lot in real-mode, and 64-bit Book3S KASAN doesn't support that +ifdef CONFIG_PPC_BOOK3S_64 +KASAN_SANITIZE := n +endif diff --git a/arch/powerpc/kvm/book3s_64_entry.S b/arch/powerpc/kvm/book3s_64_entry.S index e42d1c609e4767f04318f2b586b88045c6e0acaa..e43704547a1eee455c44ed291aa6044413c796af 100644 --- a/arch/powerpc/kvm/book3s_64_entry.S +++ b/arch/powerpc/kvm/book3s_64_entry.S @@ -124,7 +124,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR) /* * "Skip" interrupts are part of a trick KVM uses a with hash guests to load - * the faulting instruction in guest memory from the the hypervisor without + * the faulting instruction in guest memory from the hypervisor without * walking page tables. * * When the guest takes a fault that requires the hypervisor to load the diff --git a/arch/powerpc/kvm/book3s_64_mmu_hv.c b/arch/powerpc/kvm/book3s_64_mmu_hv.c index 0aeb51738ca9b2d8e0966c291a3d6b19bf84d87a..514fd45c199478cde822f3e278ddb329090691a7 100644 --- a/arch/powerpc/kvm/book3s_64_mmu_hv.c +++ b/arch/powerpc/kvm/book3s_64_mmu_hv.c @@ -58,7 +58,7 @@ struct kvm_resize_hpt { /* Possible values and their usage: * <0 an error occurred during allocation, * -EBUSY allocation is in the progress, - * 0 allocation made successfuly. + * 0 allocation made successfully. */ int error; @@ -256,26 +256,34 @@ void kvmppc_map_vrma(struct kvm_vcpu *vcpu, struct kvm_memory_slot *memslot, int kvmppc_mmu_hv_init(void) { - unsigned long host_lpid, rsvd_lpid; + unsigned long nr_lpids; if (!mmu_has_feature(MMU_FTR_LOCKLESS_TLBIE)) return -EINVAL; - host_lpid = 0; - if (cpu_has_feature(CPU_FTR_HVMODE)) - host_lpid = mfspr(SPRN_LPID); + if (cpu_has_feature(CPU_FTR_HVMODE)) { + if (WARN_ON(mfspr(SPRN_LPID) != 0)) + return -EINVAL; + nr_lpids = 1UL << mmu_lpid_bits; + } else { + nr_lpids = 1UL << KVM_MAX_NESTED_GUESTS_SHIFT; + } - /* POWER8 and above have 12-bit LPIDs (10-bit in POWER7) */ - if (cpu_has_feature(CPU_FTR_ARCH_207S)) - rsvd_lpid = LPID_RSVD; - else - rsvd_lpid = LPID_RSVD_POWER7; + if (!cpu_has_feature(CPU_FTR_ARCH_300)) { + /* POWER7 has 10-bit LPIDs, POWER8 has 12-bit LPIDs */ + if (cpu_has_feature(CPU_FTR_ARCH_207S)) + WARN_ON(nr_lpids != 1UL << 12); + else + WARN_ON(nr_lpids != 1UL << 10); - kvmppc_init_lpid(rsvd_lpid + 1); + /* + * Reserve the last implemented LPID use in partition + * switching for POWER7 and POWER8. + */ + nr_lpids -= 1; + } - kvmppc_claim_lpid(host_lpid); - /* rsvd_lpid is reserved for use in partition switching */ - kvmppc_claim_lpid(rsvd_lpid); + kvmppc_init_lpid(nr_lpids); return 0; } @@ -879,7 +887,7 @@ static bool kvm_age_rmapp(struct kvm *kvm, struct kvm_memory_slot *memslot, struct revmap_entry *rev = kvm->arch.hpt.rev; unsigned long head, i, j; __be64 *hptep; - int ret = 0; + bool ret = false; unsigned long *rmapp; rmapp = &memslot->arch.rmap[gfn - memslot->base_gfn]; @@ -887,7 +895,7 @@ static bool kvm_age_rmapp(struct kvm *kvm, struct kvm_memory_slot *memslot, lock_rmap(rmapp); if (*rmapp & KVMPPC_RMAP_REFERENCED) { *rmapp &= ~KVMPPC_RMAP_REFERENCED; - ret = 1; + ret = true; } if (!(*rmapp & KVMPPC_RMAP_PRESENT)) { unlock_rmap(rmapp); @@ -919,7 +927,7 @@ static bool kvm_age_rmapp(struct kvm *kvm, struct kvm_memory_slot *memslot, rev[i].guest_rpte |= HPTE_R_R; note_hpte_modification(kvm, &rev[i]); } - ret = 1; + ret = true; } __unlock_hpte(hptep, be64_to_cpu(hptep[0])); } while ((i = j) != head); diff --git a/arch/powerpc/kvm/book3s_64_vio.c b/arch/powerpc/kvm/book3s_64_vio.c index 85cfa6328222b326736f2309d31c12e46a80fc6b..d6589c4fe8899e0f0c8cb2968f3506cab0a570ca 100644 --- a/arch/powerpc/kvm/book3s_64_vio.c +++ b/arch/powerpc/kvm/book3s_64_vio.c @@ -32,6 +32,18 @@ #include #include +static struct kvmppc_spapr_tce_table *kvmppc_find_table(struct kvm *kvm, + unsigned long liobn) +{ + struct kvmppc_spapr_tce_table *stt; + + list_for_each_entry_lockless(stt, &kvm->arch.spapr_tce_tables, list) + if (stt->liobn == liobn) + return stt; + + return NULL; +} + static unsigned long kvmppc_tce_pages(unsigned long iommu_pages) { return ALIGN(iommu_pages * sizeof(u64), PAGE_SIZE) / PAGE_SIZE; @@ -753,3 +765,34 @@ long kvmppc_h_stuff_tce(struct kvm_vcpu *vcpu, return ret; } EXPORT_SYMBOL_GPL(kvmppc_h_stuff_tce); + +long kvmppc_h_get_tce(struct kvm_vcpu *vcpu, unsigned long liobn, + unsigned long ioba) +{ + struct kvmppc_spapr_tce_table *stt; + long ret; + unsigned long idx; + struct page *page; + u64 *tbl; + + stt = kvmppc_find_table(vcpu->kvm, liobn); + if (!stt) + return H_TOO_HARD; + + ret = kvmppc_ioba_validate(stt, ioba, 1); + if (ret != H_SUCCESS) + return ret; + + idx = (ioba >> stt->page_shift) - stt->offset; + page = stt->pages[idx / TCES_PER_PAGE]; + if (!page) { + vcpu->arch.regs.gpr[4] = 0; + return H_SUCCESS; + } + tbl = (u64 *)page_address(page); + + vcpu->arch.regs.gpr[4] = tbl[idx % TCES_PER_PAGE]; + + return H_SUCCESS; +} +EXPORT_SYMBOL_GPL(kvmppc_h_get_tce); diff --git a/arch/powerpc/kvm/book3s_64_vio_hv.c b/arch/powerpc/kvm/book3s_64_vio_hv.c deleted file mode 100644 index fdeda6a9cff449b1a13cc45a05ae1629183b13b3..0000000000000000000000000000000000000000 --- a/arch/powerpc/kvm/book3s_64_vio_hv.c +++ /dev/null @@ -1,672 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * - * Copyright 2010 Paul Mackerras, IBM Corp. - * Copyright 2011 David Gibson, IBM Corporation - * Copyright 2016 Alexey Kardashevskiy, IBM Corporation - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef CONFIG_BUG - -#define WARN_ON_ONCE_RM(condition) ({ \ - static bool __section(".data.unlikely") __warned; \ - int __ret_warn_once = !!(condition); \ - \ - if (unlikely(__ret_warn_once && !__warned)) { \ - __warned = true; \ - pr_err("WARN_ON_ONCE_RM: (%s) at %s:%u\n", \ - __stringify(condition), \ - __func__, __LINE__); \ - dump_stack(); \ - } \ - unlikely(__ret_warn_once); \ -}) - -#else - -#define WARN_ON_ONCE_RM(condition) ({ \ - int __ret_warn_on = !!(condition); \ - unlikely(__ret_warn_on); \ -}) - -#endif - -/* - * Finds a TCE table descriptor by LIOBN. - * - * WARNING: This will be called in real or virtual mode on HV KVM and virtual - * mode on PR KVM - */ -struct kvmppc_spapr_tce_table *kvmppc_find_table(struct kvm *kvm, - unsigned long liobn) -{ - struct kvmppc_spapr_tce_table *stt; - - list_for_each_entry_lockless(stt, &kvm->arch.spapr_tce_tables, list) - if (stt->liobn == liobn) - return stt; - - return NULL; -} -EXPORT_SYMBOL_GPL(kvmppc_find_table); - -#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE -static long kvmppc_rm_tce_to_ua(struct kvm *kvm, - unsigned long tce, unsigned long *ua) -{ - unsigned long gfn = tce >> PAGE_SHIFT; - struct kvm_memory_slot *memslot; - - memslot = __gfn_to_memslot(kvm_memslots_raw(kvm), gfn); - if (!memslot) - return -EINVAL; - - *ua = __gfn_to_hva_memslot(memslot, gfn) | - (tce & ~(PAGE_MASK | TCE_PCI_READ | TCE_PCI_WRITE)); - - return 0; -} - -/* - * Validates TCE address. - * At the moment flags and page mask are validated. - * As the host kernel does not access those addresses (just puts them - * to the table and user space is supposed to process them), we can skip - * checking other things (such as TCE is a guest RAM address or the page - * was actually allocated). - */ -static long kvmppc_rm_tce_validate(struct kvmppc_spapr_tce_table *stt, - unsigned long tce) -{ - unsigned long gpa = tce & ~(TCE_PCI_READ | TCE_PCI_WRITE); - enum dma_data_direction dir = iommu_tce_direction(tce); - struct kvmppc_spapr_tce_iommu_table *stit; - unsigned long ua = 0; - - /* Allow userspace to poison TCE table */ - if (dir == DMA_NONE) - return H_SUCCESS; - - if (iommu_tce_check_gpa(stt->page_shift, gpa)) - return H_PARAMETER; - - if (kvmppc_rm_tce_to_ua(stt->kvm, tce, &ua)) - return H_TOO_HARD; - - list_for_each_entry_lockless(stit, &stt->iommu_tables, next) { - unsigned long hpa = 0; - struct mm_iommu_table_group_mem_t *mem; - long shift = stit->tbl->it_page_shift; - - mem = mm_iommu_lookup_rm(stt->kvm->mm, ua, 1ULL << shift); - if (!mem) - return H_TOO_HARD; - - if (mm_iommu_ua_to_hpa_rm(mem, ua, shift, &hpa)) - return H_TOO_HARD; - } - - return H_SUCCESS; -} - -/* Note on the use of page_address() in real mode, - * - * It is safe to use page_address() in real mode on ppc64 because - * page_address() is always defined as lowmem_page_address() - * which returns __va(PFN_PHYS(page_to_pfn(page))) which is arithmetic - * operation and does not access page struct. - * - * Theoretically page_address() could be defined different - * but either WANT_PAGE_VIRTUAL or HASHED_PAGE_VIRTUAL - * would have to be enabled. - * WANT_PAGE_VIRTUAL is never enabled on ppc32/ppc64, - * HASHED_PAGE_VIRTUAL could be enabled for ppc32 only and only - * if CONFIG_HIGHMEM is defined. As CONFIG_SPARSEMEM_VMEMMAP - * is not expected to be enabled on ppc32, page_address() - * is safe for ppc32 as well. - * - * WARNING: This will be called in real-mode on HV KVM and virtual - * mode on PR KVM - */ -static u64 *kvmppc_page_address(struct page *page) -{ -#if defined(HASHED_PAGE_VIRTUAL) || defined(WANT_PAGE_VIRTUAL) -#error TODO: fix to avoid page_address() here -#endif - return (u64 *) page_address(page); -} - -/* - * Handles TCE requests for emulated devices. - * Puts guest TCE values to the table and expects user space to convert them. - * Cannot fail so kvmppc_rm_tce_validate must be called before it. - */ -static void kvmppc_rm_tce_put(struct kvmppc_spapr_tce_table *stt, - unsigned long idx, unsigned long tce) -{ - struct page *page; - u64 *tbl; - - idx -= stt->offset; - page = stt->pages[idx / TCES_PER_PAGE]; - /* - * kvmppc_rm_ioba_validate() allows pages not be allocated if TCE is - * being cleared, otherwise it returns H_TOO_HARD and we skip this. - */ - if (!page) { - WARN_ON_ONCE_RM(tce != 0); - return; - } - tbl = kvmppc_page_address(page); - - tbl[idx % TCES_PER_PAGE] = tce; -} - -/* - * TCEs pages are allocated in kvmppc_rm_tce_put() which won't be able to do so - * in real mode. - * Check if kvmppc_rm_tce_put() can succeed in real mode, i.e. a TCEs page is - * allocated or not required (when clearing a tce entry). - */ -static long kvmppc_rm_ioba_validate(struct kvmppc_spapr_tce_table *stt, - unsigned long ioba, unsigned long npages, bool clearing) -{ - unsigned long i, idx, sttpage, sttpages; - unsigned long ret = kvmppc_ioba_validate(stt, ioba, npages); - - if (ret) - return ret; - /* - * clearing==true says kvmppc_rm_tce_put won't be allocating pages - * for empty tces. - */ - if (clearing) - return H_SUCCESS; - - idx = (ioba >> stt->page_shift) - stt->offset; - sttpage = idx / TCES_PER_PAGE; - sttpages = ALIGN(idx % TCES_PER_PAGE + npages, TCES_PER_PAGE) / - TCES_PER_PAGE; - for (i = sttpage; i < sttpage + sttpages; ++i) - if (!stt->pages[i]) - return H_TOO_HARD; - - return H_SUCCESS; -} - -static long iommu_tce_xchg_no_kill_rm(struct mm_struct *mm, - struct iommu_table *tbl, - unsigned long entry, unsigned long *hpa, - enum dma_data_direction *direction) -{ - long ret; - - ret = tbl->it_ops->xchg_no_kill(tbl, entry, hpa, direction, true); - - if (!ret && ((*direction == DMA_FROM_DEVICE) || - (*direction == DMA_BIDIRECTIONAL))) { - __be64 *pua = IOMMU_TABLE_USERSPACE_ENTRY_RO(tbl, entry); - /* - * kvmppc_rm_tce_iommu_do_map() updates the UA cache after - * calling this so we still get here a valid UA. - */ - if (pua && *pua) - mm_iommu_ua_mark_dirty_rm(mm, be64_to_cpu(*pua)); - } - - return ret; -} - -static void iommu_tce_kill_rm(struct iommu_table *tbl, - unsigned long entry, unsigned long pages) -{ - if (tbl->it_ops->tce_kill) - tbl->it_ops->tce_kill(tbl, entry, pages, true); -} - -static void kvmppc_rm_clear_tce(struct kvm *kvm, struct kvmppc_spapr_tce_table *stt, - struct iommu_table *tbl, unsigned long entry) -{ - unsigned long i; - unsigned long subpages = 1ULL << (stt->page_shift - tbl->it_page_shift); - unsigned long io_entry = entry << (stt->page_shift - tbl->it_page_shift); - - for (i = 0; i < subpages; ++i) { - unsigned long hpa = 0; - enum dma_data_direction dir = DMA_NONE; - - iommu_tce_xchg_no_kill_rm(kvm->mm, tbl, io_entry + i, &hpa, &dir); - } -} - -static long kvmppc_rm_tce_iommu_mapped_dec(struct kvm *kvm, - struct iommu_table *tbl, unsigned long entry) -{ - struct mm_iommu_table_group_mem_t *mem = NULL; - const unsigned long pgsize = 1ULL << tbl->it_page_shift; - __be64 *pua = IOMMU_TABLE_USERSPACE_ENTRY_RO(tbl, entry); - - if (!pua) - /* it_userspace allocation might be delayed */ - return H_TOO_HARD; - - mem = mm_iommu_lookup_rm(kvm->mm, be64_to_cpu(*pua), pgsize); - if (!mem) - return H_TOO_HARD; - - mm_iommu_mapped_dec(mem); - - *pua = cpu_to_be64(0); - - return H_SUCCESS; -} - -static long kvmppc_rm_tce_iommu_do_unmap(struct kvm *kvm, - struct iommu_table *tbl, unsigned long entry) -{ - enum dma_data_direction dir = DMA_NONE; - unsigned long hpa = 0; - long ret; - - if (iommu_tce_xchg_no_kill_rm(kvm->mm, tbl, entry, &hpa, &dir)) - /* - * real mode xchg can fail if struct page crosses - * a page boundary - */ - return H_TOO_HARD; - - if (dir == DMA_NONE) - return H_SUCCESS; - - ret = kvmppc_rm_tce_iommu_mapped_dec(kvm, tbl, entry); - if (ret) - iommu_tce_xchg_no_kill_rm(kvm->mm, tbl, entry, &hpa, &dir); - - return ret; -} - -static long kvmppc_rm_tce_iommu_unmap(struct kvm *kvm, - struct kvmppc_spapr_tce_table *stt, struct iommu_table *tbl, - unsigned long entry) -{ - unsigned long i, ret = H_SUCCESS; - unsigned long subpages = 1ULL << (stt->page_shift - tbl->it_page_shift); - unsigned long io_entry = entry * subpages; - - for (i = 0; i < subpages; ++i) { - ret = kvmppc_rm_tce_iommu_do_unmap(kvm, tbl, io_entry + i); - if (ret != H_SUCCESS) - break; - } - - iommu_tce_kill_rm(tbl, io_entry, subpages); - - return ret; -} - -static long kvmppc_rm_tce_iommu_do_map(struct kvm *kvm, struct iommu_table *tbl, - unsigned long entry, unsigned long ua, - enum dma_data_direction dir) -{ - long ret; - unsigned long hpa = 0; - __be64 *pua = IOMMU_TABLE_USERSPACE_ENTRY_RO(tbl, entry); - struct mm_iommu_table_group_mem_t *mem; - - if (!pua) - /* it_userspace allocation might be delayed */ - return H_TOO_HARD; - - mem = mm_iommu_lookup_rm(kvm->mm, ua, 1ULL << tbl->it_page_shift); - if (!mem) - return H_TOO_HARD; - - if (WARN_ON_ONCE_RM(mm_iommu_ua_to_hpa_rm(mem, ua, tbl->it_page_shift, - &hpa))) - return H_TOO_HARD; - - if (WARN_ON_ONCE_RM(mm_iommu_mapped_inc(mem))) - return H_TOO_HARD; - - ret = iommu_tce_xchg_no_kill_rm(kvm->mm, tbl, entry, &hpa, &dir); - if (ret) { - mm_iommu_mapped_dec(mem); - /* - * real mode xchg can fail if struct page crosses - * a page boundary - */ - return H_TOO_HARD; - } - - if (dir != DMA_NONE) - kvmppc_rm_tce_iommu_mapped_dec(kvm, tbl, entry); - - *pua = cpu_to_be64(ua); - - return 0; -} - -static long kvmppc_rm_tce_iommu_map(struct kvm *kvm, - struct kvmppc_spapr_tce_table *stt, struct iommu_table *tbl, - unsigned long entry, unsigned long ua, - enum dma_data_direction dir) -{ - unsigned long i, pgoff, ret = H_SUCCESS; - unsigned long subpages = 1ULL << (stt->page_shift - tbl->it_page_shift); - unsigned long io_entry = entry * subpages; - - for (i = 0, pgoff = 0; i < subpages; - ++i, pgoff += IOMMU_PAGE_SIZE(tbl)) { - - ret = kvmppc_rm_tce_iommu_do_map(kvm, tbl, - io_entry + i, ua + pgoff, dir); - if (ret != H_SUCCESS) - break; - } - - iommu_tce_kill_rm(tbl, io_entry, subpages); - - return ret; -} - -long kvmppc_rm_h_put_tce(struct kvm_vcpu *vcpu, unsigned long liobn, - unsigned long ioba, unsigned long tce) -{ - struct kvmppc_spapr_tce_table *stt; - long ret; - struct kvmppc_spapr_tce_iommu_table *stit; - unsigned long entry, ua = 0; - enum dma_data_direction dir; - - /* udbg_printf("H_PUT_TCE(): liobn=0x%lx ioba=0x%lx, tce=0x%lx\n", */ - /* liobn, ioba, tce); */ - - stt = kvmppc_find_table(vcpu->kvm, liobn); - if (!stt) - return H_TOO_HARD; - - ret = kvmppc_rm_ioba_validate(stt, ioba, 1, tce == 0); - if (ret != H_SUCCESS) - return ret; - - ret = kvmppc_rm_tce_validate(stt, tce); - if (ret != H_SUCCESS) - return ret; - - dir = iommu_tce_direction(tce); - if ((dir != DMA_NONE) && kvmppc_rm_tce_to_ua(vcpu->kvm, tce, &ua)) - return H_PARAMETER; - - entry = ioba >> stt->page_shift; - - list_for_each_entry_lockless(stit, &stt->iommu_tables, next) { - if (dir == DMA_NONE) - ret = kvmppc_rm_tce_iommu_unmap(vcpu->kvm, stt, - stit->tbl, entry); - else - ret = kvmppc_rm_tce_iommu_map(vcpu->kvm, stt, - stit->tbl, entry, ua, dir); - - if (ret != H_SUCCESS) { - kvmppc_rm_clear_tce(vcpu->kvm, stt, stit->tbl, entry); - return ret; - } - } - - kvmppc_rm_tce_put(stt, entry, tce); - - return H_SUCCESS; -} - -static long kvmppc_rm_ua_to_hpa(struct kvm_vcpu *vcpu, unsigned long mmu_seq, - unsigned long ua, unsigned long *phpa) -{ - pte_t *ptep, pte; - unsigned shift = 0; - - /* - * Called in real mode with MSR_EE = 0. We are safe here. - * It is ok to do the lookup with arch.pgdir here, because - * we are doing this on secondary cpus and current task there - * is not the hypervisor. Also this is safe against THP in the - * host, because an IPI to primary thread will wait for the secondary - * to exit which will agains result in the below page table walk - * to finish. - */ - /* an rmap lock won't make it safe. because that just ensure hash - * page table entries are removed with rmap lock held. After that - * mmu notifier returns and we go ahead and removing ptes from Qemu page table. - */ - ptep = find_kvm_host_pte(vcpu->kvm, mmu_seq, ua, &shift); - if (!ptep) - return -ENXIO; - - pte = READ_ONCE(*ptep); - if (!pte_present(pte)) - return -ENXIO; - - if (!shift) - shift = PAGE_SHIFT; - - /* Avoid handling anything potentially complicated in realmode */ - if (shift > PAGE_SHIFT) - return -EAGAIN; - - if (!pte_young(pte)) - return -EAGAIN; - - *phpa = (pte_pfn(pte) << PAGE_SHIFT) | (ua & ((1ULL << shift) - 1)) | - (ua & ~PAGE_MASK); - - return 0; -} - -long kvmppc_rm_h_put_tce_indirect(struct kvm_vcpu *vcpu, - unsigned long liobn, unsigned long ioba, - unsigned long tce_list, unsigned long npages) -{ - struct kvm *kvm = vcpu->kvm; - struct kvmppc_spapr_tce_table *stt; - long i, ret = H_SUCCESS; - unsigned long tces, entry, ua = 0; - unsigned long mmu_seq; - bool prereg = false; - struct kvmppc_spapr_tce_iommu_table *stit; - - /* - * used to check for invalidations in progress - */ - mmu_seq = kvm->mmu_notifier_seq; - smp_rmb(); - - stt = kvmppc_find_table(vcpu->kvm, liobn); - if (!stt) - return H_TOO_HARD; - - entry = ioba >> stt->page_shift; - /* - * The spec says that the maximum size of the list is 512 TCEs - * so the whole table addressed resides in 4K page - */ - if (npages > 512) - return H_PARAMETER; - - if (tce_list & (SZ_4K - 1)) - return H_PARAMETER; - - ret = kvmppc_rm_ioba_validate(stt, ioba, npages, false); - if (ret != H_SUCCESS) - return ret; - - if (mm_iommu_preregistered(vcpu->kvm->mm)) { - /* - * We get here if guest memory was pre-registered which - * is normally VFIO case and gpa->hpa translation does not - * depend on hpt. - */ - struct mm_iommu_table_group_mem_t *mem; - - if (kvmppc_rm_tce_to_ua(vcpu->kvm, tce_list, &ua)) - return H_TOO_HARD; - - mem = mm_iommu_lookup_rm(vcpu->kvm->mm, ua, IOMMU_PAGE_SIZE_4K); - if (mem) - prereg = mm_iommu_ua_to_hpa_rm(mem, ua, - IOMMU_PAGE_SHIFT_4K, &tces) == 0; - } - - if (!prereg) { - /* - * This is usually a case of a guest with emulated devices only - * when TCE list is not in preregistered memory. - * We do not require memory to be preregistered in this case - * so lock rmap and do __find_linux_pte_or_hugepte(). - */ - if (kvmppc_rm_tce_to_ua(vcpu->kvm, tce_list, &ua)) - return H_TOO_HARD; - - arch_spin_lock(&kvm->mmu_lock.rlock.raw_lock); - if (kvmppc_rm_ua_to_hpa(vcpu, mmu_seq, ua, &tces)) { - ret = H_TOO_HARD; - goto unlock_exit; - } - } - - for (i = 0; i < npages; ++i) { - unsigned long tce = be64_to_cpu(((u64 *)tces)[i]); - - ret = kvmppc_rm_tce_validate(stt, tce); - if (ret != H_SUCCESS) - goto unlock_exit; - } - - for (i = 0; i < npages; ++i) { - unsigned long tce = be64_to_cpu(((u64 *)tces)[i]); - - ua = 0; - if (kvmppc_rm_tce_to_ua(vcpu->kvm, tce, &ua)) { - ret = H_PARAMETER; - goto unlock_exit; - } - - list_for_each_entry_lockless(stit, &stt->iommu_tables, next) { - ret = kvmppc_rm_tce_iommu_map(vcpu->kvm, stt, - stit->tbl, entry + i, ua, - iommu_tce_direction(tce)); - - if (ret != H_SUCCESS) { - kvmppc_rm_clear_tce(vcpu->kvm, stt, stit->tbl, - entry + i); - goto unlock_exit; - } - } - - kvmppc_rm_tce_put(stt, entry + i, tce); - } - -unlock_exit: - if (!prereg) - arch_spin_unlock(&kvm->mmu_lock.rlock.raw_lock); - return ret; -} - -long kvmppc_rm_h_stuff_tce(struct kvm_vcpu *vcpu, - unsigned long liobn, unsigned long ioba, - unsigned long tce_value, unsigned long npages) -{ - struct kvmppc_spapr_tce_table *stt; - long i, ret; - struct kvmppc_spapr_tce_iommu_table *stit; - - stt = kvmppc_find_table(vcpu->kvm, liobn); - if (!stt) - return H_TOO_HARD; - - ret = kvmppc_rm_ioba_validate(stt, ioba, npages, tce_value == 0); - if (ret != H_SUCCESS) - return ret; - - /* Check permission bits only to allow userspace poison TCE for debug */ - if (tce_value & (TCE_PCI_WRITE | TCE_PCI_READ)) - return H_PARAMETER; - - list_for_each_entry_lockless(stit, &stt->iommu_tables, next) { - unsigned long entry = ioba >> stt->page_shift; - - for (i = 0; i < npages; ++i) { - ret = kvmppc_rm_tce_iommu_unmap(vcpu->kvm, stt, - stit->tbl, entry + i); - - if (ret == H_SUCCESS) - continue; - - if (ret == H_TOO_HARD) - return ret; - - WARN_ON_ONCE_RM(1); - kvmppc_rm_clear_tce(vcpu->kvm, stt, stit->tbl, entry + i); - } - } - - for (i = 0; i < npages; ++i, ioba += (1ULL << stt->page_shift)) - kvmppc_rm_tce_put(stt, ioba >> stt->page_shift, tce_value); - - return ret; -} - -/* This can be called in either virtual mode or real mode */ -long kvmppc_h_get_tce(struct kvm_vcpu *vcpu, unsigned long liobn, - unsigned long ioba) -{ - struct kvmppc_spapr_tce_table *stt; - long ret; - unsigned long idx; - struct page *page; - u64 *tbl; - - stt = kvmppc_find_table(vcpu->kvm, liobn); - if (!stt) - return H_TOO_HARD; - - ret = kvmppc_ioba_validate(stt, ioba, 1); - if (ret != H_SUCCESS) - return ret; - - idx = (ioba >> stt->page_shift) - stt->offset; - page = stt->pages[idx / TCES_PER_PAGE]; - if (!page) { - vcpu->arch.regs.gpr[4] = 0; - return H_SUCCESS; - } - tbl = (u64 *)page_address(page); - - vcpu->arch.regs.gpr[4] = tbl[idx % TCES_PER_PAGE]; - - return H_SUCCESS; -} -EXPORT_SYMBOL_GPL(kvmppc_h_get_tce); - -#endif /* KVM_BOOK3S_HV_POSSIBLE */ diff --git a/arch/powerpc/kvm/book3s_emulate.c b/arch/powerpc/kvm/book3s_emulate.c index fdb57be71aa659542d5e4195e3904bc66ec52a92..5bbfb2eed1277f2ec6257dc8aee469ceac503e5c 100644 --- a/arch/powerpc/kvm/book3s_emulate.c +++ b/arch/powerpc/kvm/book3s_emulate.c @@ -268,7 +268,7 @@ int kvmppc_core_emulate_op_pr(struct kvm_vcpu *vcpu, /* * add rules to fit in ISA specification regarding TM - * state transistion in TM disable/Suspended state, + * state transition in TM disable/Suspended state, * and target TM state is TM inactive(00) state. (the * change should be suppressed). */ diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c index 6fa518f6501d513076200e994c25ef4cbd594a35..e08fb3124dcaa06ed3d2fe9bf93c7d06d613c909 100644 --- a/arch/powerpc/kvm/book3s_hv.c +++ b/arch/powerpc/kvm/book3s_hv.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #include @@ -1326,6 +1327,12 @@ static int kvmppc_hcall_impl_hv(unsigned long cmd) case H_CONFER: case H_REGISTER_VPA: case H_SET_MODE: +#ifdef CONFIG_SPAPR_TCE_IOMMU + case H_GET_TCE: + case H_PUT_TCE: + case H_PUT_TCE_INDIRECT: + case H_STUFF_TCE: +#endif case H_LOGICAL_CI_LOAD: case H_LOGICAL_CI_STORE: #ifdef CONFIG_KVM_XICS @@ -2834,7 +2841,7 @@ static int kvmppc_core_vcpu_create_hv(struct kvm_vcpu *vcpu) * to trap and then we emulate them. */ vcpu->arch.hfscr = HFSCR_TAR | HFSCR_EBB | HFSCR_PM | HFSCR_BHRB | - HFSCR_DSCR | HFSCR_VECVSX | HFSCR_FP | HFSCR_PREFIX; + HFSCR_DSCR | HFSCR_VECVSX | HFSCR_FP; if (cpu_has_feature(CPU_FTR_HVMODE)) { vcpu->arch.hfscr &= mfspr(SPRN_HFSCR); #ifdef CONFIG_PPC_TRANSACTIONAL_MEM @@ -3967,6 +3974,7 @@ static int kvmhv_vcpu_entry_p9_nested(struct kvm_vcpu *vcpu, u64 time_limit, uns kvmhv_save_hv_regs(vcpu, &hvregs); hvregs.lpcr = lpcr; + hvregs.amor = ~0; vcpu->arch.regs.msr = vcpu->arch.shregs.msr; hvregs.version = HV_GUEST_STATE_VERSION; if (vcpu->arch.nested) { @@ -4029,6 +4037,8 @@ static int kvmhv_vcpu_entry_p9_nested(struct kvm_vcpu *vcpu, u64 time_limit, uns static int kvmhv_p9_guest_entry(struct kvm_vcpu *vcpu, u64 time_limit, unsigned long lpcr, u64 *tb) { + struct kvm *kvm = vcpu->kvm; + struct kvm_nested_guest *nested = vcpu->arch.nested; u64 next_timer; int trap; @@ -4048,34 +4058,61 @@ static int kvmhv_p9_guest_entry(struct kvm_vcpu *vcpu, u64 time_limit, trap = kvmhv_vcpu_entry_p9_nested(vcpu, time_limit, lpcr, tb); /* H_CEDE has to be handled now, not later */ - if (trap == BOOK3S_INTERRUPT_SYSCALL && !vcpu->arch.nested && + if (trap == BOOK3S_INTERRUPT_SYSCALL && !nested && kvmppc_get_gpr(vcpu, 3) == H_CEDE) { kvmppc_cede(vcpu); kvmppc_set_gpr(vcpu, 3, 0); trap = 0; } - } else { - struct kvm *kvm = vcpu->kvm; + } else if (nested) { + __this_cpu_write(cpu_in_guest, kvm); + trap = kvmhv_vcpu_entry_p9(vcpu, time_limit, lpcr, tb); + __this_cpu_write(cpu_in_guest, NULL); + } else { kvmppc_xive_push_vcpu(vcpu); __this_cpu_write(cpu_in_guest, kvm); trap = kvmhv_vcpu_entry_p9(vcpu, time_limit, lpcr, tb); __this_cpu_write(cpu_in_guest, NULL); - if (trap == BOOK3S_INTERRUPT_SYSCALL && !vcpu->arch.nested && + if (trap == BOOK3S_INTERRUPT_SYSCALL && !(vcpu->arch.shregs.msr & MSR_PR)) { unsigned long req = kvmppc_get_gpr(vcpu, 3); - /* H_CEDE has to be handled now, not later */ + /* + * XIVE rearm and XICS hcalls must be handled + * before xive context is pulled (is this + * true?) + */ if (req == H_CEDE) { + /* H_CEDE has to be handled now */ kvmppc_cede(vcpu); - kvmppc_xive_rearm_escalation(vcpu); /* may un-cede */ + if (!kvmppc_xive_rearm_escalation(vcpu)) { + /* + * Pending escalation so abort + * the cede. + */ + vcpu->arch.ceded = 0; + } kvmppc_set_gpr(vcpu, 3, 0); trap = 0; - /* XICS hcalls must be handled before xive is pulled */ + } else if (req == H_ENTER_NESTED) { + /* + * L2 should not run with the L1 + * context so rearm and pull it. + */ + if (!kvmppc_xive_rearm_escalation(vcpu)) { + /* + * Pending escalation so abort + * H_ENTER_NESTED. + */ + kvmppc_set_gpr(vcpu, 3, 0); + trap = 0; + } + } else if (hcall_is_xics(req)) { int ret; @@ -4233,13 +4270,13 @@ static void kvmppc_vcore_blocked(struct kvmppc_vcore *vc) start_wait = ktime_get(); vc->vcore_state = VCORE_SLEEPING; - trace_kvmppc_vcore_blocked(vc, 0); + trace_kvmppc_vcore_blocked(vc->runner, 0); spin_unlock(&vc->lock); schedule(); finish_rcuwait(&vc->wait); spin_lock(&vc->lock); vc->vcore_state = VCORE_INACTIVE; - trace_kvmppc_vcore_blocked(vc, 1); + trace_kvmppc_vcore_blocked(vc->runner, 1); ++vc->runner->stat.halt_successful_wait; cur = ktime_get(); @@ -4519,9 +4556,14 @@ int kvmhv_run_single_vcpu(struct kvm_vcpu *vcpu, u64 time_limit, if (!nested) { kvmppc_core_prepare_to_enter(vcpu); - if (test_bit(BOOK3S_IRQPRIO_EXTERNAL, - &vcpu->arch.pending_exceptions)) + if (vcpu->arch.shregs.msr & MSR_EE) { + if (xive_interrupt_pending(vcpu)) + kvmppc_inject_interrupt_hv(vcpu, + BOOK3S_INTERRUPT_EXTERNAL, 0); + } else if (test_bit(BOOK3S_IRQPRIO_EXTERNAL, + &vcpu->arch.pending_exceptions)) { lpcr |= LPCR_MER; + } } else if (vcpu->arch.pending_exceptions || vcpu->arch.doorbell_request || xive_interrupt_pending(vcpu)) { @@ -4619,9 +4661,9 @@ int kvmhv_run_single_vcpu(struct kvm_vcpu *vcpu, u64 time_limit, if (kvmppc_vcpu_check_block(vcpu)) break; - trace_kvmppc_vcore_blocked(vc, 0); + trace_kvmppc_vcore_blocked(vcpu, 0); schedule(); - trace_kvmppc_vcore_blocked(vc, 1); + trace_kvmppc_vcore_blocked(vcpu, 1); } finish_rcuwait(wait); } @@ -5283,6 +5325,10 @@ static int kvmppc_core_init_vm_hv(struct kvm *kvm) kvm->arch.host_lpcr = lpcr = mfspr(SPRN_LPCR); lpcr &= LPCR_PECE | LPCR_LPES; } else { + /* + * The L2 LPES mode will be set by the L0 according to whether + * or not it needs to take external interrupts in HV mode. + */ lpcr = 0; } lpcr |= (4UL << LPCR_DPFD_SH) | LPCR_HDICE | diff --git a/arch/powerpc/kvm/book3s_hv_builtin.c b/arch/powerpc/kvm/book3s_hv_builtin.c index 7e52d0beee77679de39204528b9a0df89e679c10..88a8f6473c4e05bfcf54d0eedff0c5ea4be082ce 100644 --- a/arch/powerpc/kvm/book3s_hv_builtin.c +++ b/arch/powerpc/kvm/book3s_hv_builtin.c @@ -489,70 +489,6 @@ static long kvmppc_read_one_intr(bool *again) return kvmppc_check_passthru(xisr, xirr, again); } -#ifdef CONFIG_KVM_XICS -unsigned long kvmppc_rm_h_xirr(struct kvm_vcpu *vcpu) -{ - if (!kvmppc_xics_enabled(vcpu)) - return H_TOO_HARD; - if (xics_on_xive()) - return xive_rm_h_xirr(vcpu); - else - return xics_rm_h_xirr(vcpu); -} - -unsigned long kvmppc_rm_h_xirr_x(struct kvm_vcpu *vcpu) -{ - if (!kvmppc_xics_enabled(vcpu)) - return H_TOO_HARD; - vcpu->arch.regs.gpr[5] = get_tb(); - if (xics_on_xive()) - return xive_rm_h_xirr(vcpu); - else - return xics_rm_h_xirr(vcpu); -} - -unsigned long kvmppc_rm_h_ipoll(struct kvm_vcpu *vcpu, unsigned long server) -{ - if (!kvmppc_xics_enabled(vcpu)) - return H_TOO_HARD; - if (xics_on_xive()) - return xive_rm_h_ipoll(vcpu, server); - else - return H_TOO_HARD; -} - -int kvmppc_rm_h_ipi(struct kvm_vcpu *vcpu, unsigned long server, - unsigned long mfrr) -{ - if (!kvmppc_xics_enabled(vcpu)) - return H_TOO_HARD; - if (xics_on_xive()) - return xive_rm_h_ipi(vcpu, server, mfrr); - else - return xics_rm_h_ipi(vcpu, server, mfrr); -} - -int kvmppc_rm_h_cppr(struct kvm_vcpu *vcpu, unsigned long cppr) -{ - if (!kvmppc_xics_enabled(vcpu)) - return H_TOO_HARD; - if (xics_on_xive()) - return xive_rm_h_cppr(vcpu, cppr); - else - return xics_rm_h_cppr(vcpu, cppr); -} - -int kvmppc_rm_h_eoi(struct kvm_vcpu *vcpu, unsigned long xirr) -{ - if (!kvmppc_xics_enabled(vcpu)) - return H_TOO_HARD; - if (xics_on_xive()) - return xive_rm_h_eoi(vcpu, xirr); - else - return xics_rm_h_eoi(vcpu, xirr); -} -#endif /* CONFIG_KVM_XICS */ - void kvmppc_bad_interrupt(struct pt_regs *regs) { /* diff --git a/arch/powerpc/kvm/book3s_hv_nested.c b/arch/powerpc/kvm/book3s_hv_nested.c index c943a051c6e700c2b58416aef857b9e310563678..0644732d1a2569dded4a81c7f9e48a0584ba5e80 100644 --- a/arch/powerpc/kvm/book3s_hv_nested.c +++ b/arch/powerpc/kvm/book3s_hv_nested.c @@ -261,8 +261,7 @@ static void load_l2_hv_regs(struct kvm_vcpu *vcpu, /* * Don't let L1 change LPCR bits for the L2 except these: */ - mask = LPCR_DPFD | LPCR_ILE | LPCR_TC | LPCR_AIL | LPCR_LD | - LPCR_LPES | LPCR_MER; + mask = LPCR_DPFD | LPCR_ILE | LPCR_TC | LPCR_AIL | LPCR_LD | LPCR_MER; /* * Additional filtering is required depending on hardware @@ -439,10 +438,11 @@ long kvmhv_nested_init(void) if (!radix_enabled()) return -ENODEV; - /* find log base 2 of KVMPPC_NR_LPIDS, rounding up */ - ptb_order = __ilog2(KVMPPC_NR_LPIDS - 1) + 1; - if (ptb_order < 8) - ptb_order = 8; + /* Partition table entry is 1<<4 bytes in size, hence the 4. */ + ptb_order = KVM_MAX_NESTED_GUESTS_SHIFT + 4; + /* Minimum partition table size is 1<<12 bytes */ + if (ptb_order < 12) + ptb_order = 12; pseries_partition_tb = kmalloc(sizeof(struct patb_entry) << ptb_order, GFP_KERNEL); if (!pseries_partition_tb) { @@ -450,7 +450,7 @@ long kvmhv_nested_init(void) return -ENOMEM; } - ptcr = __pa(pseries_partition_tb) | (ptb_order - 8); + ptcr = __pa(pseries_partition_tb) | (ptb_order - 12); rc = plpar_hcall_norets(H_SET_PARTITION_TABLE, ptcr); if (rc != H_SUCCESS) { pr_err("kvm-hv: Parent hypervisor does not support nesting (rc=%ld)\n", @@ -521,11 +521,6 @@ static void kvmhv_set_nested_ptbl(struct kvm_nested_guest *gp) kvmhv_set_ptbl_entry(gp->shadow_lpid, dw0, gp->process_table); } -void kvmhv_vm_nested_init(struct kvm *kvm) -{ - kvm->arch.max_nested_lpid = -1; -} - /* * Handle the H_SET_PARTITION_TABLE hcall. * r4 = guest real address of partition table + log_2(size) - 12 @@ -539,16 +534,14 @@ long kvmhv_set_partition_table(struct kvm_vcpu *vcpu) long ret = H_SUCCESS; srcu_idx = srcu_read_lock(&kvm->srcu); - /* - * Limit the partition table to 4096 entries (because that's what - * hardware supports), and check the base address. - */ - if ((ptcr & PRTS_MASK) > 12 - 8 || + /* Check partition size and base address. */ + if ((ptcr & PRTS_MASK) + 12 - 4 > KVM_MAX_NESTED_GUESTS_SHIFT || !kvm_is_visible_gfn(vcpu->kvm, (ptcr & PRTB_MASK) >> PAGE_SHIFT)) ret = H_PARAMETER; srcu_read_unlock(&kvm->srcu, srcu_idx); if (ret == H_SUCCESS) kvm->arch.l1_ptcr = ptcr; + return ret; } @@ -644,7 +637,7 @@ static void kvmhv_update_ptbl_cache(struct kvm_nested_guest *gp) ret = -EFAULT; ptbl_addr = (kvm->arch.l1_ptcr & PRTB_MASK) + (gp->l1_lpid << 4); - if (gp->l1_lpid < (1ul << ((kvm->arch.l1_ptcr & PRTS_MASK) + 8))) { + if (gp->l1_lpid < (1ul << ((kvm->arch.l1_ptcr & PRTS_MASK) + 12 - 4))) { int srcu_idx = srcu_read_lock(&kvm->srcu); ret = kvm_read_guest(kvm, ptbl_addr, &ptbl_entry, sizeof(ptbl_entry)); @@ -660,6 +653,35 @@ static void kvmhv_update_ptbl_cache(struct kvm_nested_guest *gp) kvmhv_set_nested_ptbl(gp); } +void kvmhv_vm_nested_init(struct kvm *kvm) +{ + idr_init(&kvm->arch.kvm_nested_guest_idr); +} + +static struct kvm_nested_guest *__find_nested(struct kvm *kvm, int lpid) +{ + return idr_find(&kvm->arch.kvm_nested_guest_idr, lpid); +} + +static bool __prealloc_nested(struct kvm *kvm, int lpid) +{ + if (idr_alloc(&kvm->arch.kvm_nested_guest_idr, + NULL, lpid, lpid + 1, GFP_KERNEL) != lpid) + return false; + return true; +} + +static void __add_nested(struct kvm *kvm, int lpid, struct kvm_nested_guest *gp) +{ + if (idr_replace(&kvm->arch.kvm_nested_guest_idr, gp, lpid)) + WARN_ON(1); +} + +static void __remove_nested(struct kvm *kvm, int lpid) +{ + idr_remove(&kvm->arch.kvm_nested_guest_idr, lpid); +} + static struct kvm_nested_guest *kvmhv_alloc_nested(struct kvm *kvm, unsigned int lpid) { struct kvm_nested_guest *gp; @@ -720,13 +742,8 @@ static void kvmhv_remove_nested(struct kvm_nested_guest *gp) long ref; spin_lock(&kvm->mmu_lock); - if (gp == kvm->arch.nested_guests[lpid]) { - kvm->arch.nested_guests[lpid] = NULL; - if (lpid == kvm->arch.max_nested_lpid) { - while (--lpid >= 0 && !kvm->arch.nested_guests[lpid]) - ; - kvm->arch.max_nested_lpid = lpid; - } + if (gp == __find_nested(kvm, lpid)) { + __remove_nested(kvm, lpid); --gp->refcnt; } ref = gp->refcnt; @@ -743,24 +760,22 @@ static void kvmhv_remove_nested(struct kvm_nested_guest *gp) */ void kvmhv_release_all_nested(struct kvm *kvm) { - int i; + int lpid; struct kvm_nested_guest *gp; struct kvm_nested_guest *freelist = NULL; struct kvm_memory_slot *memslot; int srcu_idx, bkt; spin_lock(&kvm->mmu_lock); - for (i = 0; i <= kvm->arch.max_nested_lpid; i++) { - gp = kvm->arch.nested_guests[i]; - if (!gp) - continue; - kvm->arch.nested_guests[i] = NULL; + idr_for_each_entry(&kvm->arch.kvm_nested_guest_idr, gp, lpid) { + __remove_nested(kvm, lpid); if (--gp->refcnt == 0) { gp->next = freelist; freelist = gp; } } - kvm->arch.max_nested_lpid = -1; + idr_destroy(&kvm->arch.kvm_nested_guest_idr); + /* idr is empty and may be reused at this point */ spin_unlock(&kvm->mmu_lock); while ((gp = freelist) != NULL) { freelist = gp->next; @@ -792,12 +807,11 @@ struct kvm_nested_guest *kvmhv_get_nested(struct kvm *kvm, int l1_lpid, { struct kvm_nested_guest *gp, *newgp; - if (l1_lpid >= KVM_MAX_NESTED_GUESTS || - l1_lpid >= (1ul << ((kvm->arch.l1_ptcr & PRTS_MASK) + 12 - 4))) + if (l1_lpid >= (1ul << ((kvm->arch.l1_ptcr & PRTS_MASK) + 12 - 4))) return NULL; spin_lock(&kvm->mmu_lock); - gp = kvm->arch.nested_guests[l1_lpid]; + gp = __find_nested(kvm, l1_lpid); if (gp) ++gp->refcnt; spin_unlock(&kvm->mmu_lock); @@ -808,17 +822,19 @@ struct kvm_nested_guest *kvmhv_get_nested(struct kvm *kvm, int l1_lpid, newgp = kvmhv_alloc_nested(kvm, l1_lpid); if (!newgp) return NULL; + + if (!__prealloc_nested(kvm, l1_lpid)) { + kvmhv_release_nested(newgp); + return NULL; + } + spin_lock(&kvm->mmu_lock); - if (kvm->arch.nested_guests[l1_lpid]) { - /* someone else beat us to it */ - gp = kvm->arch.nested_guests[l1_lpid]; - } else { - kvm->arch.nested_guests[l1_lpid] = newgp; + gp = __find_nested(kvm, l1_lpid); + if (!gp) { + __add_nested(kvm, l1_lpid, newgp); ++newgp->refcnt; gp = newgp; newgp = NULL; - if (l1_lpid > kvm->arch.max_nested_lpid) - kvm->arch.max_nested_lpid = l1_lpid; } ++gp->refcnt; spin_unlock(&kvm->mmu_lock); @@ -841,20 +857,13 @@ void kvmhv_put_nested(struct kvm_nested_guest *gp) kvmhv_release_nested(gp); } -static struct kvm_nested_guest *kvmhv_find_nested(struct kvm *kvm, int lpid) -{ - if (lpid > kvm->arch.max_nested_lpid) - return NULL; - return kvm->arch.nested_guests[lpid]; -} - pte_t *find_kvm_nested_guest_pte(struct kvm *kvm, unsigned long lpid, unsigned long ea, unsigned *hshift) { struct kvm_nested_guest *gp; pte_t *pte; - gp = kvmhv_find_nested(kvm, lpid); + gp = __find_nested(kvm, lpid); if (!gp) return NULL; @@ -960,7 +969,7 @@ static void kvmhv_remove_nest_rmap(struct kvm *kvm, u64 n_rmap, gpa = n_rmap & RMAP_NESTED_GPA_MASK; lpid = (n_rmap & RMAP_NESTED_LPID_MASK) >> RMAP_NESTED_LPID_SHIFT; - gp = kvmhv_find_nested(kvm, lpid); + gp = __find_nested(kvm, lpid); if (!gp) return; @@ -1152,16 +1161,13 @@ static void kvmhv_emulate_tlbie_all_lpid(struct kvm_vcpu *vcpu, int ric) { struct kvm *kvm = vcpu->kvm; struct kvm_nested_guest *gp; - int i; + int lpid; spin_lock(&kvm->mmu_lock); - for (i = 0; i <= kvm->arch.max_nested_lpid; i++) { - gp = kvm->arch.nested_guests[i]; - if (gp) { - spin_unlock(&kvm->mmu_lock); - kvmhv_emulate_tlbie_lpid(vcpu, gp, ric); - spin_lock(&kvm->mmu_lock); - } + idr_for_each_entry(&kvm->arch.kvm_nested_guest_idr, gp, lpid) { + spin_unlock(&kvm->mmu_lock); + kvmhv_emulate_tlbie_lpid(vcpu, gp, ric); + spin_lock(&kvm->mmu_lock); } spin_unlock(&kvm->mmu_lock); } @@ -1313,7 +1319,7 @@ long do_h_rpt_invalidate_pat(struct kvm_vcpu *vcpu, unsigned long lpid, * H_ENTER_NESTED call. Since we can't differentiate this case from * the invalid case, we ignore such flush requests and return success. */ - if (!kvmhv_find_nested(vcpu->kvm, lpid)) + if (!__find_nested(vcpu->kvm, lpid)) return H_SUCCESS; /* @@ -1657,15 +1663,12 @@ long int kvmhv_nested_page_fault(struct kvm_vcpu *vcpu) int kvmhv_nested_next_lpid(struct kvm *kvm, int lpid) { - int ret = -1; + int ret = lpid + 1; spin_lock(&kvm->mmu_lock); - while (++lpid <= kvm->arch.max_nested_lpid) { - if (kvm->arch.nested_guests[lpid]) { - ret = lpid; - break; - } - } + if (!idr_get_next(&kvm->arch.kvm_nested_guest_idr, &ret)) + ret = -1; spin_unlock(&kvm->mmu_lock); + return ret; } diff --git a/arch/powerpc/kvm/book3s_hv_p9_entry.c b/arch/powerpc/kvm/book3s_hv_p9_entry.c index a28e5b3daabdfefa742cb6a900d81d21312aa85c..112a09b33328876d995e27107bc62ca2fe8489f4 100644 --- a/arch/powerpc/kvm/book3s_hv_p9_entry.c +++ b/arch/powerpc/kvm/book3s_hv_p9_entry.c @@ -379,7 +379,7 @@ void restore_p9_host_os_sprs(struct kvm_vcpu *vcpu, { /* * current->thread.xxx registers must all be restored to host - * values before a potential context switch, othrewise the context + * values before a potential context switch, otherwise the context * switch itself will overwrite current->thread.xxx with the values * from the guest SPRs. */ @@ -539,8 +539,10 @@ static void switch_mmu_to_guest_radix(struct kvm *kvm, struct kvm_vcpu *vcpu, u6 { struct kvm_nested_guest *nested = vcpu->arch.nested; u32 lpid; + u32 pid; lpid = nested ? nested->shadow_lpid : kvm->arch.lpid; + pid = vcpu->arch.pid; /* * Prior memory accesses to host PID Q3 must be completed before we @@ -551,7 +553,7 @@ static void switch_mmu_to_guest_radix(struct kvm *kvm, struct kvm_vcpu *vcpu, u6 isync(); mtspr(SPRN_LPID, lpid); mtspr(SPRN_LPCR, lpcr); - mtspr(SPRN_PID, vcpu->arch.pid); + mtspr(SPRN_PID, pid); /* * isync not required here because we are HRFID'ing to guest before * any guest context access, which is context synchronising. @@ -561,9 +563,11 @@ static void switch_mmu_to_guest_radix(struct kvm *kvm, struct kvm_vcpu *vcpu, u6 static void switch_mmu_to_guest_hpt(struct kvm *kvm, struct kvm_vcpu *vcpu, u64 lpcr) { u32 lpid; + u32 pid; int i; lpid = kvm->arch.lpid; + pid = vcpu->arch.pid; /* * See switch_mmu_to_guest_radix. ptesync should not be required here @@ -574,7 +578,7 @@ static void switch_mmu_to_guest_hpt(struct kvm *kvm, struct kvm_vcpu *vcpu, u64 isync(); mtspr(SPRN_LPID, lpid); mtspr(SPRN_LPCR, lpcr); - mtspr(SPRN_PID, vcpu->arch.pid); + mtspr(SPRN_PID, pid); for (i = 0; i < vcpu->arch.slb_max; i++) mtslb(vcpu->arch.slb[i].orige, vcpu->arch.slb[i].origv); @@ -585,6 +589,9 @@ static void switch_mmu_to_guest_hpt(struct kvm *kvm, struct kvm_vcpu *vcpu, u64 static void switch_mmu_to_host(struct kvm *kvm, u32 pid) { + u32 lpid = kvm->arch.host_lpid; + u64 lpcr = kvm->arch.host_lpcr; + /* * The guest has exited, so guest MMU context is no longer being * non-speculatively accessed, but a hwsync is needed before the @@ -594,8 +601,8 @@ static void switch_mmu_to_host(struct kvm *kvm, u32 pid) asm volatile("hwsync" ::: "memory"); isync(); mtspr(SPRN_PID, pid); - mtspr(SPRN_LPID, kvm->arch.host_lpid); - mtspr(SPRN_LPCR, kvm->arch.host_lpcr); + mtspr(SPRN_LPID, lpid); + mtspr(SPRN_LPCR, lpcr); /* * isync is not required after the switch, because mtmsrd with L=0 * is performed after this switch, which is context synchronising. diff --git a/arch/powerpc/kvm/book3s_hv_rm_xics.c b/arch/powerpc/kvm/book3s_hv_rm_xics.c index 587c33fc45640fd0e808766c94fe72c742ff4a97..e165bfa842bfca8c27bb2676a1d098964db10584 100644 --- a/arch/powerpc/kvm/book3s_hv_rm_xics.c +++ b/arch/powerpc/kvm/book3s_hv_rm_xics.c @@ -479,6 +479,11 @@ static void icp_rm_down_cppr(struct kvmppc_xics *xics, struct kvmppc_icp *icp, } } +unsigned long xics_rm_h_xirr_x(struct kvm_vcpu *vcpu) +{ + vcpu->arch.regs.gpr[5] = get_tb(); + return xics_rm_h_xirr(vcpu); +} unsigned long xics_rm_h_xirr(struct kvm_vcpu *vcpu) { @@ -883,7 +888,7 @@ long kvmppc_deliver_irq_passthru(struct kvm_vcpu *vcpu, /* --- Non-real mode XICS-related built-in routines --- */ -/** +/* * Host Operations poked by RM KVM */ static void rm_host_ipi_action(int action, void *data) diff --git a/arch/powerpc/kvm/book3s_hv_rm_xive.c b/arch/powerpc/kvm/book3s_hv_rm_xive.c deleted file mode 100644 index dd9880731bd61d7a588d4197480423a67b9fa996..0000000000000000000000000000000000000000 --- a/arch/powerpc/kvm/book3s_hv_rm_xive.c +++ /dev/null @@ -1,46 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "book3s_xive.h" - -/* XXX */ -#include -//#define DBG(fmt...) udbg_printf(fmt) -#define DBG(fmt...) do { } while(0) - -static inline void __iomem *get_tima_phys(void) -{ - return local_paca->kvm_hstate.xive_tima_phys; -} - -#undef XIVE_RUNTIME_CHECKS -#define X_PFX xive_rm_ -#define X_STATIC -#define X_STAT_PFX stat_rm_ -#define __x_tima get_tima_phys() -#define __x_eoi_page(xd) ((void __iomem *)((xd)->eoi_page)) -#define __x_trig_page(xd) ((void __iomem *)((xd)->trig_page)) -#define __x_writeb __raw_rm_writeb -#define __x_readw __raw_rm_readw -#define __x_readq __raw_rm_readq -#define __x_writeq __raw_rm_writeq - -#include "book3s_xive_template.c" diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S index d185dee2602681d57b06cfe3bec5423e91e73a86..0fc0e68d20d063b109f31f323e0867915835bced 100644 --- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S +++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S @@ -50,6 +50,14 @@ #define STACK_SLOT_UAMOR (SFS-88) #define STACK_SLOT_FSCR (SFS-96) +/* + * Use the last LPID (all implemented LPID bits = 1) for partition switching. + * This is reserved in the LPID allocator. POWER7 only implements 0x3ff, but + * we write 0xfff into the LPID SPR anyway, which seems to work and just + * ignores the top bits. + */ +#define LPID_RSVD 0xfff + /* * Call kvmppc_hv_entry in real mode. * Must be called with interrupts hard-disabled. @@ -1784,13 +1792,8 @@ hcall_real_table: .long DOTSYM(kvmppc_h_clear_mod) - hcall_real_table .long DOTSYM(kvmppc_h_clear_ref) - hcall_real_table .long DOTSYM(kvmppc_h_protect) - hcall_real_table -#ifdef CONFIG_SPAPR_TCE_IOMMU - .long DOTSYM(kvmppc_h_get_tce) - hcall_real_table - .long DOTSYM(kvmppc_rm_h_put_tce) - hcall_real_table -#else .long 0 /* 0x1c */ .long 0 /* 0x20 */ -#endif .long 0 /* 0x24 - H_SET_SPRG0 */ .long DOTSYM(kvmppc_h_set_dabr) - hcall_real_table .long DOTSYM(kvmppc_rm_h_page_init) - hcall_real_table @@ -1808,11 +1811,11 @@ hcall_real_table: .long 0 /* 0x5c */ .long 0 /* 0x60 */ #ifdef CONFIG_KVM_XICS - .long DOTSYM(kvmppc_rm_h_eoi) - hcall_real_table - .long DOTSYM(kvmppc_rm_h_cppr) - hcall_real_table - .long DOTSYM(kvmppc_rm_h_ipi) - hcall_real_table - .long DOTSYM(kvmppc_rm_h_ipoll) - hcall_real_table - .long DOTSYM(kvmppc_rm_h_xirr) - hcall_real_table + .long DOTSYM(xics_rm_h_eoi) - hcall_real_table + .long DOTSYM(xics_rm_h_cppr) - hcall_real_table + .long DOTSYM(xics_rm_h_ipi) - hcall_real_table + .long 0 /* 0x70 - H_IPOLL */ + .long DOTSYM(xics_rm_h_xirr) - hcall_real_table #else .long 0 /* 0x64 - H_EOI */ .long 0 /* 0x68 - H_CPPR */ @@ -1868,13 +1871,8 @@ hcall_real_table: .long 0 /* 0x12c */ .long 0 /* 0x130 */ .long DOTSYM(kvmppc_h_set_xdabr) - hcall_real_table -#ifdef CONFIG_SPAPR_TCE_IOMMU - .long DOTSYM(kvmppc_rm_h_stuff_tce) - hcall_real_table - .long DOTSYM(kvmppc_rm_h_put_tce_indirect) - hcall_real_table -#else .long 0 /* 0x138 */ .long 0 /* 0x13c */ -#endif .long 0 /* 0x140 */ .long 0 /* 0x144 */ .long 0 /* 0x148 */ @@ -1987,7 +1985,7 @@ hcall_real_table: .long 0 /* 0x2f4 */ .long 0 /* 0x2f8 */ #ifdef CONFIG_KVM_XICS - .long DOTSYM(kvmppc_rm_h_xirr_x) - hcall_real_table + .long DOTSYM(xics_rm_h_xirr_x) - hcall_real_table #else .long 0 /* 0x2fc - H_XIRR_X*/ #endif diff --git a/arch/powerpc/kvm/book3s_hv_uvmem.c b/arch/powerpc/kvm/book3s_hv_uvmem.c index 45c993dd05f5ef87b52d256165c3a6b7e86e8284..5980063016207f94594cfdbb22f3b966e7f56974 100644 --- a/arch/powerpc/kvm/book3s_hv_uvmem.c +++ b/arch/powerpc/kvm/book3s_hv_uvmem.c @@ -120,7 +120,7 @@ static DEFINE_SPINLOCK(kvmppc_uvmem_bitmap_lock); * content is un-encrypted. * * (c) Normal - The GFN is a normal. The GFN is associated with - * a normal VM. The contents of the GFN is accesible to + * a normal VM. The contents of the GFN is accessible to * the Hypervisor. Its content is never encrypted. * * States of a VM. @@ -361,13 +361,15 @@ static bool kvmppc_gfn_is_uvmem_pfn(unsigned long gfn, struct kvm *kvm, static bool kvmppc_next_nontransitioned_gfn(const struct kvm_memory_slot *memslot, struct kvm *kvm, unsigned long *gfn) { - struct kvmppc_uvmem_slot *p; + struct kvmppc_uvmem_slot *p = NULL, *iter; bool ret = false; unsigned long i; - list_for_each_entry(p, &kvm->arch.uvmem_pfns, list) - if (*gfn >= p->base_pfn && *gfn < p->base_pfn + p->nr_pfns) + list_for_each_entry(iter, &kvm->arch.uvmem_pfns, list) + if (*gfn >= iter->base_pfn && *gfn < iter->base_pfn + iter->nr_pfns) { + p = iter; break; + } if (!p) return ret; /* diff --git a/arch/powerpc/kvm/book3s_interrupts.S b/arch/powerpc/kvm/book3s_interrupts.S index 25a3679fb59041eff7314e49616f9e28edcaedcd..f4bec2fc51aa3389445019eacdfeccf7da7ca136 100644 --- a/arch/powerpc/kvm/book3s_interrupts.S +++ b/arch/powerpc/kvm/book3s_interrupts.S @@ -15,7 +15,7 @@ #include #if defined(CONFIG_PPC_BOOK3S_64) -#ifdef PPC64_ELF_ABI_v2 +#ifdef CONFIG_PPC64_ELF_ABI_V2 #define FUNC(name) name #else #define FUNC(name) GLUE(.,name) diff --git a/arch/powerpc/kvm/book3s_pr.c b/arch/powerpc/kvm/book3s_pr.c index 7bf9e6ca5c2df60506bb2225a92c1914c71d5b26..d6abed6e51e6995a66df51b59d544fce56a6dfee 100644 --- a/arch/powerpc/kvm/book3s_pr.c +++ b/arch/powerpc/kvm/book3s_pr.c @@ -1287,7 +1287,7 @@ int kvmppc_handle_exit_pr(struct kvm_vcpu *vcpu, unsigned int exit_nr) /* Get last sc for papr */ if (vcpu->arch.papr_enabled) { - /* The sc instuction points SRR0 to the next inst */ + /* The sc instruction points SRR0 to the next inst */ emul = kvmppc_get_last_inst(vcpu, INST_SC, &last_sc); if (emul != EMULATE_DONE) { kvmppc_set_pc(vcpu, kvmppc_get_pc(vcpu) - 4); diff --git a/arch/powerpc/kvm/book3s_pr_papr.c b/arch/powerpc/kvm/book3s_pr_papr.c index dc4f51ac84bc6012a068eb4c9793e344a86b9221..a1f2978b2a8654ff2daddc6834a66e5166d41229 100644 --- a/arch/powerpc/kvm/book3s_pr_papr.c +++ b/arch/powerpc/kvm/book3s_pr_papr.c @@ -433,9 +433,12 @@ int kvmppc_hcall_impl_pr(unsigned long cmd) case H_REMOVE: case H_PROTECT: case H_BULK_REMOVE: +#ifdef CONFIG_SPAPR_TCE_IOMMU + case H_GET_TCE: case H_PUT_TCE: case H_PUT_TCE_INDIRECT: case H_STUFF_TCE: +#endif case H_CEDE: case H_LOGICAL_CI_LOAD: case H_LOGICAL_CI_STORE: @@ -464,7 +467,10 @@ static unsigned int default_hcall_list[] = { H_REMOVE, H_PROTECT, H_BULK_REMOVE, +#ifdef CONFIG_SPAPR_TCE_IOMMU + H_GET_TCE, H_PUT_TCE, +#endif H_CEDE, H_SET_MODE, #ifdef CONFIG_KVM_XICS diff --git a/arch/powerpc/kvm/book3s_rmhandlers.S b/arch/powerpc/kvm/book3s_rmhandlers.S index b45b750fa77a6f0a9626d0306251882771dd5676..03886ca24498380937f7a6563b2dceab118deeb5 100644 --- a/arch/powerpc/kvm/book3s_rmhandlers.S +++ b/arch/powerpc/kvm/book3s_rmhandlers.S @@ -26,7 +26,7 @@ #if defined(CONFIG_PPC_BOOK3S_64) -#ifdef PPC64_ELF_ABI_v2 +#ifdef CONFIG_PPC64_ELF_ABI_V2 #define FUNC(name) name #else #define FUNC(name) GLUE(.,name) diff --git a/arch/powerpc/kvm/book3s_xics.c b/arch/powerpc/kvm/book3s_xics.c index ab6d37d78c62d4efa8047d7d0b8f1ea136e7fbb7..589a8f2571201ce56897afbf28078cb8a23ca713 100644 --- a/arch/powerpc/kvm/book3s_xics.c +++ b/arch/powerpc/kvm/book3s_xics.c @@ -462,7 +462,7 @@ static void icp_deliver_irq(struct kvmppc_xics *xics, struct kvmppc_icp *icp, * new guy. We cannot assume that the rejected interrupt is less * favored than the new one, and thus doesn't need to be delivered, * because by the time we exit icp_try_to_deliver() the target - * processor may well have alrady consumed & completed it, and thus + * processor may well have already consumed & completed it, and thus * the rejected interrupt might actually be already acceptable. */ if (icp_try_to_deliver(icp, new_irq, state->priority, &reject)) { diff --git a/arch/powerpc/kvm/book3s_xive.c b/arch/powerpc/kvm/book3s_xive.c index c0ce5531d9bcb7461db6f7c8a68e2c6a6014009b..4ca23644f75258d23812eb15ac2d8f77e319ef88 100644 --- a/arch/powerpc/kvm/book3s_xive.c +++ b/arch/powerpc/kvm/book3s_xive.c @@ -30,27 +30,629 @@ #include "book3s_xive.h" - -/* - * Virtual mode variants of the hcalls for use on radix/radix - * with AIL. They require the VCPU's VP to be "pushed" - * - * We still instantiate them here because we use some of the - * generated utility functions as well in this file. - */ -#define XIVE_RUNTIME_CHECKS -#define X_PFX xive_vm_ -#define X_STATIC static -#define X_STAT_PFX stat_vm_ -#define __x_tima xive_tima #define __x_eoi_page(xd) ((void __iomem *)((xd)->eoi_mmio)) #define __x_trig_page(xd) ((void __iomem *)((xd)->trig_mmio)) -#define __x_writeb __raw_writeb -#define __x_readw __raw_readw -#define __x_readq __raw_readq -#define __x_writeq __raw_writeq -#include "book3s_xive_template.c" +/* Dummy interrupt used when taking interrupts out of a queue in H_CPPR */ +#define XICS_DUMMY 1 + +static void xive_vm_ack_pending(struct kvmppc_xive_vcpu *xc) +{ + u8 cppr; + u16 ack; + + /* + * Ensure any previous store to CPPR is ordered vs. + * the subsequent loads from PIPR or ACK. + */ + eieio(); + + /* Perform the acknowledge OS to register cycle. */ + ack = be16_to_cpu(__raw_readw(xive_tima + TM_SPC_ACK_OS_REG)); + + /* Synchronize subsequent queue accesses */ + mb(); + + /* XXX Check grouping level */ + + /* Anything ? */ + if (!((ack >> 8) & TM_QW1_NSR_EO)) + return; + + /* Grab CPPR of the most favored pending interrupt */ + cppr = ack & 0xff; + if (cppr < 8) + xc->pending |= 1 << cppr; + + /* Check consistency */ + if (cppr >= xc->hw_cppr) + pr_warn("KVM-XIVE: CPU %d odd ack CPPR, got %d at %d\n", + smp_processor_id(), cppr, xc->hw_cppr); + + /* + * Update our image of the HW CPPR. We don't yet modify + * xc->cppr, this will be done as we scan for interrupts + * in the queues. + */ + xc->hw_cppr = cppr; +} + +static u8 xive_vm_esb_load(struct xive_irq_data *xd, u32 offset) +{ + u64 val; + + if (offset == XIVE_ESB_SET_PQ_10 && xd->flags & XIVE_IRQ_FLAG_STORE_EOI) + offset |= XIVE_ESB_LD_ST_MO; + + val = __raw_readq(__x_eoi_page(xd) + offset); +#ifdef __LITTLE_ENDIAN__ + val >>= 64-8; +#endif + return (u8)val; +} + + +static void xive_vm_source_eoi(u32 hw_irq, struct xive_irq_data *xd) +{ + /* If the XIVE supports the new "store EOI facility, use it */ + if (xd->flags & XIVE_IRQ_FLAG_STORE_EOI) + __raw_writeq(0, __x_eoi_page(xd) + XIVE_ESB_STORE_EOI); + else if (xd->flags & XIVE_IRQ_FLAG_LSI) { + /* + * For LSIs the HW EOI cycle is used rather than PQ bits, + * as they are automatically re-triggred in HW when still + * pending. + */ + __raw_readq(__x_eoi_page(xd) + XIVE_ESB_LOAD_EOI); + } else { + uint64_t eoi_val; + + /* + * Otherwise for EOI, we use the special MMIO that does + * a clear of both P and Q and returns the old Q, + * except for LSIs where we use the "EOI cycle" special + * load. + * + * This allows us to then do a re-trigger if Q was set + * rather than synthetizing an interrupt in software + */ + eoi_val = xive_vm_esb_load(xd, XIVE_ESB_SET_PQ_00); + + /* Re-trigger if needed */ + if ((eoi_val & 1) && __x_trig_page(xd)) + __raw_writeq(0, __x_trig_page(xd)); + } +} + +enum { + scan_fetch, + scan_poll, + scan_eoi, +}; + +static u32 xive_vm_scan_interrupts(struct kvmppc_xive_vcpu *xc, + u8 pending, int scan_type) +{ + u32 hirq = 0; + u8 prio = 0xff; + + /* Find highest pending priority */ + while ((xc->mfrr != 0xff || pending != 0) && hirq == 0) { + struct xive_q *q; + u32 idx, toggle; + __be32 *qpage; + + /* + * If pending is 0 this will return 0xff which is what + * we want + */ + prio = ffs(pending) - 1; + + /* Don't scan past the guest cppr */ + if (prio >= xc->cppr || prio > 7) { + if (xc->mfrr < xc->cppr) { + prio = xc->mfrr; + hirq = XICS_IPI; + } + break; + } + + /* Grab queue and pointers */ + q = &xc->queues[prio]; + idx = q->idx; + toggle = q->toggle; + + /* + * Snapshot the queue page. The test further down for EOI + * must use the same "copy" that was used by __xive_read_eq + * since qpage can be set concurrently and we don't want + * to miss an EOI. + */ + qpage = READ_ONCE(q->qpage); + +skip_ipi: + /* + * Try to fetch from the queue. Will return 0 for a + * non-queueing priority (ie, qpage = 0). + */ + hirq = __xive_read_eq(qpage, q->msk, &idx, &toggle); + + /* + * If this was a signal for an MFFR change done by + * H_IPI we skip it. Additionally, if we were fetching + * we EOI it now, thus re-enabling reception of a new + * such signal. + * + * We also need to do that if prio is 0 and we had no + * page for the queue. In this case, we have non-queued + * IPI that needs to be EOId. + * + * This is safe because if we have another pending MFRR + * change that wasn't observed above, the Q bit will have + * been set and another occurrence of the IPI will trigger. + */ + if (hirq == XICS_IPI || (prio == 0 && !qpage)) { + if (scan_type == scan_fetch) { + xive_vm_source_eoi(xc->vp_ipi, + &xc->vp_ipi_data); + q->idx = idx; + q->toggle = toggle; + } + /* Loop back on same queue with updated idx/toggle */ + WARN_ON(hirq && hirq != XICS_IPI); + if (hirq) + goto skip_ipi; + } + + /* If it's the dummy interrupt, continue searching */ + if (hirq == XICS_DUMMY) + goto skip_ipi; + + /* Clear the pending bit if the queue is now empty */ + if (!hirq) { + pending &= ~(1 << prio); + + /* + * Check if the queue count needs adjusting due to + * interrupts being moved away. + */ + if (atomic_read(&q->pending_count)) { + int p = atomic_xchg(&q->pending_count, 0); + + if (p) { + WARN_ON(p > atomic_read(&q->count)); + atomic_sub(p, &q->count); + } + } + } + + /* + * If the most favoured prio we found pending is less + * favored (or equal) than a pending IPI, we return + * the IPI instead. + */ + if (prio >= xc->mfrr && xc->mfrr < xc->cppr) { + prio = xc->mfrr; + hirq = XICS_IPI; + break; + } + + /* If fetching, update queue pointers */ + if (scan_type == scan_fetch) { + q->idx = idx; + q->toggle = toggle; + } + } + + /* If we are just taking a "peek", do nothing else */ + if (scan_type == scan_poll) + return hirq; + + /* Update the pending bits */ + xc->pending = pending; + + /* + * If this is an EOI that's it, no CPPR adjustment done here, + * all we needed was cleanup the stale pending bits and check + * if there's anything left. + */ + if (scan_type == scan_eoi) + return hirq; + + /* + * If we found an interrupt, adjust what the guest CPPR should + * be as if we had just fetched that interrupt from HW. + * + * Note: This can only make xc->cppr smaller as the previous + * loop will only exit with hirq != 0 if prio is lower than + * the current xc->cppr. Thus we don't need to re-check xc->mfrr + * for pending IPIs. + */ + if (hirq) + xc->cppr = prio; + /* + * If it was an IPI the HW CPPR might have been lowered too much + * as the HW interrupt we use for IPIs is routed to priority 0. + * + * We re-sync it here. + */ + if (xc->cppr != xc->hw_cppr) { + xc->hw_cppr = xc->cppr; + __raw_writeb(xc->cppr, xive_tima + TM_QW1_OS + TM_CPPR); + } + + return hirq; +} + +static unsigned long xive_vm_h_xirr(struct kvm_vcpu *vcpu) +{ + struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu; + u8 old_cppr; + u32 hirq; + + pr_devel("H_XIRR\n"); + + xc->stat_vm_h_xirr++; + + /* First collect pending bits from HW */ + xive_vm_ack_pending(xc); + + pr_devel(" new pending=0x%02x hw_cppr=%d cppr=%d\n", + xc->pending, xc->hw_cppr, xc->cppr); + + /* Grab previous CPPR and reverse map it */ + old_cppr = xive_prio_to_guest(xc->cppr); + + /* Scan for actual interrupts */ + hirq = xive_vm_scan_interrupts(xc, xc->pending, scan_fetch); + + pr_devel(" got hirq=0x%x hw_cppr=%d cppr=%d\n", + hirq, xc->hw_cppr, xc->cppr); + + /* That should never hit */ + if (hirq & 0xff000000) + pr_warn("XIVE: Weird guest interrupt number 0x%08x\n", hirq); + + /* + * XXX We could check if the interrupt is masked here and + * filter it. If we chose to do so, we would need to do: + * + * if (masked) { + * lock(); + * if (masked) { + * old_Q = true; + * hirq = 0; + * } + * unlock(); + * } + */ + + /* Return interrupt and old CPPR in GPR4 */ + vcpu->arch.regs.gpr[4] = hirq | (old_cppr << 24); + + return H_SUCCESS; +} + +static unsigned long xive_vm_h_ipoll(struct kvm_vcpu *vcpu, unsigned long server) +{ + struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu; + u8 pending = xc->pending; + u32 hirq; + + pr_devel("H_IPOLL(server=%ld)\n", server); + + xc->stat_vm_h_ipoll++; + + /* Grab the target VCPU if not the current one */ + if (xc->server_num != server) { + vcpu = kvmppc_xive_find_server(vcpu->kvm, server); + if (!vcpu) + return H_PARAMETER; + xc = vcpu->arch.xive_vcpu; + + /* Scan all priorities */ + pending = 0xff; + } else { + /* Grab pending interrupt if any */ + __be64 qw1 = __raw_readq(xive_tima + TM_QW1_OS); + u8 pipr = be64_to_cpu(qw1) & 0xff; + + if (pipr < 8) + pending |= 1 << pipr; + } + + hirq = xive_vm_scan_interrupts(xc, pending, scan_poll); + + /* Return interrupt and old CPPR in GPR4 */ + vcpu->arch.regs.gpr[4] = hirq | (xc->cppr << 24); + + return H_SUCCESS; +} + +static void xive_vm_push_pending_to_hw(struct kvmppc_xive_vcpu *xc) +{ + u8 pending, prio; + + pending = xc->pending; + if (xc->mfrr != 0xff) { + if (xc->mfrr < 8) + pending |= 1 << xc->mfrr; + else + pending |= 0x80; + } + if (!pending) + return; + prio = ffs(pending) - 1; + + __raw_writeb(prio, xive_tima + TM_SPC_SET_OS_PENDING); +} + +static void xive_vm_scan_for_rerouted_irqs(struct kvmppc_xive *xive, + struct kvmppc_xive_vcpu *xc) +{ + unsigned int prio; + + /* For each priority that is now masked */ + for (prio = xc->cppr; prio < KVMPPC_XIVE_Q_COUNT; prio++) { + struct xive_q *q = &xc->queues[prio]; + struct kvmppc_xive_irq_state *state; + struct kvmppc_xive_src_block *sb; + u32 idx, toggle, entry, irq, hw_num; + struct xive_irq_data *xd; + __be32 *qpage; + u16 src; + + idx = q->idx; + toggle = q->toggle; + qpage = READ_ONCE(q->qpage); + if (!qpage) + continue; + + /* For each interrupt in the queue */ + for (;;) { + entry = be32_to_cpup(qpage + idx); + + /* No more ? */ + if ((entry >> 31) == toggle) + break; + irq = entry & 0x7fffffff; + + /* Skip dummies and IPIs */ + if (irq == XICS_DUMMY || irq == XICS_IPI) + goto next; + sb = kvmppc_xive_find_source(xive, irq, &src); + if (!sb) + goto next; + state = &sb->irq_state[src]; + + /* Has it been rerouted ? */ + if (xc->server_num == state->act_server) + goto next; + + /* + * Allright, it *has* been re-routed, kill it from + * the queue. + */ + qpage[idx] = cpu_to_be32((entry & 0x80000000) | XICS_DUMMY); + + /* Find the HW interrupt */ + kvmppc_xive_select_irq(state, &hw_num, &xd); + + /* If it's not an LSI, set PQ to 11 the EOI will force a resend */ + if (!(xd->flags & XIVE_IRQ_FLAG_LSI)) + xive_vm_esb_load(xd, XIVE_ESB_SET_PQ_11); + + /* EOI the source */ + xive_vm_source_eoi(hw_num, xd); + +next: + idx = (idx + 1) & q->msk; + if (idx == 0) + toggle ^= 1; + } + } +} + +static int xive_vm_h_cppr(struct kvm_vcpu *vcpu, unsigned long cppr) +{ + struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu; + struct kvmppc_xive *xive = vcpu->kvm->arch.xive; + u8 old_cppr; + + pr_devel("H_CPPR(cppr=%ld)\n", cppr); + + xc->stat_vm_h_cppr++; + + /* Map CPPR */ + cppr = xive_prio_from_guest(cppr); + + /* Remember old and update SW state */ + old_cppr = xc->cppr; + xc->cppr = cppr; + + /* + * Order the above update of xc->cppr with the subsequent + * read of xc->mfrr inside push_pending_to_hw() + */ + smp_mb(); + + if (cppr > old_cppr) { + /* + * We are masking less, we need to look for pending things + * to deliver and set VP pending bits accordingly to trigger + * a new interrupt otherwise we might miss MFRR changes for + * which we have optimized out sending an IPI signal. + */ + xive_vm_push_pending_to_hw(xc); + } else { + /* + * We are masking more, we need to check the queue for any + * interrupt that has been routed to another CPU, take + * it out (replace it with the dummy) and retrigger it. + * + * This is necessary since those interrupts may otherwise + * never be processed, at least not until this CPU restores + * its CPPR. + * + * This is in theory racy vs. HW adding new interrupts to + * the queue. In practice this works because the interesting + * cases are when the guest has done a set_xive() to move the + * interrupt away, which flushes the xive, followed by the + * target CPU doing a H_CPPR. So any new interrupt coming into + * the queue must still be routed to us and isn't a source + * of concern. + */ + xive_vm_scan_for_rerouted_irqs(xive, xc); + } + + /* Apply new CPPR */ + xc->hw_cppr = cppr; + __raw_writeb(cppr, xive_tima + TM_QW1_OS + TM_CPPR); + + return H_SUCCESS; +} + +static int xive_vm_h_eoi(struct kvm_vcpu *vcpu, unsigned long xirr) +{ + struct kvmppc_xive *xive = vcpu->kvm->arch.xive; + struct kvmppc_xive_src_block *sb; + struct kvmppc_xive_irq_state *state; + struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu; + struct xive_irq_data *xd; + u8 new_cppr = xirr >> 24; + u32 irq = xirr & 0x00ffffff, hw_num; + u16 src; + int rc = 0; + + pr_devel("H_EOI(xirr=%08lx)\n", xirr); + + xc->stat_vm_h_eoi++; + + xc->cppr = xive_prio_from_guest(new_cppr); + + /* + * IPIs are synthetized from MFRR and thus don't need + * any special EOI handling. The underlying interrupt + * used to signal MFRR changes is EOId when fetched from + * the queue. + */ + if (irq == XICS_IPI || irq == 0) { + /* + * This barrier orders the setting of xc->cppr vs. + * subsquent test of xc->mfrr done inside + * scan_interrupts and push_pending_to_hw + */ + smp_mb(); + goto bail; + } + + /* Find interrupt source */ + sb = kvmppc_xive_find_source(xive, irq, &src); + if (!sb) { + pr_devel(" source not found !\n"); + rc = H_PARAMETER; + /* Same as above */ + smp_mb(); + goto bail; + } + state = &sb->irq_state[src]; + kvmppc_xive_select_irq(state, &hw_num, &xd); + + state->in_eoi = true; + + /* + * This barrier orders both setting of in_eoi above vs, + * subsequent test of guest_priority, and the setting + * of xc->cppr vs. subsquent test of xc->mfrr done inside + * scan_interrupts and push_pending_to_hw + */ + smp_mb(); + +again: + if (state->guest_priority == MASKED) { + arch_spin_lock(&sb->lock); + if (state->guest_priority != MASKED) { + arch_spin_unlock(&sb->lock); + goto again; + } + pr_devel(" EOI on saved P...\n"); + + /* Clear old_p, that will cause unmask to perform an EOI */ + state->old_p = false; + + arch_spin_unlock(&sb->lock); + } else { + pr_devel(" EOI on source...\n"); + + /* Perform EOI on the source */ + xive_vm_source_eoi(hw_num, xd); + + /* If it's an emulated LSI, check level and resend */ + if (state->lsi && state->asserted) + __raw_writeq(0, __x_trig_page(xd)); + + } + + /* + * This barrier orders the above guest_priority check + * and spin_lock/unlock with clearing in_eoi below. + * + * It also has to be a full mb() as it must ensure + * the MMIOs done in source_eoi() are completed before + * state->in_eoi is visible. + */ + mb(); + state->in_eoi = false; +bail: + + /* Re-evaluate pending IRQs and update HW */ + xive_vm_scan_interrupts(xc, xc->pending, scan_eoi); + xive_vm_push_pending_to_hw(xc); + pr_devel(" after scan pending=%02x\n", xc->pending); + + /* Apply new CPPR */ + xc->hw_cppr = xc->cppr; + __raw_writeb(xc->cppr, xive_tima + TM_QW1_OS + TM_CPPR); + + return rc; +} + +static int xive_vm_h_ipi(struct kvm_vcpu *vcpu, unsigned long server, + unsigned long mfrr) +{ + struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu; + + pr_devel("H_IPI(server=%08lx,mfrr=%ld)\n", server, mfrr); + + xc->stat_vm_h_ipi++; + + /* Find target */ + vcpu = kvmppc_xive_find_server(vcpu->kvm, server); + if (!vcpu) + return H_PARAMETER; + xc = vcpu->arch.xive_vcpu; + + /* Locklessly write over MFRR */ + xc->mfrr = mfrr; + + /* + * The load of xc->cppr below and the subsequent MMIO store + * to the IPI must happen after the above mfrr update is + * globally visible so that: + * + * - Synchronize with another CPU doing an H_EOI or a H_CPPR + * updating xc->cppr then reading xc->mfrr. + * + * - The target of the IPI sees the xc->mfrr update + */ + mb(); + + /* Shoot the IPI if most favored than target cppr */ + if (mfrr < xc->cppr) + __raw_writeq(0, __x_trig_page(&xc->vp_ipi_data)); + + return H_SUCCESS; +} /* * We leave a gap of a couple of interrupts in the queue to @@ -124,7 +726,7 @@ void kvmppc_xive_push_vcpu(struct kvm_vcpu *vcpu) * interrupt might have fired and be on its way to the * host queue while we mask it, and if we unmask it * early enough (re-cede right away), there is a - * theorical possibility that it fires again, thus + * theoretical possibility that it fires again, thus * landing in the target queue more than once which is * a big no-no. * @@ -179,12 +781,13 @@ void kvmppc_xive_pull_vcpu(struct kvm_vcpu *vcpu) } EXPORT_SYMBOL_GPL(kvmppc_xive_pull_vcpu); -void kvmppc_xive_rearm_escalation(struct kvm_vcpu *vcpu) +bool kvmppc_xive_rearm_escalation(struct kvm_vcpu *vcpu) { void __iomem *esc_vaddr = (void __iomem *)vcpu->arch.xive_esc_vaddr; + bool ret = true; if (!esc_vaddr) - return; + return ret; /* we are using XIVE with single escalation */ @@ -197,7 +800,7 @@ void kvmppc_xive_rearm_escalation(struct kvm_vcpu *vcpu) * we also don't want to set xive_esc_on to 1 here in * case we race with xive_esc_irq(). */ - vcpu->arch.ceded = 0; + ret = false; /* * The escalation interrupts are special as we don't EOI them. * There is no need to use the load-after-store ordering offset @@ -210,6 +813,8 @@ void kvmppc_xive_rearm_escalation(struct kvm_vcpu *vcpu) __raw_readq(esc_vaddr + XIVE_ESB_SET_PQ_00); } mb(); + + return ret; } EXPORT_SYMBOL_GPL(kvmppc_xive_rearm_escalation); @@ -238,7 +843,7 @@ static irqreturn_t xive_esc_irq(int irq, void *data) vcpu->arch.irq_pending = 1; smp_mb(); - if (vcpu->arch.ceded) + if (vcpu->arch.ceded || vcpu->arch.nested) kvmppc_fast_vcpu_kick(vcpu); /* Since we have the no-EOI flag, the interrupt is effectively @@ -622,7 +1227,7 @@ static int xive_target_interrupt(struct kvm *kvm, /* * Targetting rules: In order to avoid losing track of - * pending interrupts accross mask and unmask, which would + * pending interrupts across mask and unmask, which would * allow queue overflows, we implement the following rules: * * - Unless it was never enabled (or we run out of capacity) @@ -1073,7 +1678,7 @@ int kvmppc_xive_clr_mapped(struct kvm *kvm, unsigned long guest_irq, /* * If old_p is set, the interrupt is pending, we switch it to * PQ=11. This will force a resend in the host so the interrupt - * isn't lost to whatver host driver may pick it up + * isn't lost to whatever host driver may pick it up */ if (state->old_p) xive_vm_esb_load(state->pt_data, XIVE_ESB_SET_PQ_11); diff --git a/arch/powerpc/kvm/book3s_xive.h b/arch/powerpc/kvm/book3s_xive.h index 09d0657596c329b9aeb334816f04b9fac4bdca81..1e48f72e8aa5d3ed8351dd148bd5361ffc3cfbd5 100644 --- a/arch/powerpc/kvm/book3s_xive.h +++ b/arch/powerpc/kvm/book3s_xive.h @@ -285,13 +285,6 @@ static inline u32 __xive_read_eq(__be32 *qpage, u32 msk, u32 *idx, u32 *toggle) return cur & 0x7fffffff; } -extern unsigned long xive_rm_h_xirr(struct kvm_vcpu *vcpu); -extern unsigned long xive_rm_h_ipoll(struct kvm_vcpu *vcpu, unsigned long server); -extern int xive_rm_h_ipi(struct kvm_vcpu *vcpu, unsigned long server, - unsigned long mfrr); -extern int xive_rm_h_cppr(struct kvm_vcpu *vcpu, unsigned long cppr); -extern int xive_rm_h_eoi(struct kvm_vcpu *vcpu, unsigned long xirr); - /* * Common Xive routines for XICS-over-XIVE and XIVE native */ diff --git a/arch/powerpc/kvm/book3s_xive_native.c b/arch/powerpc/kvm/book3s_xive_native.c index f81ba6f84e722cc92428ffe60c1c265a2102bc4a..5271c33fe79e4d5f6e83c5afa21a089bfec92c81 100644 --- a/arch/powerpc/kvm/book3s_xive_native.c +++ b/arch/powerpc/kvm/book3s_xive_native.c @@ -209,7 +209,7 @@ static int kvmppc_xive_native_reset_mapped(struct kvm *kvm, unsigned long irq) /* * Clear the ESB pages of the IRQ number being mapped (or - * unmapped) into the guest and let the the VM fault handler + * unmapped) into the guest and let the VM fault handler * repopulate with the appropriate ESB pages (device or IC) */ pr_debug("clearing esb pages for girq 0x%lx\n", irq); diff --git a/arch/powerpc/kvm/book3s_xive_template.c b/arch/powerpc/kvm/book3s_xive_template.c deleted file mode 100644 index b0015e05d99a94478d5269313dfe0a249ac23d3c..0000000000000000000000000000000000000000 --- a/arch/powerpc/kvm/book3s_xive_template.c +++ /dev/null @@ -1,636 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright 2017 Benjamin Herrenschmidt, IBM Corporation - */ - -/* File to be included by other .c files */ - -#define XGLUE(a,b) a##b -#define GLUE(a,b) XGLUE(a,b) - -/* Dummy interrupt used when taking interrupts out of a queue in H_CPPR */ -#define XICS_DUMMY 1 - -static void GLUE(X_PFX,ack_pending)(struct kvmppc_xive_vcpu *xc) -{ - u8 cppr; - u16 ack; - - /* - * Ensure any previous store to CPPR is ordered vs. - * the subsequent loads from PIPR or ACK. - */ - eieio(); - - /* Perform the acknowledge OS to register cycle. */ - ack = be16_to_cpu(__x_readw(__x_tima + TM_SPC_ACK_OS_REG)); - - /* Synchronize subsequent queue accesses */ - mb(); - - /* XXX Check grouping level */ - - /* Anything ? */ - if (!((ack >> 8) & TM_QW1_NSR_EO)) - return; - - /* Grab CPPR of the most favored pending interrupt */ - cppr = ack & 0xff; - if (cppr < 8) - xc->pending |= 1 << cppr; - -#ifdef XIVE_RUNTIME_CHECKS - /* Check consistency */ - if (cppr >= xc->hw_cppr) - pr_warn("KVM-XIVE: CPU %d odd ack CPPR, got %d at %d\n", - smp_processor_id(), cppr, xc->hw_cppr); -#endif - - /* - * Update our image of the HW CPPR. We don't yet modify - * xc->cppr, this will be done as we scan for interrupts - * in the queues. - */ - xc->hw_cppr = cppr; -} - -static u8 GLUE(X_PFX,esb_load)(struct xive_irq_data *xd, u32 offset) -{ - u64 val; - - if (offset == XIVE_ESB_SET_PQ_10 && xd->flags & XIVE_IRQ_FLAG_STORE_EOI) - offset |= XIVE_ESB_LD_ST_MO; - - val =__x_readq(__x_eoi_page(xd) + offset); -#ifdef __LITTLE_ENDIAN__ - val >>= 64-8; -#endif - return (u8)val; -} - - -static void GLUE(X_PFX,source_eoi)(u32 hw_irq, struct xive_irq_data *xd) -{ - /* If the XIVE supports the new "store EOI facility, use it */ - if (xd->flags & XIVE_IRQ_FLAG_STORE_EOI) - __x_writeq(0, __x_eoi_page(xd) + XIVE_ESB_STORE_EOI); - else if (xd->flags & XIVE_IRQ_FLAG_LSI) { - /* - * For LSIs the HW EOI cycle is used rather than PQ bits, - * as they are automatically re-triggred in HW when still - * pending. - */ - __x_readq(__x_eoi_page(xd) + XIVE_ESB_LOAD_EOI); - } else { - uint64_t eoi_val; - - /* - * Otherwise for EOI, we use the special MMIO that does - * a clear of both P and Q and returns the old Q, - * except for LSIs where we use the "EOI cycle" special - * load. - * - * This allows us to then do a re-trigger if Q was set - * rather than synthetizing an interrupt in software - */ - eoi_val = GLUE(X_PFX,esb_load)(xd, XIVE_ESB_SET_PQ_00); - - /* Re-trigger if needed */ - if ((eoi_val & 1) && __x_trig_page(xd)) - __x_writeq(0, __x_trig_page(xd)); - } -} - -enum { - scan_fetch, - scan_poll, - scan_eoi, -}; - -static u32 GLUE(X_PFX,scan_interrupts)(struct kvmppc_xive_vcpu *xc, - u8 pending, int scan_type) -{ - u32 hirq = 0; - u8 prio = 0xff; - - /* Find highest pending priority */ - while ((xc->mfrr != 0xff || pending != 0) && hirq == 0) { - struct xive_q *q; - u32 idx, toggle; - __be32 *qpage; - - /* - * If pending is 0 this will return 0xff which is what - * we want - */ - prio = ffs(pending) - 1; - - /* Don't scan past the guest cppr */ - if (prio >= xc->cppr || prio > 7) { - if (xc->mfrr < xc->cppr) { - prio = xc->mfrr; - hirq = XICS_IPI; - } - break; - } - - /* Grab queue and pointers */ - q = &xc->queues[prio]; - idx = q->idx; - toggle = q->toggle; - - /* - * Snapshot the queue page. The test further down for EOI - * must use the same "copy" that was used by __xive_read_eq - * since qpage can be set concurrently and we don't want - * to miss an EOI. - */ - qpage = READ_ONCE(q->qpage); - -skip_ipi: - /* - * Try to fetch from the queue. Will return 0 for a - * non-queueing priority (ie, qpage = 0). - */ - hirq = __xive_read_eq(qpage, q->msk, &idx, &toggle); - - /* - * If this was a signal for an MFFR change done by - * H_IPI we skip it. Additionally, if we were fetching - * we EOI it now, thus re-enabling reception of a new - * such signal. - * - * We also need to do that if prio is 0 and we had no - * page for the queue. In this case, we have non-queued - * IPI that needs to be EOId. - * - * This is safe because if we have another pending MFRR - * change that wasn't observed above, the Q bit will have - * been set and another occurrence of the IPI will trigger. - */ - if (hirq == XICS_IPI || (prio == 0 && !qpage)) { - if (scan_type == scan_fetch) { - GLUE(X_PFX,source_eoi)(xc->vp_ipi, - &xc->vp_ipi_data); - q->idx = idx; - q->toggle = toggle; - } - /* Loop back on same queue with updated idx/toggle */ -#ifdef XIVE_RUNTIME_CHECKS - WARN_ON(hirq && hirq != XICS_IPI); -#endif - if (hirq) - goto skip_ipi; - } - - /* If it's the dummy interrupt, continue searching */ - if (hirq == XICS_DUMMY) - goto skip_ipi; - - /* Clear the pending bit if the queue is now empty */ - if (!hirq) { - pending &= ~(1 << prio); - - /* - * Check if the queue count needs adjusting due to - * interrupts being moved away. - */ - if (atomic_read(&q->pending_count)) { - int p = atomic_xchg(&q->pending_count, 0); - if (p) { -#ifdef XIVE_RUNTIME_CHECKS - WARN_ON(p > atomic_read(&q->count)); -#endif - atomic_sub(p, &q->count); - } - } - } - - /* - * If the most favoured prio we found pending is less - * favored (or equal) than a pending IPI, we return - * the IPI instead. - */ - if (prio >= xc->mfrr && xc->mfrr < xc->cppr) { - prio = xc->mfrr; - hirq = XICS_IPI; - break; - } - - /* If fetching, update queue pointers */ - if (scan_type == scan_fetch) { - q->idx = idx; - q->toggle = toggle; - } - } - - /* If we are just taking a "peek", do nothing else */ - if (scan_type == scan_poll) - return hirq; - - /* Update the pending bits */ - xc->pending = pending; - - /* - * If this is an EOI that's it, no CPPR adjustment done here, - * all we needed was cleanup the stale pending bits and check - * if there's anything left. - */ - if (scan_type == scan_eoi) - return hirq; - - /* - * If we found an interrupt, adjust what the guest CPPR should - * be as if we had just fetched that interrupt from HW. - * - * Note: This can only make xc->cppr smaller as the previous - * loop will only exit with hirq != 0 if prio is lower than - * the current xc->cppr. Thus we don't need to re-check xc->mfrr - * for pending IPIs. - */ - if (hirq) - xc->cppr = prio; - /* - * If it was an IPI the HW CPPR might have been lowered too much - * as the HW interrupt we use for IPIs is routed to priority 0. - * - * We re-sync it here. - */ - if (xc->cppr != xc->hw_cppr) { - xc->hw_cppr = xc->cppr; - __x_writeb(xc->cppr, __x_tima + TM_QW1_OS + TM_CPPR); - } - - return hirq; -} - -X_STATIC unsigned long GLUE(X_PFX,h_xirr)(struct kvm_vcpu *vcpu) -{ - struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu; - u8 old_cppr; - u32 hirq; - - pr_devel("H_XIRR\n"); - - xc->GLUE(X_STAT_PFX,h_xirr)++; - - /* First collect pending bits from HW */ - GLUE(X_PFX,ack_pending)(xc); - - pr_devel(" new pending=0x%02x hw_cppr=%d cppr=%d\n", - xc->pending, xc->hw_cppr, xc->cppr); - - /* Grab previous CPPR and reverse map it */ - old_cppr = xive_prio_to_guest(xc->cppr); - - /* Scan for actual interrupts */ - hirq = GLUE(X_PFX,scan_interrupts)(xc, xc->pending, scan_fetch); - - pr_devel(" got hirq=0x%x hw_cppr=%d cppr=%d\n", - hirq, xc->hw_cppr, xc->cppr); - -#ifdef XIVE_RUNTIME_CHECKS - /* That should never hit */ - if (hirq & 0xff000000) - pr_warn("XIVE: Weird guest interrupt number 0x%08x\n", hirq); -#endif - - /* - * XXX We could check if the interrupt is masked here and - * filter it. If we chose to do so, we would need to do: - * - * if (masked) { - * lock(); - * if (masked) { - * old_Q = true; - * hirq = 0; - * } - * unlock(); - * } - */ - - /* Return interrupt and old CPPR in GPR4 */ - vcpu->arch.regs.gpr[4] = hirq | (old_cppr << 24); - - return H_SUCCESS; -} - -X_STATIC unsigned long GLUE(X_PFX,h_ipoll)(struct kvm_vcpu *vcpu, unsigned long server) -{ - struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu; - u8 pending = xc->pending; - u32 hirq; - - pr_devel("H_IPOLL(server=%ld)\n", server); - - xc->GLUE(X_STAT_PFX,h_ipoll)++; - - /* Grab the target VCPU if not the current one */ - if (xc->server_num != server) { - vcpu = kvmppc_xive_find_server(vcpu->kvm, server); - if (!vcpu) - return H_PARAMETER; - xc = vcpu->arch.xive_vcpu; - - /* Scan all priorities */ - pending = 0xff; - } else { - /* Grab pending interrupt if any */ - __be64 qw1 = __x_readq(__x_tima + TM_QW1_OS); - u8 pipr = be64_to_cpu(qw1) & 0xff; - if (pipr < 8) - pending |= 1 << pipr; - } - - hirq = GLUE(X_PFX,scan_interrupts)(xc, pending, scan_poll); - - /* Return interrupt and old CPPR in GPR4 */ - vcpu->arch.regs.gpr[4] = hirq | (xc->cppr << 24); - - return H_SUCCESS; -} - -static void GLUE(X_PFX,push_pending_to_hw)(struct kvmppc_xive_vcpu *xc) -{ - u8 pending, prio; - - pending = xc->pending; - if (xc->mfrr != 0xff) { - if (xc->mfrr < 8) - pending |= 1 << xc->mfrr; - else - pending |= 0x80; - } - if (!pending) - return; - prio = ffs(pending) - 1; - - __x_writeb(prio, __x_tima + TM_SPC_SET_OS_PENDING); -} - -static void GLUE(X_PFX,scan_for_rerouted_irqs)(struct kvmppc_xive *xive, - struct kvmppc_xive_vcpu *xc) -{ - unsigned int prio; - - /* For each priority that is now masked */ - for (prio = xc->cppr; prio < KVMPPC_XIVE_Q_COUNT; prio++) { - struct xive_q *q = &xc->queues[prio]; - struct kvmppc_xive_irq_state *state; - struct kvmppc_xive_src_block *sb; - u32 idx, toggle, entry, irq, hw_num; - struct xive_irq_data *xd; - __be32 *qpage; - u16 src; - - idx = q->idx; - toggle = q->toggle; - qpage = READ_ONCE(q->qpage); - if (!qpage) - continue; - - /* For each interrupt in the queue */ - for (;;) { - entry = be32_to_cpup(qpage + idx); - - /* No more ? */ - if ((entry >> 31) == toggle) - break; - irq = entry & 0x7fffffff; - - /* Skip dummies and IPIs */ - if (irq == XICS_DUMMY || irq == XICS_IPI) - goto next; - sb = kvmppc_xive_find_source(xive, irq, &src); - if (!sb) - goto next; - state = &sb->irq_state[src]; - - /* Has it been rerouted ? */ - if (xc->server_num == state->act_server) - goto next; - - /* - * Allright, it *has* been re-routed, kill it from - * the queue. - */ - qpage[idx] = cpu_to_be32((entry & 0x80000000) | XICS_DUMMY); - - /* Find the HW interrupt */ - kvmppc_xive_select_irq(state, &hw_num, &xd); - - /* If it's not an LSI, set PQ to 11 the EOI will force a resend */ - if (!(xd->flags & XIVE_IRQ_FLAG_LSI)) - GLUE(X_PFX,esb_load)(xd, XIVE_ESB_SET_PQ_11); - - /* EOI the source */ - GLUE(X_PFX,source_eoi)(hw_num, xd); - - next: - idx = (idx + 1) & q->msk; - if (idx == 0) - toggle ^= 1; - } - } -} - -X_STATIC int GLUE(X_PFX,h_cppr)(struct kvm_vcpu *vcpu, unsigned long cppr) -{ - struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu; - struct kvmppc_xive *xive = vcpu->kvm->arch.xive; - u8 old_cppr; - - pr_devel("H_CPPR(cppr=%ld)\n", cppr); - - xc->GLUE(X_STAT_PFX,h_cppr)++; - - /* Map CPPR */ - cppr = xive_prio_from_guest(cppr); - - /* Remember old and update SW state */ - old_cppr = xc->cppr; - xc->cppr = cppr; - - /* - * Order the above update of xc->cppr with the subsequent - * read of xc->mfrr inside push_pending_to_hw() - */ - smp_mb(); - - if (cppr > old_cppr) { - /* - * We are masking less, we need to look for pending things - * to deliver and set VP pending bits accordingly to trigger - * a new interrupt otherwise we might miss MFRR changes for - * which we have optimized out sending an IPI signal. - */ - GLUE(X_PFX,push_pending_to_hw)(xc); - } else { - /* - * We are masking more, we need to check the queue for any - * interrupt that has been routed to another CPU, take - * it out (replace it with the dummy) and retrigger it. - * - * This is necessary since those interrupts may otherwise - * never be processed, at least not until this CPU restores - * its CPPR. - * - * This is in theory racy vs. HW adding new interrupts to - * the queue. In practice this works because the interesting - * cases are when the guest has done a set_xive() to move the - * interrupt away, which flushes the xive, followed by the - * target CPU doing a H_CPPR. So any new interrupt coming into - * the queue must still be routed to us and isn't a source - * of concern. - */ - GLUE(X_PFX,scan_for_rerouted_irqs)(xive, xc); - } - - /* Apply new CPPR */ - xc->hw_cppr = cppr; - __x_writeb(cppr, __x_tima + TM_QW1_OS + TM_CPPR); - - return H_SUCCESS; -} - -X_STATIC int GLUE(X_PFX,h_eoi)(struct kvm_vcpu *vcpu, unsigned long xirr) -{ - struct kvmppc_xive *xive = vcpu->kvm->arch.xive; - struct kvmppc_xive_src_block *sb; - struct kvmppc_xive_irq_state *state; - struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu; - struct xive_irq_data *xd; - u8 new_cppr = xirr >> 24; - u32 irq = xirr & 0x00ffffff, hw_num; - u16 src; - int rc = 0; - - pr_devel("H_EOI(xirr=%08lx)\n", xirr); - - xc->GLUE(X_STAT_PFX,h_eoi)++; - - xc->cppr = xive_prio_from_guest(new_cppr); - - /* - * IPIs are synthetized from MFRR and thus don't need - * any special EOI handling. The underlying interrupt - * used to signal MFRR changes is EOId when fetched from - * the queue. - */ - if (irq == XICS_IPI || irq == 0) { - /* - * This barrier orders the setting of xc->cppr vs. - * subsquent test of xc->mfrr done inside - * scan_interrupts and push_pending_to_hw - */ - smp_mb(); - goto bail; - } - - /* Find interrupt source */ - sb = kvmppc_xive_find_source(xive, irq, &src); - if (!sb) { - pr_devel(" source not found !\n"); - rc = H_PARAMETER; - /* Same as above */ - smp_mb(); - goto bail; - } - state = &sb->irq_state[src]; - kvmppc_xive_select_irq(state, &hw_num, &xd); - - state->in_eoi = true; - - /* - * This barrier orders both setting of in_eoi above vs, - * subsequent test of guest_priority, and the setting - * of xc->cppr vs. subsquent test of xc->mfrr done inside - * scan_interrupts and push_pending_to_hw - */ - smp_mb(); - -again: - if (state->guest_priority == MASKED) { - arch_spin_lock(&sb->lock); - if (state->guest_priority != MASKED) { - arch_spin_unlock(&sb->lock); - goto again; - } - pr_devel(" EOI on saved P...\n"); - - /* Clear old_p, that will cause unmask to perform an EOI */ - state->old_p = false; - - arch_spin_unlock(&sb->lock); - } else { - pr_devel(" EOI on source...\n"); - - /* Perform EOI on the source */ - GLUE(X_PFX,source_eoi)(hw_num, xd); - - /* If it's an emulated LSI, check level and resend */ - if (state->lsi && state->asserted) - __x_writeq(0, __x_trig_page(xd)); - - } - - /* - * This barrier orders the above guest_priority check - * and spin_lock/unlock with clearing in_eoi below. - * - * It also has to be a full mb() as it must ensure - * the MMIOs done in source_eoi() are completed before - * state->in_eoi is visible. - */ - mb(); - state->in_eoi = false; -bail: - - /* Re-evaluate pending IRQs and update HW */ - GLUE(X_PFX,scan_interrupts)(xc, xc->pending, scan_eoi); - GLUE(X_PFX,push_pending_to_hw)(xc); - pr_devel(" after scan pending=%02x\n", xc->pending); - - /* Apply new CPPR */ - xc->hw_cppr = xc->cppr; - __x_writeb(xc->cppr, __x_tima + TM_QW1_OS + TM_CPPR); - - return rc; -} - -X_STATIC int GLUE(X_PFX,h_ipi)(struct kvm_vcpu *vcpu, unsigned long server, - unsigned long mfrr) -{ - struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu; - - pr_devel("H_IPI(server=%08lx,mfrr=%ld)\n", server, mfrr); - - xc->GLUE(X_STAT_PFX,h_ipi)++; - - /* Find target */ - vcpu = kvmppc_xive_find_server(vcpu->kvm, server); - if (!vcpu) - return H_PARAMETER; - xc = vcpu->arch.xive_vcpu; - - /* Locklessly write over MFRR */ - xc->mfrr = mfrr; - - /* - * The load of xc->cppr below and the subsequent MMIO store - * to the IPI must happen after the above mfrr update is - * globally visible so that: - * - * - Synchronize with another CPU doing an H_EOI or a H_CPPR - * updating xc->cppr then reading xc->mfrr. - * - * - The target of the IPI sees the xc->mfrr update - */ - mb(); - - /* Shoot the IPI if most favored than target cppr */ - if (mfrr < xc->cppr) - __x_writeq(0, __x_trig_page(&xc->vp_ipi_data)); - - return H_SUCCESS; -} diff --git a/arch/powerpc/kvm/e500mc.c b/arch/powerpc/kvm/e500mc.c index fa0d8dbbe48411c28703e0577518ed984ad96d66..57e0ad6a2ca3bed7700e569abfb50f9427b25dea 100644 --- a/arch/powerpc/kvm/e500mc.c +++ b/arch/powerpc/kvm/e500mc.c @@ -309,7 +309,7 @@ static int kvmppc_core_vcpu_create_e500mc(struct kvm_vcpu *vcpu) BUILD_BUG_ON(offsetof(struct kvmppc_vcpu_e500, vcpu) != 0); vcpu_e500 = to_e500(vcpu); - /* Invalid PIR value -- this LPID dosn't have valid state on any cpu */ + /* Invalid PIR value -- this LPID doesn't have valid state on any cpu */ vcpu->arch.oldpir = 0xffffffff; err = kvmppc_e500_tlb_init(vcpu_e500); @@ -399,7 +399,6 @@ static int __init kvmppc_e500mc_init(void) * allocator. */ kvmppc_init_lpid(KVMPPC_NR_LPIDS/threads_per_core); - kvmppc_claim_lpid(0); /* host */ r = kvm_init(NULL, sizeof(struct kvmppc_vcpu_e500), 0, THIS_MODULE); if (r) diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c index 533c4232e5abfd926c859fcdfb45c7fee658682a..191992fcb2c29953f35fd2b76f5c48ef45b41641 100644 --- a/arch/powerpc/kvm/powerpc.c +++ b/arch/powerpc/kvm/powerpc.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -2496,41 +2497,37 @@ out: return r; } -static unsigned long lpid_inuse[BITS_TO_LONGS(KVMPPC_NR_LPIDS)]; +static DEFINE_IDA(lpid_inuse); static unsigned long nr_lpids; long kvmppc_alloc_lpid(void) { - long lpid; + int lpid; - do { - lpid = find_first_zero_bit(lpid_inuse, KVMPPC_NR_LPIDS); - if (lpid >= nr_lpids) { + /* The host LPID must always be 0 (allocation starts at 1) */ + lpid = ida_alloc_range(&lpid_inuse, 1, nr_lpids - 1, GFP_KERNEL); + if (lpid < 0) { + if (lpid == -ENOMEM) + pr_err("%s: Out of memory\n", __func__); + else pr_err("%s: No LPIDs free\n", __func__); - return -ENOMEM; - } - } while (test_and_set_bit(lpid, lpid_inuse)); + return -ENOMEM; + } return lpid; } EXPORT_SYMBOL_GPL(kvmppc_alloc_lpid); -void kvmppc_claim_lpid(long lpid) -{ - set_bit(lpid, lpid_inuse); -} -EXPORT_SYMBOL_GPL(kvmppc_claim_lpid); - void kvmppc_free_lpid(long lpid) { - clear_bit(lpid, lpid_inuse); + ida_free(&lpid_inuse, lpid); } EXPORT_SYMBOL_GPL(kvmppc_free_lpid); +/* nr_lpids_param includes the host LPID */ void kvmppc_init_lpid(unsigned long nr_lpids_param) { - nr_lpids = min_t(unsigned long, KVMPPC_NR_LPIDS, nr_lpids_param); - memset(lpid_inuse, 0, sizeof(lpid_inuse)); + nr_lpids = nr_lpids_param; } EXPORT_SYMBOL_GPL(kvmppc_init_lpid); diff --git a/arch/powerpc/kvm/trace_hv.h b/arch/powerpc/kvm/trace_hv.h index 38cd0ed0a6178a5a071d4df376c3697b53433c03..32e2cb5811cc8cd0a977e55ad4ddec31a63c7e2a 100644 --- a/arch/powerpc/kvm/trace_hv.h +++ b/arch/powerpc/kvm/trace_hv.h @@ -409,9 +409,9 @@ TRACE_EVENT(kvmppc_run_core, ); TRACE_EVENT(kvmppc_vcore_blocked, - TP_PROTO(struct kvmppc_vcore *vc, int where), + TP_PROTO(struct kvm_vcpu *vcpu, int where), - TP_ARGS(vc, where), + TP_ARGS(vcpu, where), TP_STRUCT__entry( __field(int, n_runnable) @@ -421,8 +421,8 @@ TRACE_EVENT(kvmppc_vcore_blocked, ), TP_fast_assign( - __entry->runner_vcpu = vc->runner->vcpu_id; - __entry->n_runnable = vc->n_runnable; + __entry->runner_vcpu = vcpu->vcpu_id; + __entry->n_runnable = vcpu->arch.vcore->n_runnable; __entry->where = where; __entry->tgid = current->tgid; ), diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile index 5d1881d2e39a7eb52fe973dae6da474b40b8c59d..8560c912186dfcc84cea889442359571ef9e2e22 100644 --- a/arch/powerpc/lib/Makefile +++ b/arch/powerpc/lib/Makefile @@ -13,6 +13,9 @@ CFLAGS_REMOVE_feature-fixups.o = $(CC_FLAGS_FTRACE) KASAN_SANITIZE_code-patching.o := n KASAN_SANITIZE_feature-fixups.o := n +# restart_table.o contains functions called in the NMI interrupt path +# which can be in real mode. Disable KASAN. +KASAN_SANITIZE_restart_table.o := n ifdef CONFIG_KASAN CFLAGS_code-patching.o += -DDISABLE_BRANCH_PROFILING diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-patching.c index 00c68e7fb11e4cd13b20c85c8783dd921168f86f..6edf0697a526b22c91b08b05a34c169726fae603 100644 --- a/arch/powerpc/lib/code-patching.c +++ b/arch/powerpc/lib/code-patching.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -32,7 +33,7 @@ static int __patch_instruction(u32 *exec_addr, ppc_inst_t instr, u32 *patch_addr return 0; failed: - return -EFAULT; + return -EPERM; } int raw_patch_instruction(u32 *addr, ppc_inst_t instr) @@ -78,6 +79,8 @@ static int text_area_cpu_down(unsigned int cpu) return 0; } +static __ro_after_init DEFINE_STATIC_KEY_FALSE(poking_init_done); + /* * Although BUG_ON() is rude, in this case it should only happen if ENOMEM, and * we judge it as being preferable to a kernel that will crash later when @@ -88,6 +91,7 @@ void __init poking_init(void) BUG_ON(!cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "powerpc/text_poke:online", text_area_cpu_up, text_area_cpu_down)); + static_branch_enable(&poking_init_done); } /* @@ -97,7 +101,7 @@ static int map_patch_area(void *addr, unsigned long text_poke_addr) { unsigned long pfn; - if (is_vmalloc_or_module_addr(addr)) + if (IS_ENABLED(CONFIG_MODULES) && is_vmalloc_or_module_addr(addr)) pfn = vmalloc_to_pfn(addr); else pfn = __pa_symbol(addr) >> PAGE_SHIFT; @@ -170,7 +174,7 @@ static int do_patch_instruction(u32 *addr, ppc_inst_t instr) * when text_poke_area is not ready, but we still need * to allow patching. We just do the plain old patching */ - if (!this_cpu_read(text_poke_area)) + if (!static_branch_likely(&poking_init_done)) return raw_patch_instruction(addr, instr); local_irq_save(flags); @@ -188,10 +192,12 @@ static int do_patch_instruction(u32 *addr, ppc_inst_t instr) #endif /* CONFIG_STRICT_KERNEL_RWX */ +__ro_after_init DEFINE_STATIC_KEY_FALSE(init_mem_is_free); + int patch_instruction(u32 *addr, ppc_inst_t instr) { /* Make sure we aren't patching a freed init section */ - if (system_state >= SYSTEM_FREEING_INITMEM && init_section_contains(addr, 4)) + if (static_branch_likely(&init_mem_is_free) && init_section_contains(addr, 4)) return 0; return do_patch_instruction(addr, instr); @@ -208,33 +214,6 @@ int patch_branch(u32 *addr, unsigned long target, int flags) return patch_instruction(addr, instr); } -bool is_offset_in_branch_range(long offset) -{ - /* - * Powerpc branch instruction is : - * - * 0 6 30 31 - * +---------+----------------+---+---+ - * | opcode | LI |AA |LK | - * +---------+----------------+---+---+ - * Where AA = 0 and LK = 0 - * - * LI is a signed 24 bits integer. The real branch offset is computed - * by: imm32 = SignExtend(LI:'0b00', 32); - * - * So the maximum forward branch should be: - * (0x007fffff << 2) = 0x01fffffc = 0x1fffffc - * The maximum backward branch should be: - * (0xff800000 << 2) = 0xfe000000 = -0x2000000 - */ - return (offset >= -0x2000000 && offset <= 0x1fffffc && !(offset & 0x3)); -} - -bool is_offset_in_cond_branch_range(long offset) -{ - return offset >= -0x8000 && offset <= 0x7fff && !(offset & 0x3); -} - /* * Helper to check if a given instruction is a conditional branch * Derived from the conditional checks in analyse_instr() @@ -257,26 +236,6 @@ bool is_conditional_branch(ppc_inst_t instr) } NOKPROBE_SYMBOL(is_conditional_branch); -int create_branch(ppc_inst_t *instr, const u32 *addr, - unsigned long target, int flags) -{ - long offset; - - *instr = ppc_inst(0); - offset = target; - if (! (flags & BRANCH_ABSOLUTE)) - offset = offset - (unsigned long)addr; - - /* Check we can represent the target in the instruction format */ - if (!is_offset_in_branch_range(offset)) - return 1; - - /* Mask out the flags and target, so they don't step on each other. */ - *instr = ppc_inst(0x48000000 | (flags & 0x3) | (offset & 0x03FFFFFC)); - - return 0; -} - int create_cond_branch(ppc_inst_t *instr, const u32 *addr, unsigned long target, int flags) { diff --git a/arch/powerpc/lib/feature-fixups.c b/arch/powerpc/lib/feature-fixups.c index 343a78826035e8cb9f530725ded9f85496e6a2ba..993d3f31832af676303ace05ff3443e4cbe930f6 100644 --- a/arch/powerpc/lib/feature-fixups.c +++ b/arch/powerpc/lib/feature-fixups.c @@ -451,7 +451,7 @@ static int __do_rfi_flush_fixups(void *data) if (types & L1D_FLUSH_FALLBACK) /* b .+16 to fallback flush */ - instrs[0] = PPC_INST_BRANCH | 16; + instrs[0] = PPC_RAW_BRANCH(16); i = 0; if (types & L1D_FLUSH_ORI) { diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c index 6f79bde6d6c22955098258553e2af503429af741..398b5694aeb7065aae5e536a4e00a5a7e9efce3f 100644 --- a/arch/powerpc/lib/sstep.c +++ b/arch/powerpc/lib/sstep.c @@ -15,9 +15,6 @@ #include #include -extern char system_call_common[]; -extern char system_call_vectored_emulate[]; - #ifdef CONFIG_PPC64 /* Bits in SRR1 that are copied from MSR */ #define MSR_MASK 0xffffffff87c0ffffUL @@ -1166,7 +1163,7 @@ static nokprobe_inline void add_with_carry(const struct pt_regs *regs, if (carry_in) ++val; - op->type = COMPUTE + SETREG + SETXER; + op->type = COMPUTE | SETREG | SETXER; op->reg = rd; op->val = val; val = truncate_if_32bit(regs->msr, val); @@ -1187,7 +1184,7 @@ static nokprobe_inline void do_cmp_signed(const struct pt_regs *regs, { unsigned int crval, shift; - op->type = COMPUTE + SETCC; + op->type = COMPUTE | SETCC; crval = (regs->xer >> 31) & 1; /* get SO bit */ if (v1 < v2) crval |= 8; @@ -1206,7 +1203,7 @@ static nokprobe_inline void do_cmp_unsigned(const struct pt_regs *regs, { unsigned int crval, shift; - op->type = COMPUTE + SETCC; + op->type = COMPUTE | SETCC; crval = (regs->xer >> 31) & 1; /* get SO bit */ if (v1 < v2) crval |= 8; @@ -1376,7 +1373,6 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, if (branch_taken(word, regs, op)) op->type |= BRTAKEN; return 1; -#ifdef CONFIG_PPC64 case 17: /* sc */ if ((word & 0xfe2) == 2) op->type = SYSCALL; @@ -1388,7 +1384,6 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, } else op->type = UNKNOWN; return 0; -#endif case 18: /* b */ op->type = BRANCH | BRTAKEN; imm = word & 0x03fffffc; @@ -3643,43 +3638,22 @@ int emulate_step(struct pt_regs *regs, ppc_inst_t instr) regs_set_return_msr(regs, (regs->msr & ~op.val) | (val & op.val)); goto instr_done; -#ifdef CONFIG_PPC64 case SYSCALL: /* sc */ /* - * N.B. this uses knowledge about how the syscall - * entry code works. If that is changed, this will - * need to be changed also. + * Per ISA v3.1, section 7.5.15 'Trace Interrupt', we can't + * single step a system call instruction: + * + * Successful completion for an instruction means that the + * instruction caused no other interrupt. Thus a Trace + * interrupt never occurs for a System Call or System Call + * Vectored instruction, or for a Trap instruction that + * traps. */ - if (IS_ENABLED(CONFIG_PPC_FAST_ENDIAN_SWITCH) && - cpu_has_feature(CPU_FTR_REAL_LE) && - regs->gpr[0] == 0x1ebe) { - regs_set_return_msr(regs, regs->msr ^ MSR_LE); - goto instr_done; - } - regs->gpr[9] = regs->gpr[13]; - regs->gpr[10] = MSR_KERNEL; - regs->gpr[11] = regs->nip + 4; - regs->gpr[12] = regs->msr & MSR_MASK; - regs->gpr[13] = (unsigned long) get_paca(); - regs_set_return_ip(regs, (unsigned long) &system_call_common); - regs_set_return_msr(regs, MSR_KERNEL); - return 1; - -#ifdef CONFIG_PPC_BOOK3S_64 + return -1; case SYSCALL_VECTORED_0: /* scv 0 */ - regs->gpr[9] = regs->gpr[13]; - regs->gpr[10] = MSR_KERNEL; - regs->gpr[11] = regs->nip + 4; - regs->gpr[12] = regs->msr & MSR_MASK; - regs->gpr[13] = (unsigned long) get_paca(); - regs_set_return_ip(regs, (unsigned long) &system_call_vectored_emulate); - regs_set_return_msr(regs, MSR_KERNEL); - return 1; -#endif - + return -1; case RFI: return -1; -#endif } return 0; diff --git a/arch/powerpc/mm/Makefile b/arch/powerpc/mm/Makefile index df8172da2301b767d70146f31082e30350019926..503a6e249940cae8ca431901a735ed4030c194f5 100644 --- a/arch/powerpc/mm/Makefile +++ b/arch/powerpc/mm/Makefile @@ -5,7 +5,7 @@ ccflags-$(CONFIG_PPC64) := $(NO_MINIMAL_TOC) -obj-y := fault.o mem.o pgtable.o mmap.o maccess.o pageattr.o \ +obj-y := fault.o mem.o pgtable.o maccess.o pageattr.o \ init_$(BITS).o pgtable_$(BITS).o \ pgtable-frag.o ioremap.o ioremap_$(BITS).o \ init-common.o mmu_context.o drmem.o \ @@ -14,7 +14,6 @@ obj-$(CONFIG_PPC_MMU_NOHASH) += nohash/ obj-$(CONFIG_PPC_BOOK3S_32) += book3s32/ obj-$(CONFIG_PPC_BOOK3S_64) += book3s64/ obj-$(CONFIG_NUMA) += numa.o -obj-$(CONFIG_PPC_MM_SLICES) += slice.o obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o obj-$(CONFIG_NOT_COHERENT_CACHE) += dma-noncoherent.o obj-$(CONFIG_PPC_COPRO_BASE) += copro_fault.o diff --git a/arch/powerpc/mm/book3s32/mmu.c b/arch/powerpc/mm/book3s32/mmu.c index 203735caf6915ad6b5f49161f6a82e7e48d836cd..49a737fbbd1893627718d99638314c42d1b26f6b 100644 --- a/arch/powerpc/mm/book3s32/mmu.c +++ b/arch/powerpc/mm/book3s32/mmu.c @@ -23,7 +23,6 @@ #include #include -#include #include #include #include diff --git a/arch/powerpc/mm/book3s64/Makefile b/arch/powerpc/mm/book3s64/Makefile index 2d50cac499c5d7097db13c24804d5ecd2551da97..cad2abc1730fa1b3e32704b7f967e909243c2e3f 100644 --- a/arch/powerpc/mm/book3s64/Makefile +++ b/arch/powerpc/mm/book3s64/Makefile @@ -5,7 +5,7 @@ ccflags-y := $(NO_MINIMAL_TOC) obj-y += mmu_context.o pgtable.o trace.o ifdef CONFIG_PPC_64S_HASH_MMU CFLAGS_REMOVE_slb.o = $(CC_FLAGS_FTRACE) -obj-y += hash_pgtable.o hash_utils.o hash_tlb.o slb.o +obj-y += hash_pgtable.o hash_utils.o hash_tlb.o slb.o slice.o obj-$(CONFIG_PPC_HASH_MMU_NATIVE) += hash_native.o obj-$(CONFIG_PPC_4K_PAGES) += hash_4k.o obj-$(CONFIG_PPC_64K_PAGES) += hash_64k.o @@ -24,3 +24,12 @@ obj-$(CONFIG_PPC_PKEY) += pkeys.o # Instrumenting the SLB fault path can lead to duplicate SLB entries KCOV_INSTRUMENT_slb.o := n + +# Parts of these can run in real mode and therefore are +# not safe with the current outline KASAN implementation +KASAN_SANITIZE_mmu_context.o := n +KASAN_SANITIZE_pgtable.o := n +KASAN_SANITIZE_radix_pgtable.o := n +KASAN_SANITIZE_radix_tlb.o := n +KASAN_SANITIZE_slb.o := n +KASAN_SANITIZE_pkeys.o := n diff --git a/arch/powerpc/mm/book3s64/hash_pgtable.c b/arch/powerpc/mm/book3s64/hash_pgtable.c index 7ce8914992e3f5fdd14f463144bbf91cf1606433..2e0cad5817bafe7480e556e421819f69bbf90465 100644 --- a/arch/powerpc/mm/book3s64/hash_pgtable.c +++ b/arch/powerpc/mm/book3s64/hash_pgtable.c @@ -377,7 +377,7 @@ int hash__has_transparent_hugepage(void) if (mmu_psize_defs[MMU_PAGE_16M].shift != PMD_SHIFT) return 0; /* - * We need to make sure that we support 16MB hugepage in a segement + * We need to make sure that we support 16MB hugepage in a segment * with base page size 64K or 4K. We only enable THP with a PAGE_SIZE * of 64K. */ diff --git a/arch/powerpc/mm/book3s64/hash_utils.c b/arch/powerpc/mm/book3s64/hash_utils.c index 985cabdd7f67999ea11604e3e657edf0ccea7dca..fc92613dc2bfde5b896c05eede4811ab0a1d00d4 100644 --- a/arch/powerpc/mm/book3s64/hash_utils.c +++ b/arch/powerpc/mm/book3s64/hash_utils.c @@ -37,6 +37,9 @@ #include #include #include +#include +#include +#include #include #include @@ -46,7 +49,6 @@ #include #include #include -#include #include #include #include @@ -1264,7 +1266,6 @@ unsigned int hash_page_do_lazy_icache(unsigned int pp, pte_t pte, int trap) return pp; } -#ifdef CONFIG_PPC_MM_SLICES static unsigned int get_paca_psize(unsigned long addr) { unsigned char *psizes; @@ -1281,12 +1282,6 @@ static unsigned int get_paca_psize(unsigned long addr) return (psizes[index >> 1] >> (mask_index * 4)) & 0xF; } -#else -unsigned int get_paca_psize(unsigned long addr) -{ - return get_paca()->mm_ctx_user_psize; -} -#endif /* * Demote a segment to using 4k pages. @@ -1343,7 +1338,7 @@ static int subpage_protection(struct mm_struct *mm, unsigned long ea) spp >>= 30 - 2 * ((ea >> 12) & 0xf); /* - * 0 -> full premission + * 0 -> full permission * 1 -> Read only * 2 -> no access. * We return the flag that need to be cleared. @@ -1664,7 +1659,7 @@ DEFINE_INTERRUPT_HANDLER(do_hash_fault) err = hash_page_mm(mm, ea, access, TRAP(regs), flags); if (unlikely(err < 0)) { - // failed to instert a hash PTE due to an hypervisor error + // failed to insert a hash PTE due to an hypervisor error if (user_mode(regs)) { if (IS_ENABLED(CONFIG_PPC_SUBPAGE_PROT) && err == -2) _exception(SIGSEGV, regs, SEGV_ACCERR, ea); @@ -1680,7 +1675,6 @@ DEFINE_INTERRUPT_HANDLER(do_hash_fault) } } -#ifdef CONFIG_PPC_MM_SLICES static bool should_hash_preload(struct mm_struct *mm, unsigned long ea) { int psize = get_slice_psize(mm, ea); @@ -1697,12 +1691,6 @@ static bool should_hash_preload(struct mm_struct *mm, unsigned long ea) return true; } -#else -static bool should_hash_preload(struct mm_struct *mm, unsigned long ea) -{ - return true; -} -#endif static void hash_preload(struct mm_struct *mm, pte_t *ptep, unsigned long ea, bool is_exec, unsigned long trap) @@ -2147,3 +2135,20 @@ void __init print_system_hash_info(void) if (htab_hash_mask) pr_info("htab_hash_mask = 0x%lx\n", htab_hash_mask); } + +unsigned long arch_randomize_brk(struct mm_struct *mm) +{ + /* + * If we are using 1TB segments and we are allowed to randomise + * the heap, we can put it above 1TB so it is backed by a 1TB + * segment. Otherwise the heap will be in the bottom 1TB + * which always uses 256MB segments and this may result in a + * performance penalty. + */ + if (is_32bit_task()) + return randomize_page(mm->brk, SZ_32M); + else if (!radix_enabled() && mmu_highuser_ssize == MMU_SEGSIZE_1T) + return randomize_page(max_t(unsigned long, mm->brk, SZ_1T), SZ_1G); + else + return randomize_page(mm->brk, SZ_1G); +} diff --git a/arch/powerpc/mm/book3s64/iommu_api.c b/arch/powerpc/mm/book3s64/iommu_api.c index cd18e94d0843f5d5a28ffc13d637201e83a27fb1..7fcfba162e0d3400f62a190648522b21a09d3ece 100644 --- a/arch/powerpc/mm/book3s64/iommu_api.c +++ b/arch/powerpc/mm/book3s64/iommu_api.c @@ -305,24 +305,6 @@ struct mm_iommu_table_group_mem_t *mm_iommu_lookup(struct mm_struct *mm, } EXPORT_SYMBOL_GPL(mm_iommu_lookup); -struct mm_iommu_table_group_mem_t *mm_iommu_lookup_rm(struct mm_struct *mm, - unsigned long ua, unsigned long size) -{ - struct mm_iommu_table_group_mem_t *mem, *ret = NULL; - - list_for_each_entry_lockless(mem, &mm->context.iommu_group_mem_list, - next) { - if ((mem->ua <= ua) && - (ua + size <= mem->ua + - (mem->entries << PAGE_SHIFT))) { - ret = mem; - break; - } - } - - return ret; -} - struct mm_iommu_table_group_mem_t *mm_iommu_get(struct mm_struct *mm, unsigned long ua, unsigned long entries) { @@ -369,56 +351,6 @@ long mm_iommu_ua_to_hpa(struct mm_iommu_table_group_mem_t *mem, } EXPORT_SYMBOL_GPL(mm_iommu_ua_to_hpa); -long mm_iommu_ua_to_hpa_rm(struct mm_iommu_table_group_mem_t *mem, - unsigned long ua, unsigned int pageshift, unsigned long *hpa) -{ - const long entry = (ua - mem->ua) >> PAGE_SHIFT; - unsigned long *pa; - - if (entry >= mem->entries) - return -EFAULT; - - if (pageshift > mem->pageshift) - return -EFAULT; - - if (!mem->hpas) { - *hpa = mem->dev_hpa + (ua - mem->ua); - return 0; - } - - pa = (void *) vmalloc_to_phys(&mem->hpas[entry]); - if (!pa) - return -EFAULT; - - *hpa = (*pa & MM_IOMMU_TABLE_GROUP_PAGE_MASK) | (ua & ~PAGE_MASK); - - return 0; -} - -extern void mm_iommu_ua_mark_dirty_rm(struct mm_struct *mm, unsigned long ua) -{ - struct mm_iommu_table_group_mem_t *mem; - long entry; - void *va; - unsigned long *pa; - - mem = mm_iommu_lookup_rm(mm, ua, PAGE_SIZE); - if (!mem) - return; - - if (mem->dev_hpa != MM_IOMMU_TABLE_INVALID_HPA) - return; - - entry = (ua - mem->ua) >> PAGE_SHIFT; - va = &mem->hpas[entry]; - - pa = (void *) vmalloc_to_phys(va); - if (!pa) - return; - - *pa |= MM_IOMMU_TABLE_GROUP_PAGE_DIRTY; -} - bool mm_iommu_is_devmem(struct mm_struct *mm, unsigned long hpa, unsigned int pageshift, unsigned long *size) { diff --git a/arch/powerpc/mm/book3s64/pgtable.c b/arch/powerpc/mm/book3s64/pgtable.c index 8b474ab32f675aa32ce85eb491d3f800f5059076..7b9966402b25bc4e26b5fdc300e54932b367bd8e 100644 --- a/arch/powerpc/mm/book3s64/pgtable.c +++ b/arch/powerpc/mm/book3s64/pgtable.c @@ -332,7 +332,7 @@ static pmd_t *__alloc_for_pmdcache(struct mm_struct *mm) spin_lock(&mm->page_table_lock); /* * If we find pgtable_page set, we return - * the allocated page with single fragement + * the allocated page with single fragment * count. */ if (likely(!mm->context.pmd_frag)) { diff --git a/arch/powerpc/mm/book3s64/radix_hugetlbpage.c b/arch/powerpc/mm/book3s64/radix_hugetlbpage.c index 23d3e08911d3d5b4e7f69af189902ac4d59a2900..d2fb776febb4a030af9df93db5f027d8b8ddc07e 100644 --- a/arch/powerpc/mm/book3s64/radix_hugetlbpage.c +++ b/arch/powerpc/mm/book3s64/radix_hugetlbpage.c @@ -41,61 +41,6 @@ void radix__flush_hugetlb_tlb_range(struct vm_area_struct *vma, unsigned long st radix__flush_tlb_range_psize(vma->vm_mm, start, end, psize); } -/* - * A vairant of hugetlb_get_unmapped_area doing topdown search - * FIXME!! should we do as x86 does or non hugetlb area does ? - * ie, use topdown or not based on mmap_is_legacy check ? - */ -unsigned long -radix__hugetlb_get_unmapped_area(struct file *file, unsigned long addr, - unsigned long len, unsigned long pgoff, - unsigned long flags) -{ - struct mm_struct *mm = current->mm; - struct vm_area_struct *vma; - struct hstate *h = hstate_file(file); - int fixed = (flags & MAP_FIXED); - unsigned long high_limit; - struct vm_unmapped_area_info info; - - high_limit = DEFAULT_MAP_WINDOW; - if (addr >= high_limit || (fixed && (addr + len > high_limit))) - high_limit = TASK_SIZE; - - if (len & ~huge_page_mask(h)) - return -EINVAL; - if (len > high_limit) - return -ENOMEM; - - if (fixed) { - if (addr > high_limit - len) - return -ENOMEM; - if (prepare_hugepage_range(file, addr, len)) - return -EINVAL; - return addr; - } - - if (addr) { - addr = ALIGN(addr, huge_page_size(h)); - vma = find_vma(mm, addr); - if (high_limit - len >= addr && addr >= mmap_min_addr && - (!vma || addr + len <= vm_start_gap(vma))) - return addr; - } - /* - * We are always doing an topdown search here. Slice code - * does that too. - */ - info.flags = VM_UNMAPPED_AREA_TOPDOWN; - info.length = len; - info.low_limit = max(PAGE_SIZE, mmap_min_addr); - info.high_limit = mm->mmap_base + (high_limit - DEFAULT_MAP_WINDOW); - info.align_mask = PAGE_MASK & ~huge_page_mask(h); - info.align_offset = 0; - - return vm_unmapped_area(&info); -} - void radix__huge_ptep_modify_prot_commit(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep, pte_t old_pte, pte_t pte) diff --git a/arch/powerpc/mm/book3s64/radix_pgtable.c b/arch/powerpc/mm/book3s64/radix_pgtable.c index def04631a74d525322170fb36e06dc10d2b4b09e..db2f3d193448176fe2c3c142795a3fd3cc466204 100644 --- a/arch/powerpc/mm/book3s64/radix_pgtable.c +++ b/arch/powerpc/mm/book3s64/radix_pgtable.c @@ -359,7 +359,7 @@ static void __init radix_init_pgtable(void) if (!cpu_has_feature(CPU_FTR_HVMODE) && cpu_has_feature(CPU_FTR_P9_RADIX_PREFETCH_BUG)) { /* - * Older versions of KVM on these machines perfer if the + * Older versions of KVM on these machines prefer if the * guest only uses the low 19 PID bits. */ mmu_pid_bits = 19; diff --git a/arch/powerpc/mm/book3s64/radix_tlb.c b/arch/powerpc/mm/book3s64/radix_tlb.c index 7724af19ed7e68da9e4fd23767359b098e6832bf..dda51fef2d2ec4e10a1e15aa33e27afc8010c860 100644 --- a/arch/powerpc/mm/book3s64/radix_tlb.c +++ b/arch/powerpc/mm/book3s64/radix_tlb.c @@ -397,7 +397,7 @@ static inline void _tlbie_pid(unsigned long pid, unsigned long ric) /* * Workaround the fact that the "ric" argument to __tlbie_pid - * must be a compile-time contraint to match the "i" constraint + * must be a compile-time constraint to match the "i" constraint * in the asm statement. */ switch (ric) { diff --git a/arch/powerpc/mm/book3s64/slb.c b/arch/powerpc/mm/book3s64/slb.c index 81091b9587f6206e6857d7f3b5e8d88e64a7d737..6956f637a38c1062c05081bc3ad045b321563ddd 100644 --- a/arch/powerpc/mm/book3s64/slb.c +++ b/arch/powerpc/mm/book3s64/slb.c @@ -347,7 +347,7 @@ void slb_setup_new_exec(void) /* * We have no good place to clear the slb preload cache on exec, * flush_thread is about the earliest arch hook but that happens - * after we switch to the mm and have aleady preloaded the SLBEs. + * after we switch to the mm and have already preloaded the SLBEs. * * For the most part that's probably okay to use entries from the * previous exec, they will age out if unused. It may turn out to @@ -615,7 +615,7 @@ static void slb_cache_update(unsigned long esid_data) } else { /* * Our cache is full and the current cache content strictly - * doesn't indicate the active SLB conents. Bump the ptr + * doesn't indicate the active SLB contents. Bump the ptr * so that switch_slb() will ignore the cache. */ local_paca->slb_cache_ptr = SLB_CACHE_ENTRIES + 1; diff --git a/arch/powerpc/mm/slice.c b/arch/powerpc/mm/book3s64/slice.c similarity index 91% rename from arch/powerpc/mm/slice.c rename to arch/powerpc/mm/book3s64/slice.c index f42711f865f3f444308423a898340d211e049553..c0b58afb9a47628973b315d013994834048e9feb 100644 --- a/arch/powerpc/mm/slice.c +++ b/arch/powerpc/mm/book3s64/slice.c @@ -276,20 +276,18 @@ static bool slice_scan_available(unsigned long addr, } static unsigned long slice_find_area_bottomup(struct mm_struct *mm, - unsigned long len, + unsigned long addr, unsigned long len, const struct slice_mask *available, int psize, unsigned long high_limit) { int pshift = max_t(int, mmu_psize_defs[psize].shift, PAGE_SHIFT); - unsigned long addr, found, next_end; + unsigned long found, next_end; struct vm_unmapped_area_info info; info.flags = 0; info.length = len; info.align_mask = PAGE_MASK & ((1ul << pshift) - 1); info.align_offset = 0; - - addr = TASK_UNMAPPED_BASE; /* * Check till the allow max value for this mmap request */ @@ -322,12 +320,12 @@ static unsigned long slice_find_area_bottomup(struct mm_struct *mm, } static unsigned long slice_find_area_topdown(struct mm_struct *mm, - unsigned long len, + unsigned long addr, unsigned long len, const struct slice_mask *available, int psize, unsigned long high_limit) { int pshift = max_t(int, mmu_psize_defs[psize].shift, PAGE_SHIFT); - unsigned long addr, found, prev; + unsigned long found, prev; struct vm_unmapped_area_info info; unsigned long min_addr = max(PAGE_SIZE, mmap_min_addr); @@ -335,8 +333,6 @@ static unsigned long slice_find_area_topdown(struct mm_struct *mm, info.length = len; info.align_mask = PAGE_MASK & ((1ul << pshift) - 1); info.align_offset = 0; - - addr = mm->mmap_base; /* * If we are trying to allocate above DEFAULT_MAP_WINDOW * Add the different to the mmap_base. @@ -377,7 +373,7 @@ static unsigned long slice_find_area_topdown(struct mm_struct *mm, * can happen with large stack limits and large mmap() * allocations. */ - return slice_find_area_bottomup(mm, len, available, psize, high_limit); + return slice_find_area_bottomup(mm, TASK_UNMAPPED_BASE, len, available, psize, high_limit); } @@ -386,9 +382,9 @@ static unsigned long slice_find_area(struct mm_struct *mm, unsigned long len, int topdown, unsigned long high_limit) { if (topdown) - return slice_find_area_topdown(mm, len, mask, psize, high_limit); + return slice_find_area_topdown(mm, mm->mmap_base, len, mask, psize, high_limit); else - return slice_find_area_bottomup(mm, len, mask, psize, high_limit); + return slice_find_area_bottomup(mm, mm->mmap_base, len, mask, psize, high_limit); } static inline void slice_copy_mask(struct slice_mask *dst, @@ -639,6 +635,32 @@ return_addr: } EXPORT_SYMBOL_GPL(slice_get_unmapped_area); +unsigned long arch_get_unmapped_area(struct file *filp, + unsigned long addr, + unsigned long len, + unsigned long pgoff, + unsigned long flags) +{ + if (radix_enabled()) + return generic_get_unmapped_area(filp, addr, len, pgoff, flags); + + return slice_get_unmapped_area(addr, len, flags, + mm_ctx_user_psize(¤t->mm->context), 0); +} + +unsigned long arch_get_unmapped_area_topdown(struct file *filp, + const unsigned long addr0, + const unsigned long len, + const unsigned long pgoff, + const unsigned long flags) +{ + if (radix_enabled()) + return generic_get_unmapped_area_topdown(filp, addr0, len, pgoff, flags); + + return slice_get_unmapped_area(addr0, len, flags, + mm_ctx_user_psize(¤t->mm->context), 1); +} + unsigned int notrace get_slice_psize(struct mm_struct *mm, unsigned long addr) { unsigned char *psizes; @@ -692,7 +714,6 @@ void slice_init_new_context_exec(struct mm_struct *mm) bitmap_fill(mask->high_slices, SLICE_NUM_HIGH); } -#ifdef CONFIG_PPC_BOOK3S_64 void slice_setup_new_exec(void) { struct mm_struct *mm = current->mm; @@ -704,7 +725,6 @@ void slice_setup_new_exec(void) mm_ctx_set_slb_addr_limit(&mm->context, DEFAULT_MAP_WINDOW); } -#endif void slice_set_range_psize(struct mm_struct *mm, unsigned long start, unsigned long len, unsigned int psize) @@ -759,4 +779,29 @@ int slice_is_hugepage_only_range(struct mm_struct *mm, unsigned long addr, return !slice_check_range_fits(mm, maskp, addr, len); } + +unsigned long vma_mmu_pagesize(struct vm_area_struct *vma) +{ + /* With radix we don't use slice, so derive it from vma*/ + if (radix_enabled()) + return vma_kernel_pagesize(vma); + + return 1UL << mmu_psize_to_shift(get_slice_psize(vma->vm_mm, vma->vm_start)); +} + +static int file_to_psize(struct file *file) +{ + struct hstate *hstate = hstate_file(file); + return shift_to_mmu_psize(huge_page_shift(hstate)); +} + +unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr, + unsigned long len, unsigned long pgoff, + unsigned long flags) +{ + if (radix_enabled()) + return generic_hugetlb_get_unmapped_area(file, addr, len, pgoff, flags); + + return slice_get_unmapped_area(addr, len, flags, file_to_psize(file), 1); +} #endif diff --git a/arch/powerpc/mm/cacheflush.c b/arch/powerpc/mm/cacheflush.c index 63363787e0007607ae4ee10ed9f0b39df2ec6fc7..0e9b4879c0f9eae2764678d016071d259b559928 100644 --- a/arch/powerpc/mm/cacheflush.c +++ b/arch/powerpc/mm/cacheflush.c @@ -12,7 +12,7 @@ static inline bool flush_coherent_icache(void) /* * For a snooping icache, we still need a dummy icbi to purge all the * prefetched instructions from the ifetch buffers. We also need a sync - * before the icbi to order the the actual stores to memory that might + * before the icbi to order the actual stores to memory that might * have modified instructions with the icbi. */ if (cpu_has_feature(CPU_FTR_COHERENT_ICACHE)) { diff --git a/arch/powerpc/mm/drmem.c b/arch/powerpc/mm/drmem.c index 22197b18d85e3eb02823c3c4aa5bf0d22b7b42cc..2369d1bf2411e741713aba07ea419af2a9bb617c 100644 --- a/arch/powerpc/mm/drmem.c +++ b/arch/powerpc/mm/drmem.c @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include static int n_root_addr_cells, n_root_size_cells; diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c index b642a5a8668fb9233f6d5ced228537d0bbfcdd3e..b282af39fcf671ec7c8aa736c248037dea2ccd67 100644 --- a/arch/powerpc/mm/hugetlbpage.c +++ b/arch/powerpc/mm/hugetlbpage.c @@ -542,40 +542,6 @@ retry: return page; } -#ifdef HAVE_ARCH_HUGETLB_UNMAPPED_AREA -static inline int file_to_psize(struct file *file) -{ - struct hstate *hstate = hstate_file(file); - return shift_to_mmu_psize(huge_page_shift(hstate)); -} - -unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr, - unsigned long len, unsigned long pgoff, - unsigned long flags) -{ -#ifdef CONFIG_PPC_RADIX_MMU - if (radix_enabled()) - return radix__hugetlb_get_unmapped_area(file, addr, len, - pgoff, flags); -#endif -#ifdef CONFIG_PPC_MM_SLICES - return slice_get_unmapped_area(addr, len, flags, file_to_psize(file), 1); -#endif - BUG(); -} -#endif - -unsigned long vma_mmu_pagesize(struct vm_area_struct *vma) -{ - /* With radix we don't use slice, so derive it from vma*/ - if (IS_ENABLED(CONFIG_PPC_MM_SLICES) && !radix_enabled()) { - unsigned int psize = get_slice_psize(vma->vm_mm, vma->vm_start); - - return 1UL << mmu_psize_to_shift(psize); - } - return vma_kernel_pagesize(vma); -} - bool __init arch_hugetlb_valid_size(unsigned long size) { int shift = __ffs(size); diff --git a/arch/powerpc/mm/init_32.c b/arch/powerpc/mm/init_32.c index 3d690be48e845e303f448e4da8d03ecb7d251321..693a3a7a9463fcede56c433f3e44f075c43c1ae0 100644 --- a/arch/powerpc/mm/init_32.c +++ b/arch/powerpc/mm/init_32.c @@ -29,7 +29,6 @@ #include #include -#include #include #include #include diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c index 83c0ee9fbf05bc9ac7f72da02499065a61877cdf..05b0d584e50b82a1ded312baa1ba9a84d50de8ca 100644 --- a/arch/powerpc/mm/init_64.c +++ b/arch/powerpc/mm/init_64.c @@ -111,7 +111,7 @@ static int __meminit vmemmap_populated(unsigned long vmemmap_addr, int vmemmap_m } /* - * vmemmap virtual address space management does not have a traditonal page + * vmemmap virtual address space management does not have a traditional page * table to track which virtual struct pages are backed by physical mapping. * The virtual to physical mappings are tracked in a simple linked list * format. 'vmemmap_list' maintains the entire vmemmap physical mapping at @@ -128,7 +128,7 @@ static struct vmemmap_backing *next; /* * The same pointer 'next' tracks individual chunks inside the allocated - * full page during the boot time and again tracks the freeed nodes during + * full page during the boot time and again tracks the freed nodes during * runtime. It is racy but it does not happen as they are separated by the * boot process. Will create problem if some how we have memory hotplug * operation during boot !! @@ -372,6 +372,9 @@ void register_page_bootmem_memmap(unsigned long section_nr, #ifdef CONFIG_PPC_BOOK3S_64 unsigned int mmu_lpid_bits; +#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE +EXPORT_SYMBOL_GPL(mmu_lpid_bits); +#endif unsigned int mmu_pid_bits; static bool disable_radix = !IS_ENABLED(CONFIG_PPC_RADIX_MMU_DEFAULT); diff --git a/arch/powerpc/mm/kasan/Makefile b/arch/powerpc/mm/kasan/Makefile index bb1a5408b86b2cb3ca1af86c65c7f4355a0adbc6..4999aadb1867ebd337bf12554cacb3c12ca39dec 100644 --- a/arch/powerpc/mm/kasan/Makefile +++ b/arch/powerpc/mm/kasan/Makefile @@ -2,6 +2,7 @@ KASAN_SANITIZE := n -obj-$(CONFIG_PPC32) += kasan_init_32.o +obj-$(CONFIG_PPC32) += init_32.o obj-$(CONFIG_PPC_8xx) += 8xx.o obj-$(CONFIG_PPC_BOOK3S_32) += book3s_32.o +obj-$(CONFIG_PPC_BOOK3S_64) += init_book3s_64.o diff --git a/arch/powerpc/mm/kasan/kasan_init_32.c b/arch/powerpc/mm/kasan/init_32.c similarity index 100% rename from arch/powerpc/mm/kasan/kasan_init_32.c rename to arch/powerpc/mm/kasan/init_32.c diff --git a/arch/powerpc/mm/kasan/init_book3s_64.c b/arch/powerpc/mm/kasan/init_book3s_64.c new file mode 100644 index 0000000000000000000000000000000000000000..0da5566d6b84b232efeae822b9a27ef999c946e4 --- /dev/null +++ b/arch/powerpc/mm/kasan/init_book3s_64.c @@ -0,0 +1,102 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * KASAN for 64-bit Book3S powerpc + * + * Copyright 2019-2022, Daniel Axtens, IBM Corporation. + */ + +/* + * ppc64 turns on virtual memory late in boot, after calling into generic code + * like the device-tree parser, so it uses this in conjunction with a hook in + * outline mode to avoid invalid access early in boot. + */ + +#define DISABLE_BRANCH_PROFILING + +#include +#include +#include +#include +#include + +DEFINE_STATIC_KEY_FALSE(powerpc_kasan_enabled_key); + +static void __init kasan_init_phys_region(void *start, void *end) +{ + unsigned long k_start, k_end, k_cur; + void *va; + + if (start >= end) + return; + + k_start = ALIGN_DOWN((unsigned long)kasan_mem_to_shadow(start), PAGE_SIZE); + k_end = ALIGN((unsigned long)kasan_mem_to_shadow(end), PAGE_SIZE); + + va = memblock_alloc(k_end - k_start, PAGE_SIZE); + for (k_cur = k_start; k_cur < k_end; k_cur += PAGE_SIZE, va += PAGE_SIZE) + map_kernel_page(k_cur, __pa(va), PAGE_KERNEL); +} + +void __init kasan_init(void) +{ + /* + * We want to do the following things: + * 1) Map real memory into the shadow for all physical memblocks + * This takes us from c000... to c008... + * 2) Leave a hole over the shadow of vmalloc space. KASAN_VMALLOC + * will manage this for us. + * This takes us from c008... to c00a... + * 3) Map the 'early shadow'/zero page over iomap and vmemmap space. + * This takes us up to where we start at c00e... + */ + + void *k_start = kasan_mem_to_shadow((void *)RADIX_VMALLOC_END); + void *k_end = kasan_mem_to_shadow((void *)RADIX_VMEMMAP_END); + phys_addr_t start, end; + u64 i; + pte_t zero_pte = pfn_pte(virt_to_pfn(kasan_early_shadow_page), PAGE_KERNEL); + + if (!early_radix_enabled()) { + pr_warn("KASAN not enabled as it requires radix!"); + return; + } + + for_each_mem_range(i, &start, &end) + kasan_init_phys_region((void *)start, (void *)end); + + for (i = 0; i < PTRS_PER_PTE; i++) + __set_pte_at(&init_mm, (unsigned long)kasan_early_shadow_page, + &kasan_early_shadow_pte[i], zero_pte, 0); + + for (i = 0; i < PTRS_PER_PMD; i++) + pmd_populate_kernel(&init_mm, &kasan_early_shadow_pmd[i], + kasan_early_shadow_pte); + + for (i = 0; i < PTRS_PER_PUD; i++) + pud_populate(&init_mm, &kasan_early_shadow_pud[i], + kasan_early_shadow_pmd); + + /* map the early shadow over the iomap and vmemmap space */ + kasan_populate_early_shadow(k_start, k_end); + + /* mark early shadow region as RO and wipe it */ + zero_pte = pfn_pte(virt_to_pfn(kasan_early_shadow_page), PAGE_KERNEL_RO); + for (i = 0; i < PTRS_PER_PTE; i++) + __set_pte_at(&init_mm, (unsigned long)kasan_early_shadow_page, + &kasan_early_shadow_pte[i], zero_pte, 0); + + /* + * clear_page relies on some cache info that hasn't been set up yet. + * It ends up looping ~forever and blows up other data. + * Use memset instead. + */ + memset(kasan_early_shadow_page, 0, PAGE_SIZE); + + static_branch_inc(&powerpc_kasan_enabled_key); + + /* Enable error messages */ + init_task.kasan_depth = 0; + pr_info("KASAN init done\n"); +} + +void __init kasan_late_init(void) { } diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c index 46fb78e3bb36b951eb8ceaab135ee8e31f4d01ca..52b77684acda732beeb0452ea7f0cc3b03415f04 100644 --- a/arch/powerpc/mm/mem.c +++ b/arch/powerpc/mm/mem.c @@ -23,6 +23,8 @@ #include #include #include +#include +#include #include @@ -309,7 +311,9 @@ void free_initmem(void) { ppc_md.progress = ppc_printk_progress; mark_initmem_nx(); + static_branch_enable(&init_mem_is_free); free_initmem_default(POISON_FREE_INITMEM); + ftrace_free_init_tramp(); } /* diff --git a/arch/powerpc/mm/mmap.c b/arch/powerpc/mm/mmap.c deleted file mode 100644 index c475cf810aa86af8c05d6e9aefb7a16081276a40..0000000000000000000000000000000000000000 --- a/arch/powerpc/mm/mmap.c +++ /dev/null @@ -1,256 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * flexible mmap layout support - * - * Copyright 2003-2004 Red Hat Inc., Durham, North Carolina. - * All Rights Reserved. - * - * Started by Ingo Molnar - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * Top of mmap area (just below the process stack). - * - * Leave at least a ~128 MB hole. - */ -#define MIN_GAP (128*1024*1024) -#define MAX_GAP (TASK_SIZE/6*5) - -static inline int mmap_is_legacy(struct rlimit *rlim_stack) -{ - if (current->personality & ADDR_COMPAT_LAYOUT) - return 1; - - if (rlim_stack->rlim_cur == RLIM_INFINITY) - return 1; - - return sysctl_legacy_va_layout; -} - -unsigned long arch_mmap_rnd(void) -{ - unsigned long shift, rnd; - - shift = mmap_rnd_bits; -#ifdef CONFIG_COMPAT - if (is_32bit_task()) - shift = mmap_rnd_compat_bits; -#endif - rnd = get_random_long() % (1ul << shift); - - return rnd << PAGE_SHIFT; -} - -static inline unsigned long stack_maxrandom_size(void) -{ - if (!(current->flags & PF_RANDOMIZE)) - return 0; - - /* 8MB for 32bit, 1GB for 64bit */ - if (is_32bit_task()) - return (1<<23); - else - return (1<<30); -} - -static inline unsigned long mmap_base(unsigned long rnd, - struct rlimit *rlim_stack) -{ - unsigned long gap = rlim_stack->rlim_cur; - unsigned long pad = stack_maxrandom_size() + stack_guard_gap; - - /* Values close to RLIM_INFINITY can overflow. */ - if (gap + pad > gap) - gap += pad; - - if (gap < MIN_GAP) - gap = MIN_GAP; - else if (gap > MAX_GAP) - gap = MAX_GAP; - - return PAGE_ALIGN(DEFAULT_MAP_WINDOW - gap - rnd); -} - -#ifdef HAVE_ARCH_UNMAPPED_AREA -#ifdef CONFIG_PPC_RADIX_MMU -/* - * Same function as generic code used only for radix, because we don't need to overload - * the generic one. But we will have to duplicate, because hash select - * HAVE_ARCH_UNMAPPED_AREA - */ -static unsigned long -radix__arch_get_unmapped_area(struct file *filp, unsigned long addr, - unsigned long len, unsigned long pgoff, - unsigned long flags) -{ - struct mm_struct *mm = current->mm; - struct vm_area_struct *vma; - int fixed = (flags & MAP_FIXED); - unsigned long high_limit; - struct vm_unmapped_area_info info; - - high_limit = DEFAULT_MAP_WINDOW; - if (addr >= high_limit || (fixed && (addr + len > high_limit))) - high_limit = TASK_SIZE; - - if (len > high_limit) - return -ENOMEM; - - if (fixed) { - if (addr > high_limit - len) - return -ENOMEM; - return addr; - } - - if (addr) { - addr = PAGE_ALIGN(addr); - vma = find_vma(mm, addr); - if (high_limit - len >= addr && addr >= mmap_min_addr && - (!vma || addr + len <= vm_start_gap(vma))) - return addr; - } - - info.flags = 0; - info.length = len; - info.low_limit = mm->mmap_base; - info.high_limit = high_limit; - info.align_mask = 0; - - return vm_unmapped_area(&info); -} - -static unsigned long -radix__arch_get_unmapped_area_topdown(struct file *filp, - const unsigned long addr0, - const unsigned long len, - const unsigned long pgoff, - const unsigned long flags) -{ - struct vm_area_struct *vma; - struct mm_struct *mm = current->mm; - unsigned long addr = addr0; - int fixed = (flags & MAP_FIXED); - unsigned long high_limit; - struct vm_unmapped_area_info info; - - high_limit = DEFAULT_MAP_WINDOW; - if (addr >= high_limit || (fixed && (addr + len > high_limit))) - high_limit = TASK_SIZE; - - if (len > high_limit) - return -ENOMEM; - - if (fixed) { - if (addr > high_limit - len) - return -ENOMEM; - return addr; - } - - if (addr) { - addr = PAGE_ALIGN(addr); - vma = find_vma(mm, addr); - if (high_limit - len >= addr && addr >= mmap_min_addr && - (!vma || addr + len <= vm_start_gap(vma))) - return addr; - } - - info.flags = VM_UNMAPPED_AREA_TOPDOWN; - info.length = len; - info.low_limit = max(PAGE_SIZE, mmap_min_addr); - info.high_limit = mm->mmap_base + (high_limit - DEFAULT_MAP_WINDOW); - info.align_mask = 0; - - addr = vm_unmapped_area(&info); - if (!(addr & ~PAGE_MASK)) - return addr; - VM_BUG_ON(addr != -ENOMEM); - - /* - * A failed mmap() very likely causes application failure, - * so fall back to the bottom-up function here. This scenario - * can happen with large stack limits and large mmap() - * allocations. - */ - return radix__arch_get_unmapped_area(filp, addr0, len, pgoff, flags); -} -#endif - -unsigned long arch_get_unmapped_area(struct file *filp, - unsigned long addr, - unsigned long len, - unsigned long pgoff, - unsigned long flags) -{ -#ifdef CONFIG_PPC_MM_SLICES - return slice_get_unmapped_area(addr, len, flags, - mm_ctx_user_psize(¤t->mm->context), 0); -#else - BUG(); -#endif -} - -unsigned long arch_get_unmapped_area_topdown(struct file *filp, - const unsigned long addr0, - const unsigned long len, - const unsigned long pgoff, - const unsigned long flags) -{ -#ifdef CONFIG_PPC_MM_SLICES - return slice_get_unmapped_area(addr0, len, flags, - mm_ctx_user_psize(¤t->mm->context), 1); -#else - BUG(); -#endif -} -#endif /* HAVE_ARCH_UNMAPPED_AREA */ - -static void radix__arch_pick_mmap_layout(struct mm_struct *mm, - unsigned long random_factor, - struct rlimit *rlim_stack) -{ -#ifdef CONFIG_PPC_RADIX_MMU - if (mmap_is_legacy(rlim_stack)) { - mm->mmap_base = TASK_UNMAPPED_BASE; - mm->get_unmapped_area = radix__arch_get_unmapped_area; - } else { - mm->mmap_base = mmap_base(random_factor, rlim_stack); - mm->get_unmapped_area = radix__arch_get_unmapped_area_topdown; - } -#endif -} - -/* - * This function, called very early during the creation of a new - * process VM image, sets up which VM layout function to use: - */ -void arch_pick_mmap_layout(struct mm_struct *mm, struct rlimit *rlim_stack) -{ - unsigned long random_factor = 0UL; - - if (current->flags & PF_RANDOMIZE) - random_factor = arch_mmap_rnd(); - - if (radix_enabled()) - return radix__arch_pick_mmap_layout(mm, random_factor, - rlim_stack); - /* - * Fall back to the standard layout if the personality - * bit is set, or if the expected stack growth is unlimited: - */ - if (mmap_is_legacy(rlim_stack)) { - mm->mmap_base = TASK_UNMAPPED_BASE; - mm->get_unmapped_area = arch_get_unmapped_area; - } else { - mm->mmap_base = mmap_base(random_factor, rlim_stack); - mm->get_unmapped_area = arch_get_unmapped_area_topdown; - } -} diff --git a/arch/powerpc/mm/mmu_decl.h b/arch/powerpc/mm/mmu_decl.h index 0dd4c18f836312064ac94edeb386355b9bd602c3..63c4b1a4d43540da6e3d5d68d18f1c8a18defdeb 100644 --- a/arch/powerpc/mm/mmu_decl.h +++ b/arch/powerpc/mm/mmu_decl.h @@ -155,6 +155,10 @@ struct tlbcam { u32 MAS3; u32 MAS7; }; + +#define NUM_TLBCAMS 64 + +extern struct tlbcam TLBCAM[NUM_TLBCAMS]; #endif #if defined(CONFIG_PPC_BOOK3S_32) || defined(CONFIG_FSL_BOOKE) || defined(CONFIG_PPC_8xx) diff --git a/arch/powerpc/mm/nohash/40x.c b/arch/powerpc/mm/nohash/40x.c index 95751c322f6cd012ac96acdfc1ce6236f952d95c..b32e465a3d526f9031d75e767f8c08c1460bf20d 100644 --- a/arch/powerpc/mm/nohash/40x.c +++ b/arch/powerpc/mm/nohash/40x.c @@ -32,7 +32,6 @@ #include #include -#include #include #include #include diff --git a/arch/powerpc/mm/nohash/book3e_hugetlbpage.c b/arch/powerpc/mm/nohash/book3e_hugetlbpage.c index 8b88be91b622ab3922772523b91c89e15b4a67e0..307ca919d393052a38c27cc21950d4e5cfb58a9e 100644 --- a/arch/powerpc/mm/nohash/book3e_hugetlbpage.c +++ b/arch/powerpc/mm/nohash/book3e_hugetlbpage.c @@ -142,7 +142,7 @@ book3e_hugetlb_preload(struct vm_area_struct *vma, unsigned long ea, pte_t pte) tsize = shift - 10; /* * We can't be interrupted while we're setting up the MAS - * regusters or after we've confirmed that no tlb exists. + * registers or after we've confirmed that no tlb exists. */ local_irq_save(flags); diff --git a/arch/powerpc/mm/nohash/fsl_book3e.c b/arch/powerpc/mm/nohash/fsl_book3e.c index dfe715e0f70ac741ffb93f630d9bc155c900df0e..b8ae6c08c06fdce37e67b09c2fba5e813401c2be 100644 --- a/arch/powerpc/mm/nohash/fsl_book3e.c +++ b/arch/powerpc/mm/nohash/fsl_book3e.c @@ -36,8 +36,8 @@ #include #include #include +#include -#include #include #include #include @@ -51,10 +51,9 @@ unsigned int tlbcam_index; -#define NUM_TLBCAMS (64) struct tlbcam TLBCAM[NUM_TLBCAMS]; -struct tlbcamrange { +static struct { unsigned long start; unsigned long limit; phys_addr_t phys; @@ -274,7 +273,7 @@ void __init adjust_total_lowmem(void) i = switch_to_as1(); __max_low_memory = map_mem_in_cams(ram, CONFIG_LOWMEM_CAM_NUM, false, true); - restore_to_as0(i, 0, 0, 1); + restore_to_as0(i, 0, NULL, 1); pr_info("Memory CAM mapping: "); for (i = 0; i < tlbcam_index - 1; i++) @@ -287,22 +286,19 @@ void __init adjust_total_lowmem(void) #ifdef CONFIG_STRICT_KERNEL_RWX void mmu_mark_rodata_ro(void) -{ - /* Everything is done in mmu_mark_initmem_nx() */ -} -#endif - -void mmu_mark_initmem_nx(void) { unsigned long remapped; - if (!strict_kernel_rwx_enabled()) - return; - remapped = map_mem_in_cams(__max_low_memory, CONFIG_LOWMEM_CAM_NUM, false, false); WARN_ON(__max_low_memory != remapped); } +#endif + +void mmu_mark_initmem_nx(void) +{ + /* Everything is done in mmu_mark_rodata_ro() */ +} void setup_initial_memory_limit(phys_addr_t first_memblock_base, phys_addr_t first_memblock_size) diff --git a/arch/powerpc/mm/nohash/kaslr_booke.c b/arch/powerpc/mm/nohash/kaslr_booke.c index 96c38f971603fc5adbeb956629dc31f70760f310..1f3f9fedf1bc2223a0a56a6de8bb24365051e0c5 100644 --- a/arch/powerpc/mm/nohash/kaslr_booke.c +++ b/arch/powerpc/mm/nohash/kaslr_booke.c @@ -14,8 +14,9 @@ #include #include #include +#include +#include #include -#include #include #include #include @@ -315,7 +316,7 @@ static unsigned long __init kaslr_choose_location(void *dt_ptr, phys_addr_t size ram = map_mem_in_cams(ram, CONFIG_LOWMEM_CAM_NUM, true, true); linear_sz = min_t(unsigned long, ram, SZ_512M); - /* If the linear size is smaller than 64M, do not randmize */ + /* If the linear size is smaller than 64M, do not randomize */ if (linear_sz < SZ_64M) return 0; diff --git a/arch/powerpc/mm/nohash/mmu_context.c b/arch/powerpc/mm/nohash/mmu_context.c index 85b048f04c5623c24c02f79ab6e3e37710183dd9..ccd5819b1bd90d3601201fbefe29132980fd90f4 100644 --- a/arch/powerpc/mm/nohash/mmu_context.c +++ b/arch/powerpc/mm/nohash/mmu_context.c @@ -317,15 +317,6 @@ void switch_mmu_context(struct mm_struct *prev, struct mm_struct *next, */ int init_new_context(struct task_struct *t, struct mm_struct *mm) { - /* - * We have MMU_NO_CONTEXT set to be ~0. Hence check - * explicitly against context.id == 0. This ensures that we properly - * initialize context slice details for newly allocated mm's (which will - * have id == 0) and don't alter context slice inherited via fork (which - * will have id != 0). - */ - if (mm->context.id == 0) - slice_init_new_context_exec(mm); mm->context.id = MMU_NO_CONTEXT; mm->context.active = 0; pte_frag_set(&mm->context, NULL); diff --git a/arch/powerpc/mm/nohash/tlb.c b/arch/powerpc/mm/nohash/tlb.c index fd2c77af5c5549b4d473c14ff6da17f4538d92fa..5e7ccb48b79c0579619a7dba1fde067d52c358a1 100644 --- a/arch/powerpc/mm/nohash/tlb.c +++ b/arch/powerpc/mm/nohash/tlb.c @@ -358,6 +358,7 @@ void __init early_init_mmu_47x(void) /* * Flush kernel TLB entries in the given range */ +#ifndef CONFIG_PPC_8xx void flush_tlb_kernel_range(unsigned long start, unsigned long end) { #ifdef CONFIG_SMP @@ -370,6 +371,7 @@ void flush_tlb_kernel_range(unsigned long start, unsigned long end) #endif } EXPORT_SYMBOL(flush_tlb_kernel_range); +#endif /* * Currently, for range flushing, we just do a full mm flush. This should @@ -773,9 +775,5 @@ void __init early_init_mmu(void) #ifdef CONFIG_PPC_47x early_init_mmu_47x(); #endif - -#ifdef CONFIG_PPC_MM_SLICES - mm_ctx_set_slb_addr_limit(&init_mm.context, SLB_ADDR_LIMIT_DEFAULT); -#endif } #endif /* CONFIG_PPC64 */ diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c index 13022d734951b99e312a8074658d66b044558c6a..0801b2ce9b7d1053d051521c372eb3d86af2c8ee 100644 --- a/arch/powerpc/mm/numa.c +++ b/arch/powerpc/mm/numa.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include @@ -1423,43 +1422,26 @@ out: return rc; } -int find_and_online_cpu_nid(int cpu) +void find_and_update_cpu_nid(int cpu) { __be32 associativity[VPHN_ASSOC_BUFSIZE] = {0}; int new_nid; /* Use associativity from first thread for all siblings */ if (vphn_get_associativity(cpu, associativity)) - return cpu_to_node(cpu); + return; + /* Do not have previous associativity, so find it now. */ new_nid = associativity_to_nid(associativity); - if (new_nid < 0 || !node_possible(new_nid)) - new_nid = first_online_node; - if (!node_online(new_nid)) { -#ifdef CONFIG_MEMORY_HOTPLUG - /* - * Need to ensure that NODE_DATA is initialized for a node from - * available memory (see memblock_alloc_try_nid). If unable to - * init the node, then default to nearest node that has memory - * installed. Skip onlining a node if the subsystems are not - * yet initialized. - */ - if (!topology_inited || try_online_node(new_nid)) - new_nid = first_online_node; -#else - /* - * Default to using the nearest node that has memory installed. - * Otherwise, it would be necessary to patch the kernel MM code - * to deal with more memoryless-node error conditions. - */ + if (new_nid < 0 || !node_possible(new_nid)) new_nid = first_online_node; -#endif - } + else + // Associate node <-> cpu, so cpu_up() calls + // try_online_node() on the right node. + set_cpu_numa_node(cpu, new_nid); - pr_debug("%s:%d cpu %d nid %d\n", __FUNCTION__, __LINE__, - cpu, new_nid); - return new_nid; + pr_debug("%s:%d cpu %d nid %d\n", __func__, __LINE__, cpu, new_nid); } int cpu_to_coregroup_id(int cpu) diff --git a/arch/powerpc/mm/pageattr.c b/arch/powerpc/mm/pageattr.c index 85753e32a4de9867cefe32dc50e48d21c9d99cbf..6163e484bc6d4d5075385613a8788d18ce532cfb 100644 --- a/arch/powerpc/mm/pageattr.c +++ b/arch/powerpc/mm/pageattr.c @@ -31,6 +31,7 @@ static int change_page_attr(pte_t *ptep, unsigned long addr, void *data) { long action = (long)data; + addr &= PAGE_MASK; /* modify the PTE bits as desired */ switch (action) { case SET_MEMORY_RO: diff --git a/arch/powerpc/mm/pgtable-frag.c b/arch/powerpc/mm/pgtable-frag.c index 97ae4935da79905a9134ba0198a7397867ed3c9c..20652daa1d7e3ab154b1f2fcd1782b6901c81a01 100644 --- a/arch/powerpc/mm/pgtable-frag.c +++ b/arch/powerpc/mm/pgtable-frag.c @@ -83,7 +83,7 @@ static pte_t *__alloc_for_ptecache(struct mm_struct *mm, int kernel) spin_lock(&mm->page_table_lock); /* * If we find pgtable_page set, we return - * the allocated page with single fragement + * the allocated page with single fragment * count. */ if (likely(!pte_frag_get(&mm->context))) { diff --git a/arch/powerpc/mm/pgtable.c b/arch/powerpc/mm/pgtable.c index 6ec5a7dd79137cea25470fde53cc80ff2ff020df..e6166b71d36d4ea485cad7a4da900cc1c5666821 100644 --- a/arch/powerpc/mm/pgtable.c +++ b/arch/powerpc/mm/pgtable.c @@ -351,7 +351,7 @@ EXPORT_SYMBOL_GPL(vmalloc_to_phys); * (4) hugepd pointer, _PAGE_PTE = 0 and bits [2..6] indicate size of table * * So long as we atomically load page table pointers we are safe against teardown, - * we can follow the address down to the the page and take a ref on it. + * we can follow the address down to the page and take a ref on it. * This function need to be called with interrupts disabled. We use this variant * when we have MSR[EE] = 0 but the paca->irq_soft_mask = IRQS_ENABLED */ diff --git a/arch/powerpc/mm/pgtable_64.c b/arch/powerpc/mm/pgtable_64.c index 175aabf101e8787efdf6c23e8ab918e9b30cc765..5ac1fd30341bb29704bedabd63e43cc105e3f285 100644 --- a/arch/powerpc/mm/pgtable_64.c +++ b/arch/powerpc/mm/pgtable_64.c @@ -32,7 +32,6 @@ #include #include -#include #include #include #include diff --git a/arch/powerpc/mm/ptdump/ptdump.c b/arch/powerpc/mm/ptdump/ptdump.c index 8c846982766f612866166430af45905c431b8866..2313053fe679ed34f12c75c738b809dc115529ab 100644 --- a/arch/powerpc/mm/ptdump/ptdump.c +++ b/arch/powerpc/mm/ptdump/ptdump.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -289,11 +290,11 @@ static void populate_markers(void) #endif address_markers[i++].start_address = FIXADDR_START; address_markers[i++].start_address = FIXADDR_TOP; +#endif /* CONFIG_PPC64 */ #ifdef CONFIG_KASAN address_markers[i++].start_address = KASAN_SHADOW_START; address_markers[i++].start_address = KASAN_SHADOW_END; #endif -#endif /* CONFIG_PPC64 */ } static int ptdump_show(struct seq_file *m, void *v) diff --git a/arch/powerpc/net/bpf_jit.h b/arch/powerpc/net/bpf_jit.h index 979701d360dafbaef5a270d8a643816610c96ca8..a4f7880f959dd56b1be6f2e095b7131942e5c57b 100644 --- a/arch/powerpc/net/bpf_jit.h +++ b/arch/powerpc/net/bpf_jit.h @@ -13,7 +13,7 @@ #include #include -#ifdef PPC64_ELF_ABI_v1 +#ifdef CONFIG_PPC64_ELF_ABI_V1 #define FUNCTION_DESCR_SIZE 24 #else #define FUNCTION_DESCR_SIZE 0 @@ -35,7 +35,7 @@ } while (0) /* bl (unconditional 'branch' with link) */ -#define PPC_BL(dest) EMIT(PPC_INST_BL | (((dest) - (unsigned long)(image + ctx->idx)) & 0x03fffffc)) +#define PPC_BL(dest) EMIT(PPC_RAW_BL((dest) - (unsigned long)(image + ctx->idx))) /* "cond" here covers BO:BI fields. */ #define PPC_BCC_SHORT(cond, dest) \ diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c index 42718525621658924b3fb0ac73cdac88e7b861d0..43e6341265148aade647f9a35da6a19d4ca48dd3 100644 --- a/arch/powerpc/net/bpf_jit_comp.c +++ b/arch/powerpc/net/bpf_jit_comp.c @@ -276,7 +276,7 @@ skip_codegen_passes: */ bpf_jit_dump(flen, proglen, pass, code_base); -#ifdef PPC64_ELF_ABI_v1 +#ifdef CONFIG_PPC64_ELF_ABI_V1 /* Function descriptor nastiness: Address + TOC */ ((u64 *)image)[0] = (u64)code_base; ((u64 *)image)[1] = local_paca->kernel_toc; diff --git a/arch/powerpc/net/bpf_jit_comp64.c b/arch/powerpc/net/bpf_jit_comp64.c index 585f257da04587364fb95ee9c29f232467265cfc..594c54931e2098970e0ac4a2a0126815201a13d0 100644 --- a/arch/powerpc/net/bpf_jit_comp64.c +++ b/arch/powerpc/net/bpf_jit_comp64.c @@ -126,7 +126,7 @@ void bpf_jit_build_prologue(u32 *image, struct codegen_context *ctx) { int i; - if (__is_defined(PPC64_ELF_ABI_v2)) + if (IS_ENABLED(CONFIG_PPC64_ELF_ABI_V2)) EMIT(PPC_RAW_LD(_R2, _R13, offsetof(struct paca_struct, kernel_toc))); /* @@ -266,7 +266,7 @@ static int bpf_jit_emit_tail_call(u32 *image, struct codegen_context *ctx, u32 o int b2p_index = bpf_to_ppc(BPF_REG_3); int bpf_tailcall_prologue_size = 8; - if (__is_defined(PPC64_ELF_ABI_v2)) + if (IS_ENABLED(CONFIG_PPC64_ELF_ABI_V2)) bpf_tailcall_prologue_size += 4; /* skip past the toc load */ /* diff --git a/arch/powerpc/perf/8xx-pmu.c b/arch/powerpc/perf/8xx-pmu.c index 4738c4dbf5676c2a46fc54dbce44a0911d2cbd34..308a2e40d7be9992624b15c40ce85bfdf4df5dd0 100644 --- a/arch/powerpc/perf/8xx-pmu.c +++ b/arch/powerpc/perf/8xx-pmu.c @@ -157,7 +157,7 @@ static void mpc8xx_pmu_del(struct perf_event *event, int flags) mpc8xx_pmu_read(event); - /* If it was the last user, stop counting to avoid useles overhead */ + /* If it was the last user, stop counting to avoid useless overhead */ switch (event_type(event)) { case PERF_8xx_ID_CPU_CYCLES: break; diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c index b5b42cf0a7039d46601026b173ff1869af2a1400..140502a7fdf861d6f20ac999987a81caeea4e879 100644 --- a/arch/powerpc/perf/core-book3s.c +++ b/arch/powerpc/perf/core-book3s.c @@ -1142,7 +1142,7 @@ static u64 check_and_compute_delta(u64 prev, u64 val) /* * POWER7 can roll back counter values, if the new value is smaller * than the previous value it will cause the delta and the counter to - * have bogus values unless we rolled a counter over. If a coutner is + * have bogus values unless we rolled a counter over. If a counter is * rolled back, it will be smaller, but within 256, which is the maximum * number of events to rollback at once. If we detect a rollback * return 0. This can lead to a small lack of precision in the @@ -2057,7 +2057,7 @@ static int power_pmu_event_init(struct perf_event *event) /* * PMU config registers have fields that are * reserved and some specific values for bit fields are reserved. - * For ex., MMCRA[61:62] is Randome Sampling Mode (SM) + * For ex., MMCRA[61:62] is Random Sampling Mode (SM) * and value of 0b11 to this field is reserved. * Check for invalid values in attr.config. */ @@ -2447,7 +2447,7 @@ static void __perf_event_interrupt(struct pt_regs *regs) } /* - * During system wide profling or while specific CPU is monitored for an + * During system wide profiling or while specific CPU is monitored for an * event, some corner cases could cause PMC to overflow in idle path. This * will trigger a PMI after waking up from idle. Since counter values are _not_ * saved/restored in idle path, can lead to below "Can't find PMC" message. diff --git a/arch/powerpc/perf/hv-24x7.c b/arch/powerpc/perf/hv-24x7.c index 12c1777187fca3db7babd703e511055d2979842b..cf5406b31e27fb7bac0cb2cae31e7125383a5cea 100644 --- a/arch/powerpc/perf/hv-24x7.c +++ b/arch/powerpc/perf/hv-24x7.c @@ -33,7 +33,7 @@ static bool aggregate_result_elements; static cpumask_t hv_24x7_cpumask; -static bool domain_is_valid(unsigned domain) +static bool domain_is_valid(unsigned int domain) { switch (domain) { #define DOMAIN(n, v, x, c) \ @@ -47,7 +47,7 @@ static bool domain_is_valid(unsigned domain) } } -static bool is_physical_domain(unsigned domain) +static bool is_physical_domain(unsigned int domain) { switch (domain) { #define DOMAIN(n, v, x, c) \ @@ -128,7 +128,7 @@ static bool domain_needs_aggregation(unsigned int domain) domain <= HV_PERF_DOMAIN_VCPU_REMOTE_NODE)); } -static const char *domain_name(unsigned domain) +static const char *domain_name(unsigned int domain) { if (!domain_is_valid(domain)) return NULL; @@ -146,7 +146,7 @@ static const char *domain_name(unsigned domain) return NULL; } -static bool catalog_entry_domain_is_valid(unsigned domain) +static bool catalog_entry_domain_is_valid(unsigned int domain) { /* POWER8 doesn't support virtual domains. */ if (interface_version == 1) @@ -258,7 +258,7 @@ static char *event_name(struct hv_24x7_event_data *ev, int *len) static char *event_desc(struct hv_24x7_event_data *ev, int *len) { - unsigned nl = be16_to_cpu(ev->event_name_len); + unsigned int nl = be16_to_cpu(ev->event_name_len); __be16 *desc_len = (__be16 *)(ev->remainder + nl - 2); *len = be16_to_cpu(*desc_len) - 2; @@ -267,9 +267,9 @@ static char *event_desc(struct hv_24x7_event_data *ev, int *len) static char *event_long_desc(struct hv_24x7_event_data *ev, int *len) { - unsigned nl = be16_to_cpu(ev->event_name_len); + unsigned int nl = be16_to_cpu(ev->event_name_len); __be16 *desc_len_ = (__be16 *)(ev->remainder + nl - 2); - unsigned desc_len = be16_to_cpu(*desc_len_); + unsigned int desc_len = be16_to_cpu(*desc_len_); __be16 *long_desc_len = (__be16 *)(ev->remainder + nl + desc_len - 2); *len = be16_to_cpu(*long_desc_len) - 2; @@ -296,8 +296,8 @@ static void *event_end(struct hv_24x7_event_data *ev, void *end) { void *start = ev; __be16 *dl_, *ldl_; - unsigned dl, ldl; - unsigned nl = be16_to_cpu(ev->event_name_len); + unsigned int dl, ldl; + unsigned int nl = be16_to_cpu(ev->event_name_len); if (nl < 2) { pr_debug("%s: name length too short: %d", __func__, nl); @@ -398,7 +398,7 @@ static long h_get_24x7_catalog_page(char page[], u64 version, u32 index) * - Specifying (i.e overriding) values for other parameters * is undefined. */ -static char *event_fmt(struct hv_24x7_event_data *event, unsigned domain) +static char *event_fmt(struct hv_24x7_event_data *event, unsigned int domain) { const char *sindex; const char *lpar; @@ -529,9 +529,9 @@ out_s: return NULL; } -static struct attribute *event_to_attr(unsigned ix, +static struct attribute *event_to_attr(unsigned int ix, struct hv_24x7_event_data *event, - unsigned domain, + unsigned int domain, int nonce) { int event_name_len; @@ -599,8 +599,8 @@ event_to_long_desc_attr(struct hv_24x7_event_data *event, int nonce) return device_str_attr_create(name, nl, nonce, desc, dl); } -static int event_data_to_attrs(unsigned ix, struct attribute **attrs, - struct hv_24x7_event_data *event, int nonce) +static int event_data_to_attrs(unsigned int ix, struct attribute **attrs, + struct hv_24x7_event_data *event, int nonce) { *attrs = event_to_attr(ix, event, event->domain, nonce); if (!*attrs) @@ -614,8 +614,8 @@ struct event_uniq { struct rb_node node; const char *name; int nl; - unsigned ct; - unsigned domain; + unsigned int ct; + unsigned int domain; }; static int memord(const void *d1, size_t s1, const void *d2, size_t s2) @@ -628,8 +628,8 @@ static int memord(const void *d1, size_t s1, const void *d2, size_t s2) return memcmp(d1, d2, s1); } -static int ev_uniq_ord(const void *v1, size_t s1, unsigned d1, const void *v2, - size_t s2, unsigned d2) +static int ev_uniq_ord(const void *v1, size_t s1, unsigned int d1, + const void *v2, size_t s2, unsigned int d2) { int r = memord(v1, s1, v2, s2); @@ -643,7 +643,7 @@ static int ev_uniq_ord(const void *v1, size_t s1, unsigned d1, const void *v2, } static int event_uniq_add(struct rb_root *root, const char *name, int nl, - unsigned domain) + unsigned int domain) { struct rb_node **new = &(root->rb_node), *parent = NULL; struct event_uniq *data; @@ -1398,7 +1398,7 @@ out: static int h_24x7_event_init(struct perf_event *event) { struct hv_perf_caps caps; - unsigned domain; + unsigned int domain; unsigned long hret; u64 ct; diff --git a/arch/powerpc/perf/imc-pmu.c b/arch/powerpc/perf/imc-pmu.c index 526d4b767534c28217efe6944ff95a12a92a6de2..d7976ab40d386d73f1ba36a49037759ececf1166 100644 --- a/arch/powerpc/perf/imc-pmu.c +++ b/arch/powerpc/perf/imc-pmu.c @@ -6,6 +6,7 @@ * (C) 2017 Anju T Sudhakar, IBM Corporation. * (C) 2017 Hemant K Shaw, IBM Corporation. */ +#include #include #include #include @@ -521,7 +522,7 @@ static int nest_imc_event_init(struct perf_event *event) /* * Nest HW counter memory resides in a per-chip reserve-memory (HOMER). - * Get the base memory addresss for this cpu. + * Get the base memory address for this cpu. */ chip_id = cpu_to_chip_id(event->cpu); @@ -674,7 +675,7 @@ static int ppc_core_imc_cpu_offline(unsigned int cpu) /* * Check whether core_imc is registered. We could end up here * if the cpuhotplug callback registration fails. i.e, callback - * invokes the offline path for all sucessfully registered cpus. + * invokes the offline path for all successfully registered cpus. * At this stage, core_imc pmu will not be registered and we * should return here. * diff --git a/arch/powerpc/perf/isa207-common.c b/arch/powerpc/perf/isa207-common.c index a74d382ecbb77f4e8f842e7c12857aa7c65a4143..42abbcfc73da1f5631ece275374d4c1d0eff6b65 100644 --- a/arch/powerpc/perf/isa207-common.c +++ b/arch/powerpc/perf/isa207-common.c @@ -82,11 +82,11 @@ static unsigned long sdar_mod_val(u64 event) static void mmcra_sdar_mode(u64 event, unsigned long *mmcra) { /* - * MMCRA[SDAR_MODE] specifices how the SDAR should be updated in - * continous sampling mode. + * MMCRA[SDAR_MODE] specifies how the SDAR should be updated in + * continuous sampling mode. * * Incase of Power8: - * MMCRA[SDAR_MODE] will be programmed as "0b01" for continous sampling + * MMCRA[SDAR_MODE] will be programmed as "0b01" for continuous sampling * mode and will be un-changed when setting MMCRA[63] (Marked events). * * Incase of Power9/power10: @@ -108,7 +108,7 @@ static void mmcra_sdar_mode(u64 event, unsigned long *mmcra) *mmcra |= MMCRA_SDAR_MODE_TLB; } -static u64 p10_thresh_cmp_val(u64 value) +static int p10_thresh_cmp_val(u64 value) { int exp = 0; u64 result = value; @@ -139,7 +139,7 @@ static u64 p10_thresh_cmp_val(u64 value) * exponent is also zero. */ if (!(value & 0xC0) && exp) - result = 0; + result = -1; else result = (exp << 8) | value; } @@ -187,7 +187,7 @@ static bool is_thresh_cmp_valid(u64 event) unsigned int cmp, exp; if (cpu_has_feature(CPU_FTR_ARCH_31)) - return p10_thresh_cmp_val(event) != 0; + return p10_thresh_cmp_val(event) >= 0; /* * Check the mantissa upper two bits are not zero, unless the @@ -502,12 +502,14 @@ int isa207_get_constraint(u64 event, unsigned long *maskp, unsigned long *valp, value |= CNST_THRESH_CTL_SEL_VAL(event >> EVENT_THRESH_SHIFT); mask |= p10_CNST_THRESH_CMP_MASK; value |= p10_CNST_THRESH_CMP_VAL(p10_thresh_cmp_val(event_config1)); - } + } else if (event_is_threshold(event)) + return -1; } else if (cpu_has_feature(CPU_FTR_ARCH_300)) { if (event_is_threshold(event) && is_thresh_cmp_valid(event)) { mask |= CNST_THRESH_MASK; value |= CNST_THRESH_VAL(event >> EVENT_THRESH_SHIFT); - } + } else if (event_is_threshold(event)) + return -1; } else { /* * Special case for PM_MRK_FAB_RSP_MATCH and PM_MRK_FAB_RSP_MATCH_CYC, diff --git a/arch/powerpc/perf/power9-pmu.c b/arch/powerpc/perf/power9-pmu.c index c393e837648e2efe34287615ef6fd2155a2b59d5..3ad40ffb92569cb71fc8c57ecca431feb826e384 100644 --- a/arch/powerpc/perf/power9-pmu.c +++ b/arch/powerpc/perf/power9-pmu.c @@ -98,7 +98,7 @@ extern u64 PERF_REG_EXTENDED_MASK; /* PowerISA v2.07 format attribute structure*/ extern const struct attribute_group isa207_pmu_format_group; -int p9_dd21_bl_ev[] = { +static int p9_dd21_bl_ev[] = { PM_MRK_ST_DONE_L2, PM_RADIX_PWC_L1_HIT, PM_FLOP_CMPL, @@ -112,7 +112,7 @@ int p9_dd21_bl_ev[] = { PM_DISP_HELD_SYNC_HOLD, }; -int p9_dd22_bl_ev[] = { +static int p9_dd22_bl_ev[] = { PM_DTLB_MISS_16G, PM_DERAT_MISS_2M, PM_DTLB_MISS_2M, diff --git a/arch/powerpc/platforms/40x/ppc40x_simple.c b/arch/powerpc/platforms/40x/ppc40x_simple.c index e70b4272932288367f53d21508f6caec42c67a4c..dce696c32679e5ee7feb492f6f82a7186c3c4282 100644 --- a/arch/powerpc/platforms/40x/ppc40x_simple.c +++ b/arch/powerpc/platforms/40x/ppc40x_simple.c @@ -13,7 +13,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/powerpc/platforms/44x/canyonlands.c b/arch/powerpc/platforms/44x/canyonlands.c index 807968a755ef8cd406f49ad747b0fc8511cd745d..5b23aef8bdefbf640872f0ab1a86d9713a0a0e5d 100644 --- a/arch/powerpc/platforms/44x/canyonlands.c +++ b/arch/powerpc/platforms/44x/canyonlands.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include "44x.h" diff --git a/arch/powerpc/platforms/44x/fsp2.c b/arch/powerpc/platforms/44x/fsp2.c index af13a59d2f60f96eefc864ba0bb352dfae4870bb..e2e4f6d8150d6103decc8e912e4b5f747a7bca89 100644 --- a/arch/powerpc/platforms/44x/fsp2.c +++ b/arch/powerpc/platforms/44x/fsp2.c @@ -14,11 +14,11 @@ */ #include +#include #include #include #include -#include #include #include #include diff --git a/arch/powerpc/platforms/44x/ppc44x_simple.c b/arch/powerpc/platforms/44x/ppc44x_simple.c index 3dbd8ddd734a3c20d33f70a11e5b844d25252110..2a0dcdf04b217366b6dd85965454c415bacdd27c 100644 --- a/arch/powerpc/platforms/44x/ppc44x_simple.c +++ b/arch/powerpc/platforms/44x/ppc44x_simple.c @@ -13,7 +13,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/powerpc/platforms/44x/ppc476.c b/arch/powerpc/platforms/44x/ppc476.c index fb7db5cedd4ee065bf8055729d287074e47e07a0..20cc8f80b086fad6262d5c7c3ad2a0d8b20f57e1 100644 --- a/arch/powerpc/platforms/44x/ppc476.c +++ b/arch/powerpc/platforms/44x/ppc476.c @@ -19,11 +19,11 @@ #include #include +#include #include #include #include -#include #include #include #include diff --git a/arch/powerpc/platforms/44x/sam440ep.c b/arch/powerpc/platforms/44x/sam440ep.c index 68ba4b009da0922384ba98d599a4e0ac13c3e1ec..ed854b53877e8f09e51c92e9758eb6cb95099bcc 100644 --- a/arch/powerpc/platforms/44x/sam440ep.c +++ b/arch/powerpc/platforms/44x/sam440ep.c @@ -17,7 +17,6 @@ #include #include -#include #include #include #include diff --git a/arch/powerpc/platforms/44x/warp.c b/arch/powerpc/platforms/44x/warp.c index 665f18e37efb29be65cc7d84498c55dfcf0d634a..f03432ef010bd12836bfd0e194abf06bdb17a126 100644 --- a/arch/powerpc/platforms/44x/warp.c +++ b/arch/powerpc/platforms/44x/warp.c @@ -11,12 +11,13 @@ #include #include #include +#include +#include #include #include #include #include -#include #include #include #include diff --git a/arch/powerpc/platforms/4xx/cpm.c b/arch/powerpc/platforms/4xx/cpm.c index 2571841625a23ea8d1231a311d11a0dbfe06f8af..1d3bc35ee1a7db3d1cba0dff66bcfce4d57c91b1 100644 --- a/arch/powerpc/platforms/4xx/cpm.c +++ b/arch/powerpc/platforms/4xx/cpm.c @@ -327,6 +327,6 @@ late_initcall(cpm_init); static int __init cpm_powersave_off(char *arg) { cpm.powersave_off = 1; - return 0; + return 1; } __setup("powersave=off", cpm_powersave_off); diff --git a/arch/powerpc/platforms/4xx/hsta_msi.c b/arch/powerpc/platforms/4xx/hsta_msi.c index fee430eadcc651efcb948c968c3dded107fdd983..d4f7fff1fc8718b27be467880202c206a3037adb 100644 --- a/arch/powerpc/platforms/4xx/hsta_msi.c +++ b/arch/powerpc/platforms/4xx/hsta_msi.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include diff --git a/arch/powerpc/platforms/4xx/pci.c b/arch/powerpc/platforms/4xx/pci.c index 24f41e178cbc80ec156443228b1c18ba19de3215..ca5dd7a5842ac8c19f05a01f84afc8ce0619c271 100644 --- a/arch/powerpc/platforms/4xx/pci.c +++ b/arch/powerpc/platforms/4xx/pci.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include diff --git a/arch/powerpc/platforms/4xx/uic.c b/arch/powerpc/platforms/4xx/uic.c index 89e2587b1a595bc7ffc5c1162641b6e3b3cb4417..d667ad039bd3a48cd7076ce7003fff8dcb7ccf59 100644 --- a/arch/powerpc/platforms/4xx/uic.c +++ b/arch/powerpc/platforms/4xx/uic.c @@ -19,9 +19,10 @@ #include #include #include +#include +#include #include #include -#include #include #define NR_UIC_INTS 32 diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c index 0b03d812baae5bb82a4b83a8641e03060aefd840..0652c7e6922560ccb75955f211735944388d3b6d 100644 --- a/arch/powerpc/platforms/512x/clock-commonclk.c +++ b/arch/powerpc/platforms/512x/clock-commonclk.c @@ -663,7 +663,7 @@ static void __init mpc512x_clk_setup_mclk(struct mclk_setup_data *entry, size_t * the PSC/MSCAN/SPDIF (serial drivers et al) need the MCLK * for their bitrate * - in the absence of "aliases" for clocks we need to create - * individial 'struct clk' items for whatever might get + * individual 'struct clk' items for whatever might get * referenced or looked up, even if several of those items are * identical from the logical POV (their rate value) * - for easier future maintenance and for better reflection of diff --git a/arch/powerpc/platforms/512x/mpc5121_ads.c b/arch/powerpc/platforms/512x/mpc5121_ads.c index 9d030c2e000470c0f377833a5d7c9f974f60ae89..fc3fb999cd744960bfaa3eb2cf708d470fc098b2 100644 --- a/arch/powerpc/platforms/512x/mpc5121_ads.c +++ b/arch/powerpc/platforms/512x/mpc5121_ads.c @@ -14,7 +14,6 @@ #include #include -#include #include #include diff --git a/arch/powerpc/platforms/512x/mpc5121_ads_cpld.c b/arch/powerpc/platforms/512x/mpc5121_ads_cpld.c index ea46870e5d6e805913f76cfcd503794529c6a6b8..6f08d07aee3b37956d92fa1e938eb48cf15eb8eb 100644 --- a/arch/powerpc/platforms/512x/mpc5121_ads_cpld.c +++ b/arch/powerpc/platforms/512x/mpc5121_ads_cpld.c @@ -14,7 +14,8 @@ #include #include #include -#include +#include +#include static struct device_node *cpld_pic_node; static struct irq_domain *cpld_pic_host; diff --git a/arch/powerpc/platforms/512x/mpc512x_generic.c b/arch/powerpc/platforms/512x/mpc512x_generic.c index 303bc308b2e61786ea36e54d0e0f982e19760928..364564c995bdbe9732760063c2926aee869d213f 100644 --- a/arch/powerpc/platforms/512x/mpc512x_generic.c +++ b/arch/powerpc/platforms/512x/mpc512x_generic.c @@ -13,7 +13,6 @@ #include #include -#include #include #include "mpc512x.h" diff --git a/arch/powerpc/platforms/512x/mpc512x_shared.c b/arch/powerpc/platforms/512x/mpc512x_shared.c index e3411663edadb7c3251d539dd71221ee2144a928..5ac0ead2540fc4d7191add949efb52011d32d5e5 100644 --- a/arch/powerpc/platforms/512x/mpc512x_shared.c +++ b/arch/powerpc/platforms/512x/mpc512x_shared.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -20,7 +21,6 @@ #include #include #include -#include #include #include #include @@ -289,7 +289,7 @@ static void __init mpc512x_setup_diu(void) /* * We do not allocate and configure new area for bitmap buffer - * because it would requere copying bitmap data (splash image) + * because it would require copying bitmap data (splash image) * and so negatively affect boot time. Instead we reserve the * already configured frame buffer area so that it won't be * destroyed. The starting address of the area to reserve and diff --git a/arch/powerpc/platforms/52xx/efika.c b/arch/powerpc/platforms/52xx/efika.c index 3b7d70d716925ffdde300245b99991efd9d759c5..e0647720ed5e9ccd017254cabac7da4207b1530a 100644 --- a/arch/powerpc/platforms/52xx/efika.c +++ b/arch/powerpc/platforms/52xx/efika.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/powerpc/platforms/52xx/lite5200.c b/arch/powerpc/platforms/52xx/lite5200.c index 04cc97397095a29fa4f3e5741766dfbbe5928399..7ea9b6ce05917f7587c1a6dacf12fee2d4a99fa9 100644 --- a/arch/powerpc/platforms/52xx/lite5200.c +++ b/arch/powerpc/platforms/52xx/lite5200.c @@ -21,7 +21,6 @@ #include #include #include -#include #include /* ************************************************************************ diff --git a/arch/powerpc/platforms/52xx/lite5200_pm.c b/arch/powerpc/platforms/52xx/lite5200_pm.c index e7da22d1df8798debded249e4d4af851d071ed0e..129313b1d02147471589aedee8d54479080883c2 100644 --- a/arch/powerpc/platforms/52xx/lite5200_pm.c +++ b/arch/powerpc/platforms/52xx/lite5200_pm.c @@ -1,6 +1,8 @@ // SPDX-License-Identifier: GPL-2.0 #include #include +#include + #include #include #include diff --git a/arch/powerpc/platforms/52xx/media5200.c b/arch/powerpc/platforms/52xx/media5200.c index 110c444f4bc794f67f6ad6101a694f0e566be636..ee367ff3ec8a49e5ce80ba04638162f0b82fb0c9 100644 --- a/arch/powerpc/platforms/52xx/media5200.c +++ b/arch/powerpc/platforms/52xx/media5200.c @@ -20,8 +20,9 @@ #include #include #include +#include +#include #include -#include #include #include diff --git a/arch/powerpc/platforms/52xx/mpc5200_simple.c b/arch/powerpc/platforms/52xx/mpc5200_simple.c index b9f5675b0a1d01fb98a07392a91ccb94ba8f4c32..cc349d579061e2038f6a8d908e4782be40681b08 100644 --- a/arch/powerpc/platforms/52xx/mpc5200_simple.c +++ b/arch/powerpc/platforms/52xx/mpc5200_simple.c @@ -22,8 +22,8 @@ */ #undef DEBUG +#include #include -#include #include #include diff --git a/arch/powerpc/platforms/52xx/mpc52xx_common.c b/arch/powerpc/platforms/52xx/mpc52xx_common.c index 565e3a83dc9ee1c1d0dc5de9dbc73d711d97fc05..4348506d667dc3ce25c3d9c7d47f65cc54b51dc4 100644 --- a/arch/powerpc/platforms/52xx/mpc52xx_common.c +++ b/arch/powerpc/platforms/52xx/mpc52xx_common.c @@ -15,11 +15,11 @@ #include #include #include +#include #include #include #include #include -#include #include /* MPC5200 device tree match tables */ @@ -308,7 +308,7 @@ int mpc5200_psc_ac97_gpio_reset(int psc_number) spin_lock_irqsave(&gpio_lock, flags); - /* Reconfiure pin-muxing to gpio */ + /* Reconfigure pin-muxing to gpio */ mux = in_be32(&simple_gpio->port_config); out_be32(&simple_gpio->port_config, mux & (~gpio)); diff --git a/arch/powerpc/platforms/52xx/mpc52xx_gpt.c b/arch/powerpc/platforms/52xx/mpc52xx_gpt.c index f862b48b48242dd8d0fd40a2b3084b0a0c143315..968f5b727273f279cad159f14c00b552a0cb76d0 100644 --- a/arch/powerpc/platforms/52xx/mpc52xx_gpt.c +++ b/arch/powerpc/platforms/52xx/mpc52xx_gpt.c @@ -5,7 +5,7 @@ * Copyright (c) 2009 Secret Lab Technologies Ltd. * Copyright (c) 2008 Sascha Hauer , Pengutronix * - * This file is a driver for the the General Purpose Timer (gpt) devices + * This file is a driver for the General Purpose Timer (gpt) devices * found on the MPC5200 SoC. Each timer has an IO pin which can be used * for GPIO or can be used to raise interrupts. The timer function can * be used independently from the IO pin, or it can be used to control @@ -55,6 +55,8 @@ #include #include #include +#include +#include #include #include #include @@ -398,7 +400,7 @@ static int mpc52xx_gpt_do_start(struct mpc52xx_gpt_priv *gpt, u64 period, set |= MPC52xx_GPT_MODE_CONTINUOUS; /* Determine the number of clocks in the requested period. 64 bit - * arithmatic is done here to preserve the precision until the value + * arithmetic is done here to preserve the precision until the value * is scaled back down into the u32 range. Period is in 'ns', bus * frequency is in Hz. */ clocks = period * (u64)gpt->ipb_freq; @@ -502,7 +504,7 @@ u64 mpc52xx_gpt_timer_period(struct mpc52xx_gpt_priv *gpt) if (prescale == 0) prescale = 0x10000; period = period * prescale * 1000000000ULL; - do_div(period, (u64)gpt->ipb_freq); + do_div(period, gpt->ipb_freq); return period; } EXPORT_SYMBOL(mpc52xx_gpt_timer_period); diff --git a/arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c b/arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c index b91ebebd9ff20e70da9a38f1c3477215ec80ae0b..48038aaedbd3672e42c92193cb3f794231785264 100644 --- a/arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c +++ b/arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c @@ -11,11 +11,12 @@ #include #include #include +#include +#include #include #include #include #include -#include #include #include @@ -104,7 +105,7 @@ static void mpc52xx_lpbfifo_kick(struct mpc52xx_lpbfifo_request *req) * * Configure the watermarks so DMA will always complete correctly. * It may be worth experimenting with the ALARM value to see if - * there is a performance impacit. However, if it is wrong there + * there is a performance impact. However, if it is wrong there * is a risk of DMA not transferring the last chunk of data */ if (write) { diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pci.c b/arch/powerpc/platforms/52xx/mpc52xx_pci.c index af0f799952147b05438f2bfc8d2c701d06657a20..859e2818c43d5736aa15d8e242ced26c4b78adb0 100644 --- a/arch/powerpc/platforms/52xx/mpc52xx_pci.c +++ b/arch/powerpc/platforms/52xx/mpc52xx_pci.c @@ -13,6 +13,7 @@ #undef DEBUG #include +#include #include #include #include @@ -242,7 +243,7 @@ mpc52xx_pci_setup(struct pci_controller *hose, u32 tmp; int iwcr0 = 0, iwcr1 = 0, iwcr2 = 0; - pr_debug("mpc52xx_pci_setup(hose=%p, pci_regs=%p)\n", hose, pci_regs); + pr_debug("%s(hose=%p, pci_regs=%p)\n", __func__, hose, pci_regs); /* pci_process_bridge_OF_ranges() found all our addresses for us; * now store them in the right places */ @@ -257,11 +258,7 @@ mpc52xx_pci_setup(struct pci_controller *hose, /* Memory windows */ res = &hose->mem_resources[0]; if (res->flags) { - pr_debug("mem_resource[0] = " - "{.start=%llx, .end=%llx, .flags=%llx}\n", - (unsigned long long)res->start, - (unsigned long long)res->end, - (unsigned long long)res->flags); + pr_debug("mem_resource[0] = %pr\n", res); out_be32(&pci_regs->iw0btar, MPC52xx_PCI_IWBTAR_TRANSLATION(res->start, res->start, resource_size(res))); @@ -274,8 +271,7 @@ mpc52xx_pci_setup(struct pci_controller *hose, res = &hose->mem_resources[1]; if (res->flags) { - pr_debug("mem_resource[1] = {.start=%x, .end=%x, .flags=%lx}\n", - res->start, res->end, res->flags); + pr_debug("mem_resource[1] = %pr\n", res); out_be32(&pci_regs->iw1btar, MPC52xx_PCI_IWBTAR_TRANSLATION(res->start, res->start, resource_size(res))); @@ -292,11 +288,8 @@ mpc52xx_pci_setup(struct pci_controller *hose, printk(KERN_ERR "%s: Didn't find IO resources\n", __FILE__); return; } - pr_debug(".io_resource={.start=%llx,.end=%llx,.flags=%llx} " - ".io_base_phys=0x%p\n", - (unsigned long long)res->start, - (unsigned long long)res->end, - (unsigned long long)res->flags, (void*)hose->io_base_phys); + pr_debug(".io_resource = %pr .io_base_phys=0x%pa\n", + res, &hose->io_base_phys); out_be32(&pci_regs->iw2btar, MPC52xx_PCI_IWBTAR_TRANSLATION(hose->io_base_phys, res->start, @@ -336,8 +329,7 @@ mpc52xx_pci_fixup_resources(struct pci_dev *dev) { int i; - pr_debug("mpc52xx_pci_fixup_resources() %.4x:%.4x\n", - dev->vendor, dev->device); + pr_debug("%s() %.4x:%.4x\n", __func__, dev->vendor, dev->device); /* We don't rely on boot loader for PCI and resets all devices */ diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pic.c b/arch/powerpc/platforms/52xx/mpc52xx_pic.c index 76a8102bdb987588b95120a387f757499045d160..1e0a5e9644dc1dfb91f938f1553b172044496159 100644 --- a/arch/powerpc/platforms/52xx/mpc52xx_pic.c +++ b/arch/powerpc/platforms/52xx/mpc52xx_pic.c @@ -101,8 +101,9 @@ #include #include #include +#include +#include #include -#include #include /* HW IRQ mapping */ diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pm.c b/arch/powerpc/platforms/52xx/mpc52xx_pm.c index b1d208ded981982d09bbd2135e5dddf9f311d0a7..549b3629e39a6a1b3c1aac378b00094a41d084a2 100644 --- a/arch/powerpc/platforms/52xx/mpc52xx_pm.c +++ b/arch/powerpc/platforms/52xx/mpc52xx_pm.c @@ -2,6 +2,8 @@ #include #include #include +#include + #include #include #include diff --git a/arch/powerpc/platforms/82xx/ep8248e.c b/arch/powerpc/platforms/82xx/ep8248e.c index 369ebb1b7af15cd8e98929163c5d2d31562f457c..28e627f8a320f5678cfa934fba7bde2c3a0e5dab 100644 --- a/arch/powerpc/platforms/82xx/ep8248e.c +++ b/arch/powerpc/platforms/82xx/ep8248e.c @@ -20,7 +20,6 @@ #include #include #include -#include #include #include diff --git a/arch/powerpc/platforms/82xx/km82xx.c b/arch/powerpc/platforms/82xx/km82xx.c index 745ed61df5d81e39bf03aca53cccd12c41810a23..1c8bbf4251d97db5669db9911e364b9fde92a147 100644 --- a/arch/powerpc/platforms/82xx/km82xx.c +++ b/arch/powerpc/platforms/82xx/km82xx.c @@ -20,7 +20,6 @@ #include #include #include -#include #include #include diff --git a/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c b/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c index 285bfe19b798f6c90aa919a5453bd8b029760fc3..cf3210042a2e197c42cd832cbe15323d09a8b6b1 100644 --- a/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c +++ b/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c @@ -14,9 +14,9 @@ #include #include #include +#include #include -#include #include #include "pq2.h" diff --git a/arch/powerpc/platforms/83xx/km83xx.c b/arch/powerpc/platforms/83xx/km83xx.c index d9eed0decb28f225436bdda091bee8b250db0549..907acdecc94afea192d390fe301c8f8ce0d416d6 100644 --- a/arch/powerpc/platforms/83xx/km83xx.c +++ b/arch/powerpc/platforms/83xx/km83xx.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c b/arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c index a38372f9ac12c65cc59bfc7ac888a376523c6c78..abb62fa630effbc7a5444de55f07411a96c5b87c 100644 --- a/arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c +++ b/arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c @@ -8,17 +8,16 @@ */ #include +#include #include #include #include #include #include -#include -#include #include #include +#include #include -#include #include /* @@ -116,21 +115,17 @@ static int mcu_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) static int mcu_gpiochip_add(struct mcu *mcu) { - struct device_node *np; + struct device *dev = &mcu->client->dev; struct gpio_chip *gc = &mcu->gc; - np = of_find_compatible_node(NULL, NULL, "fsl,mcu-mpc8349emitx"); - if (!np) - return -ENODEV; - gc->owner = THIS_MODULE; - gc->label = kasprintf(GFP_KERNEL, "%pOF", np); + gc->label = kasprintf(GFP_KERNEL, "%pfw", dev_fwnode(dev)); gc->can_sleep = 1; gc->ngpio = MCU_NUM_GPIO; gc->base = -1; gc->set = mcu_gpio_set; gc->direction_output = mcu_gpio_dir_out; - gc->of_node = np; + gc->parent = dev; return gpiochip_add_data(gc, mcu); } diff --git a/arch/powerpc/platforms/83xx/mpc832x_mds.c b/arch/powerpc/platforms/83xx/mpc832x_mds.c index 850d566ef900bde97821140f2b6476ed64101b73..435344405d2c7dcbb3dced8992bab02bd0fb88ff 100644 --- a/arch/powerpc/platforms/83xx/mpc832x_mds.c +++ b/arch/powerpc/platforms/83xx/mpc832x_mds.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/powerpc/platforms/83xx/mpc832x_rdb.c b/arch/powerpc/platforms/83xx/mpc832x_rdb.c index b6133a237a70953e867ccd0a39c5f5bab1aeecc2..bb8caa5071f8cf356fde2934a22154d2f43cb20f 100644 --- a/arch/powerpc/platforms/83xx/mpc832x_rdb.c +++ b/arch/powerpc/platforms/83xx/mpc832x_rdb.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include diff --git a/arch/powerpc/platforms/83xx/mpc834x_itx.c b/arch/powerpc/platforms/83xx/mpc834x_itx.c index 9630f3aa4d9c08fd9611930fe3e5513c3924aaf7..6a110f275304ade3b568a0eac86946c7857b04a8 100644 --- a/arch/powerpc/platforms/83xx/mpc834x_itx.c +++ b/arch/powerpc/platforms/83xx/mpc834x_itx.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/powerpc/platforms/83xx/mpc834x_mds.c b/arch/powerpc/platforms/83xx/mpc834x_mds.c index 0713deffb40cdfd48816de1e374152bac0471b10..7dde5a75332b6033405fa5a8d35dc239de005c7f 100644 --- a/arch/powerpc/platforms/83xx/mpc834x_mds.c +++ b/arch/powerpc/platforms/83xx/mpc834x_mds.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -27,7 +28,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/powerpc/platforms/83xx/mpc836x_mds.c b/arch/powerpc/platforms/83xx/mpc836x_mds.c index da4cf52cb55b5ba0b943841c53670b4cad7d6c35..b1e6665be5d3572cf06cd4b343c1d334ef9cfe30 100644 --- a/arch/powerpc/platforms/83xx/mpc836x_mds.c +++ b/arch/powerpc/platforms/83xx/mpc836x_mds.c @@ -35,7 +35,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/powerpc/platforms/83xx/mpc836x_rdk.c b/arch/powerpc/platforms/83xx/mpc836x_rdk.c index 3427ad0d9d387a9bc1639486e8901ed497df54f5..731bc5ce726de646cf33b09ee6fe7b0f25c3da28 100644 --- a/arch/powerpc/platforms/83xx/mpc836x_rdk.c +++ b/arch/powerpc/platforms/83xx/mpc836x_rdk.c @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/powerpc/platforms/83xx/mpc837x_mds.c b/arch/powerpc/platforms/83xx/mpc837x_mds.c index fc88ab97f6e3d1988b8aca9c7c3a2a71c1375a2c..fa3538803af761999b2cde1c30d466b45fed03c9 100644 --- a/arch/powerpc/platforms/83xx/mpc837x_mds.c +++ b/arch/powerpc/platforms/83xx/mpc837x_mds.c @@ -9,12 +9,12 @@ #include #include +#include #include #include #include #include -#include #include #include "mpc83xx.h" diff --git a/arch/powerpc/platforms/83xx/suspend.c b/arch/powerpc/platforms/83xx/suspend.c index bb147d34d4a69fd555c401704fae56001af3b354..6d47a5b81485f17b1144b33373aec19827a2c355 100644 --- a/arch/powerpc/platforms/83xx/suspend.c +++ b/arch/powerpc/platforms/83xx/suspend.c @@ -322,18 +322,15 @@ static const struct platform_suspend_ops mpc83xx_suspend_ops = { static const struct of_device_id pmc_match[]; static int pmc_probe(struct platform_device *ofdev) { - const struct of_device_id *match; struct device_node *np = ofdev->dev.of_node; struct resource res; const struct pmc_type *type; int ret = 0; - match = of_match_device(pmc_match, &ofdev->dev); - if (!match) + type = of_device_get_match_data(&ofdev->dev); + if (!type) return -EINVAL; - type = match->data; - if (!of_device_is_available(np)) return -ENODEV; diff --git a/arch/powerpc/platforms/83xx/usb.c b/arch/powerpc/platforms/83xx/usb.c index b0bda20aaccf82d0b6e56b361c8751ffb55a159e..e2a13a052f961f314a2b240b787b9f3759f89a70 100644 --- a/arch/powerpc/platforms/83xx/usb.c +++ b/arch/powerpc/platforms/83xx/usb.c @@ -11,9 +11,9 @@ #include #include #include +#include #include -#include #include #include "mpc83xx.h" diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig index 4142ebf0138252f6ad79004674e1ba7cda656824..2be17ffe8714f42e9b6d3d7bebff53163c6e9e12 100644 --- a/arch/powerpc/platforms/85xx/Kconfig +++ b/arch/powerpc/platforms/85xx/Kconfig @@ -16,15 +16,6 @@ if FSL_SOC_BOOKE if PPC32 -config FSL_85XX_CACHE_SRAM - bool - select PPC_LIB_RHEAP - help - When selected, this option enables cache-sram support - for memory allocation on P1/P2 QorIQ platforms. - cache-sram-size and cache-sram-offset kernel boot - parameters should be passed when this option is enabled. - config BSC9131_RDB bool "Freescale BSC9131RDB" select DEFAULT_UIMAGE diff --git a/arch/powerpc/platforms/85xx/corenet_generic.c b/arch/powerpc/platforms/85xx/corenet_generic.c index 17ae75d62518a014b36d9c9c0debfd0ef1873b57..28d6b36f1ccdb96eae6fe2ba912d3dd0e88e6ad0 100644 --- a/arch/powerpc/platforms/85xx/corenet_generic.c +++ b/arch/powerpc/platforms/85xx/corenet_generic.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/powerpc/platforms/85xx/ge_imp3a.c b/arch/powerpc/platforms/85xx/ge_imp3a.c index 743c65e4d8e4546fedc76d0a569173f03f2cb53e..8e827376d97b8969046ed60b77b507d9c23394e1 100644 --- a/arch/powerpc/platforms/85xx/ge_imp3a.c +++ b/arch/powerpc/platforms/85xx/ge_imp3a.c @@ -17,13 +17,13 @@ #include #include #include +#include #include #include #include #include #include -#include #include #include #include diff --git a/arch/powerpc/platforms/85xx/ksi8560.c b/arch/powerpc/platforms/85xx/ksi8560.c index 6ef8580fdc0e355d4720aebee2fd8f841fddb817..bdf9d42f8521d58c5f13e36a418a6dd06fa4ebae 100644 --- a/arch/powerpc/platforms/85xx/ksi8560.c +++ b/arch/powerpc/platforms/85xx/ksi8560.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include diff --git a/arch/powerpc/platforms/85xx/mpc8536_ds.c b/arch/powerpc/platforms/85xx/mpc8536_ds.c index 53bccb8bbcbe28cfa55b75c7ce4ae701ff7d5efb..e5d7386ad61258b0327bb8c35c36c00d09cbad5b 100644 --- a/arch/powerpc/platforms/85xx/mpc8536_ds.c +++ b/arch/powerpc/platforms/85xx/mpc8536_ds.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/powerpc/platforms/85xx/mpc85xx_cds.c b/arch/powerpc/platforms/85xx/mpc85xx_cds.c index 5bd48703025649c37d37874f31dbbf4958caf542..48f3acfece0b2aaca7cc2fab328419fedaaa1af1 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_cds.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_cds.c @@ -21,6 +21,8 @@ #include #include #include +#include +#include #include #include @@ -33,7 +35,6 @@ #include #include #include -#include #include #include #include @@ -151,7 +152,7 @@ static void __init mpc85xx_cds_pci_irq_fixup(struct pci_dev *dev) */ case PCI_DEVICE_ID_VIA_82C586_2: /* There are two USB controllers. - * Identify them by functon number + * Identify them by function number */ if (PCI_FUNC(dev->devfn) == 3) dev->irq = 11; diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ds.c b/arch/powerpc/platforms/85xx/mpc85xx_ds.c index 2157a8017aa47e42b8d75b267c3505cf24adc2da..f8d2c97f39bd893c7934dcbf33596b1a04b75772 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_ds.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_ds.c @@ -15,13 +15,13 @@ #include #include #include +#include #include #include #include #include #include -#include #include #include #include diff --git a/arch/powerpc/platforms/85xx/mpc85xx_mds.c b/arch/powerpc/platforms/85xx/mpc85xx_mds.c index 7759eca7d535a635b09ec5476b0a6aa8dd8d0fa8..3a2ac410af18b7977bc2be2acd03d846da9d3384 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_mds.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_mds.c @@ -39,7 +39,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/powerpc/platforms/85xx/mpc85xx_rdb.c b/arch/powerpc/platforms/85xx/mpc85xx_rdb.c index 80a80174768c3ab144db3b1bd6010675465b8b25..d99aba158235cdc8e7bec7100077646a6badf893 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_rdb.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_rdb.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/powerpc/platforms/85xx/p1010rdb.c b/arch/powerpc/platforms/85xx/p1010rdb.c index 24855284b14ad9f8b026449940acb3fb256c9c36..8ba9306a96b6fdc2679ef234f05a958e667a54fe 100644 --- a/arch/powerpc/platforms/85xx/p1010rdb.c +++ b/arch/powerpc/platforms/85xx/p1010rdb.c @@ -16,7 +16,6 @@ #include #include #include -#include #include #include diff --git a/arch/powerpc/platforms/85xx/p1022_ds.c b/arch/powerpc/platforms/85xx/p1022_ds.c index 1f1af0557470feb924448adc98653552d1066209..537599906146441c8c068fe5b1834a2c1bd97ef6 100644 --- a/arch/powerpc/platforms/85xx/p1022_ds.c +++ b/arch/powerpc/platforms/85xx/p1022_ds.c @@ -18,6 +18,7 @@ #include #include +#include #include #include #include diff --git a/arch/powerpc/platforms/85xx/p1022_rdk.c b/arch/powerpc/platforms/85xx/p1022_rdk.c index fd9e3e7ef23475f7c9887a4338c981f546f52301..bc58a99164c9841fc19b1e4c9beaf8f82ff9d7ab 100644 --- a/arch/powerpc/platforms/85xx/p1022_rdk.c +++ b/arch/powerpc/platforms/85xx/p1022_rdk.c @@ -14,6 +14,7 @@ #include #include +#include #include #include #include diff --git a/arch/powerpc/platforms/85xx/p1023_rdb.c b/arch/powerpc/platforms/85xx/p1023_rdb.c index 3b9cc4979641ca25e2f337ff48b876ad7537398d..c04868eb2eb19ee0ce85c5a2174bcc44a315b409 100644 --- a/arch/powerpc/platforms/85xx/p1023_rdb.c +++ b/arch/powerpc/platforms/85xx/p1023_rdb.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -22,7 +23,6 @@ #include #include #include -#include #include #include #include "smp.h" diff --git a/arch/powerpc/platforms/85xx/qemu_e500.c b/arch/powerpc/platforms/85xx/qemu_e500.c index 4c4d577effd93a1ce5678762321fd04db427afbe..64109ad6736c14ca97833adc5fff251e338b93e5 100644 --- a/arch/powerpc/platforms/85xx/qemu_e500.c +++ b/arch/powerpc/platforms/85xx/qemu_e500.c @@ -12,6 +12,7 @@ */ #include +#include #include #include #include diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c index a1c6a7827c8f060c9874705be7af417f348efb89..9c43cf32f4c9fc4f3be82c00978ea5e5f7acb654 100644 --- a/arch/powerpc/platforms/85xx/smp.c +++ b/arch/powerpc/platforms/85xx/smp.c @@ -208,7 +208,7 @@ static int smp_85xx_start_cpu(int cpu) * The bootpage and highmem can be accessed via ioremap(), but * we need to directly access the spinloop if its in lowmem. */ - ioremappable = *cpu_rel_addr > virt_to_phys(high_memory); + ioremappable = *cpu_rel_addr > virt_to_phys(high_memory - 1); /* Map the spin table */ if (ioremappable) diff --git a/arch/powerpc/platforms/85xx/socrates.c b/arch/powerpc/platforms/85xx/socrates.c index 166b3515ba73e5f527218ae8c775305a41fa959e..09f64470c7658c985836debd3346b2299c442619 100644 --- a/arch/powerpc/platforms/85xx/socrates.c +++ b/arch/powerpc/platforms/85xx/socrates.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include diff --git a/arch/powerpc/platforms/85xx/stx_gp3.c b/arch/powerpc/platforms/85xx/stx_gp3.c index 69e917e3ba1c860f6f91c3ce8095d55a42ae9e3f..6b1fe7bb3a8cb93372b347ea8964d4f45cf2f24a 100644 --- a/arch/powerpc/platforms/85xx/stx_gp3.c +++ b/arch/powerpc/platforms/85xx/stx_gp3.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include diff --git a/arch/powerpc/platforms/85xx/tqm85xx.c b/arch/powerpc/platforms/85xx/tqm85xx.c index 95a1a1118a3193eb4c846b2e12bc77da5c119093..d187f4b8bff635468fe262e8900a0e1a4f808af3 100644 --- a/arch/powerpc/platforms/85xx/tqm85xx.c +++ b/arch/powerpc/platforms/85xx/tqm85xx.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include diff --git a/arch/powerpc/platforms/85xx/xes_mpc85xx.c b/arch/powerpc/platforms/85xx/xes_mpc85xx.c index 397e158c1edba62d5d0f58741f1add83f72b2306..5836e4ecb7a01207beae1a17abf62fe3d6414e0f 100644 --- a/arch/powerpc/platforms/85xx/xes_mpc85xx.c +++ b/arch/powerpc/platforms/85xx/xes_mpc85xx.c @@ -16,13 +16,13 @@ #include #include #include +#include #include #include #include #include #include -#include #include #include diff --git a/arch/powerpc/platforms/86xx/gef_ppc9a.c b/arch/powerpc/platforms/86xx/gef_ppc9a.c index 44bbbc535e1df7a7a9a98bd3743541f1348b62ae..8e358fa0bc412e848e7abf250ca459dc1eb4359f 100644 --- a/arch/powerpc/platforms/86xx/gef_ppc9a.c +++ b/arch/powerpc/platforms/86xx/gef_ppc9a.c @@ -18,12 +18,12 @@ #include #include #include +#include #include #include #include #include -#include #include #include @@ -180,7 +180,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_USB, * * This function is called to determine whether the BSP is compatible with the * supplied device-tree, which is assumed to be the correct one for the actual - * board. It is expected thati, in the future, a kernel may support multiple + * board. It is expected that, in the future, a kernel may support multiple * boards. */ static int __init gef_ppc9a_probe(void) diff --git a/arch/powerpc/platforms/86xx/gef_sbc310.c b/arch/powerpc/platforms/86xx/gef_sbc310.c index 46d6d3d4957a49115c7f4469d3bd3153cbb93c21..b5b2733567cb2ba43e7b5c682f900ffbe2a95496 100644 --- a/arch/powerpc/platforms/86xx/gef_sbc310.c +++ b/arch/powerpc/platforms/86xx/gef_sbc310.c @@ -18,12 +18,12 @@ #include #include #include +#include #include #include #include #include -#include #include #include @@ -167,7 +167,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_USB, * * This function is called to determine whether the BSP is compatible with the * supplied device-tree, which is assumed to be the correct one for the actual - * board. It is expected thati, in the future, a kernel may support multiple + * board. It is expected that, in the future, a kernel may support multiple * boards. */ static int __init gef_sbc310_probe(void) diff --git a/arch/powerpc/platforms/86xx/gef_sbc610.c b/arch/powerpc/platforms/86xx/gef_sbc610.c index acf2c6c3c1eb79d7e8ed69e480bd76af1cf089a1..bb4c8e6b44d0815016737832fa955ea30857e479 100644 --- a/arch/powerpc/platforms/86xx/gef_sbc610.c +++ b/arch/powerpc/platforms/86xx/gef_sbc610.c @@ -18,12 +18,12 @@ #include #include #include +#include #include #include #include #include -#include #include #include @@ -157,7 +157,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_USB, * * This function is called to determine whether the BSP is compatible with the * supplied device-tree, which is assumed to be the correct one for the actual - * board. It is expected thati, in the future, a kernel may support multiple + * board. It is expected that, in the future, a kernel may support multiple * boards. */ static int __init gef_sbc610_probe(void) diff --git a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c index 7733d0607da2e3bd03ba93975c4bf2e01b1448ad..b593b9afd30a9438a340618bc47eab4dfee2a3bf 100644 --- a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c +++ b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c @@ -20,12 +20,13 @@ #include #include #include +#include +#include #include #include #include #include -#include #include #include diff --git a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c index a6b8ffcbf01a2f29f3bd9183a7d6af552f0a499a..5294394c9c077114c57a5f45ac3a6a7532f512f4 100644 --- a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c +++ b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/powerpc/platforms/86xx/mvme7100.c b/arch/powerpc/platforms/86xx/mvme7100.c index ee983613570c057e634e77c86d655283b01bb10a..b2cc32a32d0bff068ee7f28022b875fd026d000b 100644 --- a/arch/powerpc/platforms/86xx/mvme7100.c +++ b/arch/powerpc/platforms/86xx/mvme7100.c @@ -19,6 +19,7 @@ #include #include +#include #include #include #include diff --git a/arch/powerpc/platforms/8xx/Makefile b/arch/powerpc/platforms/8xx/Makefile index 27a7c6f828e01b449bb744b5a4b14cdc1cea4849..5a098f7d5d31c815c8a848ec921a1bf0e9f01d2b 100644 --- a/arch/powerpc/platforms/8xx/Makefile +++ b/arch/powerpc/platforms/8xx/Makefile @@ -3,7 +3,7 @@ # Makefile for the PowerPC 8xx linux kernel. # obj-y += m8xx_setup.o machine_check.o pic.o -obj-$(CONFIG_CPM1) += cpm1.o +obj-$(CONFIG_CPM1) += cpm1.o cpm1-ic.o obj-$(CONFIG_UCODE_PATCH) += micropatch.o obj-$(CONFIG_MPC885ADS) += mpc885ads_setup.o obj-$(CONFIG_MPC86XADS) += mpc86xads_setup.o diff --git a/arch/powerpc/platforms/8xx/adder875.c b/arch/powerpc/platforms/8xx/adder875.c index 651486acb896d39020907af812e0d0765038f68a..10e6e4fe77fcbd7727628678a55b13dac5602a94 100644 --- a/arch/powerpc/platforms/8xx/adder875.c +++ b/arch/powerpc/platforms/8xx/adder875.c @@ -15,9 +15,9 @@ #include #include #include -#include #include "mpc8xx.h" +#include "pic.h" struct cpm_pin { int port, pin, flags; @@ -104,7 +104,7 @@ define_machine(adder875) { .name = "Adder MPC875", .probe = adder875_probe, .setup_arch = adder875_setup, - .init_IRQ = mpc8xx_pics_init, + .init_IRQ = mpc8xx_pic_init, .get_irq = mpc8xx_get_irq, .restart = mpc8xx_restart, .calibrate_decr = generic_calibrate_decr, diff --git a/arch/powerpc/platforms/8xx/cpm1-ic.c b/arch/powerpc/platforms/8xx/cpm1-ic.c new file mode 100644 index 0000000000000000000000000000000000000000..a18fc7c99f83a0844d38eeb442bc5501b27baa4d --- /dev/null +++ b/arch/powerpc/platforms/8xx/cpm1-ic.c @@ -0,0 +1,188 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Interrupt controller for the + * Communication Processor Module. + * Copyright (c) 1997 Dan error_act (dmalek@jlc.net) + */ +#include +#include +#include +#include +#include + +struct cpm_pic_data { + cpic8xx_t __iomem *reg; + struct irq_domain *host; +}; + +static void cpm_mask_irq(struct irq_data *d) +{ + struct cpm_pic_data *data = irq_data_get_irq_chip_data(d); + unsigned int cpm_vec = (unsigned int)irqd_to_hwirq(d); + + clrbits32(&data->reg->cpic_cimr, (1 << cpm_vec)); +} + +static void cpm_unmask_irq(struct irq_data *d) +{ + struct cpm_pic_data *data = irq_data_get_irq_chip_data(d); + unsigned int cpm_vec = (unsigned int)irqd_to_hwirq(d); + + setbits32(&data->reg->cpic_cimr, (1 << cpm_vec)); +} + +static void cpm_end_irq(struct irq_data *d) +{ + struct cpm_pic_data *data = irq_data_get_irq_chip_data(d); + unsigned int cpm_vec = (unsigned int)irqd_to_hwirq(d); + + out_be32(&data->reg->cpic_cisr, (1 << cpm_vec)); +} + +static struct irq_chip cpm_pic = { + .name = "CPM PIC", + .irq_mask = cpm_mask_irq, + .irq_unmask = cpm_unmask_irq, + .irq_eoi = cpm_end_irq, +}; + +static int cpm_get_irq(struct irq_desc *desc) +{ + struct cpm_pic_data *data = irq_desc_get_handler_data(desc); + int cpm_vec; + + /* + * Get the vector by setting the ACK bit and then reading + * the register. + */ + out_be16(&data->reg->cpic_civr, 1); + cpm_vec = in_be16(&data->reg->cpic_civr); + cpm_vec >>= 11; + + return irq_linear_revmap(data->host, cpm_vec); +} + +static void cpm_cascade(struct irq_desc *desc) +{ + generic_handle_irq(cpm_get_irq(desc)); +} + +static int cpm_pic_host_map(struct irq_domain *h, unsigned int virq, + irq_hw_number_t hw) +{ + irq_set_chip_data(virq, h->host_data); + irq_set_status_flags(virq, IRQ_LEVEL); + irq_set_chip_and_handler(virq, &cpm_pic, handle_fasteoi_irq); + return 0; +} + +static const struct irq_domain_ops cpm_pic_host_ops = { + .map = cpm_pic_host_map, +}; + +static int cpm_pic_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct resource *res; + int irq; + struct cpm_pic_data *data; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -ENODEV; + + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + data->reg = devm_ioremap(dev, res->start, resource_size(res)); + if (!data->reg) + return -ENODEV; + + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; + + /* Initialize the CPM interrupt controller. */ + out_be32(&data->reg->cpic_cicr, + (CICR_SCD_SCC4 | CICR_SCC_SCC3 | CICR_SCB_SCC2 | CICR_SCA_SCC1) | + ((virq_to_hw(irq) / 2) << 13) | CICR_HP_MASK); + + out_be32(&data->reg->cpic_cimr, 0); + + data->host = irq_domain_add_linear(dev->of_node, 64, &cpm_pic_host_ops, data); + if (!data->host) + return -ENODEV; + + irq_set_handler_data(irq, data); + irq_set_chained_handler(irq, cpm_cascade); + + setbits32(&data->reg->cpic_cicr, CICR_IEN); + + return 0; +} + +static const struct of_device_id cpm_pic_match[] = { + { + .compatible = "fsl,cpm1-pic", + }, { + .type = "cpm-pic", + .compatible = "CPM", + }, {}, +}; + +static struct platform_driver cpm_pic_driver = { + .driver = { + .name = "cpm-pic", + .of_match_table = cpm_pic_match, + }, + .probe = cpm_pic_probe, +}; + +static int __init cpm_pic_init(void) +{ + return platform_driver_register(&cpm_pic_driver); +} +arch_initcall(cpm_pic_init); + +/* + * The CPM can generate the error interrupt when there is a race condition + * between generating and masking interrupts. All we have to do is ACK it + * and return. This is a no-op function so we don't need any special + * tests in the interrupt handler. + */ +static irqreturn_t cpm_error_interrupt(int irq, void *dev) +{ + return IRQ_HANDLED; +} + +static int cpm_error_probe(struct platform_device *pdev) +{ + int irq; + + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; + + return request_irq(irq, cpm_error_interrupt, IRQF_NO_THREAD, "error", NULL); +} + +static const struct of_device_id cpm_error_ids[] = { + { .compatible = "fsl,cpm1" }, + { .type = "cpm" }, + {}, +}; + +static struct platform_driver cpm_error_driver = { + .driver = { + .name = "cpm-error", + .of_match_table = cpm_error_ids, + }, + .probe = cpm_error_probe, +}; + +static int __init cpm_error_init(void) +{ + return platform_driver_register(&cpm_error_driver); +} +subsys_initcall(cpm_error_init); diff --git a/arch/powerpc/platforms/8xx/cpm1.c b/arch/powerpc/platforms/8xx/cpm1.c index c58b6f1c40e35c3e7b9d7a2e600c89ac40b7ca82..bb38c8d8f8deac6f8a41f140fd75ace04add824a 100644 --- a/arch/powerpc/platforms/8xx/cpm1.c +++ b/arch/powerpc/platforms/8xx/cpm1.c @@ -33,12 +33,12 @@ #include #include #include +#include #include #include #include #include #include -#include #include #include @@ -51,145 +51,6 @@ cpm8xx_t __iomem *cpmp; /* Pointer to comm processor space */ immap_t __iomem *mpc8xx_immr = (void __iomem *)VIRT_IMMR_BASE; -static cpic8xx_t __iomem *cpic_reg; - -static struct irq_domain *cpm_pic_host; - -static void cpm_mask_irq(struct irq_data *d) -{ - unsigned int cpm_vec = (unsigned int)irqd_to_hwirq(d); - - clrbits32(&cpic_reg->cpic_cimr, (1 << cpm_vec)); -} - -static void cpm_unmask_irq(struct irq_data *d) -{ - unsigned int cpm_vec = (unsigned int)irqd_to_hwirq(d); - - setbits32(&cpic_reg->cpic_cimr, (1 << cpm_vec)); -} - -static void cpm_end_irq(struct irq_data *d) -{ - unsigned int cpm_vec = (unsigned int)irqd_to_hwirq(d); - - out_be32(&cpic_reg->cpic_cisr, (1 << cpm_vec)); -} - -static struct irq_chip cpm_pic = { - .name = "CPM PIC", - .irq_mask = cpm_mask_irq, - .irq_unmask = cpm_unmask_irq, - .irq_eoi = cpm_end_irq, -}; - -int cpm_get_irq(void) -{ - int cpm_vec; - - /* - * Get the vector by setting the ACK bit and then reading - * the register. - */ - out_be16(&cpic_reg->cpic_civr, 1); - cpm_vec = in_be16(&cpic_reg->cpic_civr); - cpm_vec >>= 11; - - return irq_linear_revmap(cpm_pic_host, cpm_vec); -} - -static int cpm_pic_host_map(struct irq_domain *h, unsigned int virq, - irq_hw_number_t hw) -{ - pr_debug("cpm_pic_host_map(%d, 0x%lx)\n", virq, hw); - - irq_set_status_flags(virq, IRQ_LEVEL); - irq_set_chip_and_handler(virq, &cpm_pic, handle_fasteoi_irq); - return 0; -} - -/* - * The CPM can generate the error interrupt when there is a race condition - * between generating and masking interrupts. All we have to do is ACK it - * and return. This is a no-op function so we don't need any special - * tests in the interrupt handler. - */ -static irqreturn_t cpm_error_interrupt(int irq, void *dev) -{ - return IRQ_HANDLED; -} - -static const struct irq_domain_ops cpm_pic_host_ops = { - .map = cpm_pic_host_map, -}; - -unsigned int __init cpm_pic_init(void) -{ - struct device_node *np = NULL; - struct resource res; - unsigned int sirq = 0, hwirq, eirq; - int ret; - - pr_debug("cpm_pic_init\n"); - - np = of_find_compatible_node(NULL, NULL, "fsl,cpm1-pic"); - if (np == NULL) - np = of_find_compatible_node(NULL, "cpm-pic", "CPM"); - if (np == NULL) { - printk(KERN_ERR "CPM PIC init: can not find cpm-pic node\n"); - return sirq; - } - - ret = of_address_to_resource(np, 0, &res); - if (ret) - goto end; - - cpic_reg = ioremap(res.start, resource_size(&res)); - if (cpic_reg == NULL) - goto end; - - sirq = irq_of_parse_and_map(np, 0); - if (!sirq) - goto end; - - /* Initialize the CPM interrupt controller. */ - hwirq = (unsigned int)virq_to_hw(sirq); - out_be32(&cpic_reg->cpic_cicr, - (CICR_SCD_SCC4 | CICR_SCC_SCC3 | CICR_SCB_SCC2 | CICR_SCA_SCC1) | - ((hwirq/2) << 13) | CICR_HP_MASK); - - out_be32(&cpic_reg->cpic_cimr, 0); - - cpm_pic_host = irq_domain_add_linear(np, 64, &cpm_pic_host_ops, NULL); - if (cpm_pic_host == NULL) { - printk(KERN_ERR "CPM2 PIC: failed to allocate irq host!\n"); - sirq = 0; - goto end; - } - - /* Install our own error handler. */ - np = of_find_compatible_node(NULL, NULL, "fsl,cpm1"); - if (np == NULL) - np = of_find_node_by_type(NULL, "cpm"); - if (np == NULL) { - printk(KERN_ERR "CPM PIC init: can not find cpm node\n"); - goto end; - } - - eirq = irq_of_parse_and_map(np, 0); - if (!eirq) - goto end; - - if (request_irq(eirq, cpm_error_interrupt, IRQF_NO_THREAD, "error", - NULL)) - printk(KERN_ERR "Could not allocate CPM error IRQ!"); - - setbits32(&cpic_reg->cpic_cicr, CICR_IEN); - -end: - of_node_put(np); - return sirq; -} void __init cpm_reset(void) { @@ -280,6 +141,7 @@ cpm_setbrg(uint brg, uint rate) out_be32(bp, (((BRG_UART_CLK_DIV16 / rate) - 1) << 1) | CPM_BRG_EN | CPM_BRG_DIV16); } +EXPORT_SYMBOL(cpm_setbrg); struct cpm_ioport16 { __be16 dir, par, odr_sor, dat, intr; diff --git a/arch/powerpc/platforms/8xx/ep88xc.c b/arch/powerpc/platforms/8xx/ep88xc.c index ebcf34a147894fd0b7624688e6eb1331f3fedce0..b3b22520b435fb56833eb5159a1f86d82d35ef24 100644 --- a/arch/powerpc/platforms/8xx/ep88xc.c +++ b/arch/powerpc/platforms/8xx/ep88xc.c @@ -20,6 +20,7 @@ #include #include "mpc8xx.h" +#include "pic.h" struct cpm_pin { int port, pin, flags; @@ -166,7 +167,7 @@ define_machine(ep88xc) { .name = "Embedded Planet EP88xC", .probe = ep88xc_probe, .setup_arch = ep88xc_setup_arch, - .init_IRQ = mpc8xx_pics_init, + .init_IRQ = mpc8xx_pic_init, .get_irq = mpc8xx_get_irq, .restart = mpc8xx_restart, .calibrate_decr = mpc8xx_calibrate_decr, diff --git a/arch/powerpc/platforms/8xx/m8xx_setup.c b/arch/powerpc/platforms/8xx/m8xx_setup.c index df4d57d07f9a044ecf123d19d169ad2f6eddd69f..24f358f86d16cdd2fa8f38796a27c1b4ba4b0ade 100644 --- a/arch/powerpc/platforms/8xx/m8xx_setup.c +++ b/arch/powerpc/platforms/8xx/m8xx_setup.c @@ -17,10 +17,11 @@ #include #include #include +#include +#include #include #include -#include #include #include @@ -28,9 +29,6 @@ #include "mpc8xx.h" -extern int cpm_pic_init(void); -extern int cpm_get_irq(void); - /* A place holder for time base interrupts, if they are ever enabled. */ static irqreturn_t timebase_interrupt(int irq, void *dev) { @@ -207,28 +205,3 @@ void __noreturn mpc8xx_restart(char *cmd) in_8(&clk_r->res[0]); panic("Restart failed\n"); } - -static void cpm_cascade(struct irq_desc *desc) -{ - generic_handle_irq(cpm_get_irq()); -} - -/* Initialize the internal interrupt controllers. The number of - * interrupts supported can vary with the processor type, and the - * 82xx family can have up to 64. - * External interrupts can be either edge or level triggered, and - * need to be initialized by the appropriate driver. - */ -void __init mpc8xx_pics_init(void) -{ - int irq; - - if (mpc8xx_pic_init()) { - printk(KERN_ERR "Failed interrupt 8xx controller initialization\n"); - return; - } - - irq = cpm_pic_init(); - if (irq) - irq_set_chained_handler(irq, cpm_cascade); -} diff --git a/arch/powerpc/platforms/8xx/mpc86xads_setup.c b/arch/powerpc/platforms/8xx/mpc86xads_setup.c index 8d02f5ff44819b3a99ee68dfadce282708f7502b..03267e4a44a9c068ce52019ad285668c160be15c 100644 --- a/arch/powerpc/platforms/8xx/mpc86xads_setup.c +++ b/arch/powerpc/platforms/8xx/mpc86xads_setup.c @@ -29,6 +29,7 @@ #include "mpc86xads.h" #include "mpc8xx.h" +#include "pic.h" struct cpm_pin { int port, pin, flags; @@ -140,7 +141,7 @@ define_machine(mpc86x_ads) { .name = "MPC86x ADS", .probe = mpc86xads_probe, .setup_arch = mpc86xads_setup_arch, - .init_IRQ = mpc8xx_pics_init, + .init_IRQ = mpc8xx_pic_init, .get_irq = mpc8xx_get_irq, .restart = mpc8xx_restart, .calibrate_decr = mpc8xx_calibrate_decr, diff --git a/arch/powerpc/platforms/8xx/mpc885ads_setup.c b/arch/powerpc/platforms/8xx/mpc885ads_setup.c index a0c83c1905c678a190396bbbf20ac5fb1256d3cb..b1e39f96de0002ef5972965a93a66d307ee4945c 100644 --- a/arch/powerpc/platforms/8xx/mpc885ads_setup.c +++ b/arch/powerpc/platforms/8xx/mpc885ads_setup.c @@ -42,6 +42,7 @@ #include "mpc885ads.h" #include "mpc8xx.h" +#include "pic.h" static u32 __iomem *bcsr, *bcsr5; @@ -216,7 +217,7 @@ define_machine(mpc885_ads) { .name = "Freescale MPC885 ADS", .probe = mpc885ads_probe, .setup_arch = mpc885ads_setup_arch, - .init_IRQ = mpc8xx_pics_init, + .init_IRQ = mpc8xx_pic_init, .get_irq = mpc8xx_get_irq, .restart = mpc8xx_restart, .calibrate_decr = mpc8xx_calibrate_decr, diff --git a/arch/powerpc/platforms/8xx/mpc8xx.h b/arch/powerpc/platforms/8xx/mpc8xx.h index 31cc2ecace4238bf6abef837e8f1d6cd486035c1..79fae33248661c84fcb091bbf8b1f3ab0a1b6593 100644 --- a/arch/powerpc/platforms/8xx/mpc8xx.h +++ b/arch/powerpc/platforms/8xx/mpc8xx.h @@ -15,7 +15,6 @@ extern void __noreturn mpc8xx_restart(char *cmd); extern void mpc8xx_calibrate_decr(void); extern int mpc8xx_set_rtc_time(struct rtc_time *tm); extern void mpc8xx_get_rtc_time(struct rtc_time *tm); -extern void mpc8xx_pics_init(void); extern unsigned int mpc8xx_get_irq(void); #endif /* __MPC8xx_H */ diff --git a/arch/powerpc/platforms/8xx/pic.c b/arch/powerpc/platforms/8xx/pic.c index 04a6abf14c2958ca5f3f98a3bba203152be5104c..ea6b0e523c60f05f92100c967b5ada9f565e6301 100644 --- a/arch/powerpc/platforms/8xx/pic.c +++ b/arch/powerpc/platforms/8xx/pic.c @@ -4,7 +4,8 @@ #include #include #include -#include +#include +#include #include #include #include @@ -14,8 +15,6 @@ #define PIC_VEC_SPURRIOUS 15 -extern int cpm_get_irq(struct pt_regs *regs); - static struct irq_domain *mpc8xx_pic_host; static unsigned long mpc8xx_cached_irq_mask; static sysconf8xx_t __iomem *siu_reg; @@ -125,7 +124,7 @@ static const struct irq_domain_ops mpc8xx_pic_host_ops = { .xlate = mpc8xx_pic_host_xlate, }; -int __init mpc8xx_pic_init(void) +void __init mpc8xx_pic_init(void) { struct resource res; struct device_node *np; @@ -136,7 +135,7 @@ int __init mpc8xx_pic_init(void) np = of_find_node_by_type(NULL, "mpc8xx-pic"); if (np == NULL) { printk(KERN_ERR "Could not find fsl,pq1-pic node\n"); - return -ENOMEM; + return; } ret = of_address_to_resource(np, 0, &res); @@ -144,20 +143,13 @@ int __init mpc8xx_pic_init(void) goto out; siu_reg = ioremap(res.start, resource_size(&res)); - if (siu_reg == NULL) { - ret = -EINVAL; + if (!siu_reg) goto out; - } mpc8xx_pic_host = irq_domain_add_linear(np, 64, &mpc8xx_pic_host_ops, NULL); - if (mpc8xx_pic_host == NULL) { + if (!mpc8xx_pic_host) printk(KERN_ERR "MPC8xx PIC: failed to allocate irq host!\n"); - ret = -ENOMEM; - goto out; - } - ret = 0; out: of_node_put(np); - return ret; } diff --git a/arch/powerpc/platforms/8xx/pic.h b/arch/powerpc/platforms/8xx/pic.h index 9fe00eebdc8b8cd150c11f0b1c836b092dc39b0e..c70f1b446f946c400b7e75ed621b9a3445690190 100644 --- a/arch/powerpc/platforms/8xx/pic.h +++ b/arch/powerpc/platforms/8xx/pic.h @@ -4,7 +4,7 @@ #include #include -int mpc8xx_pic_init(void); +void mpc8xx_pic_init(void); unsigned int mpc8xx_get_irq(void); /* diff --git a/arch/powerpc/platforms/8xx/tqm8xx_setup.c b/arch/powerpc/platforms/8xx/tqm8xx_setup.c index 4cea8b1afa4473ab57e1225fdda5848e2db5aba6..3725d51248df155c9c625d485d1aa905ead24ce5 100644 --- a/arch/powerpc/platforms/8xx/tqm8xx_setup.c +++ b/arch/powerpc/platforms/8xx/tqm8xx_setup.c @@ -43,6 +43,7 @@ #include #include "mpc8xx.h" +#include "pic.h" struct cpm_pin { int port, pin, flags; @@ -142,7 +143,7 @@ define_machine(tqm8xx) { .name = "TQM8xx", .probe = tqm8xx_probe, .setup_arch = tqm8xx_setup_arch, - .init_IRQ = mpc8xx_pics_init, + .init_IRQ = mpc8xx_pic_init, .get_irq = mpc8xx_get_irq, .restart = mpc8xx_restart, .calibrate_decr = mpc8xx_calibrate_decr, diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype index e2e1fec91c6ed4a6423c682673197c2da03e466f..9e2df4b66478828ada7796fdf92d58aaa3f9fc28 100644 --- a/arch/powerpc/platforms/Kconfig.cputype +++ b/arch/powerpc/platforms/Kconfig.cputype @@ -104,6 +104,7 @@ config PPC_BOOK3S_64 select HAVE_MOVE_PUD select IRQ_WORK select PPC_64S_HASH_MMU if !PPC_RADIX_MMU + select KASAN_VMALLOC if KASAN config PPC_BOOK3E_64 bool "Embedded processors" @@ -377,7 +378,6 @@ config SPE config PPC_64S_HASH_MMU bool "Hash MMU Support" depends on PPC_BOOK3S_64 - select PPC_MM_SLICES default y help Enable support for the Power ISA Hash style MMU. This is implemented @@ -451,9 +451,6 @@ config PPC_BOOK3E_MMU def_bool y depends on FSL_BOOKE || PPC_BOOK3E -config PPC_MM_SLICES - bool - config PPC_HAVE_PMU_SUPPORT bool @@ -556,6 +553,12 @@ config CPU_LITTLE_ENDIAN endchoice +config PPC64_ELF_ABI_V1 + def_bool PPC64 && CPU_BIG_ENDIAN + +config PPC64_ELF_ABI_V2 + def_bool PPC64 && CPU_LITTLE_ENDIAN + config PPC64_BOOT_WRAPPER def_bool n depends on CPU_LITTLE_ENDIAN diff --git a/arch/powerpc/platforms/amigaone/setup.c b/arch/powerpc/platforms/amigaone/setup.c index 9d252c554f7f84685b0935415d0e4c7acdf7df5d..397ce6a40bd09908bfb97ba972af6dbce9df8147 100644 --- a/arch/powerpc/platforms/amigaone/setup.c +++ b/arch/powerpc/platforms/amigaone/setup.c @@ -8,6 +8,7 @@ * Copyright 2003 by Hans-Joerg Frieden and Thomas Frieden */ +#include #include #include #include diff --git a/arch/powerpc/platforms/book3s/vas-api.c b/arch/powerpc/platforms/book3s/vas-api.c index f9a1615b74daed8bcf0120bf4b76dc41a04b6bf6..c0799fb26b6d6080a3c0f638f70eafd716af53ed 100644 --- a/arch/powerpc/platforms/book3s/vas-api.c +++ b/arch/powerpc/platforms/book3s/vas-api.c @@ -30,7 +30,7 @@ * * where "vas_copy" and "vas_paste" are defined in copy-paste.h. * copy/paste returns to the user space directly. So refer NX hardware - * documententation for exact copy/paste usage and completion / error + * documentation for exact copy/paste usage and completion / error * conditions. */ diff --git a/arch/powerpc/platforms/cell/axon_msi.c b/arch/powerpc/platforms/cell/axon_msi.c index 354a58c1e6f2dfaa9ed9c5856b4e11b796ca515a..f3291e957a19dbb2d20b749dc338b5cfed7690d2 100644 --- a/arch/powerpc/platforms/cell/axon_msi.c +++ b/arch/powerpc/platforms/cell/axon_msi.c @@ -13,10 +13,10 @@ #include #include #include +#include #include #include -#include #include "cell.h" diff --git a/arch/powerpc/platforms/cell/cbe_powerbutton.c b/arch/powerpc/platforms/cell/cbe_powerbutton.c index bda589dfb0512b89d1dfa61d8ae92d4ace1f84d1..a3ee397486f6f20979b0068e32b4052a1a546f26 100644 --- a/arch/powerpc/platforms/cell/cbe_powerbutton.c +++ b/arch/powerpc/platforms/cell/cbe_powerbutton.c @@ -9,9 +9,9 @@ #include #include +#include #include #include -#include static struct input_dev *button_dev; static struct platform_device *button_pdev; diff --git a/arch/powerpc/platforms/cell/cbe_regs.c b/arch/powerpc/platforms/cell/cbe_regs.c index 1c4c53bec66c1aa38ac5578f7e30aa77f3ae26ab..316e533afc0054808fa5d3f26ae1dfb0db52d2c5 100644 --- a/arch/powerpc/platforms/cell/cbe_regs.c +++ b/arch/powerpc/platforms/cell/cbe_regs.c @@ -10,12 +10,12 @@ #include #include #include +#include #include #include #include #include -#include #include #include @@ -23,7 +23,7 @@ * Current implementation uses "cpu" nodes. We build our own mapping * array of cpu numbers to cpu nodes locally for now to allow interrupt * time code to have a fast path rather than call of_get_cpu_node(). If - * we implement cpu hotplug, we'll have to install an appropriate norifier + * we implement cpu hotplug, we'll have to install an appropriate notifier * in order to release references to the cpu going away */ static struct cbe_regs_map diff --git a/arch/powerpc/platforms/cell/cbe_thermal.c b/arch/powerpc/platforms/cell/cbe_thermal.c index abb5e527b4db01d2d3503407b1cf3dc4ed5b5a93..2f45428e32c895ccb86abb64cef70b83c2191273 100644 --- a/arch/powerpc/platforms/cell/cbe_thermal.c +++ b/arch/powerpc/platforms/cell/cbe_thermal.c @@ -39,7 +39,6 @@ #include #include #include -#include #include #include "spu_priv1_mmio.h" diff --git a/arch/powerpc/platforms/cell/interrupt.c b/arch/powerpc/platforms/cell/interrupt.c index 0873a7a2027144400ff57a156fab3760002fc0cd..03ee8152ee97d111b3cb62f23481f22d55d5950e 100644 --- a/arch/powerpc/platforms/cell/interrupt.c +++ b/arch/powerpc/platforms/cell/interrupt.c @@ -18,15 +18,16 @@ #include #include +#include #include #include #include #include #include #include +#include #include -#include #include #include #include diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c index 25e726bf01727104f4f475fa5b01dc79c63fb22f..0ca3efeef293bdd58c3b42086f733ea04a4a7102 100644 --- a/arch/powerpc/platforms/cell/iommu.c +++ b/arch/powerpc/platforms/cell/iommu.c @@ -12,8 +12,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -582,7 +584,7 @@ static int cell_of_bus_notify(struct notifier_block *nb, unsigned long action, { struct device *dev = data; - /* We are only intereted in device addition */ + /* We are only interested in device addition */ if (action != BUS_NOTIFY_ADD_DEVICE) return 0; diff --git a/arch/powerpc/platforms/cell/pervasive.c b/arch/powerpc/platforms/cell/pervasive.c index dff8d5e7ab82bdd9e56ad21a688f60b5f8c1b457..58d967ee38b31757cf3849d2cebfa88702349de0 100644 --- a/arch/powerpc/platforms/cell/pervasive.c +++ b/arch/powerpc/platforms/cell/pervasive.c @@ -19,7 +19,6 @@ #include #include -#include #include #include #include diff --git a/arch/powerpc/platforms/cell/ras.c b/arch/powerpc/platforms/cell/ras.c index 4325c05bedd97306f4f7541d2992d248676a6946..8d934ea6270cd39ca1cfbec615ba812feea1ee30 100644 --- a/arch/powerpc/platforms/cell/ras.c +++ b/arch/powerpc/platforms/cell/ras.c @@ -12,11 +12,11 @@ #include #include #include +#include #include #include #include -#include #include #include #include diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c index edefa785d2ef0bf526e1357f8db854eadcaa58d3..52de014983c97f73d1488a4a357878c3a769e293 100644 --- a/arch/powerpc/platforms/cell/setup.c +++ b/arch/powerpc/platforms/cell/setup.c @@ -31,7 +31,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/powerpc/platforms/cell/smp.c b/arch/powerpc/platforms/cell/smp.c index d7ab868aab54afe63395be9e5bf105f6d29f04ac..31ce00b52a32499fc453fee421d2277f5376ea95 100644 --- a/arch/powerpc/platforms/cell/smp.c +++ b/arch/powerpc/platforms/cell/smp.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/powerpc/platforms/cell/spider-pci.c b/arch/powerpc/platforms/cell/spider-pci.c index a1c293f42a1fb131d06d6cfd51fe91e229325e2e..e36ebd84f55b811cabd42762f086ebc16610d28c 100644 --- a/arch/powerpc/platforms/cell/spider-pci.c +++ b/arch/powerpc/platforms/cell/spider-pci.c @@ -8,6 +8,7 @@ #undef DEBUG #include +#include #include #include #include @@ -81,7 +82,7 @@ static int __init spiderpci_pci_setup_chip(struct pci_controller *phb, /* * On CellBlade, we can't know that which XDR memory is used by * kmalloc() to allocate dummy_page_va. - * In order to imporve the performance, the XDR which is used to + * In order to improve the performance, the XDR which is used to * allocate dummy_page_va is the nearest the spider-pci. * We have to select the CBE which is the nearest the spider-pci * to allocate memory from the best XDR, but I don't know that diff --git a/arch/powerpc/platforms/cell/spider-pic.c b/arch/powerpc/platforms/cell/spider-pic.c index 8af75867cb42420e48e1b5910cb89a47bbb3249f..11df737c8c6a7c85dfe938ee7aed9330eabb4c35 100644 --- a/arch/powerpc/platforms/cell/spider-pic.c +++ b/arch/powerpc/platforms/cell/spider-pic.c @@ -10,9 +10,10 @@ #include #include #include +#include +#include #include -#include #include #include "interrupt.h" diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c index 2eecba3345c357a63601fb22a1d0063a5c13b97d..7bd0b563e163a8c4ebc293972fb780e2db5eec3a 100644 --- a/arch/powerpc/platforms/cell/spu_base.c +++ b/arch/powerpc/platforms/cell/spu_base.c @@ -24,7 +24,6 @@ #include #include #include -#include #include const struct spu_management_ops *spu_management_ops; diff --git a/arch/powerpc/platforms/cell/spu_manage.c b/arch/powerpc/platforms/cell/spu_manage.c index ddf8742f09a3e8ff3ab4dd914d4078eee95da336..ae09c5a91b4078d63ad4490b95e092a8b80a2976 100644 --- a/arch/powerpc/platforms/cell/spu_manage.c +++ b/arch/powerpc/platforms/cell/spu_manage.c @@ -16,11 +16,12 @@ #include #include #include +#include +#include #include #include #include -#include #include "spufs/spufs.h" #include "interrupt.h" @@ -457,7 +458,7 @@ static void __init init_affinity_node(int cbe) /* * Walk through each phandle in vicinity property of the spu - * (tipically two vicinity phandles per spe node) + * (typically two vicinity phandles per spe node) */ for (i = 0; i < (lenp / sizeof(phandle)); i++) { if (vic_handles[i] == avoid_ph) diff --git a/arch/powerpc/platforms/cell/spu_priv1_mmio.c b/arch/powerpc/platforms/cell/spu_priv1_mmio.c index 0c2e6bb6fe51b5922051983b978aa6987e4784f8..d150e398730425a75454583321d977d7a9c42581 100644 --- a/arch/powerpc/platforms/cell/spu_priv1_mmio.c +++ b/arch/powerpc/platforms/cell/spu_priv1_mmio.c @@ -19,7 +19,6 @@ #include #include #include -#include #include "interrupt.h" #include "spu_priv1_mmio.h" diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c index 4c702192412f180beecc61df6cd31bf74b424b09..34334c32b7f58c09ad2fa49cffb5a27e28450894 100644 --- a/arch/powerpc/platforms/cell/spufs/inode.c +++ b/arch/powerpc/platforms/cell/spufs/inode.c @@ -21,10 +21,10 @@ #include #include #include +#include #include #include -#include #include #include #include diff --git a/arch/powerpc/platforms/chrp/nvram.c b/arch/powerpc/platforms/chrp/nvram.c index e820332b59a06952d25803e5b201077cc0fa6e98..dab78076fedb40674239894377e74af006b6d39e 100644 --- a/arch/powerpc/platforms/chrp/nvram.c +++ b/arch/powerpc/platforms/chrp/nvram.c @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include #include #include "chrp.h" diff --git a/arch/powerpc/platforms/chrp/pci.c b/arch/powerpc/platforms/chrp/pci.c index 76e6256cb0a788f4199cf0ea69dd097ec397f67d..6f6598e771ff7aa10d06c448041c7f8706e745e3 100644 --- a/arch/powerpc/platforms/chrp/pci.c +++ b/arch/powerpc/platforms/chrp/pci.c @@ -9,11 +9,11 @@ #include #include #include +#include #include #include #include -#include #include #include #include diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c index 3cfc382841e52522fd15a0cc00a758aadab38e84..ec63c0558db6192d368f6309d92dec001d6b02cc 100644 --- a/arch/powerpc/platforms/chrp/setup.c +++ b/arch/powerpc/platforms/chrp/setup.c @@ -32,9 +32,11 @@ #include #include #include +#include +#include +#include #include -#include #include #include #include @@ -251,7 +253,7 @@ static void __noreturn briq_restart(char *cmd) * Per default, input/output-device points to the keyboard/screen * If no card is installed, the built-in serial port is used as a fallback. * But unfortunately, the firmware does not connect /chosen/{stdin,stdout} - * the the built-in serial node. Instead, a /failsafe node is created. + * to the built-in serial node. Instead, a /failsafe node is created. */ static __init void chrp_init(void) { diff --git a/arch/powerpc/platforms/chrp/smp.c b/arch/powerpc/platforms/chrp/smp.c index e30cd2915e54c4101f9fbea0bb5214b8076e9006..ab95155647a41851bb7bb93a1983c73b1607b558 100644 --- a/arch/powerpc/platforms/chrp/smp.c +++ b/arch/powerpc/platforms/chrp/smp.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/powerpc/platforms/chrp/time.c b/arch/powerpc/platforms/chrp/time.c index acde7bbe07164ebfb1459c5fda7255863f8a30ed..d46417e3d8e0ed442091d82d887f14ca9b68c352 100644 --- a/arch/powerpc/platforms/chrp/time.c +++ b/arch/powerpc/platforms/chrp/time.c @@ -21,17 +21,15 @@ #include #include #include +#include #include #include -#include #include #include #include -extern spinlock_t rtc_lock; - #define NVRAM_AS0 0x74 #define NVRAM_AS1 0x75 #define NVRAM_DATA 0x77 diff --git a/arch/powerpc/platforms/embedded6xx/gamecube.c b/arch/powerpc/platforms/embedded6xx/gamecube.c index ade928f7ea73e3c02508a4dc8a00b040c2245b97..5c2575adcc7e6b320aaf99686f3ed3b778d264a2 100644 --- a/arch/powerpc/platforms/embedded6xx/gamecube.c +++ b/arch/powerpc/platforms/embedded6xx/gamecube.c @@ -16,7 +16,6 @@ #include #include -#include #include #include diff --git a/arch/powerpc/platforms/embedded6xx/holly.c b/arch/powerpc/platforms/embedded6xx/holly.c index 07e71ba3e846429b721745114200ca23ff51f173..78f2378d9223f3765df3f9c7fb1bd0467cb0887b 100644 --- a/arch/powerpc/platforms/embedded6xx/holly.c +++ b/arch/powerpc/platforms/embedded6xx/holly.c @@ -22,12 +22,13 @@ #include #include #include +#include +#include #include #include #include #include -#include #include #include #include diff --git a/arch/powerpc/platforms/embedded6xx/linkstation.c b/arch/powerpc/platforms/embedded6xx/linkstation.c index eb8342e7f84e9ec07149753d390e3ff5c491d973..1830e1ac1f8f01e4519c797d7033310be8e050fb 100644 --- a/arch/powerpc/platforms/embedded6xx/linkstation.c +++ b/arch/powerpc/platforms/embedded6xx/linkstation.c @@ -15,7 +15,6 @@ #include #include -#include #include #include diff --git a/arch/powerpc/platforms/embedded6xx/ls_uart.c b/arch/powerpc/platforms/embedded6xx/ls_uart.c index 9d891bd5df5a8a21701d5a1461b9fb97908d8aaa..0133e175a0fcd26c81afee1ff3b316a91eef9129 100644 --- a/arch/powerpc/platforms/embedded6xx/ls_uart.c +++ b/arch/powerpc/platforms/embedded6xx/ls_uart.c @@ -14,8 +14,8 @@ #include #include #include +#include #include -#include #include #include "mpc10x.h" diff --git a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c index 9eb9abb5bce2574bc3acc9b614a52e08e1d6ca57..8b2b422103563ff6f8196a89651424692710d140 100644 --- a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c +++ b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c @@ -27,10 +27,10 @@ #include #include #include +#include #include #include -#include #include #include #include diff --git a/arch/powerpc/platforms/embedded6xx/mvme5100.c b/arch/powerpc/platforms/embedded6xx/mvme5100.c index c06a0490d157f0e61acd3337b3ecae8ec75f8c9e..4854cc592cecffee48bfd3424f4a00132ec84e48 100644 --- a/arch/powerpc/platforms/embedded6xx/mvme5100.c +++ b/arch/powerpc/platforms/embedded6xx/mvme5100.c @@ -12,12 +12,12 @@ * Author: Stephen Chivers */ +#include #include #include #include #include -#include #include #include diff --git a/arch/powerpc/platforms/embedded6xx/storcenter.c b/arch/powerpc/platforms/embedded6xx/storcenter.c index e188b90f7016e7f545db8dc57eca9b9639d0be98..5f16e80b6ed61b8935ff7675cf73feeae38107cd 100644 --- a/arch/powerpc/platforms/embedded6xx/storcenter.c +++ b/arch/powerpc/platforms/embedded6xx/storcenter.c @@ -17,7 +17,6 @@ #include #include -#include #include #include diff --git a/arch/powerpc/platforms/embedded6xx/usbgecko_udbg.c b/arch/powerpc/platforms/embedded6xx/usbgecko_udbg.c index 5aea46566233db27f62d163f2dbdc2031a11b034..e02bdabf358ca4e099b8c9eab5fd977d3d6a331d 100644 --- a/arch/powerpc/platforms/embedded6xx/usbgecko_udbg.c +++ b/arch/powerpc/platforms/embedded6xx/usbgecko_udbg.c @@ -7,10 +7,11 @@ * Copyright (C) 2008,2009 Albert Herranz */ +#include + #include #include -#include #include #include diff --git a/arch/powerpc/platforms/embedded6xx/wii.c b/arch/powerpc/platforms/embedded6xx/wii.c index f60ade584bb21e39c7be6d93107e0fb80d9f8e21..9e03ff8f631c4f14d929c37149acbe306d99fb4a 100644 --- a/arch/powerpc/platforms/embedded6xx/wii.c +++ b/arch/powerpc/platforms/embedded6xx/wii.c @@ -13,13 +13,13 @@ #include #include #include +#include #include #include #include #include #include -#include #include #include diff --git a/arch/powerpc/platforms/fsl_uli1575.c b/arch/powerpc/platforms/fsl_uli1575.c index 044a20c1fbdea43529ad2f7b53e2bc109906965c..84afae7a25617dc931f8434c225ac16f61f72e26 100644 --- a/arch/powerpc/platforms/fsl_uli1575.c +++ b/arch/powerpc/platforms/fsl_uli1575.c @@ -10,6 +10,7 @@ #include #include #include +#include #include diff --git a/arch/powerpc/platforms/maple/pci.c b/arch/powerpc/platforms/maple/pci.c index 37875e478b3a7186188faf002caf4321343db989..b911b31717cc6978da8ac6c76852eb31d87be65c 100644 --- a/arch/powerpc/platforms/maple/pci.c +++ b/arch/powerpc/platforms/maple/pci.c @@ -12,10 +12,10 @@ #include #include #include +#include #include #include -#include #include #include #include diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c index 4e9ad5bf3efb4f7218965e7fd3efaddb6bd0649f..c26c379e1cc823ed3cc4fe85315c528afdcf2c91 100644 --- a/arch/powerpc/platforms/maple/setup.c +++ b/arch/powerpc/platforms/maple/setup.c @@ -36,12 +36,12 @@ #include #include #include +#include #include #include #include #include -#include #include #include #include diff --git a/arch/powerpc/platforms/maple/time.c b/arch/powerpc/platforms/maple/time.c index 78209bb7629c5a28bd3e18983e328e8f5a5adcc0..823e219ef8ee7c86560445d19e4314a599174403 100644 --- a/arch/powerpc/platforms/maple/time.c +++ b/arch/powerpc/platforms/maple/time.c @@ -19,9 +19,9 @@ #include #include #include +#include #include -#include #include #include #include diff --git a/arch/powerpc/platforms/pasemi/dma_lib.c b/arch/powerpc/platforms/pasemi/dma_lib.c index 26427311fc7255a8826c330a2bdf333d69f37423..1be1f18f6f09823caa146f2211bbb59f05bbf56e 100644 --- a/arch/powerpc/platforms/pasemi/dma_lib.c +++ b/arch/powerpc/platforms/pasemi/dma_lib.c @@ -10,6 +10,8 @@ #include #include #include +#include +#include #include #include diff --git a/arch/powerpc/platforms/pasemi/iommu.c b/arch/powerpc/platforms/pasemi/iommu.c index 5be7242fbd866cf5c3814b4509509eda68728e1c..0a38663d44ed74b72c15e8699a52c1b1ee6c452d 100644 --- a/arch/powerpc/platforms/pasemi/iommu.c +++ b/arch/powerpc/platforms/pasemi/iommu.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include diff --git a/arch/powerpc/platforms/pasemi/misc.c b/arch/powerpc/platforms/pasemi/misc.c index 1bf65d02d3ba3bee4cd5f840bc81cccc6475eef6..f859ada29074a31903a333e2e90babea31603441 100644 --- a/arch/powerpc/platforms/pasemi/misc.c +++ b/arch/powerpc/platforms/pasemi/misc.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #ifdef CONFIG_I2C_BOARDINFO diff --git a/arch/powerpc/platforms/pasemi/msi.c b/arch/powerpc/platforms/pasemi/msi.c index ea1e414514080298f3db511db18df30bc62e642b..dc1846660005c0c3b2e403a0f7c730847e803048 100644 --- a/arch/powerpc/platforms/pasemi/msi.c +++ b/arch/powerpc/platforms/pasemi/msi.c @@ -9,9 +9,9 @@ */ #include +#include #include #include -#include #include #include #include diff --git a/arch/powerpc/platforms/pasemi/pci.c b/arch/powerpc/platforms/pasemi/pci.c index d4b922759d6ea7cd4fa2ae4ab44da6ae7d283e80..55f0160910bf487fa94d36231eb728610e6112bc 100644 --- a/arch/powerpc/platforms/pasemi/pci.c +++ b/arch/powerpc/platforms/pasemi/pci.c @@ -12,6 +12,7 @@ #include +#include #include #include diff --git a/arch/powerpc/platforms/pasemi/setup.c b/arch/powerpc/platforms/pasemi/setup.c index f974bfe7fde1e27d1fa4af8300c65a3ff95abcaa..2aef49e04dd49615a92098e05c8dd26e63c76a41 100644 --- a/arch/powerpc/platforms/pasemi/setup.c +++ b/arch/powerpc/platforms/pasemi/setup.c @@ -18,8 +18,8 @@ #include #include #include +#include -#include #include #include #include diff --git a/arch/powerpc/platforms/powermac/backlight.c b/arch/powerpc/platforms/powermac/backlight.c index 32224cb489d757dda98eb733f6ad7edbbf3a578e..aeb79a8b3e1090cd02f5bbd7d2ca02892ccba27b 100644 --- a/arch/powerpc/platforms/powermac/backlight.c +++ b/arch/powerpc/platforms/powermac/backlight.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #define OLD_BACKLIGHT_MAX 15 diff --git a/arch/powerpc/platforms/powermac/bootx_init.c b/arch/powerpc/platforms/powermac/bootx_init.c index d20ef35e6d9da18ebbf0b7627f81182b82314c8d..72eb99aba40f844ca2a72ab1bcd0855a71a1517d 100644 --- a/arch/powerpc/platforms/powermac/bootx_init.c +++ b/arch/powerpc/platforms/powermac/bootx_init.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -243,7 +244,7 @@ static void __init bootx_scan_dt_build_strings(unsigned long base, DBG(" detected display ! adding properties names !\n"); bootx_dt_add_string("linux,boot-display", mem_end); bootx_dt_add_string("linux,opened", mem_end); - strlcpy(bootx_disp_path, namep, sizeof(bootx_disp_path)); + strscpy(bootx_disp_path, namep, sizeof(bootx_disp_path)); } /* get and store all property names */ diff --git a/arch/powerpc/platforms/powermac/feature.c b/arch/powerpc/platforms/powermac/feature.c index e67c624f35a2ea1ad4b67a7602079b62d99e6e36..5cc958adba13f1280b089261a4db3e8d3d161bd7 100644 --- a/arch/powerpc/platforms/powermac/feature.c +++ b/arch/powerpc/platforms/powermac/feature.c @@ -31,7 +31,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/powerpc/platforms/powermac/low_i2c.c b/arch/powerpc/platforms/powermac/low_i2c.c index df89d916236d965595702eef3a5f7a813deae485..c1c430c66dc9e9aa7ea36574e3f0e1648c27a769 100644 --- a/arch/powerpc/platforms/powermac/low_i2c.c +++ b/arch/powerpc/platforms/powermac/low_i2c.c @@ -40,10 +40,10 @@ #include #include #include +#include #include #include #include -#include #include #include #include @@ -1472,7 +1472,7 @@ int __init pmac_i2c_init(void) smu_i2c_probe(); #endif - /* Now add plaform functions for some known devices */ + /* Now add platform functions for some known devices */ pmac_i2c_devscan(pmac_i2c_dev_create); return 0; diff --git a/arch/powerpc/platforms/powermac/nvram.c b/arch/powerpc/platforms/powermac/nvram.c index de8fcb60729039ae58d37588358e63a152f45135..fe2e0249cbc28595aa004ef529d11fb64ad270b2 100644 --- a/arch/powerpc/platforms/powermac/nvram.c +++ b/arch/powerpc/platforms/powermac/nvram.c @@ -17,9 +17,9 @@ #include #include #include +#include #include #include -#include #include #include @@ -71,7 +71,7 @@ struct core99_header { static int nvram_naddrs; static volatile unsigned char __iomem *nvram_data; static int is_core_99; -static int core99_bank = 0; +static int core99_bank; static int nvram_partitions[3]; // XXX Turn that into a sem static DEFINE_RAW_SPINLOCK(nv_lock); diff --git a/arch/powerpc/platforms/powermac/pci.c b/arch/powerpc/platforms/powermac/pci.c index e9abe0f2e7f0a7b9bd14f32df45157500694b756..d71359b5331c3b661ccbf5909d9339695192bde6 100644 --- a/arch/powerpc/platforms/powermac/pci.c +++ b/arch/powerpc/platforms/powermac/pci.c @@ -12,11 +12,12 @@ #include #include #include +#include +#include #include #include #include -#include #include #include #include diff --git a/arch/powerpc/platforms/powermac/pfunc_core.c b/arch/powerpc/platforms/powermac/pfunc_core.c index 94df0a91b46fdb5c4a7d52c219830d4334055507..22741ddfd5b26dc85a803130ab898dfc52895cdc 100644 --- a/arch/powerpc/platforms/powermac/pfunc_core.c +++ b/arch/powerpc/platforms/powermac/pfunc_core.c @@ -12,8 +12,8 @@ #include #include #include +#include -#include #include /* Debug */ @@ -685,7 +685,7 @@ static int pmf_add_functions(struct pmf_device *dev, void *driverdata) const int plen = strlen(PP_PREFIX); int count = 0; - for (pp = dev->node->properties; pp != 0; pp = pp->next) { + for_each_property_of_node(dev->node, pp) { const char *name; if (strncmp(pp->name, PP_PREFIX, plen) != 0) continue; diff --git a/arch/powerpc/platforms/powermac/pic.c b/arch/powerpc/platforms/powermac/pic.c index bb0566633af57f7eb3fe85378ab48d283d783e92..8c8d8e0a7d13751ef7a17c3d05cb595693ebc4f9 100644 --- a/arch/powerpc/platforms/powermac/pic.c +++ b/arch/powerpc/platforms/powermac/pic.c @@ -20,11 +20,13 @@ #include #include #include +#include +#include +#include #include #include #include -#include #include #include #include @@ -382,7 +384,7 @@ static void __init pmac_pic_probe_oldstyle(void) #endif } -int of_irq_parse_oldworld(struct device_node *device, int index, +int of_irq_parse_oldworld(const struct device_node *device, int index, struct of_phandle_args *out_irq) { const u32 *ints = NULL; diff --git a/arch/powerpc/platforms/powermac/pmac.h b/arch/powerpc/platforms/powermac/pmac.h index ba8d4e97095b07f77627e0938322ea5c635cac41..1b696f35264019e6e3966fa4d21b06858a74810e 100644 --- a/arch/powerpc/platforms/powermac/pmac.h +++ b/arch/powerpc/platforms/powermac/pmac.h @@ -16,6 +16,8 @@ struct rtc_time; extern int pmac_newworld; +void g5_phy_disable_cpu1(void); + extern long pmac_time_init(void); extern time64_t pmac_get_boot_time(void); extern void pmac_get_rtc_time(struct rtc_time *); diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c index 974d4b49867b5a91251bc2bedd747624f29e73fd..f71735ec449ffca3cb202c32753bbbd947d3f4e5 100644 --- a/arch/powerpc/platforms/powermac/setup.c +++ b/arch/powerpc/platforms/powermac/setup.c @@ -50,7 +50,6 @@ #include #include -#include #include #include #include @@ -81,10 +80,6 @@ static int current_root_goodness = -1; #define DEFAULT_ROOT_DEVICE Root_SDA1 /* sda1 - slightly silly choice */ -#ifdef CONFIG_PPC64 -int sccdbg; -#endif - sys_ctrler_t sys_ctrler = SYS_CTRLER_UNKNOWN; EXPORT_SYMBOL(sys_ctrler); diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c index da1efdc30d6c97ae733b6eb8450e8bb77d464458..d9df45741ecefbaaffcf85be7a5a706541532ce0 100644 --- a/arch/powerpc/platforms/powermac/smp.c +++ b/arch/powerpc/platforms/powermac/smp.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -39,7 +40,6 @@ #include #include #include -#include #include #include #include @@ -875,8 +875,6 @@ static int smp_core99_cpu_online(unsigned int cpu) static void __init smp_core99_bringup_done(void) { - extern void __init g5_phy_disable_cpu1(void); - /* Close i2c bus if it was used for tb sync */ if (pmac_tb_clock_chip_host) pmac_i2c_close(pmac_tb_clock_chip_host); diff --git a/arch/powerpc/platforms/powermac/time.c b/arch/powerpc/platforms/powermac/time.c index 31d6213a6c8f938898a48aeaa7f1babe27561475..4c5790aff1b54489b358a6c80be310b17db2ba15 100644 --- a/arch/powerpc/platforms/powermac/time.c +++ b/arch/powerpc/platforms/powermac/time.c @@ -24,9 +24,9 @@ #include #include #include +#include #include -#include #include #include #include diff --git a/arch/powerpc/platforms/powermac/udbg_adb.c b/arch/powerpc/platforms/powermac/udbg_adb.c index 12158bb4fed703fe7a739bd55d762eae9989be7a..b4756defd596c7e31ad0b82bd908a06ded3ea9c9 100644 --- a/arch/powerpc/platforms/powermac/udbg_adb.c +++ b/arch/powerpc/platforms/powermac/udbg_adb.c @@ -7,11 +7,11 @@ #include #include #include +#include #include #include #include #include -#include #include #include #include diff --git a/arch/powerpc/platforms/powermac/udbg_scc.c b/arch/powerpc/platforms/powermac/udbg_scc.c index 965827ac2e9c803fa2e8c3a7f6485677d16ed05f..734df5a32f994fc1ecbed4156e49a027eb9f3949 100644 --- a/arch/powerpc/platforms/powermac/udbg_scc.c +++ b/arch/powerpc/platforms/powermac/udbg_scc.c @@ -5,10 +5,10 @@ * Copyright (C) 2001-2005 PPC 64 Team, IBM Corp */ #include +#include #include #include #include -#include #include extern u8 real_readb(volatile u8 __iomem *addr); diff --git a/arch/powerpc/platforms/powernv/Makefile b/arch/powerpc/platforms/powernv/Makefile index dc7b37c23b60dccf7c87d31ca9d8bb2aa7d61143..6488b38421999efd62dff4be1f30294cfb368559 100644 --- a/arch/powerpc/platforms/powernv/Makefile +++ b/arch/powerpc/platforms/powernv/Makefile @@ -1,4 +1,12 @@ # SPDX-License-Identifier: GPL-2.0 + +# nothing that deals with real mode is safe to KASAN +# in particular, idle code runs a bunch of things in real mode +KASAN_SANITIZE_idle.o := n +KASAN_SANITIZE_pci-ioda.o := n +# pnv_machine_check_early +KASAN_SANITIZE_setup.o := n + obj-y += setup.o opal-call.o opal-wrappers.o opal.o opal-async.o obj-y += idle.o opal-rtc.o opal-nvram.o opal-lpc.o opal-flash.o obj-y += rng.o opal-elog.o opal-dump.o opal-sysparam.o opal-sensor.o diff --git a/arch/powerpc/platforms/powernv/eeh-powernv.c b/arch/powerpc/platforms/powernv/eeh-powernv.c index 89e22c460ebf982c3de6dc76ba2fe04019d10f06..a83cb679dd59f5f72c1237077a76119c55bba0bc 100644 --- a/arch/powerpc/platforms/powernv/eeh-powernv.c +++ b/arch/powerpc/platforms/powernv/eeh-powernv.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -390,7 +391,7 @@ static struct eeh_dev *pnv_eeh_probe(struct pci_dev *pdev) * should be blocked until PE reset. MMIO access is dropped * by hardware certainly. In order to drop PCI config requests, * one more flag (EEH_PE_CFG_RESTRICTED) is introduced, which - * will be checked in the backend for PE state retrival. If + * will be checked in the backend for PE state retrieval. If * the PE becomes frozen for the first time and the flag has * been set for the PE, we will set EEH_PE_CFG_BLOCKED for * that PE to block its config space. @@ -981,7 +982,7 @@ static int pnv_eeh_do_af_flr(struct pci_dn *pdn, int option) case EEH_RESET_FUNDAMENTAL: /* * Wait for Transaction Pending bit to clear. A word-aligned - * test is used, so we use the conrol offset rather than status + * test is used, so we use the control offset rather than status * and shift the test bit to match. */ pnv_eeh_wait_for_pending(pdn, "AF", @@ -1048,7 +1049,7 @@ static int pnv_eeh_reset(struct eeh_pe *pe, int option) * frozen state during PE reset. However, the good idea here from * benh is to keep frozen state before we get PE reset done completely * (until BAR restore). With the frozen state, HW drops illegal IO - * or MMIO access, which can incur recrusive frozen PE during PE + * or MMIO access, which can incur recursive frozen PE during PE * reset. The side effect is that EEH core has to clear the frozen * state explicitly after BAR restore. */ @@ -1095,8 +1096,8 @@ static int pnv_eeh_reset(struct eeh_pe *pe, int option) * bus is behind a hotplug slot and it will use the slot provided * reset methods to prevent spurious hotplug events during the reset. * - * Fundemental resets need to be handled internally to EEH since the - * PCI core doesn't really have a concept of a fundemental reset, + * Fundamental resets need to be handled internally to EEH since the + * PCI core doesn't really have a concept of a fundamental reset, * mainly because there's no standard way to generate one. Only a * few devices require an FRESET so it should be fine. */ @@ -1640,24 +1641,6 @@ static struct eeh_ops pnv_eeh_ops = { .notify_resume = NULL }; -#ifdef CONFIG_PCI_IOV -static void pnv_pci_fixup_vf_mps(struct pci_dev *pdev) -{ - struct pci_dn *pdn = pci_get_pdn(pdev); - int parent_mps; - - if (!pdev->is_virtfn) - return; - - /* Synchronize MPS for VF and PF */ - parent_mps = pcie_get_mps(pdev->physfn); - if ((128 << pdev->pcie_mpss) >= parent_mps) - pcie_set_mps(pdev, parent_mps); - pdn->mps = pcie_get_mps(pdev); -} -DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pnv_pci_fixup_vf_mps); -#endif /* CONFIG_PCI_IOV */ - /** * eeh_powernv_init - Register platform dependent EEH operations * diff --git a/arch/powerpc/platforms/powernv/idle.c b/arch/powerpc/platforms/powernv/idle.c index a6677a111aca148ef208cc52d7779d48c92dc812..6f94b808dd39ac3d7369ee2fb6e3514d88d03bf7 100644 --- a/arch/powerpc/platforms/powernv/idle.c +++ b/arch/powerpc/platforms/powernv/idle.c @@ -112,7 +112,7 @@ static int __init pnv_save_sprs_for_deep_states(void) if (rc != 0) return rc; - /* Only p8 needs to set extra HID regiters */ + /* Only p8 needs to set extra HID registers */ if (!cpu_has_feature(CPU_FTR_ARCH_300)) { uint64_t hid1_val = mfspr(SPRN_HID1); uint64_t hid4_val = mfspr(SPRN_HID4); @@ -1204,7 +1204,7 @@ static void __init pnv_arch300_idle_init(void) * The idle code does not deal with TB loss occurring * in a shallower state than SPR loss, so force it to * behave like SPRs are lost if TB is lost. POWER9 would - * never encouter this, but a POWER8 core would if it + * never encounter this, but a POWER8 core would if it * implemented the stop instruction. So this is for forward * compatibility. */ diff --git a/arch/powerpc/platforms/powernv/ocxl.c b/arch/powerpc/platforms/powernv/ocxl.c index 28b009b46464a8d797f7b42dee8cbb1c9428d49c..27c936075031a652c869210c83b4ca3922713889 100644 --- a/arch/powerpc/platforms/powernv/ocxl.c +++ b/arch/powerpc/platforms/powernv/ocxl.c @@ -289,7 +289,7 @@ int pnv_ocxl_get_pasid_count(struct pci_dev *dev, int *count) * be used by a function depends on how many functions exist * on the device. The NPU needs to be configured to know how * many bits are available to PASIDs and how many are to be - * used by the function BDF indentifier. + * used by the function BDF identifier. * * We only support one AFU-carrying function for now. */ diff --git a/arch/powerpc/platforms/powernv/opal-fadump.c b/arch/powerpc/platforms/powernv/opal-fadump.c index c8ad057c722104965114822adc09dded6e10f800..964f464b1b0e38fb305a591d45350d172066c483 100644 --- a/arch/powerpc/platforms/powernv/opal-fadump.c +++ b/arch/powerpc/platforms/powernv/opal-fadump.c @@ -60,7 +60,7 @@ void __init opal_fadump_dt_scan(struct fw_dump *fadump_conf, u64 node) addr = be64_to_cpu(addr); pr_debug("Kernel metadata addr: %llx\n", addr); opal_fdm_active = (void *)addr; - if (opal_fdm_active->registered_regions == 0) + if (be16_to_cpu(opal_fdm_active->registered_regions) == 0) return; ret = opal_mpipl_query_tag(OPAL_MPIPL_TAG_BOOT_MEM, &addr); @@ -95,17 +95,17 @@ static int opal_fadump_unregister(struct fw_dump *fadump_conf); static void opal_fadump_update_config(struct fw_dump *fadump_conf, const struct opal_fadump_mem_struct *fdm) { - pr_debug("Boot memory regions count: %d\n", fdm->region_cnt); + pr_debug("Boot memory regions count: %d\n", be16_to_cpu(fdm->region_cnt)); /* * The destination address of the first boot memory region is the * destination address of boot memory regions. */ - fadump_conf->boot_mem_dest_addr = fdm->rgn[0].dest; + fadump_conf->boot_mem_dest_addr = be64_to_cpu(fdm->rgn[0].dest); pr_debug("Destination address of boot memory regions: %#016llx\n", fadump_conf->boot_mem_dest_addr); - fadump_conf->fadumphdr_addr = fdm->fadumphdr_addr; + fadump_conf->fadumphdr_addr = be64_to_cpu(fdm->fadumphdr_addr); } /* @@ -126,9 +126,9 @@ static void __init opal_fadump_get_config(struct fw_dump *fadump_conf, fadump_conf->boot_memory_size = 0; pr_debug("Boot memory regions:\n"); - for (i = 0; i < fdm->region_cnt; i++) { - base = fdm->rgn[i].src; - size = fdm->rgn[i].size; + for (i = 0; i < be16_to_cpu(fdm->region_cnt); i++) { + base = be64_to_cpu(fdm->rgn[i].src); + size = be64_to_cpu(fdm->rgn[i].size); pr_debug("\t[%03d] base: 0x%lx, size: 0x%lx\n", i, base, size); fadump_conf->boot_mem_addr[i] = base; @@ -143,7 +143,7 @@ static void __init opal_fadump_get_config(struct fw_dump *fadump_conf, * Start address of reserve dump area (permanent reservation) for * re-registering FADump after dump capture. */ - fadump_conf->reserve_dump_area_start = fdm->rgn[0].dest; + fadump_conf->reserve_dump_area_start = be64_to_cpu(fdm->rgn[0].dest); /* * Rarely, but it can so happen that system crashes before all @@ -155,13 +155,14 @@ static void __init opal_fadump_get_config(struct fw_dump *fadump_conf, * Hope the memory that could not be preserved only has pages * that are usually filtered out while saving the vmcore. */ - if (fdm->region_cnt > fdm->registered_regions) { + if (be16_to_cpu(fdm->region_cnt) > be16_to_cpu(fdm->registered_regions)) { pr_warn("Not all memory regions were saved!!!\n"); pr_warn(" Unsaved memory regions:\n"); - i = fdm->registered_regions; - while (i < fdm->region_cnt) { + i = be16_to_cpu(fdm->registered_regions); + while (i < be16_to_cpu(fdm->region_cnt)) { pr_warn("\t[%03d] base: 0x%llx, size: 0x%llx\n", - i, fdm->rgn[i].src, fdm->rgn[i].size); + i, be64_to_cpu(fdm->rgn[i].src), + be64_to_cpu(fdm->rgn[i].size)); i++; } @@ -170,7 +171,7 @@ static void __init opal_fadump_get_config(struct fw_dump *fadump_conf, } fadump_conf->boot_mem_top = (fadump_conf->boot_memory_size + hole_size); - fadump_conf->boot_mem_regs_cnt = fdm->region_cnt; + fadump_conf->boot_mem_regs_cnt = be16_to_cpu(fdm->region_cnt); opal_fadump_update_config(fadump_conf, fdm); } @@ -178,35 +179,38 @@ static void __init opal_fadump_get_config(struct fw_dump *fadump_conf, static void opal_fadump_init_metadata(struct opal_fadump_mem_struct *fdm) { fdm->version = OPAL_FADUMP_VERSION; - fdm->region_cnt = 0; - fdm->registered_regions = 0; - fdm->fadumphdr_addr = 0; + fdm->region_cnt = cpu_to_be16(0); + fdm->registered_regions = cpu_to_be16(0); + fdm->fadumphdr_addr = cpu_to_be64(0); } static u64 opal_fadump_init_mem_struct(struct fw_dump *fadump_conf) { u64 addr = fadump_conf->reserve_dump_area_start; + u16 reg_cnt; int i; opal_fdm = __va(fadump_conf->kernel_metadata); opal_fadump_init_metadata(opal_fdm); /* Boot memory regions */ + reg_cnt = be16_to_cpu(opal_fdm->region_cnt); for (i = 0; i < fadump_conf->boot_mem_regs_cnt; i++) { - opal_fdm->rgn[i].src = fadump_conf->boot_mem_addr[i]; - opal_fdm->rgn[i].dest = addr; - opal_fdm->rgn[i].size = fadump_conf->boot_mem_sz[i]; + opal_fdm->rgn[i].src = cpu_to_be64(fadump_conf->boot_mem_addr[i]); + opal_fdm->rgn[i].dest = cpu_to_be64(addr); + opal_fdm->rgn[i].size = cpu_to_be64(fadump_conf->boot_mem_sz[i]); - opal_fdm->region_cnt++; + reg_cnt++; addr += fadump_conf->boot_mem_sz[i]; } + opal_fdm->region_cnt = cpu_to_be16(reg_cnt); /* - * Kernel metadata is passed to f/w and retrieved in capture kerenl. + * Kernel metadata is passed to f/w and retrieved in capture kernel. * So, use it to save fadump header address instead of calculating it. */ - opal_fdm->fadumphdr_addr = (opal_fdm->rgn[0].dest + - fadump_conf->boot_memory_size); + opal_fdm->fadumphdr_addr = cpu_to_be64(be64_to_cpu(opal_fdm->rgn[0].dest) + + fadump_conf->boot_memory_size); opal_fadump_update_config(fadump_conf, opal_fdm); @@ -269,18 +273,21 @@ static u64 opal_fadump_get_bootmem_min(void) static int opal_fadump_register(struct fw_dump *fadump_conf) { s64 rc = OPAL_PARAMETER; + u16 registered_regs; int i, err = -EIO; - for (i = 0; i < opal_fdm->region_cnt; i++) { + registered_regs = be16_to_cpu(opal_fdm->registered_regions); + for (i = 0; i < be16_to_cpu(opal_fdm->region_cnt); i++) { rc = opal_mpipl_update(OPAL_MPIPL_ADD_RANGE, - opal_fdm->rgn[i].src, - opal_fdm->rgn[i].dest, - opal_fdm->rgn[i].size); + be64_to_cpu(opal_fdm->rgn[i].src), + be64_to_cpu(opal_fdm->rgn[i].dest), + be64_to_cpu(opal_fdm->rgn[i].size)); if (rc != OPAL_SUCCESS) break; - opal_fdm->registered_regions++; + registered_regs++; } + opal_fdm->registered_regions = cpu_to_be16(registered_regs); switch (rc) { case OPAL_SUCCESS: @@ -291,7 +298,8 @@ static int opal_fadump_register(struct fw_dump *fadump_conf) case OPAL_RESOURCE: /* If MAX regions limit in f/w is hit, warn and proceed. */ pr_warn("%d regions could not be registered for MPIPL as MAX limit is reached!\n", - (opal_fdm->region_cnt - opal_fdm->registered_regions)); + (be16_to_cpu(opal_fdm->region_cnt) - + be16_to_cpu(opal_fdm->registered_regions))); fadump_conf->dump_registered = 1; err = 0; break; @@ -312,7 +320,7 @@ static int opal_fadump_register(struct fw_dump *fadump_conf) * If some regions were registered before OPAL_MPIPL_ADD_RANGE * OPAL call failed, unregister all regions. */ - if ((err < 0) && (opal_fdm->registered_regions > 0)) + if ((err < 0) && (be16_to_cpu(opal_fdm->registered_regions) > 0)) opal_fadump_unregister(fadump_conf); return err; @@ -328,7 +336,7 @@ static int opal_fadump_unregister(struct fw_dump *fadump_conf) return -EIO; } - opal_fdm->registered_regions = 0; + opal_fdm->registered_regions = cpu_to_be16(0); fadump_conf->dump_registered = 0; return 0; } @@ -563,25 +571,26 @@ static void opal_fadump_region_show(struct fw_dump *fadump_conf, else fdm_ptr = opal_fdm; - for (i = 0; i < fdm_ptr->region_cnt; i++) { + for (i = 0; i < be16_to_cpu(fdm_ptr->region_cnt); i++) { /* * Only regions that are registered for MPIPL * would have dump data. */ if ((fadump_conf->dump_active) && - (i < fdm_ptr->registered_regions)) - dumped_bytes = fdm_ptr->rgn[i].size; + (i < be16_to_cpu(fdm_ptr->registered_regions))) + dumped_bytes = be64_to_cpu(fdm_ptr->rgn[i].size); seq_printf(m, "DUMP: Src: %#016llx, Dest: %#016llx, ", - fdm_ptr->rgn[i].src, fdm_ptr->rgn[i].dest); + be64_to_cpu(fdm_ptr->rgn[i].src), + be64_to_cpu(fdm_ptr->rgn[i].dest)); seq_printf(m, "Size: %#llx, Dumped: %#llx bytes\n", - fdm_ptr->rgn[i].size, dumped_bytes); + be64_to_cpu(fdm_ptr->rgn[i].size), dumped_bytes); } - /* Dump is active. Show reserved area start address. */ + /* Dump is active. Show preserved area start address. */ if (fadump_conf->dump_active) { - seq_printf(m, "\nMemory above %#016lx is reserved for saving crash dump\n", - fadump_conf->reserve_dump_area_start); + seq_printf(m, "\nMemory above %#016llx is reserved for saving crash dump\n", + fadump_conf->boot_mem_top); } } @@ -624,6 +633,7 @@ void __init opal_fadump_dt_scan(struct fw_dump *fadump_conf, u64 node) { const __be32 *prop; unsigned long dn; + __be64 be_addr; u64 addr = 0; int i, len; s64 ret; @@ -680,13 +690,13 @@ void __init opal_fadump_dt_scan(struct fw_dump *fadump_conf, u64 node) if (!prop) return; - ret = opal_mpipl_query_tag(OPAL_MPIPL_TAG_KERNEL, &addr); - if ((ret != OPAL_SUCCESS) || !addr) { + ret = opal_mpipl_query_tag(OPAL_MPIPL_TAG_KERNEL, &be_addr); + if ((ret != OPAL_SUCCESS) || !be_addr) { pr_err("Failed to get Kernel metadata (%lld)\n", ret); return; } - addr = be64_to_cpu(addr); + addr = be64_to_cpu(be_addr); pr_debug("Kernel metadata addr: %llx\n", addr); opal_fdm_active = __va(addr); @@ -697,14 +707,14 @@ void __init opal_fadump_dt_scan(struct fw_dump *fadump_conf, u64 node) } /* Kernel regions not registered with f/w for MPIPL */ - if (opal_fdm_active->registered_regions == 0) { + if (be16_to_cpu(opal_fdm_active->registered_regions) == 0) { opal_fdm_active = NULL; return; } - ret = opal_mpipl_query_tag(OPAL_MPIPL_TAG_CPU, &addr); - if (addr) { - addr = be64_to_cpu(addr); + ret = opal_mpipl_query_tag(OPAL_MPIPL_TAG_CPU, &be_addr); + if (be_addr) { + addr = be64_to_cpu(be_addr); pr_debug("CPU metadata addr: %llx\n", addr); opal_cpu_metadata = __va(addr); } diff --git a/arch/powerpc/platforms/powernv/opal-fadump.h b/arch/powerpc/platforms/powernv/opal-fadump.h index f1e9ecf548c5d1dbe0364e897b77f3ba57ef1b8e..3f715efb0aa6ee4e3ee9ddc9e02eef7db5b2150d 100644 --- a/arch/powerpc/platforms/powernv/opal-fadump.h +++ b/arch/powerpc/platforms/powernv/opal-fadump.h @@ -31,14 +31,14 @@ * OPAL FADump kernel metadata * * The address of this structure will be registered with f/w for retrieving - * and processing during crash dump. + * in the capture kernel to process the crash dump. */ struct opal_fadump_mem_struct { u8 version; u8 reserved[3]; - u16 region_cnt; /* number of regions */ - u16 registered_regions; /* Regions registered for MPIPL */ - u64 fadumphdr_addr; + __be16 region_cnt; /* number of regions */ + __be16 registered_regions; /* Regions registered for MPIPL */ + __be64 fadumphdr_addr; struct opal_mpipl_region rgn[FADUMP_MAX_MEM_REGS]; } __packed; @@ -135,7 +135,7 @@ static inline void opal_fadump_read_regs(char *bufp, unsigned int regs_cnt, for (i = 0; i < regs_cnt; i++, bufp += reg_entry_size) { reg_entry = (struct hdat_fadump_reg_entry *)bufp; val = (cpu_endian ? be64_to_cpu(reg_entry->reg_val) : - reg_entry->reg_val); + (u64)(reg_entry->reg_val)); opal_fadump_set_regval_regnum(regs, be32_to_cpu(reg_entry->reg_type), be32_to_cpu(reg_entry->reg_num), diff --git a/arch/powerpc/platforms/powernv/opal-flash.c b/arch/powerpc/platforms/powernv/opal-flash.c index 18481a8c52fa1b1db47867a97f3fc62d6af921d2..d5ea04e8e4c526b99ca8f1ab613266b385362d82 100644 --- a/arch/powerpc/platforms/powernv/opal-flash.c +++ b/arch/powerpc/platforms/powernv/opal-flash.c @@ -520,6 +520,10 @@ void __init opal_flash_update_init(void) { int ret; + /* Firmware update is not supported by firmware */ + if (!opal_check_token(OPAL_FLASH_VALIDATE)) + return; + /* Allocate validate image buffer */ validate_flash_data.buf = kzalloc(VALIDATE_BUF_SIZE, GFP_KERNEL); if (!validate_flash_data.buf) { diff --git a/arch/powerpc/platforms/powernv/opal-imc.c b/arch/powerpc/platforms/powernv/opal-imc.c index 3fea5da6d1b363ed7e8118843e7651e4d818ec0f..348a8cdaecd6d0b359650251e5b8ee639581741a 100644 --- a/arch/powerpc/platforms/powernv/opal-imc.c +++ b/arch/powerpc/platforms/powernv/opal-imc.c @@ -211,7 +211,7 @@ static void disable_core_pmu_counters(void) get_hard_smp_processor_id(cpu)); if (rc) pr_err("%s: Failed to stop Core (cpu = %d)\n", - __FUNCTION__, cpu); + __func__, cpu); } cpus_read_unlock(); } diff --git a/arch/powerpc/platforms/powernv/opal-lpc.c b/arch/powerpc/platforms/powernv/opal-lpc.c index 5390c888db162b16fb9849a327af269911356e23..d129d6d45a500b2b0d659b1c85ccb600ccc7937a 100644 --- a/arch/powerpc/platforms/powernv/opal-lpc.c +++ b/arch/powerpc/platforms/powernv/opal-lpc.c @@ -197,7 +197,7 @@ static ssize_t lpc_debug_read(struct file *filp, char __user *ubuf, /* * Select access size based on count and alignment and - * access type. IO and MEM only support byte acceses, + * access type. IO and MEM only support byte accesses, * FW supports all 3. */ len = 1; diff --git a/arch/powerpc/platforms/powernv/opal-memory-errors.c b/arch/powerpc/platforms/powernv/opal-memory-errors.c index 1e8e17df9ce807a90b56a26d8e9fb7f5df58e61d..a1754a28265dd0ec6191c9532294f0ca884dca44 100644 --- a/arch/powerpc/platforms/powernv/opal-memory-errors.c +++ b/arch/powerpc/platforms/powernv/opal-memory-errors.c @@ -82,7 +82,7 @@ static DECLARE_WORK(mem_error_work, mem_error_handler); /* * opal_memory_err_event - notifier handler that queues up the opal message - * to be preocessed later. + * to be processed later. */ static int opal_memory_err_event(struct notifier_block *nb, unsigned long msg_type, void *msg) diff --git a/arch/powerpc/platforms/powernv/pci-cxl.c b/arch/powerpc/platforms/powernv/pci-cxl.c index 53172862d23bd3dbda6780334e6fb609979025b4..7e419de71db8e0e39c53716767f1dd8f1bb39815 100644 --- a/arch/powerpc/platforms/powernv/pci-cxl.c +++ b/arch/powerpc/platforms/powernv/pci-cxl.c @@ -4,6 +4,7 @@ */ #include +#include #include #include diff --git a/arch/powerpc/platforms/powernv/pci-ioda-tce.c b/arch/powerpc/platforms/powernv/pci-ioda-tce.c index 30551bbd7988aca459748df92ffe7300c3bd68c4..e96324502db0c030e01aa9bbbe4a17d7e335af95 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda-tce.c +++ b/arch/powerpc/platforms/powernv/pci-ioda-tce.c @@ -145,8 +145,7 @@ int pnv_tce_build(struct iommu_table *tbl, long index, long npages, #ifdef CONFIG_IOMMU_API int pnv_tce_xchg(struct iommu_table *tbl, long index, - unsigned long *hpa, enum dma_data_direction *direction, - bool alloc) + unsigned long *hpa, enum dma_data_direction *direction) { u64 proto_tce = iommu_direction_to_tce_perm(*direction); unsigned long newtce = *hpa | proto_tce, oldtce; @@ -164,7 +163,7 @@ int pnv_tce_xchg(struct iommu_table *tbl, long index, } if (!ptce) { - ptce = pnv_tce(tbl, false, idx, alloc); + ptce = pnv_tce(tbl, false, idx, true); if (!ptce) return -ENOMEM; } diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index b722ac902269d8344a3d11e3b5793ca17563117b..c8cf2728031a2337c17b0994e415caff6bf5c3ee 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -21,10 +21,11 @@ #include #include #include +#include +#include #include #include -#include #include #include #include @@ -1267,22 +1268,20 @@ static bool pnv_pci_ioda_iommu_bypass_supported(struct pci_dev *pdev, return false; } -static inline __be64 __iomem *pnv_ioda_get_inval_reg(struct pnv_phb *phb, - bool real_mode) +static inline __be64 __iomem *pnv_ioda_get_inval_reg(struct pnv_phb *phb) { - return real_mode ? (__be64 __iomem *)(phb->regs_phys + 0x210) : - (phb->regs + 0x210); + return phb->regs + 0x210; } static void pnv_pci_p7ioc_tce_invalidate(struct iommu_table *tbl, - unsigned long index, unsigned long npages, bool rm) + unsigned long index, unsigned long npages) { struct iommu_table_group_link *tgl = list_first_entry_or_null( &tbl->it_group_list, struct iommu_table_group_link, next); struct pnv_ioda_pe *pe = container_of(tgl->table_group, struct pnv_ioda_pe, table_group); - __be64 __iomem *invalidate = pnv_ioda_get_inval_reg(pe->phb, rm); + __be64 __iomem *invalidate = pnv_ioda_get_inval_reg(pe->phb); unsigned long start, end, inc; start = __pa(((__be64 *)tbl->it_base) + index - tbl->it_offset); @@ -1297,11 +1296,7 @@ static void pnv_pci_p7ioc_tce_invalidate(struct iommu_table *tbl, mb(); /* Ensure above stores are visible */ while (start <= end) { - if (rm) - __raw_rm_writeq_be(start, invalidate); - else - __raw_writeq_be(start, invalidate); - + __raw_writeq_be(start, invalidate); start += inc; } @@ -1320,7 +1315,7 @@ static int pnv_ioda1_tce_build(struct iommu_table *tbl, long index, attrs); if (!ret) - pnv_pci_p7ioc_tce_invalidate(tbl, index, npages, false); + pnv_pci_p7ioc_tce_invalidate(tbl, index, npages); return ret; } @@ -1328,10 +1323,9 @@ static int pnv_ioda1_tce_build(struct iommu_table *tbl, long index, #ifdef CONFIG_IOMMU_API /* Common for IODA1 and IODA2 */ static int pnv_ioda_tce_xchg_no_kill(struct iommu_table *tbl, long index, - unsigned long *hpa, enum dma_data_direction *direction, - bool realmode) + unsigned long *hpa, enum dma_data_direction *direction) { - return pnv_tce_xchg(tbl, index, hpa, direction, !realmode); + return pnv_tce_xchg(tbl, index, hpa, direction); } #endif @@ -1340,7 +1334,7 @@ static void pnv_ioda1_tce_free(struct iommu_table *tbl, long index, { pnv_tce_free(tbl, index, npages); - pnv_pci_p7ioc_tce_invalidate(tbl, index, npages, false); + pnv_pci_p7ioc_tce_invalidate(tbl, index, npages); } static struct iommu_table_ops pnv_ioda1_iommu_ops = { @@ -1361,18 +1355,18 @@ static struct iommu_table_ops pnv_ioda1_iommu_ops = { static inline void pnv_pci_phb3_tce_invalidate_pe(struct pnv_ioda_pe *pe) { /* 01xb - invalidate TCEs that match the specified PE# */ - __be64 __iomem *invalidate = pnv_ioda_get_inval_reg(pe->phb, false); + __be64 __iomem *invalidate = pnv_ioda_get_inval_reg(pe->phb); unsigned long val = PHB3_TCE_KILL_INVAL_PE | (pe->pe_number & 0xFF); mb(); /* Ensure above stores are visible */ __raw_writeq_be(val, invalidate); } -static void pnv_pci_phb3_tce_invalidate(struct pnv_ioda_pe *pe, bool rm, +static void pnv_pci_phb3_tce_invalidate(struct pnv_ioda_pe *pe, unsigned shift, unsigned long index, unsigned long npages) { - __be64 __iomem *invalidate = pnv_ioda_get_inval_reg(pe->phb, rm); + __be64 __iomem *invalidate = pnv_ioda_get_inval_reg(pe->phb); unsigned long start, end, inc; /* We'll invalidate DMA address in PE scope */ @@ -1387,10 +1381,7 @@ static void pnv_pci_phb3_tce_invalidate(struct pnv_ioda_pe *pe, bool rm, mb(); while (start <= end) { - if (rm) - __raw_rm_writeq_be(start, invalidate); - else - __raw_writeq_be(start, invalidate); + __raw_writeq_be(start, invalidate); start += inc; } } @@ -1407,7 +1398,7 @@ static inline void pnv_pci_ioda2_tce_invalidate_pe(struct pnv_ioda_pe *pe) } static void pnv_pci_ioda2_tce_invalidate(struct iommu_table *tbl, - unsigned long index, unsigned long npages, bool rm) + unsigned long index, unsigned long npages) { struct iommu_table_group_link *tgl; @@ -1418,7 +1409,7 @@ static void pnv_pci_ioda2_tce_invalidate(struct iommu_table *tbl, unsigned int shift = tbl->it_page_shift; if (phb->model == PNV_PHB_MODEL_PHB3 && phb->regs) - pnv_pci_phb3_tce_invalidate(pe, rm, shift, + pnv_pci_phb3_tce_invalidate(pe, shift, index, npages); else opal_pci_tce_kill(phb->opal_id, @@ -1437,7 +1428,7 @@ static int pnv_ioda2_tce_build(struct iommu_table *tbl, long index, attrs); if (!ret) - pnv_pci_ioda2_tce_invalidate(tbl, index, npages, false); + pnv_pci_ioda2_tce_invalidate(tbl, index, npages); return ret; } @@ -1447,7 +1438,7 @@ static void pnv_ioda2_tce_free(struct iommu_table *tbl, long index, { pnv_tce_free(tbl, index, npages); - pnv_pci_ioda2_tce_invalidate(tbl, index, npages, false); + pnv_pci_ioda2_tce_invalidate(tbl, index, npages); } static struct iommu_table_ops pnv_ioda2_iommu_ops = { @@ -2383,7 +2374,7 @@ static void pnv_ioda_setup_pe_res(struct pnv_ioda_pe *pe, /* * This function is supposed to be called on basis of PE from top - * to bottom style. So the the I/O or MMIO segment assigned to + * to bottom style. So the I/O or MMIO segment assigned to * parent PE could be overridden by its child PEs if necessary. */ static void pnv_ioda_setup_pe_seg(struct pnv_ioda_pe *pe) @@ -2738,7 +2729,7 @@ static void pnv_pci_ioda1_release_pe_dma(struct pnv_ioda_pe *pe) if (rc != OPAL_SUCCESS) return; - pnv_pci_p7ioc_tce_invalidate(tbl, tbl->it_offset, tbl->it_size, false); + pnv_pci_p7ioc_tce_invalidate(tbl, tbl->it_offset, tbl->it_size); if (pe->table_group.group) { iommu_group_put(pe->table_group.group); WARN_ON(pe->table_group.group); diff --git a/arch/powerpc/platforms/powernv/pci-sriov.c b/arch/powerpc/platforms/powernv/pci-sriov.c index 04155aaaadb1d2a51f133db8b9920359dcfeecee..7195133b26bb9eeafca1bc4efb2c0f1df125cfaf 100644 --- a/arch/powerpc/platforms/powernv/pci-sriov.c +++ b/arch/powerpc/platforms/powernv/pci-sriov.c @@ -22,7 +22,7 @@ * have the same requirement. * * For a SR-IOV BAR things are a little more awkward since size and alignment - * are not coupled. The alignment is set based on the the per-VF BAR size, but + * are not coupled. The alignment is set based on the per-VF BAR size, but * the total BAR area is: number-of-vfs * per-vf-size. The number of VFs * isn't necessarily a power of two, so neither is the total size. To fix that * we need to finesse (read: hack) the Linux BAR allocator so that it will @@ -699,7 +699,7 @@ static int pnv_pci_sriov_enable(struct pci_dev *pdev, u16 num_vfs) return -ENOSPC; } - /* allocate a contigious block of PEs for our VFs */ + /* allocate a contiguous block of PEs for our VFs */ base_pe = pnv_ioda_alloc_pe(phb, num_vfs); if (!base_pe) { pci_err(pdev, "Unable to allocate PEs for %d VFs\n", num_vfs); diff --git a/arch/powerpc/platforms/powernv/pci.c b/arch/powerpc/platforms/powernv/pci.c index f7054879ecd4bee02676766e1a7033beb57adaa4..233a50e65fceddf8d641d71c40f989df7a219144 100644 --- a/arch/powerpc/platforms/powernv/pci.c +++ b/arch/powerpc/platforms/powernv/pci.c @@ -18,7 +18,6 @@ #include #include -#include #include #include #include diff --git a/arch/powerpc/platforms/powernv/pci.h b/arch/powerpc/platforms/powernv/pci.h index 966a9eb643390c40803772300dde6e7c660ee841..f12643958b8d88ca1f8e77bf126fd9366c8a9b10 100644 --- a/arch/powerpc/platforms/powernv/pci.h +++ b/arch/powerpc/platforms/powernv/pci.h @@ -311,8 +311,7 @@ extern int pnv_tce_build(struct iommu_table *tbl, long index, long npages, unsigned long attrs); extern void pnv_tce_free(struct iommu_table *tbl, long index, long npages); extern int pnv_tce_xchg(struct iommu_table *tbl, long index, - unsigned long *hpa, enum dma_data_direction *direction, - bool alloc); + unsigned long *hpa, enum dma_data_direction *direction); extern __be64 *pnv_tce_useraddrptr(struct iommu_table *tbl, long index, bool alloc); extern unsigned long pnv_tce_get(struct iommu_table *tbl, long index); diff --git a/arch/powerpc/platforms/powernv/setup.c b/arch/powerpc/platforms/powernv/setup.c index 105d889abd51a4a45a37484afc6d574d361b2602..824c3ad7a0fafb650fd4691b935a857d13a7a70d 100644 --- a/arch/powerpc/platforms/powernv/setup.c +++ b/arch/powerpc/platforms/powernv/setup.c @@ -96,6 +96,15 @@ static void __init init_fw_feat_flags(struct device_node *np) if (fw_feature_is("disabled", "needs-spec-barrier-for-bound-checks", np)) security_ftr_clear(SEC_FTR_BNDS_CHK_SPEC_BAR); + + if (fw_feature_is("enabled", "no-need-l1d-flush-msr-pr-1-to-0", np)) + security_ftr_clear(SEC_FTR_L1D_FLUSH_ENTRY); + + if (fw_feature_is("enabled", "no-need-l1d-flush-kernel-on-user-access", np)) + security_ftr_clear(SEC_FTR_L1D_FLUSH_UACCESS); + + if (fw_feature_is("enabled", "no-need-store-drain-on-priv-state-switch", np)) + security_ftr_clear(SEC_FTR_STF_BARRIER); } static void __init pnv_setup_security_mitigations(void) diff --git a/arch/powerpc/platforms/powernv/smp.c b/arch/powerpc/platforms/powernv/smp.c index cbb67813cd5df2babcf58477ae014feda352a57d..9e1a25398f98cbe383be9fdaaf6f2194f9fab3fc 100644 --- a/arch/powerpc/platforms/powernv/smp.c +++ b/arch/powerpc/platforms/powernv/smp.c @@ -345,7 +345,7 @@ static void __init pnv_smp_probe(void) } } -static int pnv_system_reset_exception(struct pt_regs *regs) +noinstr static int pnv_system_reset_exception(struct pt_regs *regs) { if (smp_handle_nmi_ipi(regs)) return 1; diff --git a/arch/powerpc/platforms/powernv/ultravisor.c b/arch/powerpc/platforms/powernv/ultravisor.c index e4a00ad06f9d3fe6ab8239a90cc27e480381bd46..67c8c4b2d8b17c3662507121e97f48587d3ef82b 100644 --- a/arch/powerpc/platforms/powernv/ultravisor.c +++ b/arch/powerpc/platforms/powernv/ultravisor.c @@ -55,6 +55,7 @@ static int __init uv_init(void) return -ENODEV; uv_memcons = memcons_init(node, "memcons"); + of_node_put(node); if (!uv_memcons) return -ENOENT; diff --git a/arch/powerpc/platforms/powernv/vas-fault.c b/arch/powerpc/platforms/powernv/vas-fault.c index a7aabc18039eb4bd2bbe6e8876d482701d12341c..c1bfad56447d4c420752056fa93430b1b1c34e73 100644 --- a/arch/powerpc/platforms/powernv/vas-fault.c +++ b/arch/powerpc/platforms/powernv/vas-fault.c @@ -216,7 +216,7 @@ int vas_setup_fault_window(struct vas_instance *vinst) vas_init_rx_win_attr(&attr, VAS_COP_TYPE_FAULT); attr.rx_fifo_size = vinst->fault_fifo_size; - attr.rx_fifo = vinst->fault_fifo; + attr.rx_fifo = __pa(vinst->fault_fifo); /* * Max creds is based on number of CRBs can fit in the FIFO. diff --git a/arch/powerpc/platforms/powernv/vas-window.c b/arch/powerpc/platforms/powernv/vas-window.c index 0f8d39fbf2b21a04e6c8b35db0bbdf975e3ab1aa..0072682531d8064e638958e120d17a3dcea725c5 100644 --- a/arch/powerpc/platforms/powernv/vas-window.c +++ b/arch/powerpc/platforms/powernv/vas-window.c @@ -404,7 +404,7 @@ static void init_winctx_regs(struct pnv_vas_window *window, * * See also: Design note in function header. */ - val = __pa(winctx->rx_fifo); + val = winctx->rx_fifo; val = SET_FIELD(VAS_PAGE_MIGRATION_SELECT, val, 0); write_hvwc_reg(window, VREG(LFIFO_BAR), val); @@ -739,7 +739,7 @@ static void init_winctx_for_rxwin(struct pnv_vas_window *rxwin, */ winctx->fifo_disable = true; winctx->intr_disable = true; - winctx->rx_fifo = NULL; + winctx->rx_fifo = 0; } winctx->lnotify_lpid = rxattr->lnotify_lpid; diff --git a/arch/powerpc/platforms/powernv/vas.h b/arch/powerpc/platforms/powernv/vas.h index 8bb08e395de059a16813c59fed51a52da95e5c09..08d9d3d5a22b08091817c62a8dc48c285e67f9af 100644 --- a/arch/powerpc/platforms/powernv/vas.h +++ b/arch/powerpc/platforms/powernv/vas.h @@ -376,7 +376,7 @@ struct pnv_vas_window { * is a container for the register fields in the window context. */ struct vas_winctx { - void *rx_fifo; + u64 rx_fifo; int rx_fifo_size; int wcreds_max; int rsvd_txbuf_count; diff --git a/arch/powerpc/platforms/ps3/Kconfig b/arch/powerpc/platforms/ps3/Kconfig index a4048b8c8c507cfeff218e77896a677074a15754..610682caabc46dd5c5087d99c6ae5ab0fbeb629a 100644 --- a/arch/powerpc/platforms/ps3/Kconfig +++ b/arch/powerpc/platforms/ps3/Kconfig @@ -90,7 +90,7 @@ config PS3_VERBOSE_RESULT bool "PS3 Verbose LV1 hypercall results" if PS3_ADVANCED depends on PPC_PS3 help - Enables more verbose log mesages for LV1 hypercall results. + Enables more verbose log messages for LV1 hypercall results. If in doubt, say N here and reduce the size of the kernel by a small amount. diff --git a/arch/powerpc/platforms/ps3/htab.c b/arch/powerpc/platforms/ps3/htab.c index ef710a7159035f87b6cb98308a921773cc9f2060..c27e6cf852729d98ee24af3f7d05f22ec7df4c02 100644 --- a/arch/powerpc/platforms/ps3/htab.c +++ b/arch/powerpc/platforms/ps3/htab.c @@ -10,7 +10,6 @@ #include #include -#include #include #include #include diff --git a/arch/powerpc/platforms/ps3/mm.c b/arch/powerpc/platforms/ps3/mm.c index 5ce924611b941bdaf9a676e4151139cd1ce967ea..1326de55fda655167467aa5ddc9a347abbcbc7da 100644 --- a/arch/powerpc/platforms/ps3/mm.c +++ b/arch/powerpc/platforms/ps3/mm.c @@ -14,7 +14,6 @@ #include #include -#include #include #include #include @@ -364,7 +363,7 @@ static void __maybe_unused _dma_dump_region(const struct ps3_dma_region *r, * @bus_addr: Starting ioc bus address of the area to map. * @len: Length in bytes of the area to map. * @link: A struct list_head used with struct ps3_dma_region.chunk_list, the - * list of all chuncks owned by the region. + * list of all chunks owned by the region. * * This implementation uses a very simple dma page manager * based on the dma_chunk structure. This scheme assumes diff --git a/arch/powerpc/platforms/ps3/os-area.c b/arch/powerpc/platforms/ps3/os-area.c index cb844e0add2b0ff6cc534e51bddab62a70ca80b3..b384cd2d6b99b41b96b875868d6640fb9bdf4885 100644 --- a/arch/powerpc/platforms/ps3/os-area.c +++ b/arch/powerpc/platforms/ps3/os-area.c @@ -17,8 +17,6 @@ #include #include -#include - #include "platform.h" enum { diff --git a/arch/powerpc/platforms/ps3/setup.c b/arch/powerpc/platforms/ps3/setup.c index 3de9145c20bc0bb5d189208fcab1fae21f41cce9..d7495785fe47bc8f0e6be113331f2832dcc093ef 100644 --- a/arch/powerpc/platforms/ps3/setup.c +++ b/arch/powerpc/platforms/ps3/setup.c @@ -13,13 +13,13 @@ #include #include #include +#include #include #include #include #include #include -#include #include #include diff --git a/arch/powerpc/platforms/ps3/system-bus.c b/arch/powerpc/platforms/ps3/system-bus.c index b637bf2920474e8254f57583fa09b8245a3ad9f0..2502e9b17df4abe7b4eb9472e4b2d1e3d9187e78 100644 --- a/arch/powerpc/platforms/ps3/system-bus.c +++ b/arch/powerpc/platforms/ps3/system-bus.c @@ -601,7 +601,7 @@ static dma_addr_t ps3_ioc0_map_page(struct device *_dev, struct page *page, iopte_flag |= CBE_IOPTE_PP_W | CBE_IOPTE_SO_RW; break; default: - /* not happned */ + /* not happened */ BUG(); } result = ps3_dma_map(dev->d_region, (unsigned long)ptr, size, diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile index 9764e1a2ed5c6d82d8ab7f4c2ca6f3adeb7075a4..7aaff5323544261b231c4a3a26efa57747d2d4ae 100644 --- a/arch/powerpc/platforms/pseries/Makefile +++ b/arch/powerpc/platforms/pseries/Makefile @@ -33,3 +33,7 @@ obj-$(CONFIG_SUSPEND) += suspend.o obj-$(CONFIG_PPC_VAS) += vas.o vas-sysfs.o obj-$(CONFIG_ARCH_HAS_CC_PLATFORM) += cc_platform.o + +# nothing that operates in real mode is safe for KASAN +KASAN_SANITIZE_ras.o := n +KASAN_SANITIZE_kexec.o := n diff --git a/arch/powerpc/platforms/pseries/cmm.c b/arch/powerpc/platforms/pseries/cmm.c index 45a3a3022a85c9061ed7b724c1424369f83b0ee9..15ed8206c4630db978f99103566ec891856fab20 100644 --- a/arch/powerpc/platforms/pseries/cmm.c +++ b/arch/powerpc/platforms/pseries/cmm.c @@ -475,8 +475,6 @@ static struct notifier_block cmm_reboot_nb = { static int cmm_memory_cb(struct notifier_block *self, unsigned long action, void *arg) { - int ret = 0; - switch (action) { case MEM_GOING_OFFLINE: mutex_lock(&hotplug_mutex); @@ -493,7 +491,7 @@ static int cmm_memory_cb(struct notifier_block *self, break; } - return notifier_from_errno(ret); + return NOTIFY_OK; } static struct notifier_block cmm_mem_nb = { diff --git a/arch/powerpc/platforms/pseries/dlpar.c b/arch/powerpc/platforms/pseries/dlpar.c index b1f01ac0c29e3f670a386c1d43b7c2a6054907d0..498d6efcb5ae7eb7e12084184d92a848e50730df 100644 --- a/arch/powerpc/platforms/pseries/dlpar.c +++ b/arch/powerpc/platforms/pseries/dlpar.c @@ -19,7 +19,6 @@ #include "of_helpers.h" #include "pseries.h" -#include #include #include #include @@ -389,7 +388,7 @@ static void pseries_hp_work_fn(struct work_struct *work) handle_dlpar_errorlog(hp_work->errlog); kfree(hp_work->errlog); - kfree((void *)work); + kfree(work); } void queue_hotplug_event(struct pseries_hp_errorlog *hp_errlog) diff --git a/arch/powerpc/platforms/pseries/eeh_pseries.c b/arch/powerpc/platforms/pseries/eeh_pseries.c index 09fafcf2d3a060d9ba1e28658447d659bc993819..1b0c901a6f3b111aa8dbdb22f478e3def1ce6aaa 100644 --- a/arch/powerpc/platforms/pseries/eeh_pseries.c +++ b/arch/powerpc/platforms/pseries/eeh_pseries.c @@ -43,6 +43,8 @@ static int ibm_get_config_addr_info; static int ibm_get_config_addr_info2; static int ibm_configure_pe; +static void pseries_eeh_init_edev(struct pci_dn *pdn); + static void pseries_pcibios_bus_add_device(struct pci_dev *pdev) { struct pci_dn *pdn = pci_get_pdn(pdev); @@ -359,7 +361,7 @@ static struct eeh_pe *pseries_eeh_pe_get_parent(struct eeh_dev *edev) * This function takes care of the initialisation and inserts the eeh_dev * into the correct eeh_pe. If no eeh_pe exists we'll allocate one. */ -void pseries_eeh_init_edev(struct pci_dn *pdn) +static void pseries_eeh_init_edev(struct pci_dn *pdn) { struct eeh_pe pe, *parent; struct eeh_dev *edev; @@ -510,7 +512,7 @@ static int pseries_eeh_set_option(struct eeh_pe *pe, int option) int ret = 0; /* - * When we're enabling or disabling EEH functioality on + * When we're enabling or disabling EEH functionality on * the particular PE, the PE config address is possibly * unavailable. Therefore, we have to figure it out from * the FDT node. @@ -845,8 +847,7 @@ static int __init eeh_pseries_init(void) return -EINVAL; } - /* Initialize error log lock and size */ - spin_lock_init(&slot_errbuf_lock); + /* Initialize error log size */ eeh_error_buf_size = rtas_token("rtas-error-log-max"); if (eeh_error_buf_size == RTAS_UNKNOWN_SERVICE) { pr_info("%s: unknown EEH error log size\n", diff --git a/arch/powerpc/platforms/pseries/hotplug-cpu.c b/arch/powerpc/platforms/pseries/hotplug-cpu.c index b81fc846d99cfdbd45f0698de871cd3ce0177965..0f8cd8b06432d21a02bd0ddae4a0b8677de962ae 100644 --- a/arch/powerpc/platforms/pseries/hotplug-cpu.c +++ b/arch/powerpc/platforms/pseries/hotplug-cpu.c @@ -398,7 +398,7 @@ static int dlpar_online_cpu(struct device_node *dn) if (get_hard_smp_processor_id(cpu) != thread) continue; cpu_maps_update_done(); - find_and_online_cpu_nid(cpu); + find_and_update_cpu_nid(cpu); rc = device_online(get_cpu_device(cpu)); if (rc) { dlpar_offline_cpu(dn); diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c index 91cf23495ccb580b10dd7518cb48348805de2bce..2e3a317722a81d27112d5750dfe024fbab4645a3 100644 --- a/arch/powerpc/platforms/pseries/hotplug-memory.c +++ b/arch/powerpc/platforms/pseries/hotplug-memory.c @@ -16,7 +16,6 @@ #include #include -#include #include #include #include diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c index 4d991cf840d9104c0fb2ba538592a9f92dde97e1..fba64304e85973b9b8e508b6093530eecae3274c 100644 --- a/arch/powerpc/platforms/pseries/iommu.c +++ b/arch/powerpc/platforms/pseries/iommu.c @@ -666,8 +666,7 @@ static void pci_dma_bus_setup_pSeries(struct pci_bus *bus) #ifdef CONFIG_IOMMU_API static int tce_exchange_pseries(struct iommu_table *tbl, long index, unsigned - long *tce, enum dma_data_direction *direction, - bool realmode) + long *tce, enum dma_data_direction *direction) { long rc; unsigned long ioba = (unsigned long) index << tbl->it_page_shift; @@ -1430,7 +1429,7 @@ static bool enable_ddw(struct pci_dev *dev, struct device_node *pdn) pci->table_group->tables[1] = newtbl; - /* Keep default DMA window stuct if removed */ + /* Keep default DMA window struct if removed */ if (default_win_removed) { tbl->it_size = 0; vfree(tbl->it_map); diff --git a/arch/powerpc/platforms/pseries/kexec.c b/arch/powerpc/platforms/pseries/kexec.c index 145fcfbc017f2e8376b14beef0ea2fdc7353e874..ab6cdbebb35e2b9f3b8a30b1c9efafdceec59b3a 100644 --- a/arch/powerpc/platforms/pseries/kexec.c +++ b/arch/powerpc/platforms/pseries/kexec.c @@ -61,3 +61,11 @@ void pseries_kexec_cpu_down(int crash_shutdown, int secondary) } else xics_kexec_teardown_cpu(secondary); } + +void pseries_machine_kexec(struct kimage *image) +{ + if (firmware_has_feature(FW_FEATURE_SET_MODE)) + pseries_disable_reloc_on_exc(); + + default_machine_kexec(image); +} diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c index 760581c5752f00f36563d8a9dbc894988e2cf322..937f9c010b22cde03be0f5c80231b7ac920bf589 100644 --- a/arch/powerpc/platforms/pseries/lpar.c +++ b/arch/powerpc/platforms/pseries/lpar.c @@ -31,7 +31,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/powerpc/platforms/pseries/lparcfg.c b/arch/powerpc/platforms/pseries/lparcfg.c index 2119c003fcf938a16aa77001ba5582e84aaf5809..507dc0b5987d01e70fff4d9e32bd777a497d7e3e 100644 --- a/arch/powerpc/platforms/pseries/lparcfg.c +++ b/arch/powerpc/platforms/pseries/lparcfg.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/powerpc/platforms/pseries/msi.c b/arch/powerpc/platforms/pseries/msi.c index fb2919fd6bc03066e67c8dadaae669b9d15c57cc..a3a71d37cb9a624b6ba4be707819f66a4db60aec 100644 --- a/arch/powerpc/platforms/pseries/msi.c +++ b/arch/powerpc/platforms/pseries/msi.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include diff --git a/arch/powerpc/platforms/pseries/nvram.c b/arch/powerpc/platforms/pseries/nvram.c index 69db2eca367f7fc4a765b0762ac99eb6e17d985f..cbf1720eb4aadcae3d208e69e7d530e80d9c3a1e 100644 --- a/arch/powerpc/platforms/pseries/nvram.c +++ b/arch/powerpc/platforms/pseries/nvram.c @@ -13,9 +13,9 @@ #include #include #include +#include #include #include -#include #include /* Max bytes to read/write in one go */ diff --git a/arch/powerpc/platforms/pseries/papr_scm.c b/arch/powerpc/platforms/pseries/papr_scm.c index 39962c9055422eea5b9ee23d43b1c67fb520f1cd..181b855b30509c8bf549bd246c70f4a428b6fc82 100644 --- a/arch/powerpc/platforms/pseries/papr_scm.c +++ b/arch/powerpc/platforms/pseries/papr_scm.c @@ -125,8 +125,8 @@ struct papr_scm_priv { /* The bits which needs to be overridden */ u64 health_bitmap_inject_mask; - /* array to have event_code and stat_id mappings */ - char **nvdimm_events_map; + /* array to have event_code and stat_id mappings */ + u8 *nvdimm_events_map; }; static int papr_scm_pmem_flush(struct nd_region *nd_region, @@ -370,7 +370,7 @@ static int papr_scm_pmu_get_value(struct perf_event *event, struct device *dev, stat = &stats->scm_statistic[0]; memcpy(&stat->stat_id, - p->nvdimm_events_map[event->attr.config], + &p->nvdimm_events_map[event->attr.config * sizeof(stat->stat_id)], sizeof(stat->stat_id)); stat->stat_val = 0; @@ -462,14 +462,13 @@ static int papr_scm_pmu_check_events(struct papr_scm_priv *p, struct nvdimm_pmu { struct papr_scm_perf_stat *stat; struct papr_scm_perf_stats *stats; - int index, rc, count; u32 available_events; - - if (!p->stat_buffer_len) - return -ENOENT; + int index, rc = 0; available_events = (p->stat_buffer_len - sizeof(struct papr_scm_perf_stats)) / sizeof(struct papr_scm_perf_stat); + if (available_events == 0) + return -EOPNOTSUPP; /* Allocate the buffer for phyp where stats are written */ stats = kzalloc(p->stat_buffer_len, GFP_KERNEL); @@ -478,35 +477,30 @@ static int papr_scm_pmu_check_events(struct papr_scm_priv *p, struct nvdimm_pmu return rc; } - /* Allocate memory to nvdimm_event_map */ - p->nvdimm_events_map = kcalloc(available_events, sizeof(char *), GFP_KERNEL); - if (!p->nvdimm_events_map) { - rc = -ENOMEM; - goto out_stats; - } - /* Called to get list of events supported */ rc = drc_pmem_query_stats(p, stats, 0); if (rc) - goto out_nvdimm_events_map; - - for (index = 0, stat = stats->scm_statistic, count = 0; - index < available_events; index++, ++stat) { - p->nvdimm_events_map[count] = kmemdup_nul(stat->stat_id, 8, GFP_KERNEL); - if (!p->nvdimm_events_map[count]) { - rc = -ENOMEM; - goto out_nvdimm_events_map; - } + goto out; - count++; + /* + * Allocate memory and populate nvdimm_event_map. + * Allocate an extra element for NULL entry + */ + p->nvdimm_events_map = kcalloc(available_events + 1, + sizeof(stat->stat_id), + GFP_KERNEL); + if (!p->nvdimm_events_map) { + rc = -ENOMEM; + goto out; } - p->nvdimm_events_map[count] = NULL; - kfree(stats); - return 0; -out_nvdimm_events_map: - kfree(p->nvdimm_events_map); -out_stats: + /* Copy all stat_ids to event map */ + for (index = 0, stat = stats->scm_statistic; + index < available_events; index++, ++stat) { + memcpy(&p->nvdimm_events_map[index * sizeof(stat->stat_id)], + &stat->stat_id, sizeof(stat->stat_id)); + } +out: kfree(stats); return rc; } diff --git a/arch/powerpc/platforms/pseries/pci.c b/arch/powerpc/platforms/pseries/pci.c index 3b6800f774c241bdd935970f8c381c4ceb429380..6e671c3809ecfdf9c7df5707779afe6a49b908b1 100644 --- a/arch/powerpc/platforms/pseries/pci.c +++ b/arch/powerpc/platforms/pseries/pci.c @@ -14,7 +14,6 @@ #include #include -#include #include #include #include "pseries.h" diff --git a/arch/powerpc/platforms/pseries/pmem.c b/arch/powerpc/platforms/pseries/pmem.c index 439ac72c247088d19a66a81a96f749f2af8b985f..3c290b9ed01b39e20a191e7dbc709a8198bd2d9e 100644 --- a/arch/powerpc/platforms/pseries/pmem.c +++ b/arch/powerpc/platforms/pseries/pmem.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/powerpc/platforms/pseries/pseries.h b/arch/powerpc/platforms/pseries/pseries.h index af162aeeae86d8d0d5ad69dc0c08477216e4bce4..f5c916c839c9854931ee060774b907511a01871b 100644 --- a/arch/powerpc/platforms/pseries/pseries.h +++ b/arch/powerpc/platforms/pseries/pseries.h @@ -38,6 +38,7 @@ static inline void smp_init_pseries(void) { } #endif extern void pseries_kexec_cpu_down(int crash_shutdown, int secondary); +void pseries_machine_kexec(struct kimage *image); extern void pSeries_final_fixup(void); diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c index 7f7369fec46b80cf58d715f0395ec01a817720db..cad7a0c9311705912a64b1e9fd9e321cc532f39f 100644 --- a/arch/powerpc/platforms/pseries/reconfig.c +++ b/arch/powerpc/platforms/pseries/reconfig.c @@ -13,7 +13,6 @@ #include #include -#include #include #include #include diff --git a/arch/powerpc/platforms/pseries/rtas-fadump.c b/arch/powerpc/platforms/pseries/rtas-fadump.c index 35f9cb602c304bb3fc595c32447a126564fa09ae..b5853e9fcc3c157cc8ce972faf71b0f8ef7f7b87 100644 --- a/arch/powerpc/platforms/pseries/rtas-fadump.c +++ b/arch/powerpc/platforms/pseries/rtas-fadump.c @@ -13,9 +13,10 @@ #include #include #include +#include +#include #include -#include #include #include #include @@ -108,6 +109,12 @@ static u64 rtas_fadump_init_mem_struct(struct fw_dump *fadump_conf) fdm.hpte_region.destination_address = cpu_to_be64(addr); addr += fadump_conf->hpte_region_size; + /* + * Align boot memory area destination address to page boundary to + * be able to mmap read this area in the vmcore. + */ + addr = PAGE_ALIGN(addr); + /* RMA region section */ fdm.rmr_region.request_flag = cpu_to_be32(RTAS_FADUMP_REQUEST_FLAG); fdm.rmr_region.source_data_type = @@ -351,7 +358,7 @@ static int __init rtas_fadump_build_cpu_notes(struct fw_dump *fadump_conf) /* Lower 4 bytes of reg_value contains logical cpu id */ cpu = (be64_to_cpu(reg_entry->reg_value) & RTAS_FADUMP_CPU_ID_MASK); - if (fdh && !cpumask_test_cpu(cpu, &fdh->online_mask)) { + if (fdh && !cpumask_test_cpu(cpu, &fdh->cpu_mask)) { RTAS_FADUMP_SKIP_TO_NEXT_CPU(reg_entry); continue; } @@ -462,10 +469,10 @@ static void rtas_fadump_region_show(struct fw_dump *fadump_conf, be64_to_cpu(fdm_ptr->rmr_region.source_len), be64_to_cpu(fdm_ptr->rmr_region.bytes_dumped)); - /* Dump is active. Show reserved area start address. */ + /* Dump is active. Show preserved area start address. */ if (fdm_active) { - seq_printf(m, "\nMemory above %#016lx is reserved for saving crash dump\n", - fadump_conf->reserve_dump_area_start); + seq_printf(m, "\nMemory above %#016llx is reserved for saving crash dump\n", + fadump_conf->boot_mem_top); } } diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index 0f74b22847733f3bff6350a7b199b5b090b6c929..afb074269b42b0124119ae6c5504133981ee58cb 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -43,7 +44,6 @@ #include #include #include -#include #include #include #include @@ -421,16 +421,6 @@ void pseries_disable_reloc_on_exc(void) } EXPORT_SYMBOL(pseries_disable_reloc_on_exc); -#ifdef CONFIG_KEXEC_CORE -static void pSeries_machine_kexec(struct kimage *image) -{ - if (firmware_has_feature(FW_FEATURE_SET_MODE)) - pseries_disable_reloc_on_exc(); - - default_machine_kexec(image); -} -#endif - #ifdef __LITTLE_ENDIAN__ void pseries_big_endian_exceptions(void) { @@ -658,7 +648,7 @@ static resource_size_t pseries_get_iov_fw_value(struct pci_dev *dev, int resno, */ num_res = of_read_number(&indexes[NUM_RES_PROPERTY], 1); if (resno >= num_res) - return 0; /* or an errror */ + return 0; /* or an error */ i = START_OF_ENTRIES + NEXT_ENTRY * resno; switch (value) { @@ -762,7 +752,7 @@ static void pseries_pci_fixup_iov_resources(struct pci_dev *pdev) if (!pdev->is_physfn) return; - /*Firmware must support open sriov otherwise dont configure*/ + /*Firmware must support open sriov otherwise don't configure*/ indexes = of_get_property(dn, "ibm,open-sriov-vf-bar-info", NULL); if (indexes) of_pci_parse_iov_addrs(pdev, indexes); @@ -1096,7 +1086,7 @@ define_machine(pseries) { .machine_check_exception = pSeries_machine_check_exception, .machine_check_log_err = pSeries_machine_check_log_err, #ifdef CONFIG_KEXEC_CORE - .machine_kexec = pSeries_machine_kexec, + .machine_kexec = pseries_machine_kexec, .kexec_cpu_down = pseries_kexec_cpu_down, #endif #ifdef CONFIG_MEMORY_HOTPLUG diff --git a/arch/powerpc/platforms/pseries/smp.c b/arch/powerpc/platforms/pseries/smp.c index f47429323eee946994014c985b110616dbf35b63..fd2174edfa1dcbaff9f85fdb05568a40563a0438 100644 --- a/arch/powerpc/platforms/pseries/smp.c +++ b/arch/powerpc/platforms/pseries/smp.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/powerpc/platforms/pseries/vas-sysfs.c b/arch/powerpc/platforms/pseries/vas-sysfs.c index ec65586cbeb39092886544d7c4213656f78d5dc3..f9f682724e776356fee595da562c1dfac75fa847 100644 --- a/arch/powerpc/platforms/pseries/vas-sysfs.c +++ b/arch/powerpc/platforms/pseries/vas-sysfs.c @@ -74,26 +74,26 @@ struct vas_sysfs_entry { /* * Create sysfs interface: - * /sys/devices/vas/vas0/gzip/default_capabilities + * /sys/devices/virtual/misc/vas/vas0/gzip/default_capabilities * This directory contains the following VAS GZIP capabilities - * for the defaule credit type. - * /sys/devices/vas/vas0/gzip/default_capabilities/nr_total_credits + * for the default credit type. + * /sys/devices/virtual/misc/vas/vas0/gzip/default_capabilities/nr_total_credits * Total number of default credits assigned to the LPAR which * can be changed with DLPAR operation. - * /sys/devices/vas/vas0/gzip/default_capabilities/nr_used_credits + * /sys/devices/virtual/misc/vas/vas0/gzip/default_capabilities/nr_used_credits * Number of credits used by the user space. One credit will * be assigned for each window open. * - * /sys/devices/vas/vas0/gzip/qos_capabilities + * /sys/devices/virtual/misc/vas/vas0/gzip/qos_capabilities * This directory contains the following VAS GZIP capabilities * for the Quality of Service (QoS) credit type. - * /sys/devices/vas/vas0/gzip/qos_capabilities/nr_total_credits + * /sys/devices/virtual/misc/vas/vas0/gzip/qos_capabilities/nr_total_credits * Total number of QoS credits assigned to the LPAR. The user * has to define this value using HMC interface. It can be * changed dynamically by the user. - * /sys/devices/vas/vas0/gzip/qos_capabilities/nr_used_credits + * /sys/devices/virtual/misc/vas/vas0/gzip/qos_capabilities/nr_used_credits * Number of credits used by the user space. - * /sys/devices/vas/vas0/gzip/qos_capabilities/update_total_credits + * /sys/devices/virtual/misc/vas/vas0/gzip/qos_capabilities/update_total_credits * Update total QoS credits dynamically */ @@ -248,6 +248,7 @@ int __init sysfs_pseries_vas_init(struct vas_all_caps *vas_caps) pseries_vas_kobj = kobject_create_and_add("vas0", &vas_miscdev.this_device->kobj); if (!pseries_vas_kobj) { + misc_deregister(&vas_miscdev); pr_err("Failed to create VAS sysfs entry\n"); return -ENOMEM; } @@ -259,6 +260,7 @@ int __init sysfs_pseries_vas_init(struct vas_all_caps *vas_caps) if (!gzip_caps_kobj) { pr_err("Failed to create VAS GZIP capability entry\n"); kobject_put(pseries_vas_kobj); + misc_deregister(&vas_miscdev); return -ENOMEM; } } diff --git a/arch/powerpc/platforms/pseries/vas.c b/arch/powerpc/platforms/pseries/vas.c index ec643bbdb67fcabf2428f34c1eeaee613a174859..500a1fc4a1d7d524191bbf0126673d497f4f8635 100644 --- a/arch/powerpc/platforms/pseries/vas.c +++ b/arch/powerpc/platforms/pseries/vas.c @@ -801,7 +801,7 @@ int vas_reconfig_capabilties(u8 type, int new_nr_creds) atomic_set(&caps->nr_total_credits, new_nr_creds); /* * The total number of available credits may be decreased or - * inceased with DLPAR operation. Means some windows have to be + * increased with DLPAR operation. Means some windows have to be * closed / reopened. Hold the vas_pseries_mutex so that the * the user space can not open new windows. */ diff --git a/arch/powerpc/platforms/pseries/vio.c b/arch/powerpc/platforms/pseries/vio.c index c9f9be4ea26a0a58fb906dab8f81efebdab7ad0d..00ecac2c205b0d38f858601a6765765463fc141a 100644 --- a/arch/powerpc/platforms/pseries/vio.c +++ b/arch/powerpc/platforms/pseries/vio.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile index 026b3f01a99123eab1ccc6375c737536b23d6852..9cb1d029511a0154b6348f2ab101907d955eee9c 100644 --- a/arch/powerpc/sysdev/Makefile +++ b/arch/powerpc/sysdev/Makefile @@ -23,7 +23,6 @@ obj-$(CONFIG_FSL_PMC) += fsl_pmc.o obj-$(CONFIG_FSL_CORENET_RCPM) += fsl_rcpm.o obj-$(CONFIG_FSL_LBC) += fsl_lbc.o obj-$(CONFIG_FSL_GTM) += fsl_gtm.o -obj-$(CONFIG_FSL_85XX_CACHE_SRAM) += fsl_85xx_l2ctlr.o fsl_85xx_cache_sram.o obj-$(CONFIG_FSL_RIO) += fsl_rio.o fsl_rmu.o obj-$(CONFIG_TSI108_BRIDGE) += tsi108_pci.o tsi108_dev.o obj-$(CONFIG_RTC_DRV_CMOS) += rtc_cmos_setup.o diff --git a/arch/powerpc/sysdev/cpm2_pic.c b/arch/powerpc/sysdev/cpm2_pic.c index 9e86074719a96e2f3c47b4a1f69f453483e61f8f..cb9ba4ef557a3f320e6b8577bf8307d8ae41281d 100644 --- a/arch/powerpc/sysdev/cpm2_pic.c +++ b/arch/powerpc/sysdev/cpm2_pic.c @@ -30,11 +30,11 @@ #include #include #include +#include #include #include #include -#include #include #include "cpm2_pic.h" diff --git a/arch/powerpc/sysdev/dart_iommu.c b/arch/powerpc/sysdev/dart_iommu.c index be6b99b1b3523405f1650b85a7d163e5b32ac2b2..98096bbfd62e8d503a3bcf2029dfdf06eed8da18 100644 --- a/arch/powerpc/sysdev/dart_iommu.c +++ b/arch/powerpc/sysdev/dart_iommu.c @@ -25,8 +25,8 @@ #include #include #include +#include #include -#include #include #include #include @@ -404,9 +404,10 @@ void __init iommu_init_early_dart(struct pci_controller_ops *controller_ops) } /* Initialize the DART HW */ - if (dart_init(dn) != 0) + if (dart_init(dn) != 0) { + of_node_put(dn); return; - + } /* * U4 supports a DART bypass, we use it for 64-bit capable devices to * improve performance. However, that only works for devices connected @@ -419,6 +420,7 @@ void __init iommu_init_early_dart(struct pci_controller_ops *controller_ops) /* Setup pci_dma ops */ set_pci_dma_ops(&dma_iommu_ops); + of_node_put(dn); } #ifdef CONFIG_PM diff --git a/arch/powerpc/sysdev/dcr.c b/arch/powerpc/sysdev/dcr.c index 22991e1128e3cba208adb73d974df7c79239d55d..3093f14111e612a7da44272abe4b61de60c80a02 100644 --- a/arch/powerpc/sysdev/dcr.c +++ b/arch/powerpc/sysdev/dcr.c @@ -8,7 +8,7 @@ #include #include -#include +#include #include #ifdef CONFIG_PPC_DCR_MMIO diff --git a/arch/powerpc/sysdev/fsl_85xx_cache_ctlr.h b/arch/powerpc/sysdev/fsl_85xx_cache_ctlr.h deleted file mode 100644 index ce370749add977474b6a5f5c065fa5ab10760e60..0000000000000000000000000000000000000000 --- a/arch/powerpc/sysdev/fsl_85xx_cache_ctlr.h +++ /dev/null @@ -1,88 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Copyright 2009-2010, 2012 Freescale Semiconductor, Inc - * - * QorIQ based Cache Controller Memory Mapped Registers - * - * Author: Vivek Mahajan - */ - -#ifndef __FSL_85XX_CACHE_CTLR_H__ -#define __FSL_85XX_CACHE_CTLR_H__ - -#define L2CR_L2FI 0x40000000 /* L2 flash invalidate */ -#define L2CR_L2IO 0x00200000 /* L2 instruction only */ -#define L2CR_SRAM_ZERO 0x00000000 /* L2SRAM zero size */ -#define L2CR_SRAM_FULL 0x00010000 /* L2SRAM full size */ -#define L2CR_SRAM_HALF 0x00020000 /* L2SRAM half size */ -#define L2CR_SRAM_TWO_HALFS 0x00030000 /* L2SRAM two half sizes */ -#define L2CR_SRAM_QUART 0x00040000 /* L2SRAM one quarter size */ -#define L2CR_SRAM_TWO_QUARTS 0x00050000 /* L2SRAM two quarter size */ -#define L2CR_SRAM_EIGHTH 0x00060000 /* L2SRAM one eighth size */ -#define L2CR_SRAM_TWO_EIGHTH 0x00070000 /* L2SRAM two eighth size */ - -#define L2SRAM_OPTIMAL_SZ_SHIFT 0x00000003 /* Optimum size for L2SRAM */ - -#define L2SRAM_BAR_MSK_LO18 0xFFFFC000 /* Lower 18 bits */ -#define L2SRAM_BARE_MSK_HI4 0x0000000F /* Upper 4 bits */ - -enum cache_sram_lock_ways { - LOCK_WAYS_ZERO, - LOCK_WAYS_EIGHTH, - LOCK_WAYS_TWO_EIGHTH, - LOCK_WAYS_HALF = 4, - LOCK_WAYS_FULL = 8, -}; - -struct mpc85xx_l2ctlr { - u32 ctl; /* 0x000 - L2 control */ - u8 res1[0xC]; - u32 ewar0; /* 0x010 - External write address 0 */ - u32 ewarea0; /* 0x014 - External write address extended 0 */ - u32 ewcr0; /* 0x018 - External write ctrl */ - u8 res2[4]; - u32 ewar1; /* 0x020 - External write address 1 */ - u32 ewarea1; /* 0x024 - External write address extended 1 */ - u32 ewcr1; /* 0x028 - External write ctrl 1 */ - u8 res3[4]; - u32 ewar2; /* 0x030 - External write address 2 */ - u32 ewarea2; /* 0x034 - External write address extended 2 */ - u32 ewcr2; /* 0x038 - External write ctrl 2 */ - u8 res4[4]; - u32 ewar3; /* 0x040 - External write address 3 */ - u32 ewarea3; /* 0x044 - External write address extended 3 */ - u32 ewcr3; /* 0x048 - External write ctrl 3 */ - u8 res5[0xB4]; - u32 srbar0; /* 0x100 - SRAM base address 0 */ - u32 srbarea0; /* 0x104 - SRAM base addr reg ext address 0 */ - u32 srbar1; /* 0x108 - SRAM base address 1 */ - u32 srbarea1; /* 0x10C - SRAM base addr reg ext address 1 */ - u8 res6[0xCF0]; - u32 errinjhi; /* 0xE00 - Error injection mask high */ - u32 errinjlo; /* 0xE04 - Error injection mask low */ - u32 errinjctl; /* 0xE08 - Error injection tag/ecc control */ - u8 res7[0x14]; - u32 captdatahi; /* 0xE20 - Error data high capture */ - u32 captdatalo; /* 0xE24 - Error data low capture */ - u32 captecc; /* 0xE28 - Error syndrome */ - u8 res8[0x14]; - u32 errdet; /* 0xE40 - Error detect */ - u32 errdis; /* 0xE44 - Error disable */ - u32 errinten; /* 0xE48 - Error interrupt enable */ - u32 errattr; /* 0xE4c - Error attribute capture */ - u32 erradrrl; /* 0xE50 - Error address capture low */ - u32 erradrrh; /* 0xE54 - Error address capture high */ - u32 errctl; /* 0xE58 - Error control */ - u8 res9[0x1A4]; -}; - -struct sram_parameters { - unsigned int sram_size; - phys_addr_t sram_offset; -}; - -extern int instantiate_cache_sram(struct platform_device *dev, - struct sram_parameters sram_params); -extern void remove_cache_sram(struct platform_device *dev); - -#endif /* __FSL_85XX_CACHE_CTLR_H__ */ diff --git a/arch/powerpc/sysdev/fsl_85xx_cache_sram.c b/arch/powerpc/sysdev/fsl_85xx_cache_sram.c deleted file mode 100644 index a3aeaa5f0f1b9f73e7763cceb5602297c93318fd..0000000000000000000000000000000000000000 --- a/arch/powerpc/sysdev/fsl_85xx_cache_sram.c +++ /dev/null @@ -1,147 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Copyright 2009-2010 Freescale Semiconductor, Inc. - * - * Simple memory allocator abstraction for QorIQ (P1/P2) based Cache-SRAM - * - * Author: Vivek Mahajan - * - * This file is derived from the original work done - * by Sylvain Munaut for the Bestcomm SRAM allocator. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "fsl_85xx_cache_ctlr.h" - -struct mpc85xx_cache_sram *cache_sram; - -void *mpc85xx_cache_sram_alloc(unsigned int size, - phys_addr_t *phys, unsigned int align) -{ - unsigned long offset; - unsigned long flags; - - if (unlikely(cache_sram == NULL)) - return NULL; - - if (!size || (size > cache_sram->size) || (align > cache_sram->size)) { - pr_err("%s(): size(=%x) or align(=%x) zero or too big\n", - __func__, size, align); - return NULL; - } - - if ((align & (align - 1)) || align <= 1) { - pr_err("%s(): align(=%x) must be power of two and >1\n", - __func__, align); - return NULL; - } - - spin_lock_irqsave(&cache_sram->lock, flags); - offset = rh_alloc_align(cache_sram->rh, size, align, NULL); - spin_unlock_irqrestore(&cache_sram->lock, flags); - - if (IS_ERR_VALUE(offset)) - return NULL; - - *phys = cache_sram->base_phys + offset; - - return (unsigned char *)cache_sram->base_virt + offset; -} -EXPORT_SYMBOL(mpc85xx_cache_sram_alloc); - -void mpc85xx_cache_sram_free(void *ptr) -{ - unsigned long flags; - BUG_ON(!ptr); - - spin_lock_irqsave(&cache_sram->lock, flags); - rh_free(cache_sram->rh, ptr - cache_sram->base_virt); - spin_unlock_irqrestore(&cache_sram->lock, flags); -} -EXPORT_SYMBOL(mpc85xx_cache_sram_free); - -int __init instantiate_cache_sram(struct platform_device *dev, - struct sram_parameters sram_params) -{ - int ret = 0; - - if (cache_sram) { - dev_err(&dev->dev, "Already initialized cache-sram\n"); - return -EBUSY; - } - - cache_sram = kzalloc(sizeof(struct mpc85xx_cache_sram), GFP_KERNEL); - if (!cache_sram) { - dev_err(&dev->dev, "Out of memory for cache_sram structure\n"); - return -ENOMEM; - } - - cache_sram->base_phys = sram_params.sram_offset; - cache_sram->size = sram_params.sram_size; - - if (!request_mem_region(cache_sram->base_phys, cache_sram->size, - "fsl_85xx_cache_sram")) { - dev_err(&dev->dev, "%pOF: request memory failed\n", - dev->dev.of_node); - ret = -ENXIO; - goto out_free; - } - - cache_sram->base_virt = ioremap_coherent(cache_sram->base_phys, - cache_sram->size); - if (!cache_sram->base_virt) { - dev_err(&dev->dev, "%pOF: ioremap_coherent failed\n", - dev->dev.of_node); - ret = -ENOMEM; - goto out_release; - } - - cache_sram->rh = rh_create(sizeof(unsigned int)); - if (IS_ERR(cache_sram->rh)) { - dev_err(&dev->dev, "%pOF: Unable to create remote heap\n", - dev->dev.of_node); - ret = PTR_ERR(cache_sram->rh); - goto out_unmap; - } - - rh_attach_region(cache_sram->rh, 0, cache_sram->size); - spin_lock_init(&cache_sram->lock); - - dev_info(&dev->dev, "[base:0x%llx, size:0x%x] configured and loaded\n", - (unsigned long long)cache_sram->base_phys, cache_sram->size); - - return 0; - -out_unmap: - iounmap(cache_sram->base_virt); - -out_release: - release_mem_region(cache_sram->base_phys, cache_sram->size); - -out_free: - kfree(cache_sram); - return ret; -} - -void remove_cache_sram(struct platform_device *dev) -{ - BUG_ON(!cache_sram); - - rh_detach_region(cache_sram->rh, 0, cache_sram->size); - rh_destroy(cache_sram->rh); - - iounmap(cache_sram->base_virt); - release_mem_region(cache_sram->base_phys, cache_sram->size); - - kfree(cache_sram); - cache_sram = NULL; - - dev_info(&dev->dev, "MPC85xx Cache-SRAM driver unloaded\n"); -} diff --git a/arch/powerpc/sysdev/fsl_85xx_l2ctlr.c b/arch/powerpc/sysdev/fsl_85xx_l2ctlr.c deleted file mode 100644 index 2d0af0c517bbbd148c0076877396a7453e411be1..0000000000000000000000000000000000000000 --- a/arch/powerpc/sysdev/fsl_85xx_l2ctlr.c +++ /dev/null @@ -1,216 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Copyright 2009-2010, 2012 Freescale Semiconductor, Inc. - * - * QorIQ (P1/P2) L2 controller init for Cache-SRAM instantiation - * - * Author: Vivek Mahajan - */ - -#include -#include -#include -#include - -#include "fsl_85xx_cache_ctlr.h" - -static char *sram_size; -static char *sram_offset; -struct mpc85xx_l2ctlr __iomem *l2ctlr; - -static int get_cache_sram_params(struct sram_parameters *sram_params) -{ - unsigned long long addr; - unsigned int size; - - if (!sram_size || (kstrtouint(sram_size, 0, &size) < 0)) - return -EINVAL; - - if (!sram_offset || (kstrtoull(sram_offset, 0, &addr) < 0)) - return -EINVAL; - - sram_params->sram_offset = addr; - sram_params->sram_size = size; - - return 0; -} - -static int __init get_size_from_cmdline(char *str) -{ - if (!str) - return 0; - - sram_size = str; - return 1; -} - -static int __init get_offset_from_cmdline(char *str) -{ - if (!str) - return 0; - - sram_offset = str; - return 1; -} - -__setup("cache-sram-size=", get_size_from_cmdline); -__setup("cache-sram-offset=", get_offset_from_cmdline); - -static int mpc85xx_l2ctlr_of_probe(struct platform_device *dev) -{ - long rval; - unsigned int rem; - unsigned char ways; - const unsigned int *prop; - unsigned int l2cache_size; - struct sram_parameters sram_params; - - if (!dev->dev.of_node) { - dev_err(&dev->dev, "Device's OF-node is NULL\n"); - return -EINVAL; - } - - prop = of_get_property(dev->dev.of_node, "cache-size", NULL); - if (!prop) { - dev_err(&dev->dev, "Missing L2 cache-size\n"); - return -EINVAL; - } - l2cache_size = *prop; - - if (get_cache_sram_params(&sram_params)) - return 0; /* fall back to L2 cache only */ - - rem = l2cache_size % sram_params.sram_size; - ways = LOCK_WAYS_FULL * sram_params.sram_size / l2cache_size; - if (rem || (ways & (ways - 1))) { - dev_err(&dev->dev, "Illegal cache-sram-size in command line\n"); - return -EINVAL; - } - - l2ctlr = of_iomap(dev->dev.of_node, 0); - if (!l2ctlr) { - dev_err(&dev->dev, "Can't map L2 controller\n"); - return -EINVAL; - } - - /* - * Write bits[0-17] to srbar0 - */ - out_be32(&l2ctlr->srbar0, - lower_32_bits(sram_params.sram_offset) & L2SRAM_BAR_MSK_LO18); - - /* - * Write bits[18-21] to srbare0 - */ -#ifdef CONFIG_PHYS_64BIT - out_be32(&l2ctlr->srbarea0, - upper_32_bits(sram_params.sram_offset) & L2SRAM_BARE_MSK_HI4); -#endif - - clrsetbits_be32(&l2ctlr->ctl, L2CR_L2E, L2CR_L2FI); - - switch (ways) { - case LOCK_WAYS_EIGHTH: - setbits32(&l2ctlr->ctl, - L2CR_L2E | L2CR_L2FI | L2CR_SRAM_EIGHTH); - break; - - case LOCK_WAYS_TWO_EIGHTH: - setbits32(&l2ctlr->ctl, - L2CR_L2E | L2CR_L2FI | L2CR_SRAM_QUART); - break; - - case LOCK_WAYS_HALF: - setbits32(&l2ctlr->ctl, - L2CR_L2E | L2CR_L2FI | L2CR_SRAM_HALF); - break; - - case LOCK_WAYS_FULL: - default: - setbits32(&l2ctlr->ctl, - L2CR_L2E | L2CR_L2FI | L2CR_SRAM_FULL); - break; - } - eieio(); - - rval = instantiate_cache_sram(dev, sram_params); - if (rval < 0) { - dev_err(&dev->dev, "Can't instantiate Cache-SRAM\n"); - iounmap(l2ctlr); - return -EINVAL; - } - - return 0; -} - -static int mpc85xx_l2ctlr_of_remove(struct platform_device *dev) -{ - BUG_ON(!l2ctlr); - - iounmap(l2ctlr); - remove_cache_sram(dev); - dev_info(&dev->dev, "MPC85xx L2 controller unloaded\n"); - - return 0; -} - -static const struct of_device_id mpc85xx_l2ctlr_of_match[] = { - { - .compatible = "fsl,p2020-l2-cache-controller", - }, - { - .compatible = "fsl,p2010-l2-cache-controller", - }, - { - .compatible = "fsl,p1020-l2-cache-controller", - }, - { - .compatible = "fsl,p1011-l2-cache-controller", - }, - { - .compatible = "fsl,p1013-l2-cache-controller", - }, - { - .compatible = "fsl,p1022-l2-cache-controller", - }, - { - .compatible = "fsl,mpc8548-l2-cache-controller", - }, - { .compatible = "fsl,mpc8544-l2-cache-controller",}, - { .compatible = "fsl,mpc8572-l2-cache-controller",}, - { .compatible = "fsl,mpc8536-l2-cache-controller",}, - { .compatible = "fsl,p1021-l2-cache-controller",}, - { .compatible = "fsl,p1012-l2-cache-controller",}, - { .compatible = "fsl,p1025-l2-cache-controller",}, - { .compatible = "fsl,p1016-l2-cache-controller",}, - { .compatible = "fsl,p1024-l2-cache-controller",}, - { .compatible = "fsl,p1015-l2-cache-controller",}, - { .compatible = "fsl,p1010-l2-cache-controller",}, - { .compatible = "fsl,bsc9131-l2-cache-controller",}, - {}, -}; - -static struct platform_driver mpc85xx_l2ctlr_of_platform_driver = { - .driver = { - .name = "fsl-l2ctlr", - .of_match_table = mpc85xx_l2ctlr_of_match, - }, - .probe = mpc85xx_l2ctlr_of_probe, - .remove = mpc85xx_l2ctlr_of_remove, -}; - -static __init int mpc85xx_l2ctlr_of_init(void) -{ - return platform_driver_register(&mpc85xx_l2ctlr_of_platform_driver); -} - -static void __exit mpc85xx_l2ctlr_of_exit(void) -{ - platform_driver_unregister(&mpc85xx_l2ctlr_of_platform_driver); -} - -subsys_initcall(mpc85xx_l2ctlr_of_init); -module_exit(mpc85xx_l2ctlr_of_exit); - -MODULE_DESCRIPTION("Freescale MPC85xx L2 controller init"); -MODULE_LICENSE("GPL v2"); diff --git a/arch/powerpc/sysdev/fsl_lbc.c b/arch/powerpc/sysdev/fsl_lbc.c index 1985e067e952e7b7b88d61fe17d737607048507c..217cea150987df1e1b5c6dbf9e9a1607dd5ce49b 100644 --- a/arch/powerpc/sysdev/fsl_lbc.c +++ b/arch/powerpc/sysdev/fsl_lbc.c @@ -18,13 +18,14 @@ #include #include #include +#include +#include #include #include #include #include #include #include -#include #include static DEFINE_SPINLOCK(fsl_lbc_lock); @@ -37,7 +38,7 @@ EXPORT_SYMBOL(fsl_lbc_ctrl_dev); * * This function converts a base address of lbc into the right format for the * BR register. If the SOC has eLBC then it returns 32bit physical address - * else it convers a 34bit local bus physical address to correct format of + * else it converts a 34bit local bus physical address to correct format of * 32bit address for BR register (Example: MPC8641). */ u32 fsl_lbc_addr(phys_addr_t addr_base) diff --git a/arch/powerpc/sysdev/fsl_msi.c b/arch/powerpc/sysdev/fsl_msi.c index b3475ae9f236da6c418598affbda88248b9b8d32..ef9a5999fa93ddfef9e8851701a8a2d517c60761 100644 --- a/arch/powerpc/sysdev/fsl_msi.c +++ b/arch/powerpc/sysdev/fsl_msi.c @@ -11,11 +11,13 @@ #include #include #include +#include +#include #include #include +#include #include #include -#include #include #include #include diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c index a97ce602394e580836bf1db2b0831f8c84b6bd77..1011cfea2e3277a73a13f8b71a52477bdfdd69bb 100644 --- a/arch/powerpc/sysdev/fsl_pci.c +++ b/arch/powerpc/sysdev/fsl_pci.c @@ -22,6 +22,8 @@ #include #include #include +#include +#include #include #include #include @@ -29,7 +31,6 @@ #include #include -#include #include #include #include @@ -218,7 +219,7 @@ static void setup_pci_atmu(struct pci_controller *hose) * windows have implemented the default target value as 0xf * for CCSR space.In all Freescale legacy devices the target * of 0xf is reserved for local memory space. 9132 Rev1.0 - * now has local mempry space mapped to target 0x0 instead of + * now has local memory space mapped to target 0x0 instead of * 0xf. Hence adding a workaround to remove the target 0xf * defined for memory space from Inbound window attributes. */ diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c index ff7906b48ca1e99c8d619daa89ab4c7d2c94927b..1bfc9afa8a1a12e672d8c8c52abb8677860ed87b 100644 --- a/arch/powerpc/sysdev/fsl_rio.c +++ b/arch/powerpc/sysdev/fsl_rio.c @@ -505,8 +505,10 @@ int fsl_rio_setup(struct platform_device *dev) if (rc) { dev_err(&dev->dev, "Can't get %pOF property 'reg'\n", rmu_node); + of_node_put(rmu_node); goto err_rmu; } + of_node_put(rmu_node); rmu_regs_win = ioremap(rmu_regs.start, resource_size(&rmu_regs)); if (!rmu_regs_win) { dev_err(&dev->dev, "Unable to map rmu register window\n"); diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c index 90ad161616043086ef5efc71a9d1fa81338bfae7..78118c1889936bf9af334fe78cb7e152db446d52 100644 --- a/arch/powerpc/sysdev/fsl_soc.c +++ b/arch/powerpc/sysdev/fsl_soc.c @@ -31,7 +31,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/powerpc/sysdev/ge/ge_pic.c b/arch/powerpc/sysdev/ge/ge_pic.c index 02553a8ce19197695700b5d3a6b8950a39470811..a6c424680c377633d2b9d56e0360ae53d0a5d553 100644 --- a/arch/powerpc/sysdev/ge/ge_pic.c +++ b/arch/powerpc/sysdev/ge/ge_pic.c @@ -14,12 +14,14 @@ #include #include #include +#include #include +#include +#include #include #include #include -#include #include #include "ge_pic.h" @@ -150,7 +152,7 @@ static struct irq_chip gef_pic_chip = { }; -/* When an interrupt is being configured, this call allows some flexibilty +/* When an interrupt is being configured, this call allows some flexibility * in deciding which irq_chip structure is used */ static int gef_pic_host_map(struct irq_domain *h, unsigned int virq, diff --git a/arch/powerpc/sysdev/grackle.c b/arch/powerpc/sysdev/grackle.c index aaba0b8090322da35be2355ed03d1071cbb2ce18..fd2f94a884f04657e0fad52a631a807554496426 100644 --- a/arch/powerpc/sysdev/grackle.c +++ b/arch/powerpc/sysdev/grackle.c @@ -9,9 +9,9 @@ #include #include #include +#include #include -#include #include #include diff --git a/arch/powerpc/sysdev/i8259.c b/arch/powerpc/sysdev/i8259.c index 3b1ae98e3ce923a439fade339b74730dcccd7a46..06e391485da72f1a70214072fd2d27824419ad05 100644 --- a/arch/powerpc/sysdev/i8259.c +++ b/arch/powerpc/sysdev/i8259.c @@ -6,11 +6,11 @@ #include #include +#include #include #include #include #include -#include static volatile void __iomem *pci_intack; /* RO, gives us the irq vector */ diff --git a/arch/powerpc/sysdev/indirect_pci.c b/arch/powerpc/sysdev/indirect_pci.c index 09b36617425ea2929f0a54930a47b7c34e40c760..1aacb403a01087ead88a9be936f7a950e929c478 100644 --- a/arch/powerpc/sysdev/indirect_pci.c +++ b/arch/powerpc/sysdev/indirect_pci.c @@ -12,7 +12,6 @@ #include #include -#include #include #include diff --git a/arch/powerpc/sysdev/ipic.c b/arch/powerpc/sysdev/ipic.c index 3f10c9fc3b683115025c2e298e455d28b8ce8c71..5f69e2d50f2688139cf03f3699c922403d4f9255 100644 --- a/arch/powerpc/sysdev/ipic.c +++ b/arch/powerpc/sysdev/ipic.c @@ -18,9 +18,10 @@ #include #include #include +#include +#include #include #include -#include #include #include "ipic.h" diff --git a/arch/powerpc/sysdev/mmio_nvram.c b/arch/powerpc/sysdev/mmio_nvram.c index 628f9b759c8486f0aea5d2af6d0155e1c3c7d003..eb48210ef98e6f3a7d63ea2004df57f08a079a8e 100644 --- a/arch/powerpc/sysdev/mmio_nvram.c +++ b/arch/powerpc/sysdev/mmio_nvram.c @@ -10,12 +10,12 @@ #include #include #include +#include #include #include #include #include -#include static void __iomem *mmio_nvram_start; static long mmio_nvram_len; diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index dbcbaa4c06635a26c08b53947b57f1baf1eb1660..9a9381f102d6b403013eaace239694f5e9f2b46c 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c @@ -30,6 +30,8 @@ #include #include #include +#include +#include #include #include diff --git a/arch/powerpc/sysdev/mpic_msgr.c b/arch/powerpc/sysdev/mpic_msgr.c index 36ec0bdd8b63c41d2c98b1a2121f616f832d928d..698fefaaa6dd8a5fe080122e90f8a4a8059039be 100644 --- a/arch/powerpc/sysdev/mpic_msgr.c +++ b/arch/powerpc/sysdev/mpic_msgr.c @@ -7,12 +7,13 @@ */ #include +#include +#include #include #include #include #include #include -#include #include #include #include @@ -99,7 +100,7 @@ void mpic_msgr_disable(struct mpic_msgr *msgr) EXPORT_SYMBOL_GPL(mpic_msgr_disable); /* The following three functions are used to compute the order and number of - * the message register blocks. They are clearly very inefficent. However, + * the message register blocks. They are clearly very inefficient. However, * they are called *only* a few times during device initialization. */ static unsigned int mpic_msgr_number_of_blocks(void) diff --git a/arch/powerpc/sysdev/mpic_msi.c b/arch/powerpc/sysdev/mpic_msi.c index f412d6ad0b6602f63cb6a286d03734a454d29e64..34246c8e01c2b4a652f53131786d600ccb47c1db 100644 --- a/arch/powerpc/sysdev/mpic_msi.c +++ b/arch/powerpc/sysdev/mpic_msi.c @@ -4,10 +4,11 @@ */ #include +#include +#include #include #include #include -#include #include #include #include @@ -37,7 +38,7 @@ static int __init mpic_msi_reserve_u3_hwirqs(struct mpic *mpic) /* Reserve source numbers we know are reserved in the HW. * * This is a bit of a mix of U3 and U4 reserves but that's going - * to work fine, we have plenty enugh numbers left so let's just + * to work fine, we have plenty enough numbers left so let's just * mark anything we don't like reserved. */ for (i = 0; i < 8; i++) diff --git a/arch/powerpc/sysdev/mpic_timer.c b/arch/powerpc/sysdev/mpic_timer.c index 444e9ce42d0a5175be39320714989ebef8ed1570..b2f0a73e8f930ee1f8bbb9401cfc0b5e354ff73f 100644 --- a/arch/powerpc/sysdev/mpic_timer.c +++ b/arch/powerpc/sysdev/mpic_timer.c @@ -255,7 +255,7 @@ EXPORT_SYMBOL(mpic_start_timer); /** * mpic_stop_timer - stop hardware timer - * @handle: the timer to be stoped + * @handle: the timer to be stopped * * The timer periodically generates an interrupt. Unless user stops the timer. */ diff --git a/arch/powerpc/sysdev/mpic_u3msi.c b/arch/powerpc/sysdev/mpic_u3msi.c index 3f4841dfefb5f86d37ee7c818a656fd2a79d67e1..1d8cfdfdf115ec284f3b615d48dff21d5fdef414 100644 --- a/arch/powerpc/sysdev/mpic_u3msi.c +++ b/arch/powerpc/sysdev/mpic_u3msi.c @@ -5,9 +5,9 @@ */ #include +#include #include #include -#include #include #include #include @@ -78,7 +78,7 @@ static u64 find_u4_magic_addr(struct pci_dev *pdev, unsigned int hwirq) /* U4 PCIe MSIs need to write to the special register in * the bridge that generates interrupts. There should be - * theorically a register at 0xf8005000 where you just write + * theoretically a register at 0xf8005000 where you just write * the MSI number and that triggers the right interrupt, but * unfortunately, this is busted in HW, the bridge endian swaps * the value and hits the wrong nibble in the register. diff --git a/arch/powerpc/sysdev/msi_bitmap.c b/arch/powerpc/sysdev/msi_bitmap.c index fdd3e17150fc0add656bed9af9c36b714d6567a6..0b6e37f3ffb8d58f10984a7a86aecfc0fc04ece5 100644 --- a/arch/powerpc/sysdev/msi_bitmap.c +++ b/arch/powerpc/sysdev/msi_bitmap.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include diff --git a/arch/powerpc/sysdev/pmi.c b/arch/powerpc/sysdev/pmi.c index 9c8744e09a9c27af215fa0d149e4d4ac3d4cfd8b..9dabb50c36eb268660165993a29144c5d15ed8da 100644 --- a/arch/powerpc/sysdev/pmi.c +++ b/arch/powerpc/sysdev/pmi.c @@ -17,12 +17,13 @@ #include #include #include +#include #include +#include #include #include #include -#include struct pmi_data { struct list_head handler; diff --git a/arch/powerpc/sysdev/rtc_cmos_setup.c b/arch/powerpc/sysdev/rtc_cmos_setup.c index af0f9beddca9be85b3720bf84109033a1ee13aa3..47cc87bd6a3365be87dbcaaf8579d12801e0d87d 100644 --- a/arch/powerpc/sysdev/rtc_cmos_setup.c +++ b/arch/powerpc/sysdev/rtc_cmos_setup.c @@ -14,8 +14,8 @@ #include #include #include +#include -#include static int __init add_rtc(void) { diff --git a/arch/powerpc/sysdev/tsi108_dev.c b/arch/powerpc/sysdev/tsi108_dev.c index 9e13fb35ed5c56932d7f317dbb56ce614cf53b82..30051397292f5e2160110cb2e7a657f9cbb03f61 100644 --- a/arch/powerpc/sysdev/tsi108_dev.c +++ b/arch/powerpc/sysdev/tsi108_dev.c @@ -16,13 +16,14 @@ #include #include #include +#include +#include #include #include #include #include #include -#include #include #undef DEBUG diff --git a/arch/powerpc/sysdev/tsi108_pci.c b/arch/powerpc/sysdev/tsi108_pci.c index 1070220f15d596a9b0416adc5e0ec8250f5fd870..5af4c35ff58420741b7aa8ff003f3b8e0c5bb51c 100644 --- a/arch/powerpc/sysdev/tsi108_pci.c +++ b/arch/powerpc/sysdev/tsi108_pci.c @@ -12,7 +12,9 @@ #include #include #include +#include #include +#include #include #include @@ -23,7 +25,6 @@ #include #include #include -#include #undef DEBUG #ifdef DEBUG diff --git a/arch/powerpc/sysdev/xics/icp-native.c b/arch/powerpc/sysdev/xics/icp-native.c index 7d13d2ef5a9054eaf009be6891a7132ff59dade6..edc17b6b1cc2fa9022a03550530b236c442a6a92 100644 --- a/arch/powerpc/sysdev/xics/icp-native.c +++ b/arch/powerpc/sysdev/xics/icp-native.c @@ -6,15 +6,16 @@ #include #include #include +#include #include #include #include #include #include +#include #include #include -#include #include #include #include diff --git a/arch/powerpc/sysdev/xics/icp-opal.c b/arch/powerpc/sysdev/xics/icp-opal.c index bda4c32582d973c21bde4fc41f4c2ea2f79917de..4dae624b9f2f4bb50ab9392a32b47122a108662a 100644 --- a/arch/powerpc/sysdev/xics/icp-opal.c +++ b/arch/powerpc/sysdev/xics/icp-opal.c @@ -196,6 +196,7 @@ int __init icp_opal_init(void) printk("XICS: Using OPAL ICP fallbacks\n"); + of_node_put(np); return 0; } diff --git a/arch/powerpc/sysdev/xics/ics-native.c b/arch/powerpc/sysdev/xics/ics-native.c index dec7d93a8ba164a5933aa3931b78293a0626493e..112c8a1e81590f739b7be9d297deaf0071257788 100644 --- a/arch/powerpc/sysdev/xics/ics-native.c +++ b/arch/powerpc/sysdev/xics/ics-native.c @@ -15,11 +15,11 @@ #include #include #include +#include #include #include #include -#include #include #include #include diff --git a/arch/powerpc/sysdev/xics/ics-opal.c b/arch/powerpc/sysdev/xics/ics-opal.c index c4d95d8beb6fe73aec687d13ee8765a3f5e8f350..6cfbb4fac7fb623d7963c560d7cb6b7e205ac56b 100644 --- a/arch/powerpc/sysdev/xics/ics-opal.c +++ b/arch/powerpc/sysdev/xics/ics-opal.c @@ -18,7 +18,6 @@ #include #include -#include #include #include #include diff --git a/arch/powerpc/sysdev/xics/ics-rtas.c b/arch/powerpc/sysdev/xics/ics-rtas.c index b9da317b7a2d75f91788e4780576b94e6e3d284a..9e7007f9aca5cbe369ca5941a4ee6c3f964cd83e 100644 --- a/arch/powerpc/sysdev/xics/ics-rtas.c +++ b/arch/powerpc/sysdev/xics/ics-rtas.c @@ -10,7 +10,6 @@ #include #include -#include #include #include #include diff --git a/arch/powerpc/sysdev/xics/xics-common.c b/arch/powerpc/sysdev/xics/xics-common.c index f3fb2a12124c3dc235494423eb25cb8e866f6256..d3a4156e8788125d610f114ab21c6a3bc2c84452 100644 --- a/arch/powerpc/sysdev/xics/xics-common.c +++ b/arch/powerpc/sysdev/xics/xics-common.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -17,7 +18,6 @@ #include #include -#include #include #include #include @@ -146,7 +146,7 @@ void __init xics_smp_probe(void) #endif /* CONFIG_SMP */ -void xics_teardown_cpu(void) +noinstr void xics_teardown_cpu(void) { struct xics_cppr *os_cppr = this_cpu_ptr(&xics_cppr); @@ -159,7 +159,7 @@ void xics_teardown_cpu(void) icp_ops->teardown_cpu(); } -void xics_kexec_teardown_cpu(int secondary) +noinstr void xics_kexec_teardown_cpu(int secondary) { xics_teardown_cpu(); diff --git a/arch/powerpc/sysdev/xive/common.c b/arch/powerpc/sysdev/xive/common.c index bb5bda6b2357bacf6cfb9b158e65af7e552e5af1..61b9f98dfd4a4bdb26ed3d759d2464368ff70272 100644 --- a/arch/powerpc/sysdev/xive/common.c +++ b/arch/powerpc/sysdev/xive/common.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -21,7 +22,6 @@ #include #include -#include #include #include #include @@ -1241,7 +1241,7 @@ static int xive_setup_cpu_ipi(unsigned int cpu) return 0; } -static void xive_cleanup_cpu_ipi(unsigned int cpu, struct xive_cpu *xc) +noinstr static void xive_cleanup_cpu_ipi(unsigned int cpu, struct xive_cpu *xc) { unsigned int xive_ipi_irq = xive_ipi_cpu_to_irq(cpu); @@ -1634,7 +1634,7 @@ void xive_flush_interrupt(void) #endif /* CONFIG_SMP */ -void xive_teardown_cpu(void) +noinstr void xive_teardown_cpu(void) { struct xive_cpu *xc = __this_cpu_read(xive_cpu); unsigned int cpu = smp_processor_id(); diff --git a/arch/powerpc/sysdev/xive/native.c b/arch/powerpc/sysdev/xive/native.c index f940428ad13fed6135d853665581a30d2f3c97de..d25d8c69290942aa4b55461217307ce7967e1b30 100644 --- a/arch/powerpc/sysdev/xive/native.c +++ b/arch/powerpc/sysdev/xive/native.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -21,7 +22,6 @@ #include #include -#include #include #include #include @@ -617,7 +617,7 @@ bool __init xive_native_init(void) xive_tima_os = r.start; - /* Grab size of provisionning pages */ + /* Grab size of provisioning pages */ xive_parse_provisioning(np); /* Switch the XIVE to exploitation mode */ diff --git a/arch/powerpc/sysdev/xive/spapr.c b/arch/powerpc/sysdev/xive/spapr.c index 29456c255f9f7f057708e553e4fb99cf79e4ec3f..7d5128676e830082ba1a21436aa8b99dc2dd12b9 100644 --- a/arch/powerpc/sysdev/xive/spapr.c +++ b/arch/powerpc/sysdev/xive/spapr.c @@ -11,6 +11,8 @@ #include #include #include +#include +#include #include #include #include @@ -830,12 +832,12 @@ bool __init xive_spapr_init(void) /* Resource 1 is the OS ring TIMA */ if (of_address_to_resource(np, 1, &r)) { pr_err("Failed to get thread mgmnt area resource\n"); - return false; + goto err_put; } tima = ioremap(r.start, resource_size(&r)); if (!tima) { pr_err("Failed to map thread mgmnt area\n"); - return false; + goto err_put; } if (!xive_get_max_prio(&max_prio)) @@ -871,6 +873,7 @@ bool __init xive_spapr_init(void) if (!xive_core_init(np, &xive_spapr_ops, tima, TM_QW1_OS, max_prio)) goto err_mem_free; + of_node_put(np); pr_info("Using %dkB queues\n", 1 << (xive_queue_shift - 10)); return true; @@ -878,6 +881,8 @@ err_mem_free: xive_irq_bitmap_remove_all(); err_unmap: iounmap(tima); +err_put: + of_node_put(np); return false; } diff --git a/arch/powerpc/xmon/ppc-opc.c b/arch/powerpc/xmon/ppc-opc.c index dfb80810b16cbfc5325c8386b3bf25979e70b2e0..0774d711453efaf1508924518e193329970577e9 100644 --- a/arch/powerpc/xmon/ppc-opc.c +++ b/arch/powerpc/xmon/ppc-opc.c @@ -408,7 +408,7 @@ const struct powerpc_operand powerpc_operands[] = #define FXM4 FXM + 1 { 0xff, 12, insert_fxm, extract_fxm, PPC_OPERAND_OPTIONAL | PPC_OPERAND_OPTIONAL_VALUE}, - /* If the FXM4 operand is ommitted, use the sentinel value -1. */ + /* If the FXM4 operand is omitted, use the sentinel value -1. */ { -1, -1, NULL, NULL, 0}, /* The IMM20 field in an LI instruction. */ diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c index fd72753e8ad5023761b9363fc33726c4e26647f2..3d9782ea3fa7b6af297aa216cd2641f515b6180b 100644 --- a/arch/powerpc/xmon/xmon.c +++ b/arch/powerpc/xmon/xmon.c @@ -31,7 +31,6 @@ #include #include #include -#include #include #include #include @@ -373,7 +372,7 @@ static void write_ciabr(unsigned long ciabr) * set_ciabr() - set the CIABR * @addr: The value to set. * - * This function sets the correct privilege value into the the HW + * This function sets the correct privilege value into the HW * breakpoint address before writing it up in the CIABR register. */ static void set_ciabr(unsigned long addr) @@ -921,9 +920,9 @@ static void insert_bpts(void) bp->enabled = 0; continue; } - if (IS_MTMSRD(instr) || IS_RFID(instr)) { - printf("Breakpoint at %lx is on an mtmsrd or rfid " - "instruction, disabling it\n", bp->address); + if (!can_single_step(ppc_inst_val(instr))) { + printf("Breakpoint at %lx is on an instruction that can't be single stepped, disabling it\n", + bp->address); bp->enabled = 0; continue; } @@ -1243,8 +1242,7 @@ static void bootcmds(void) } else if (cmd == 'h') { ppc_md.halt(); } else if (cmd == 'p') { - if (pm_power_off) - pm_power_off(); + do_kernel_power_off(); } } @@ -1470,9 +1468,8 @@ static long check_bp_loc(unsigned long addr) printf("Can't read instruction at address %lx\n", addr); return 0; } - if (IS_MTMSRD(instr) || IS_RFID(instr)) { - printf("Breakpoints may not be placed on mtmsrd or rfid " - "instructions\n"); + if (!can_single_step(ppc_inst_val(instr))) { + printf("Breakpoints may not be placed on instructions that can't be single stepped\n"); return 0; } return 1; @@ -2024,7 +2021,7 @@ static void dump_206_sprs(void) if (!cpu_has_feature(CPU_FTR_ARCH_206)) return; - /* Actually some of these pre-date 2.06, but whatevs */ + /* Actually some of these pre-date 2.06, but whatever */ printf("srr0 = %.16lx srr1 = %.16lx dsisr = %.8lx\n", mfspr(SPRN_SRR0), mfspr(SPRN_SRR1), mfspr(SPRN_DSISR)); diff --git a/arch/riscv/Kbuild b/arch/riscv/Kbuild index fb3397223d5204d11a909ee11f88dfee0f967c84..f562c7343fda7fe1f3cc8b0be2a7e9a47dfab77d 100644 --- a/arch/riscv/Kbuild +++ b/arch/riscv/Kbuild @@ -3,5 +3,7 @@ obj-y += kernel/ mm/ net/ obj-$(CONFIG_BUILTIN_DTB) += boot/dts/ +obj-$(CONFIG_ARCH_HAS_KEXEC_PURGATORY) += purgatory/ + # for cleaning subdir- += boot diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index c0853f1474a7088947daea5593e827b1434c8fee..905e550e0fd3b49f43bfd10c902047e347697955 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -78,6 +78,7 @@ config RISCV select HAVE_ARCH_KGDB if !XIP_KERNEL select HAVE_ARCH_KGDB_QXFER_PKT select HAVE_ARCH_MMAP_RND_BITS if MMU + select HAVE_ARCH_MMAP_RND_COMPAT_BITS if COMPAT select HAVE_ARCH_SECCOMP_FILTER select HAVE_ARCH_TRACEHOOK select HAVE_ARCH_TRANSPARENT_HUGEPAGE if 64BIT && MMU @@ -129,12 +130,18 @@ config ARCH_MMAP_RND_BITS_MIN default 18 if 64BIT default 8 +config ARCH_MMAP_RND_COMPAT_BITS_MIN + default 8 + # max bits determined by the following formula: # VA_BITS - PAGE_SHIFT - 3 config ARCH_MMAP_RND_BITS_MAX default 24 if 64BIT # SV39 based default 17 +config ARCH_MMAP_RND_COMPAT_BITS_MAX + default 17 + # set if we run in machine mode, cleared if we run in supervisor mode config RISCV_M_MODE bool @@ -326,6 +333,21 @@ config NODES_SHIFT Specify the maximum number of NUMA Nodes available on the target system. Increases memory reserved to accommodate various tables. +config RISCV_ALTERNATIVE + bool + depends on !XIP_KERNEL + help + This Kconfig allows the kernel to automatically patch the + errata required by the execution platform at run time. The + code patching is performed once in the boot stages. It means + that the overhead from this mechanism is just taken once. + +config RISCV_ALTERNATIVE_EARLY + bool + depends on RISCV_ALTERNATIVE + help + Allows early patching of the kernel for special errata + config RISCV_ISA_C bool "Emit compressed instructions when building Linux" default y @@ -336,6 +358,19 @@ config RISCV_ISA_C If you don't know what to do here, say Y. +config RISCV_ISA_SVPBMT + bool "SVPBMT extension support" + depends on 64BIT && MMU + select RISCV_ALTERNATIVE + default y + help + Adds support to dynamically detect the presence of the SVPBMT extension + (Supervisor-mode: page-based memory types) and enable its usage. + + The SVPBMT extension is only available on 64Bit cpus. + + If you don't know what to do here, say Y. + config FPU bool "FPU support" default y @@ -385,6 +420,26 @@ config KEXEC The name comes from the similarity to the exec system call. +config KEXEC_FILE + bool "kexec file based systmem call" + select KEXEC_CORE + select KEXEC_ELF + select HAVE_IMA_KEXEC if IMA + depends on 64BIT + help + This is new version of kexec system call. This system call is + file based and takes file descriptors as system call argument + for kernel and initramfs as opposed to list of segments as + accepted by previous system call. + + If you don't know what to do here, say Y. + +config ARCH_HAS_KEXEC_PURGATORY + def_bool KEXEC_FILE + select BUILD_BIN2C + depends on CRYPTO=y + depends on CRYPTO_SHA256=y + config CRASH_DUMP bool "Build kdump crash kernel" help @@ -396,6 +451,18 @@ config CRASH_DUMP For more details see Documentation/admin-guide/kdump/kdump.rst +config COMPAT + bool "Kernel support for 32-bit U-mode" + default 64BIT + depends on 64BIT && MMU + help + This option enables support for a 32-bit U-mode running under a 64-bit + kernel at S-mode. riscv32-specific components such as system calls, + the user helper functions (vdso), signal rt_frame functions and the + ptrace interface are handled appropriately by the kernel. + + If you want to execute 32-bit userspace applications, say Y. + endmenu menu "Boot options" diff --git a/arch/riscv/Kconfig.erratas b/arch/riscv/Kconfig.erratas index 0aacd7052585b5e2820bbcc633a5e8126cbef923..ebfcd5cc6eaf2fc720d603a366f74657c7cab892 100644 --- a/arch/riscv/Kconfig.erratas +++ b/arch/riscv/Kconfig.erratas @@ -1,18 +1,9 @@ menu "CPU errata selection" -config RISCV_ERRATA_ALTERNATIVE - bool "RISC-V alternative scheme" - depends on !XIP_KERNEL - default y - help - This Kconfig allows the kernel to automatically patch the - errata required by the execution platform at run time. The - code patching is performed once in the boot stages. It means - that the overhead from this mechanism is just taken once. - config ERRATA_SIFIVE bool "SiFive errata" - depends on RISCV_ERRATA_ALTERNATIVE + depends on !XIP_KERNEL + select RISCV_ALTERNATIVE help All SiFive errata Kconfig depend on this Kconfig. Disabling this Kconfig will disable all SiFive errata. Please say "Y" @@ -42,4 +33,25 @@ config ERRATA_SIFIVE_CIP_1200 If you don't know what to do here, say "Y". +config ERRATA_THEAD + bool "T-HEAD errata" + select RISCV_ALTERNATIVE + help + All T-HEAD errata Kconfig depend on this Kconfig. Disabling + this Kconfig will disable all T-HEAD errata. Please say "Y" + here if your platform uses T-HEAD CPU cores. + + Otherwise, please say "N" here to avoid unnecessary overhead. + +config ERRATA_THEAD_PBMT + bool "Apply T-Head memory type errata" + depends on ERRATA_THEAD && 64BIT + select RISCV_ALTERNATIVE_EARLY + default y + help + This will apply the memory type errata to handle the non-standard + memory type bits in page-table-entries on T-Head SoCs. + + If you don't know what to do here, say "Y". + endmenu diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs index f6ef358d8a2cf6eb628a054ef96794a682a12d3d..85670dc9fe95d5779df78b733668429cb3bc9775 100644 --- a/arch/riscv/Kconfig.socs +++ b/arch/riscv/Kconfig.socs @@ -14,7 +14,6 @@ config SOC_SIFIVE select CLK_SIFIVE select CLK_SIFIVE_PRCI select SIFIVE_PLIC - select RISCV_ERRATA_ALTERNATIVE if !XIP_KERNEL select ERRATA_SIFIVE if !XIP_KERNEL help This enables support for SiFive SoC platform hardware. diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile index 2b93ca9f4fc3a324cba0747ff933fb544306c538..e3b1d06e4db1d93b6f4d30702bc7fc8104fdae14 100644 --- a/arch/riscv/Makefile +++ b/arch/riscv/Makefile @@ -103,7 +103,7 @@ endif head-y := arch/riscv/kernel/head.o -core-$(CONFIG_RISCV_ERRATA_ALTERNATIVE) += arch/riscv/errata/ +core-y += arch/riscv/errata/ core-$(CONFIG_KVM) += arch/riscv/kvm/ libs-y += arch/riscv/lib/ @@ -112,12 +112,17 @@ libs-$(CONFIG_EFI_STUB) += $(objtree)/drivers/firmware/efi/libstub/lib.a PHONY += vdso_install vdso_install: $(Q)$(MAKE) $(build)=arch/riscv/kernel/vdso $@ + $(if $(CONFIG_COMPAT),$(Q)$(MAKE) \ + $(build)=arch/riscv/kernel/compat_vdso $@) ifeq ($(KBUILD_EXTMOD),) ifeq ($(CONFIG_MMU),y) prepare: vdso_prepare vdso_prepare: prepare0 $(Q)$(MAKE) $(build)=arch/riscv/kernel/vdso include/generated/vdso-offsets.h + $(if $(CONFIG_COMPAT),$(Q)$(MAKE) \ + $(build)=arch/riscv/kernel/compat_vdso include/generated/compat_vdso-offsets.h) + endif endif @@ -153,3 +158,7 @@ PHONY += rv64_randconfig rv64_randconfig: $(Q)$(MAKE) KCONFIG_ALLCONFIG=$(srctree)/arch/riscv/configs/64-bit.config \ -f $(srctree)/Makefile randconfig + +PHONY += rv32_defconfig +rv32_defconfig: + $(Q)$(MAKE) -f $(srctree)/Makefile defconfig 32-bit.config diff --git a/arch/riscv/boot/.gitignore b/arch/riscv/boot/.gitignore index 90e66adb7de5751f61b6c6533477b3730a6e0324..0cea9f7fa9d5c86a70eadb312592619045400122 100644 --- a/arch/riscv/boot/.gitignore +++ b/arch/riscv/boot/.gitignore @@ -4,3 +4,4 @@ Image.* loader loader.lds loader.bin +xipImage diff --git a/arch/riscv/boot/dts/sifive/fu540-c000.dtsi b/arch/riscv/boot/dts/sifive/fu540-c000.dtsi index 5c638fd5b35c78fb0e914e0f8724c01056f43d6a..e3172d0ffac4f1e6da4b32d9cf5e9007cc355f13 100644 --- a/arch/riscv/boot/dts/sifive/fu540-c000.dtsi +++ b/arch/riscv/boot/dts/sifive/fu540-c000.dtsi @@ -168,11 +168,12 @@ status = "disabled"; }; dma: dma-controller@3000000 { - compatible = "sifive,fu540-c000-pdma"; + compatible = "sifive,fu540-c000-pdma", "sifive,pdma0"; reg = <0x0 0x3000000 0x0 0x8000>; interrupt-parent = <&plic0>; interrupts = <23>, <24>, <25>, <26>, <27>, <28>, <29>, <30>; + dma-channels = <4>; #dma-cells = <1>; }; uart1: serial@10011000 { diff --git a/arch/riscv/errata/Makefile b/arch/riscv/errata/Makefile index b8f8740a3e442cb8d1a91c78676a8570feb3fb5e..a1055965fbee6a6da0b173f9e894e79f8930dfd1 100644 --- a/arch/riscv/errata/Makefile +++ b/arch/riscv/errata/Makefile @@ -1,2 +1,2 @@ -obj-y += alternative.o obj-$(CONFIG_ERRATA_SIFIVE) += sifive/ +obj-$(CONFIG_ERRATA_THEAD) += thead/ diff --git a/arch/riscv/errata/alternative.c b/arch/riscv/errata/alternative.c deleted file mode 100644 index e8b4a0fe488c14afcda9b9081989cd237df68948..0000000000000000000000000000000000000000 --- a/arch/riscv/errata/alternative.c +++ /dev/null @@ -1,75 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * alternative runtime patching - * inspired by the ARM64 and x86 version - * - * Copyright (C) 2021 Sifive. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -static struct cpu_manufacturer_info_t { - unsigned long vendor_id; - unsigned long arch_id; - unsigned long imp_id; -} cpu_mfr_info; - -static void (*vendor_patch_func)(struct alt_entry *begin, struct alt_entry *end, - unsigned long archid, - unsigned long impid) __initdata; - -static inline void __init riscv_fill_cpu_mfr_info(void) -{ -#ifdef CONFIG_RISCV_M_MODE - cpu_mfr_info.vendor_id = csr_read(CSR_MVENDORID); - cpu_mfr_info.arch_id = csr_read(CSR_MARCHID); - cpu_mfr_info.imp_id = csr_read(CSR_MIMPID); -#else - cpu_mfr_info.vendor_id = sbi_get_mvendorid(); - cpu_mfr_info.arch_id = sbi_get_marchid(); - cpu_mfr_info.imp_id = sbi_get_mimpid(); -#endif -} - -static void __init init_alternative(void) -{ - riscv_fill_cpu_mfr_info(); - - switch (cpu_mfr_info.vendor_id) { -#ifdef CONFIG_ERRATA_SIFIVE - case SIFIVE_VENDOR_ID: - vendor_patch_func = sifive_errata_patch_func; - break; -#endif - default: - vendor_patch_func = NULL; - } -} - -/* - * This is called very early in the boot process (directly after we run - * a feature detect on the boot CPU). No need to worry about other CPUs - * here. - */ -void __init apply_boot_alternatives(void) -{ - /* If called on non-boot cpu things could go wrong */ - WARN_ON(smp_processor_id() != 0); - - init_alternative(); - - if (!vendor_patch_func) - return; - - vendor_patch_func((struct alt_entry *)__alt_start, - (struct alt_entry *)__alt_end, - cpu_mfr_info.arch_id, cpu_mfr_info.imp_id); -} - diff --git a/arch/riscv/errata/sifive/errata.c b/arch/riscv/errata/sifive/errata.c index f5e5ae70e829f70f1bc49cb1c019e63c6a05924d..672f02b21ce02de7a758a11b68955ed1c036f067 100644 --- a/arch/riscv/errata/sifive/errata.c +++ b/arch/riscv/errata/sifive/errata.c @@ -4,6 +4,7 @@ */ #include +#include #include #include #include @@ -54,7 +55,8 @@ static struct errata_info_t errata_list[ERRATA_SIFIVE_NUMBER] = { }, }; -static u32 __init sifive_errata_probe(unsigned long archid, unsigned long impid) +static u32 __init_or_module sifive_errata_probe(unsigned long archid, + unsigned long impid) { int idx; u32 cpu_req_errata = 0; @@ -66,7 +68,7 @@ static u32 __init sifive_errata_probe(unsigned long archid, unsigned long impid) return cpu_req_errata; } -static void __init warn_miss_errata(u32 miss_errata) +static void __init_or_module warn_miss_errata(u32 miss_errata) { int i; @@ -79,14 +81,22 @@ static void __init warn_miss_errata(u32 miss_errata) pr_warn("----------------------------------------------------------------\n"); } -void __init sifive_errata_patch_func(struct alt_entry *begin, struct alt_entry *end, - unsigned long archid, unsigned long impid) +void __init_or_module sifive_errata_patch_func(struct alt_entry *begin, + struct alt_entry *end, + unsigned long archid, + unsigned long impid, + unsigned int stage) { struct alt_entry *alt; - u32 cpu_req_errata = sifive_errata_probe(archid, impid); + u32 cpu_req_errata; u32 cpu_apply_errata = 0; u32 tmp; + if (stage == RISCV_ALTERNATIVES_EARLY_BOOT) + return; + + cpu_req_errata = sifive_errata_probe(archid, impid); + for (alt = begin; alt < end; alt++) { if (alt->vendor_id != SIFIVE_VENDOR_ID) continue; diff --git a/arch/riscv/errata/thead/Makefile b/arch/riscv/errata/thead/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..137e700d9d3f8ed79ac03f996934c54af99a56b3 --- /dev/null +++ b/arch/riscv/errata/thead/Makefile @@ -0,0 +1,11 @@ +ifdef CONFIG_RISCV_ALTERNATIVE_EARLY +CFLAGS_errata.o := -mcmodel=medany +ifdef CONFIG_FTRACE +CFLAGS_REMOVE_errata.o = $(CC_FLAGS_FTRACE) +endif +ifdef CONFIG_KASAN +KASAN_SANITIZE_errata.o := n +endif +endif + +obj-y += errata.o diff --git a/arch/riscv/errata/thead/errata.c b/arch/riscv/errata/thead/errata.c new file mode 100644 index 0000000000000000000000000000000000000000..e5d75270b99ccfadcca58394f438fa38cc1e141c --- /dev/null +++ b/arch/riscv/errata/thead/errata.c @@ -0,0 +1,82 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2021 Heiko Stuebner + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct errata_info { + char name[ERRATA_STRING_LENGTH_MAX]; + bool (*check_func)(unsigned long arch_id, unsigned long impid); + unsigned int stage; +}; + +static bool errata_mt_check_func(unsigned long arch_id, unsigned long impid) +{ + if (arch_id != 0 || impid != 0) + return false; + return true; +} + +static const struct errata_info errata_list[ERRATA_THEAD_NUMBER] = { + { + .name = "memory-types", + .stage = RISCV_ALTERNATIVES_EARLY_BOOT, + .check_func = errata_mt_check_func + }, +}; + +static u32 thead_errata_probe(unsigned int stage, unsigned long archid, unsigned long impid) +{ + const struct errata_info *info; + u32 cpu_req_errata = 0; + int idx; + + for (idx = 0; idx < ERRATA_THEAD_NUMBER; idx++) { + info = &errata_list[idx]; + + if ((stage == RISCV_ALTERNATIVES_MODULE || + info->stage == stage) && info->check_func(archid, impid)) + cpu_req_errata |= (1U << idx); + } + + return cpu_req_errata; +} + +void __init_or_module thead_errata_patch_func(struct alt_entry *begin, struct alt_entry *end, + unsigned long archid, unsigned long impid, + unsigned int stage) +{ + struct alt_entry *alt; + u32 cpu_req_errata = thead_errata_probe(stage, archid, impid); + u32 tmp; + + for (alt = begin; alt < end; alt++) { + if (alt->vendor_id != THEAD_VENDOR_ID) + continue; + if (alt->errata_id >= ERRATA_THEAD_NUMBER) + continue; + + tmp = (1U << alt->errata_id); + if (cpu_req_errata & tmp) { + /* On vm-alternatives, the mmu isn't running yet */ + if (stage == RISCV_ALTERNATIVES_EARLY_BOOT) + memcpy((void *)__pa_symbol(alt->old_ptr), + (void *)__pa_symbol(alt->alt_ptr), alt->alt_len); + else + patch_text_nosync(alt->old_ptr, alt->alt_ptr, alt->alt_len); + } + } + + if (stage == RISCV_ALTERNATIVES_EARLY_BOOT) + local_flush_icache_all(); +} diff --git a/arch/riscv/include/asm/alternative-macros.h b/arch/riscv/include/asm/alternative-macros.h index 67406c37638903a24ef420e9bd679678050bb1e0..e13b1f6bb400b1d64532b17d3adabac9928bdfda 100644 --- a/arch/riscv/include/asm/alternative-macros.h +++ b/arch/riscv/include/asm/alternative-macros.h @@ -2,7 +2,7 @@ #ifndef __ASM_ALTERNATIVE_MACROS_H #define __ASM_ALTERNATIVE_MACROS_H -#ifdef CONFIG_RISCV_ERRATA_ALTERNATIVE +#ifdef CONFIG_RISCV_ALTERNATIVE #ifdef __ASSEMBLY__ @@ -21,7 +21,11 @@ .popsection .subsection 1 888 : + .option push + .option norvc + .option norelax \new_c + .option pop 889 : .previous .org . - (889b - 888b) + (887b - 886b) @@ -31,7 +35,11 @@ .macro __ALTERNATIVE_CFG old_c, new_c, vendor_id, errata_id, enable 886 : + .option push + .option norvc + .option norelax \old_c + .option pop 887 : ALT_NEW_CONTENT \vendor_id, \errata_id, \enable, \new_c .endm @@ -39,44 +47,97 @@ #define _ALTERNATIVE_CFG(old_c, new_c, vendor_id, errata_id, CONFIG_k) \ __ALTERNATIVE_CFG old_c, new_c, vendor_id, errata_id, IS_ENABLED(CONFIG_k) +.macro __ALTERNATIVE_CFG_2 old_c, new_c_1, vendor_id_1, errata_id_1, enable_1, \ + new_c_2, vendor_id_2, errata_id_2, enable_2 +886 : + .option push + .option norvc + .option norelax + \old_c + .option pop +887 : + ALT_NEW_CONTENT \vendor_id_1, \errata_id_1, \enable_1, \new_c_1 + ALT_NEW_CONTENT \vendor_id_2, \errata_id_2, \enable_2, \new_c_2 +.endm + +#define _ALTERNATIVE_CFG_2(old_c, new_c_1, vendor_id_1, errata_id_1, \ + CONFIG_k_1, \ + new_c_2, vendor_id_2, errata_id_2, \ + CONFIG_k_2) \ + __ALTERNATIVE_CFG_2 old_c, new_c_1, vendor_id_1, errata_id_1, \ + IS_ENABLED(CONFIG_k_1), \ + new_c_2, vendor_id_2, errata_id_2, \ + IS_ENABLED(CONFIG_k_2) + #else /* !__ASSEMBLY__ */ #include #include -#define ALT_ENTRY(oldptr, newptr, vendor_id, errata_id, newlen) \ - RISCV_PTR " " oldptr "\n" \ - RISCV_PTR " " newptr "\n" \ - REG_ASM " " vendor_id "\n" \ - REG_ASM " " newlen "\n" \ +#define ALT_ENTRY(oldptr, newptr, vendor_id, errata_id, newlen) \ + RISCV_PTR " " oldptr "\n" \ + RISCV_PTR " " newptr "\n" \ + REG_ASM " " vendor_id "\n" \ + REG_ASM " " newlen "\n" \ ".word " errata_id "\n" -#define ALT_NEW_CONTENT(vendor_id, errata_id, enable, new_c) \ +#define ALT_NEW_CONTENT(vendor_id, errata_id, enable, new_c) \ ".if " __stringify(enable) " == 1\n" \ ".pushsection .alternative, \"a\"\n" \ ALT_ENTRY("886b", "888f", __stringify(vendor_id), __stringify(errata_id), "889f - 888f") \ ".popsection\n" \ ".subsection 1\n" \ "888 :\n" \ + ".option push\n" \ + ".option norvc\n" \ + ".option norelax\n" \ new_c "\n" \ + ".option pop\n" \ "889 :\n" \ ".previous\n" \ ".org . - (887b - 886b) + (889b - 888b)\n" \ ".org . - (889b - 888b) + (887b - 886b)\n" \ ".endif\n" -#define __ALTERNATIVE_CFG(old_c, new_c, vendor_id, errata_id, enable) \ - "886 :\n" \ - old_c "\n" \ - "887 :\n" \ +#define __ALTERNATIVE_CFG(old_c, new_c, vendor_id, errata_id, enable) \ + "886 :\n" \ + ".option push\n" \ + ".option norvc\n" \ + ".option norelax\n" \ + old_c "\n" \ + ".option pop\n" \ + "887 :\n" \ ALT_NEW_CONTENT(vendor_id, errata_id, enable, new_c) #define _ALTERNATIVE_CFG(old_c, new_c, vendor_id, errata_id, CONFIG_k) \ __ALTERNATIVE_CFG(old_c, new_c, vendor_id, errata_id, IS_ENABLED(CONFIG_k)) +#define __ALTERNATIVE_CFG_2(old_c, new_c_1, vendor_id_1, errata_id_1, \ + enable_1, \ + new_c_2, vendor_id_2, errata_id_2, \ + enable_2) \ + "886 :\n" \ + ".option push\n" \ + ".option norvc\n" \ + ".option norelax\n" \ + old_c "\n" \ + ".option pop\n" \ + "887 :\n" \ + ALT_NEW_CONTENT(vendor_id_1, errata_id_1, enable_1, new_c_1) \ + ALT_NEW_CONTENT(vendor_id_2, errata_id_2, enable_2, new_c_2) + +#define _ALTERNATIVE_CFG_2(old_c, new_c_1, vendor_id_1, errata_id_1, \ + CONFIG_k_1, \ + new_c_2, vendor_id_2, errata_id_2, \ + CONFIG_k_2) \ + __ALTERNATIVE_CFG_2(old_c, new_c_1, vendor_id_1, errata_id_1, \ + IS_ENABLED(CONFIG_k_1), \ + new_c_2, vendor_id_2, errata_id_2, \ + IS_ENABLED(CONFIG_k_2)) + #endif /* __ASSEMBLY__ */ -#else /* !CONFIG_RISCV_ERRATA_ALTERNATIVE*/ +#else /* CONFIG_RISCV_ALTERNATIVE */ #ifdef __ASSEMBLY__ .macro __ALTERNATIVE_CFG old_c @@ -86,6 +147,12 @@ #define _ALTERNATIVE_CFG(old_c, new_c, vendor_id, errata_id, CONFIG_k) \ __ALTERNATIVE_CFG old_c +#define _ALTERNATIVE_CFG_2(old_c, new_c_1, vendor_id_1, errata_id_1, \ + CONFIG_k_1, \ + new_c_2, vendor_id_2, errata_id_2, \ + CONFIG_k_2) \ + __ALTERNATIVE_CFG old_c + #else /* !__ASSEMBLY__ */ #define __ALTERNATIVE_CFG(old_c) \ @@ -94,8 +161,15 @@ #define _ALTERNATIVE_CFG(old_c, new_c, vendor_id, errata_id, CONFIG_k) \ __ALTERNATIVE_CFG(old_c) +#define _ALTERNATIVE_CFG_2(old_c, new_c_1, vendor_id_1, errata_id_1, \ + CONFIG_k_1, \ + new_c_2, vendor_id_2, errata_id_2, \ + CONFIG_k_2) \ + __ALTERNATIVE_CFG(old_c) + #endif /* __ASSEMBLY__ */ -#endif /* CONFIG_RISCV_ERRATA_ALTERNATIVE */ +#endif /* CONFIG_RISCV_ALTERNATIVE */ + /* * Usage: * ALTERNATIVE(old_content, new_content, vendor_id, errata_id, CONFIG_k) @@ -118,25 +192,14 @@ * this case, this vendor can create a new macro ALTERNATIVE_2() based * on the following sample code and then replace ALTERNATIVE() with * ALTERNATIVE_2() to append its customized content. - * - * .macro __ALTERNATIVE_CFG_2 old_c, new_c_1, vendor_id_1, errata_id_1, enable_1, \ - * new_c_2, vendor_id_2, errata_id_2, enable_2 - * 886 : - * \old_c - * 887 : - * ALT_NEW_CONTENT \vendor_id_1, \errata_id_1, \enable_1, \new_c_1 - * ALT_NEW_CONTENT \vendor_id_2, \errata_id_2, \enable_2, \new_c_2 - * .endm - * - * #define _ALTERNATIVE_CFG_2(old_c, new_c_1, vendor_id_1, errata_id_1, CONFIG_k_1, \ - * new_c_2, vendor_id_2, errata_id_2, CONFIG_k_2) \ - * __ALTERNATIVE_CFG_2 old_c, new_c_1, vendor_id_1, errata_id_1, IS_ENABLED(CONFIG_k_1), \ - * new_c_2, vendor_id_2, errata_id_2, IS_ENABLED(CONFIG_k_2) \ - * - * #define ALTERNATIVE_2(old_content, new_content_1, vendor_id_1, errata_id_1, CONFIG_k_1, \ - * new_content_2, vendor_id_2, errata_id_2, CONFIG_k_2) \ - * _ALTERNATIVE_CFG_2(old_content, new_content_1, vendor_id_1, errata_id_1, CONFIG_k_1, \ - * new_content_2, vendor_id_2, errata_id_2, CONFIG_k_2) - * */ +#define ALTERNATIVE_2(old_content, new_content_1, vendor_id_1, \ + errata_id_1, CONFIG_k_1, \ + new_content_2, vendor_id_2, \ + errata_id_2, CONFIG_k_2) \ + _ALTERNATIVE_CFG_2(old_content, new_content_1, vendor_id_1, \ + errata_id_1, CONFIG_k_1, \ + new_content_2, vendor_id_2, \ + errata_id_2, CONFIG_k_2) + #endif diff --git a/arch/riscv/include/asm/alternative.h b/arch/riscv/include/asm/alternative.h index e625d3cafbed5440201ac9bf31afc283aeda45bf..6511dd73e812e215c6da33821373577c624cdcf2 100644 --- a/arch/riscv/include/asm/alternative.h +++ b/arch/riscv/include/asm/alternative.h @@ -12,12 +12,20 @@ #ifndef __ASSEMBLY__ +#ifdef CONFIG_RISCV_ALTERNATIVE + #include #include #include #include +#define RISCV_ALTERNATIVES_BOOT 0 /* alternatives applied during regular boot */ +#define RISCV_ALTERNATIVES_MODULE 1 /* alternatives applied during module-init */ +#define RISCV_ALTERNATIVES_EARLY_BOOT 2 /* alternatives applied before mmu start */ + void __init apply_boot_alternatives(void); +void __init apply_early_boot_alternatives(void); +void apply_module_alternatives(void *start, size_t length); struct alt_entry { void *old_ptr; /* address of original instruciton or data */ @@ -33,7 +41,22 @@ struct errata_checkfunc_id { }; void sifive_errata_patch_func(struct alt_entry *begin, struct alt_entry *end, - unsigned long archid, unsigned long impid); + unsigned long archid, unsigned long impid, + unsigned int stage); +void thead_errata_patch_func(struct alt_entry *begin, struct alt_entry *end, + unsigned long archid, unsigned long impid, + unsigned int stage); + +void riscv_cpufeature_patch_func(struct alt_entry *begin, struct alt_entry *end, + unsigned int stage); + +#else /* CONFIG_RISCV_ALTERNATIVE */ + +static inline void apply_boot_alternatives(void) { } +static inline void apply_early_boot_alternatives(void) { } +static inline void apply_module_alternatives(void *start, size_t length) { } + +#endif /* CONFIG_RISCV_ALTERNATIVE */ #endif #endif diff --git a/arch/riscv/include/asm/asm.h b/arch/riscv/include/asm/asm.h index 8c2549b16ac06f7291dee8d2a478734b1e7a3c3b..618d7c5af1a2df39e54ef3565dedfa86bd0dc5c4 100644 --- a/arch/riscv/include/asm/asm.h +++ b/arch/riscv/include/asm/asm.h @@ -67,30 +67,4 @@ #error "Unexpected __SIZEOF_SHORT__" #endif -#ifdef __ASSEMBLY__ - -/* Common assembly source macros */ - -#ifdef CONFIG_XIP_KERNEL -.macro XIP_FIXUP_OFFSET reg - REG_L t0, _xip_fixup - add \reg, \reg, t0 -.endm -.macro XIP_FIXUP_FLASH_OFFSET reg - la t1, __data_loc - REG_L t1, _xip_phys_offset - sub \reg, \reg, t1 - add \reg, \reg, t0 -.endm -_xip_fixup: .dword CONFIG_PHYS_RAM_BASE - CONFIG_XIP_PHYS_ADDR - XIP_OFFSET -_xip_phys_offset: .dword CONFIG_XIP_PHYS_ADDR + XIP_OFFSET -#else -.macro XIP_FIXUP_OFFSET reg -.endm -.macro XIP_FIXUP_FLASH_OFFSET reg -.endm -#endif /* CONFIG_XIP_KERNEL */ - -#endif /* __ASSEMBLY__ */ - #endif /* _ASM_RISCV_ASM_H */ diff --git a/arch/riscv/include/asm/atomic.h b/arch/riscv/include/asm/atomic.h index ac9bdf4fc4044b0b784836e40dd6b4e9aab9f294..0dfe9d857a762b6be9a5089b0a5a154a47f46d6a 100644 --- a/arch/riscv/include/asm/atomic.h +++ b/arch/riscv/include/asm/atomic.h @@ -310,47 +310,129 @@ ATOMIC_OPS() #undef ATOMIC_OPS #undef ATOMIC_OP -static __always_inline int arch_atomic_sub_if_positive(atomic_t *v, int offset) +static __always_inline bool arch_atomic_inc_unless_negative(atomic_t *v) +{ + int prev, rc; + + __asm__ __volatile__ ( + "0: lr.w %[p], %[c]\n" + " bltz %[p], 1f\n" + " addi %[rc], %[p], 1\n" + " sc.w.rl %[rc], %[rc], %[c]\n" + " bnez %[rc], 0b\n" + " fence rw, rw\n" + "1:\n" + : [p]"=&r" (prev), [rc]"=&r" (rc), [c]"+A" (v->counter) + : + : "memory"); + return !(prev < 0); +} + +#define arch_atomic_inc_unless_negative arch_atomic_inc_unless_negative + +static __always_inline bool arch_atomic_dec_unless_positive(atomic_t *v) +{ + int prev, rc; + + __asm__ __volatile__ ( + "0: lr.w %[p], %[c]\n" + " bgtz %[p], 1f\n" + " addi %[rc], %[p], -1\n" + " sc.w.rl %[rc], %[rc], %[c]\n" + " bnez %[rc], 0b\n" + " fence rw, rw\n" + "1:\n" + : [p]"=&r" (prev), [rc]"=&r" (rc), [c]"+A" (v->counter) + : + : "memory"); + return !(prev > 0); +} + +#define arch_atomic_dec_unless_positive arch_atomic_dec_unless_positive + +static __always_inline int arch_atomic_dec_if_positive(atomic_t *v) { int prev, rc; __asm__ __volatile__ ( "0: lr.w %[p], %[c]\n" - " sub %[rc], %[p], %[o]\n" + " addi %[rc], %[p], -1\n" " bltz %[rc], 1f\n" " sc.w.rl %[rc], %[rc], %[c]\n" " bnez %[rc], 0b\n" " fence rw, rw\n" "1:\n" : [p]"=&r" (prev), [rc]"=&r" (rc), [c]"+A" (v->counter) - : [o]"r" (offset) + : : "memory"); - return prev - offset; + return prev - 1; } -#define arch_atomic_dec_if_positive(v) arch_atomic_sub_if_positive(v, 1) +#define arch_atomic_dec_if_positive arch_atomic_dec_if_positive #ifndef CONFIG_GENERIC_ATOMIC64 -static __always_inline s64 arch_atomic64_sub_if_positive(atomic64_t *v, s64 offset) +static __always_inline bool arch_atomic64_inc_unless_negative(atomic64_t *v) +{ + s64 prev; + long rc; + + __asm__ __volatile__ ( + "0: lr.d %[p], %[c]\n" + " bltz %[p], 1f\n" + " addi %[rc], %[p], 1\n" + " sc.d.rl %[rc], %[rc], %[c]\n" + " bnez %[rc], 0b\n" + " fence rw, rw\n" + "1:\n" + : [p]"=&r" (prev), [rc]"=&r" (rc), [c]"+A" (v->counter) + : + : "memory"); + return !(prev < 0); +} + +#define arch_atomic64_inc_unless_negative arch_atomic64_inc_unless_negative + +static __always_inline bool arch_atomic64_dec_unless_positive(atomic64_t *v) +{ + s64 prev; + long rc; + + __asm__ __volatile__ ( + "0: lr.d %[p], %[c]\n" + " bgtz %[p], 1f\n" + " addi %[rc], %[p], -1\n" + " sc.d.rl %[rc], %[rc], %[c]\n" + " bnez %[rc], 0b\n" + " fence rw, rw\n" + "1:\n" + : [p]"=&r" (prev), [rc]"=&r" (rc), [c]"+A" (v->counter) + : + : "memory"); + return !(prev > 0); +} + +#define arch_atomic64_dec_unless_positive arch_atomic64_dec_unless_positive + +static __always_inline s64 arch_atomic64_dec_if_positive(atomic64_t *v) { s64 prev; long rc; __asm__ __volatile__ ( "0: lr.d %[p], %[c]\n" - " sub %[rc], %[p], %[o]\n" + " addi %[rc], %[p], -1\n" " bltz %[rc], 1f\n" " sc.d.rl %[rc], %[rc], %[c]\n" " bnez %[rc], 0b\n" " fence rw, rw\n" "1:\n" : [p]"=&r" (prev), [rc]"=&r" (rc), [c]"+A" (v->counter) - : [o]"r" (offset) + : : "memory"); - return prev - offset; + return prev - 1; } -#define arch_atomic64_dec_if_positive(v) arch_atomic64_sub_if_positive(v, 1) +#define arch_atomic64_dec_if_positive arch_atomic64_dec_if_positive #endif #endif /* _ASM_RISCV_ATOMIC_H */ diff --git a/arch/riscv/include/asm/cmpxchg.h b/arch/riscv/include/asm/cmpxchg.h index 36dc962f634366002ce6861c8aacb74bf0a480ea..12debce235e52d04ecccc057defa96b10672f885 100644 --- a/arch/riscv/include/asm/cmpxchg.h +++ b/arch/riscv/include/asm/cmpxchg.h @@ -348,18 +348,6 @@ #define arch_cmpxchg_local(ptr, o, n) \ (__cmpxchg_relaxed((ptr), (o), (n), sizeof(*(ptr)))) -#define cmpxchg32(ptr, o, n) \ -({ \ - BUILD_BUG_ON(sizeof(*(ptr)) != 4); \ - arch_cmpxchg((ptr), (o), (n)); \ -}) - -#define cmpxchg32_local(ptr, o, n) \ -({ \ - BUILD_BUG_ON(sizeof(*(ptr)) != 4); \ - arch_cmpxchg_relaxed((ptr), (o), (n)) \ -}) - #define arch_cmpxchg64(ptr, o, n) \ ({ \ BUILD_BUG_ON(sizeof(*(ptr)) != 8); \ diff --git a/arch/riscv/include/asm/compat.h b/arch/riscv/include/asm/compat.h new file mode 100644 index 0000000000000000000000000000000000000000..2ac955b51148f4f12d23c03b42aae76d79b79bed --- /dev/null +++ b/arch/riscv/include/asm/compat.h @@ -0,0 +1,129 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef __ASM_COMPAT_H +#define __ASM_COMPAT_H + +#define COMPAT_UTS_MACHINE "riscv\0\0" + +/* + * Architecture specific compatibility types + */ +#include +#include +#include +#include + +static inline int is_compat_task(void) +{ + return test_thread_flag(TIF_32BIT); +} + +struct compat_user_regs_struct { + compat_ulong_t pc; + compat_ulong_t ra; + compat_ulong_t sp; + compat_ulong_t gp; + compat_ulong_t tp; + compat_ulong_t t0; + compat_ulong_t t1; + compat_ulong_t t2; + compat_ulong_t s0; + compat_ulong_t s1; + compat_ulong_t a0; + compat_ulong_t a1; + compat_ulong_t a2; + compat_ulong_t a3; + compat_ulong_t a4; + compat_ulong_t a5; + compat_ulong_t a6; + compat_ulong_t a7; + compat_ulong_t s2; + compat_ulong_t s3; + compat_ulong_t s4; + compat_ulong_t s5; + compat_ulong_t s6; + compat_ulong_t s7; + compat_ulong_t s8; + compat_ulong_t s9; + compat_ulong_t s10; + compat_ulong_t s11; + compat_ulong_t t3; + compat_ulong_t t4; + compat_ulong_t t5; + compat_ulong_t t6; +}; + +static inline void regs_to_cregs(struct compat_user_regs_struct *cregs, + struct pt_regs *regs) +{ + cregs->pc = (compat_ulong_t) regs->epc; + cregs->ra = (compat_ulong_t) regs->ra; + cregs->sp = (compat_ulong_t) regs->sp; + cregs->gp = (compat_ulong_t) regs->gp; + cregs->tp = (compat_ulong_t) regs->tp; + cregs->t0 = (compat_ulong_t) regs->t0; + cregs->t1 = (compat_ulong_t) regs->t1; + cregs->t2 = (compat_ulong_t) regs->t2; + cregs->s0 = (compat_ulong_t) regs->s0; + cregs->s1 = (compat_ulong_t) regs->s1; + cregs->a0 = (compat_ulong_t) regs->a0; + cregs->a1 = (compat_ulong_t) regs->a1; + cregs->a2 = (compat_ulong_t) regs->a2; + cregs->a3 = (compat_ulong_t) regs->a3; + cregs->a4 = (compat_ulong_t) regs->a4; + cregs->a5 = (compat_ulong_t) regs->a5; + cregs->a6 = (compat_ulong_t) regs->a6; + cregs->a7 = (compat_ulong_t) regs->a7; + cregs->s2 = (compat_ulong_t) regs->s2; + cregs->s3 = (compat_ulong_t) regs->s3; + cregs->s4 = (compat_ulong_t) regs->s4; + cregs->s5 = (compat_ulong_t) regs->s5; + cregs->s6 = (compat_ulong_t) regs->s6; + cregs->s7 = (compat_ulong_t) regs->s7; + cregs->s8 = (compat_ulong_t) regs->s8; + cregs->s9 = (compat_ulong_t) regs->s9; + cregs->s10 = (compat_ulong_t) regs->s10; + cregs->s11 = (compat_ulong_t) regs->s11; + cregs->t3 = (compat_ulong_t) regs->t3; + cregs->t4 = (compat_ulong_t) regs->t4; + cregs->t5 = (compat_ulong_t) regs->t5; + cregs->t6 = (compat_ulong_t) regs->t6; +}; + +static inline void cregs_to_regs(struct compat_user_regs_struct *cregs, + struct pt_regs *regs) +{ + regs->epc = (unsigned long) cregs->pc; + regs->ra = (unsigned long) cregs->ra; + regs->sp = (unsigned long) cregs->sp; + regs->gp = (unsigned long) cregs->gp; + regs->tp = (unsigned long) cregs->tp; + regs->t0 = (unsigned long) cregs->t0; + regs->t1 = (unsigned long) cregs->t1; + regs->t2 = (unsigned long) cregs->t2; + regs->s0 = (unsigned long) cregs->s0; + regs->s1 = (unsigned long) cregs->s1; + regs->a0 = (unsigned long) cregs->a0; + regs->a1 = (unsigned long) cregs->a1; + regs->a2 = (unsigned long) cregs->a2; + regs->a3 = (unsigned long) cregs->a3; + regs->a4 = (unsigned long) cregs->a4; + regs->a5 = (unsigned long) cregs->a5; + regs->a6 = (unsigned long) cregs->a6; + regs->a7 = (unsigned long) cregs->a7; + regs->s2 = (unsigned long) cregs->s2; + regs->s3 = (unsigned long) cregs->s3; + regs->s4 = (unsigned long) cregs->s4; + regs->s5 = (unsigned long) cregs->s5; + regs->s6 = (unsigned long) cregs->s6; + regs->s7 = (unsigned long) cregs->s7; + regs->s8 = (unsigned long) cregs->s8; + regs->s9 = (unsigned long) cregs->s9; + regs->s10 = (unsigned long) cregs->s10; + regs->s11 = (unsigned long) cregs->s11; + regs->t3 = (unsigned long) cregs->t3; + regs->t4 = (unsigned long) cregs->t4; + regs->t5 = (unsigned long) cregs->t5; + regs->t6 = (unsigned long) cregs->t6; +}; + +#endif /* __ASM_COMPAT_H */ diff --git a/arch/riscv/include/asm/csr.h b/arch/riscv/include/asm/csr.h index cc40521e438b32147767393fc9b96eed0610a754..6d85655e7edf26aabfe4b8345a3d95851fd8a87b 100644 --- a/arch/riscv/include/asm/csr.h +++ b/arch/riscv/include/asm/csr.h @@ -36,6 +36,13 @@ #define SR_SD _AC(0x8000000000000000, UL) /* FS/XS dirty */ #endif +#ifdef CONFIG_64BIT +#define SR_UXL _AC(0x300000000, UL) /* XLEN mask for U-mode */ +#define SR_UXL_32 _AC(0x100000000, UL) /* XLEN = 32 for U-mode */ +#define SR_UXL_64 _AC(0x200000000, UL) /* XLEN = 64 for U-mode */ +#define SR_UXL_SHIFT 32 +#endif + /* SATP flags */ #ifndef CONFIG_64BIT #define SATP_PPN _AC(0x003FFFFF, UL) diff --git a/arch/riscv/include/asm/elf.h b/arch/riscv/include/asm/elf.h index f53c40026c7aa08e0170d8d58b6873760fdfb87f..14fc7342490bfc6151e500e34cc774cbfeb49005 100644 --- a/arch/riscv/include/asm/elf.h +++ b/arch/riscv/include/asm/elf.h @@ -8,6 +8,8 @@ #ifndef _ASM_RISCV_ELF_H #define _ASM_RISCV_ELF_H +#include +#include #include #include #include @@ -18,18 +20,24 @@ */ #define ELF_ARCH EM_RISCV +#ifndef ELF_CLASS #ifdef CONFIG_64BIT #define ELF_CLASS ELFCLASS64 #else #define ELF_CLASS ELFCLASS32 #endif +#endif #define ELF_DATA ELFDATA2LSB /* * This is used to ensure we don't load something for the wrong architecture. */ -#define elf_check_arch(x) ((x)->e_machine == EM_RISCV) +#define elf_check_arch(x) (((x)->e_machine == EM_RISCV) && \ + ((x)->e_ident[EI_CLASS] == ELF_CLASS)) + +extern bool compat_elf_check_arch(Elf32_Ehdr *hdr); +#define compat_elf_check_arch compat_elf_check_arch #define CORE_DUMP_USE_REGSET #define ELF_EXEC_PAGESIZE (PAGE_SIZE) @@ -43,8 +51,14 @@ #define ELF_ET_DYN_BASE ((TASK_SIZE / 3) * 2) #ifdef CONFIG_64BIT +#ifdef CONFIG_COMPAT +#define STACK_RND_MASK (test_thread_flag(TIF_32BIT) ? \ + 0x7ff >> (PAGE_SHIFT - 12) : \ + 0x3ffff >> (PAGE_SHIFT - 12)) +#else #define STACK_RND_MASK (0x3ffff >> (PAGE_SHIFT - 12)) #endif +#endif /* * This yields a mask that user programs can use to figure out what * instruction set this CPU supports. This could be done in user space, @@ -60,11 +74,19 @@ extern unsigned long elf_hwcap; */ #define ELF_PLATFORM (NULL) +#define COMPAT_ELF_PLATFORM (NULL) + #ifdef CONFIG_MMU #define ARCH_DLINFO \ do { \ + /* \ + * Note that we add ulong after elf_addr_t because \ + * casting current->mm->context.vdso triggers a cast \ + * warning of cast from pointer to integer for \ + * COMPAT ELFCLASS32. \ + */ \ NEW_AUX_ENT(AT_SYSINFO_EHDR, \ - (elf_addr_t)current->mm->context.vdso); \ + (elf_addr_t)(ulong)current->mm->context.vdso); \ NEW_AUX_ENT(AT_L1I_CACHESIZE, \ get_cache_size(1, CACHE_TYPE_INST)); \ NEW_AUX_ENT(AT_L1I_CACHEGEOMETRY, \ @@ -90,4 +112,28 @@ do { \ *(struct user_regs_struct *)regs; \ } while (0); +#ifdef CONFIG_COMPAT + +#define SET_PERSONALITY(ex) \ +do { if ((ex).e_ident[EI_CLASS] == ELFCLASS32) \ + set_thread_flag(TIF_32BIT); \ + else \ + clear_thread_flag(TIF_32BIT); \ + if (personality(current->personality) != PER_LINUX32) \ + set_personality(PER_LINUX | \ + (current->personality & (~PER_MASK))); \ +} while (0) + +#define COMPAT_ELF_ET_DYN_BASE ((TASK_SIZE_32 / 3) * 2) + +/* rv32 registers */ +typedef compat_ulong_t compat_elf_greg_t; +typedef compat_elf_greg_t compat_elf_gregset_t[ELF_NGREG]; + +extern int compat_arch_setup_additional_pages(struct linux_binprm *bprm, + int uses_interp); +#define compat_arch_setup_additional_pages \ + compat_arch_setup_additional_pages + +#endif /* CONFIG_COMPAT */ #endif /* _ASM_RISCV_ELF_H */ diff --git a/arch/riscv/include/asm/errata_list.h b/arch/riscv/include/asm/errata_list.h index 5f1046e82d9f9de108bbdac11cbcbfd3552b8a68..9e2888dbb5b1316b8a66990067b9b9cd50c6246b 100644 --- a/arch/riscv/include/asm/errata_list.h +++ b/arch/riscv/include/asm/errata_list.h @@ -14,6 +14,14 @@ #define ERRATA_SIFIVE_NUMBER 2 #endif +#ifdef CONFIG_ERRATA_THEAD +#define ERRATA_THEAD_PBMT 0 +#define ERRATA_THEAD_NUMBER 1 +#endif + +#define CPUFEATURE_SVPBMT 0 +#define CPUFEATURE_NUMBER 1 + #ifdef __ASSEMBLY__ #define ALT_INSN_FAULT(x) \ @@ -34,6 +42,57 @@ asm(ALTERNATIVE("sfence.vma %0", "sfence.vma", SIFIVE_VENDOR_ID, \ ERRATA_SIFIVE_CIP_1200, CONFIG_ERRATA_SIFIVE_CIP_1200) \ : : "r" (addr) : "memory") +/* + * _val is marked as "will be overwritten", so need to set it to 0 + * in the default case. + */ +#define ALT_SVPBMT_SHIFT 61 +#define ALT_THEAD_PBMT_SHIFT 59 +#define ALT_SVPBMT(_val, prot) \ +asm(ALTERNATIVE_2("li %0, 0\t\nnop", \ + "li %0, %1\t\nslli %0,%0,%3", 0, \ + CPUFEATURE_SVPBMT, CONFIG_RISCV_ISA_SVPBMT, \ + "li %0, %2\t\nslli %0,%0,%4", THEAD_VENDOR_ID, \ + ERRATA_THEAD_PBMT, CONFIG_ERRATA_THEAD_PBMT) \ + : "=r"(_val) \ + : "I"(prot##_SVPBMT >> ALT_SVPBMT_SHIFT), \ + "I"(prot##_THEAD >> ALT_THEAD_PBMT_SHIFT), \ + "I"(ALT_SVPBMT_SHIFT), \ + "I"(ALT_THEAD_PBMT_SHIFT)) + +#ifdef CONFIG_ERRATA_THEAD_PBMT +/* + * IO/NOCACHE memory types are handled together with svpbmt, + * so on T-Head chips, check if no other memory type is set, + * and set the non-0 PMA type if applicable. + */ +#define ALT_THEAD_PMA(_val) \ +asm volatile(ALTERNATIVE( \ + "nop\n\t" \ + "nop\n\t" \ + "nop\n\t" \ + "nop\n\t" \ + "nop\n\t" \ + "nop\n\t" \ + "nop", \ + "li t3, %2\n\t" \ + "slli t3, t3, %4\n\t" \ + "and t3, %0, t3\n\t" \ + "bne t3, zero, 2f\n\t" \ + "li t3, %3\n\t" \ + "slli t3, t3, %4\n\t" \ + "or %0, %0, t3\n\t" \ + "2:", THEAD_VENDOR_ID, \ + ERRATA_THEAD_PBMT, CONFIG_ERRATA_THEAD_PBMT) \ + : "+r"(_val) \ + : "0"(_val), \ + "I"(_PAGE_MTMASK_THEAD >> ALT_THEAD_PBMT_SHIFT), \ + "I"(_PAGE_PMA_THEAD >> ALT_THEAD_PBMT_SHIFT), \ + "I"(ALT_THEAD_PBMT_SHIFT)) +#else +#define ALT_THEAD_PMA(_val) +#endif + #endif /* __ASSEMBLY__ */ #endif diff --git a/arch/riscv/include/asm/fixmap.h b/arch/riscv/include/asm/fixmap.h index 3cfece8b65681c15aadf1c5b95b15f0d526cd79b..5c3e7b97fcc6f6356b5a11bb7476609d90dd713a 100644 --- a/arch/riscv/include/asm/fixmap.h +++ b/arch/riscv/include/asm/fixmap.h @@ -45,8 +45,6 @@ enum fixed_addresses { __end_of_fixed_addresses }; -#define FIXMAP_PAGE_IO PAGE_KERNEL - #define __early_set_fixmap __set_fixmap #define __late_set_fixmap __set_fixmap diff --git a/arch/riscv/include/asm/hwcap.h b/arch/riscv/include/asm/hwcap.h index 0734e42f74f2f49af0a45feff875c7264bff4a0a..4e24868818408d001844dd2f16507bafcb091369 100644 --- a/arch/riscv/include/asm/hwcap.h +++ b/arch/riscv/include/asm/hwcap.h @@ -52,6 +52,7 @@ extern unsigned long elf_hwcap; */ enum riscv_isa_ext_id { RISCV_ISA_EXT_SSCOFPMF = RISCV_ISA_EXT_BASE, + RISCV_ISA_EXT_SVPBMT, RISCV_ISA_EXT_ID_MAX = RISCV_ISA_EXT_MAX, }; diff --git a/arch/riscv/include/asm/kexec.h b/arch/riscv/include/asm/kexec.h index e4e291d40759f003143c491e2baf3ee742e37bb2..eee260e8ab308e8a033995082e1119df4739eeb3 100644 --- a/arch/riscv/include/asm/kexec.h +++ b/arch/riscv/include/asm/kexec.h @@ -53,4 +53,15 @@ typedef void (*riscv_kexec_method)(unsigned long first_ind_entry, extern riscv_kexec_method riscv_kexec_norelocate; +#ifdef CONFIG_KEXEC_FILE +extern const struct kexec_file_ops elf_kexec_ops; + +struct purgatory_info; +int arch_kexec_apply_relocations_add(struct purgatory_info *pi, + Elf_Shdr *section, + const Elf_Shdr *relsec, + const Elf_Shdr *symtab); +#define arch_kexec_apply_relocations_add arch_kexec_apply_relocations_add +#endif + #endif diff --git a/arch/riscv/include/asm/mmu.h b/arch/riscv/include/asm/mmu.h index 0099dc1161683ddd1e3c45460309e331b7e6b0a7..cedcf8ea3c7664cc144601dc67ba9c584624577f 100644 --- a/arch/riscv/include/asm/mmu.h +++ b/arch/riscv/include/asm/mmu.h @@ -16,6 +16,7 @@ typedef struct { atomic_long_t id; #endif void *vdso; + void *vdso_info; #ifdef CONFIG_SMP /* A local icache flush is needed before user execution can resume. */ cpumask_t icache_stale_mask; diff --git a/arch/riscv/include/asm/pgtable-32.h b/arch/riscv/include/asm/pgtable-32.h index 5b2e79e5bfa5bf8af384e64e3ca1888b2ff4df92..59ba1fbaf784931c680f5c9994080206d331fd54 100644 --- a/arch/riscv/include/asm/pgtable-32.h +++ b/arch/riscv/include/asm/pgtable-32.h @@ -7,6 +7,7 @@ #define _ASM_RISCV_PGTABLE_32_H #include +#include #include /* Size of region mapped by a page global directory */ @@ -16,4 +17,20 @@ #define MAX_POSSIBLE_PHYSMEM_BITS 34 +/* + * rv32 PTE format: + * | XLEN-1 10 | 9 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 + * PFN reserved for SW D A G U X W R V + */ +#define _PAGE_PFN_MASK GENMASK(31, 10) + +#define _PAGE_NOCACHE 0 +#define _PAGE_IO 0 +#define _PAGE_MTMASK 0 + +/* Set of bits to preserve across pte_modify() */ +#define _PAGE_CHG_MASK (~(unsigned long)(_PAGE_PRESENT | _PAGE_READ | \ + _PAGE_WRITE | _PAGE_EXEC | \ + _PAGE_USER | _PAGE_GLOBAL)) + #endif /* _ASM_RISCV_PGTABLE_32_H */ diff --git a/arch/riscv/include/asm/pgtable-64.h b/arch/riscv/include/asm/pgtable-64.h index ba2494cbc24f91245fdda6525c320bd1da5a05b4..5c2aba5efbd0ecf4ff302af06f016e3fa55b36bf 100644 --- a/arch/riscv/include/asm/pgtable-64.h +++ b/arch/riscv/include/asm/pgtable-64.h @@ -6,7 +6,9 @@ #ifndef _ASM_RISCV_PGTABLE_64_H #define _ASM_RISCV_PGTABLE_64_H +#include #include +#include extern bool pgtable_l4_enabled; extern bool pgtable_l5_enabled; @@ -65,6 +67,71 @@ typedef struct { #define PTRS_PER_PMD (PAGE_SIZE / sizeof(pmd_t)) +/* + * rv64 PTE format: + * | 63 | 62 61 | 60 54 | 53 10 | 9 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 + * N MT RSV PFN reserved for SW D A G U X W R V + */ +#define _PAGE_PFN_MASK GENMASK(53, 10) + +/* + * [62:61] Svpbmt Memory Type definitions: + * + * 00 - PMA Normal Cacheable, No change to implied PMA memory type + * 01 - NC Non-cacheable, idempotent, weakly-ordered Main Memory + * 10 - IO Non-cacheable, non-idempotent, strongly-ordered I/O memory + * 11 - Rsvd Reserved for future standard use + */ +#define _PAGE_NOCACHE_SVPBMT (1UL << 61) +#define _PAGE_IO_SVPBMT (1UL << 62) +#define _PAGE_MTMASK_SVPBMT (_PAGE_NOCACHE_SVPBMT | _PAGE_IO_SVPBMT) + +/* + * [63:59] T-Head Memory Type definitions: + * + * 00000 - NC Weakly-ordered, Non-cacheable, Non-bufferable, Non-shareable, Non-trustable + * 01110 - PMA Weakly-ordered, Cacheable, Bufferable, Shareable, Non-trustable + * 10000 - IO Strongly-ordered, Non-cacheable, Non-bufferable, Non-shareable, Non-trustable + */ +#define _PAGE_PMA_THEAD ((1UL << 62) | (1UL << 61) | (1UL << 60)) +#define _PAGE_NOCACHE_THEAD 0UL +#define _PAGE_IO_THEAD (1UL << 63) +#define _PAGE_MTMASK_THEAD (_PAGE_PMA_THEAD | _PAGE_IO_THEAD | (1UL << 59)) + +static inline u64 riscv_page_mtmask(void) +{ + u64 val; + + ALT_SVPBMT(val, _PAGE_MTMASK); + return val; +} + +static inline u64 riscv_page_nocache(void) +{ + u64 val; + + ALT_SVPBMT(val, _PAGE_NOCACHE); + return val; +} + +static inline u64 riscv_page_io(void) +{ + u64 val; + + ALT_SVPBMT(val, _PAGE_IO); + return val; +} + +#define _PAGE_NOCACHE riscv_page_nocache() +#define _PAGE_IO riscv_page_io() +#define _PAGE_MTMASK riscv_page_mtmask() + +/* Set of bits to preserve across pte_modify() */ +#define _PAGE_CHG_MASK (~(unsigned long)(_PAGE_PRESENT | _PAGE_READ | \ + _PAGE_WRITE | _PAGE_EXEC | \ + _PAGE_USER | _PAGE_GLOBAL | \ + _PAGE_MTMASK)) + static inline int pud_present(pud_t pud) { return (pud_val(pud) & _PAGE_PRESENT); @@ -113,12 +180,12 @@ static inline unsigned long _pud_pfn(pud_t pud) static inline pmd_t *pud_pgtable(pud_t pud) { - return (pmd_t *)pfn_to_virt(pud_val(pud) >> _PAGE_PFN_SHIFT); + return (pmd_t *)pfn_to_virt(__page_val_to_pfn(pud_val(pud))); } static inline struct page *pud_page(pud_t pud) { - return pfn_to_page(pud_val(pud) >> _PAGE_PFN_SHIFT); + return pfn_to_page(__page_val_to_pfn(pud_val(pud))); } #define mm_p4d_folded mm_p4d_folded @@ -143,12 +210,16 @@ static inline bool mm_pud_folded(struct mm_struct *mm) static inline pmd_t pfn_pmd(unsigned long pfn, pgprot_t prot) { - return __pmd((pfn << _PAGE_PFN_SHIFT) | pgprot_val(prot)); + unsigned long prot_val = pgprot_val(prot); + + ALT_THEAD_PMA(prot_val); + + return __pmd((pfn << _PAGE_PFN_SHIFT) | prot_val); } static inline unsigned long _pmd_pfn(pmd_t pmd) { - return pmd_val(pmd) >> _PAGE_PFN_SHIFT; + return __page_val_to_pfn(pmd_val(pmd)); } #define mk_pmd(page, prot) pfn_pmd(page_to_pfn(page), prot) diff --git a/arch/riscv/include/asm/pgtable-bits.h b/arch/riscv/include/asm/pgtable-bits.h index a6b0c89824c286526feb403342eb387c95fd9ed2..b9e13a8fe2b748666fd27ffc15c591b51e97910b 100644 --- a/arch/riscv/include/asm/pgtable-bits.h +++ b/arch/riscv/include/asm/pgtable-bits.h @@ -6,12 +6,6 @@ #ifndef _ASM_RISCV_PGTABLE_BITS_H #define _ASM_RISCV_PGTABLE_BITS_H -/* - * PTE format: - * | XLEN-1 10 | 9 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 - * PFN reserved for SW D A G U X W R V - */ - #define _PAGE_ACCESSED_OFFSET 6 #define _PAGE_PRESENT (1 << 0) @@ -35,10 +29,6 @@ #define _PAGE_PFN_SHIFT 10 -/* Set of bits to preserve across pte_modify() */ -#define _PAGE_CHG_MASK (~(unsigned long)(_PAGE_PRESENT | _PAGE_READ | \ - _PAGE_WRITE | _PAGE_EXEC | \ - _PAGE_USER | _PAGE_GLOBAL)) /* * when all of R/W/X are zero, the PTE is a pointer to the next level * of the page table; otherwise, it is a leaf PTE. diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h index 4200ddede880c00b6443d25d2723f3efd4985b28..1d1be9d9419c1287a7b4ede8670e488408dae2b1 100644 --- a/arch/riscv/include/asm/pgtable.h +++ b/arch/riscv/include/asm/pgtable.h @@ -108,6 +108,8 @@ #include #include +#define __page_val_to_pfn(_val) (((_val) & _PAGE_PFN_MASK) >> _PAGE_PFN_SHIFT) + #ifdef CONFIG_64BIT #include #else @@ -179,11 +181,8 @@ extern struct pt_alloc_ops pt_ops __initdata; #define PAGE_TABLE __pgprot(_PAGE_TABLE) -/* - * The RISC-V ISA doesn't yet specify how to query or modify PMAs, so we can't - * change the properties of memory regions. - */ -#define _PAGE_IOREMAP _PAGE_KERNEL +#define _PAGE_IOREMAP ((_PAGE_KERNEL & ~_PAGE_MTMASK) | _PAGE_IO) +#define PAGE_KERNEL_IO __pgprot(_PAGE_IOREMAP) extern pgd_t swapper_pg_dir[]; @@ -253,7 +252,11 @@ static inline void pmd_clear(pmd_t *pmdp) static inline pgd_t pfn_pgd(unsigned long pfn, pgprot_t prot) { - return __pgd((pfn << _PAGE_PFN_SHIFT) | pgprot_val(prot)); + unsigned long prot_val = pgprot_val(prot); + + ALT_THEAD_PMA(prot_val); + + return __pgd((pfn << _PAGE_PFN_SHIFT) | prot_val); } static inline unsigned long _pgd_pfn(pgd_t pgd) @@ -263,12 +266,12 @@ static inline unsigned long _pgd_pfn(pgd_t pgd) static inline struct page *pmd_page(pmd_t pmd) { - return pfn_to_page(pmd_val(pmd) >> _PAGE_PFN_SHIFT); + return pfn_to_page(__page_val_to_pfn(pmd_val(pmd))); } static inline unsigned long pmd_page_vaddr(pmd_t pmd) { - return (unsigned long)pfn_to_virt(pmd_val(pmd) >> _PAGE_PFN_SHIFT); + return (unsigned long)pfn_to_virt(__page_val_to_pfn(pmd_val(pmd))); } static inline pte_t pmd_pte(pmd_t pmd) @@ -284,7 +287,7 @@ static inline pte_t pud_pte(pud_t pud) /* Yields the page frame number (PFN) of a page table entry */ static inline unsigned long pte_pfn(pte_t pte) { - return (pte_val(pte) >> _PAGE_PFN_SHIFT); + return __page_val_to_pfn(pte_val(pte)); } #define pte_page(x) pfn_to_page(pte_pfn(x)) @@ -292,7 +295,11 @@ static inline unsigned long pte_pfn(pte_t pte) /* Constructs a page table entry */ static inline pte_t pfn_pte(unsigned long pfn, pgprot_t prot) { - return __pte((pfn << _PAGE_PFN_SHIFT) | pgprot_val(prot)); + unsigned long prot_val = pgprot_val(prot); + + ALT_THEAD_PMA(prot_val); + + return __pte((pfn << _PAGE_PFN_SHIFT) | prot_val); } #define mk_pte(page, prot) pfn_pte(page_to_pfn(page), prot) @@ -406,7 +413,11 @@ static inline int pmd_protnone(pmd_t pmd) /* Modify page protection bits */ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) { - return __pte((pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot)); + unsigned long newprot_val = pgprot_val(newprot); + + ALT_THEAD_PMA(newprot_val); + + return __pte((pte_val(pte) & _PAGE_CHG_MASK) | newprot_val); } #define pgd_ERROR(e) \ @@ -539,6 +550,28 @@ static inline int ptep_clear_flush_young(struct vm_area_struct *vma, return ptep_test_and_clear_young(vma, address, ptep); } +#define pgprot_noncached pgprot_noncached +static inline pgprot_t pgprot_noncached(pgprot_t _prot) +{ + unsigned long prot = pgprot_val(_prot); + + prot &= ~_PAGE_MTMASK; + prot |= _PAGE_IO; + + return __pgprot(prot); +} + +#define pgprot_writecombine pgprot_writecombine +static inline pgprot_t pgprot_writecombine(pgprot_t _prot) +{ + unsigned long prot = pgprot_val(_prot); + + prot &= ~_PAGE_MTMASK; + prot |= _PAGE_NOCACHE; + + return __pgprot(prot); +} + /* * THP functions */ @@ -761,8 +794,17 @@ static inline pmd_t pmdp_establish(struct vm_area_struct *vma, * 63–48 all equal to bit 47, or else a page-fault exception will occur." */ #ifdef CONFIG_64BIT -#define TASK_SIZE (PGDIR_SIZE * PTRS_PER_PGD / 2) -#define TASK_SIZE_MIN (PGDIR_SIZE_L3 * PTRS_PER_PGD / 2) +#define TASK_SIZE_64 (PGDIR_SIZE * PTRS_PER_PGD / 2) +#define TASK_SIZE_MIN (PGDIR_SIZE_L3 * PTRS_PER_PGD / 2) + +#ifdef CONFIG_COMPAT +#define TASK_SIZE_32 (_AC(0x80000000, UL) - PAGE_SIZE) +#define TASK_SIZE (test_thread_flag(TIF_32BIT) ? \ + TASK_SIZE_32 : TASK_SIZE_64) +#else +#define TASK_SIZE TASK_SIZE_64 +#endif + #else #define TASK_SIZE FIXADDR_START #define TASK_SIZE_MIN TASK_SIZE diff --git a/arch/riscv/include/asm/processor.h b/arch/riscv/include/asm/processor.h index 0749924d9e552dc26786a9b3be2d44d593d8fc07..21c8072dce17aaf5f818b1fdc6ead92279d60608 100644 --- a/arch/riscv/include/asm/processor.h +++ b/arch/riscv/include/asm/processor.h @@ -19,7 +19,11 @@ #define TASK_UNMAPPED_BASE PAGE_ALIGN(TASK_SIZE / 3) #define STACK_TOP TASK_SIZE -#define STACK_TOP_MAX STACK_TOP +#ifdef CONFIG_64BIT +#define STACK_TOP_MAX TASK_SIZE_64 +#else +#define STACK_TOP_MAX TASK_SIZE +#endif #define STACK_ALIGN 16 #ifndef __ASSEMBLY__ diff --git a/arch/riscv/include/asm/signal32.h b/arch/riscv/include/asm/signal32.h new file mode 100644 index 0000000000000000000000000000000000000000..96dc56932e76b0e7446f215a37745890d3145317 --- /dev/null +++ b/arch/riscv/include/asm/signal32.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef __ASM_SIGNAL32_H +#define __ASM_SIGNAL32_H + +#if IS_ENABLED(CONFIG_COMPAT) +int compat_setup_rt_frame(struct ksignal *ksig, sigset_t *set, + struct pt_regs *regs); +#else +static inline +int compat_setup_rt_frame(struct ksignal *ksig, sigset_t *set, + struct pt_regs *regs) +{ + return -1; +} +#endif + +#endif diff --git a/arch/riscv/include/asm/syscall.h b/arch/riscv/include/asm/syscall.h index 7ac6a0e275f2e6e7333785220e750e32600b954c..384a63b86420bb578a8ebfd824e1b48db48677ee 100644 --- a/arch/riscv/include/asm/syscall.h +++ b/arch/riscv/include/asm/syscall.h @@ -16,6 +16,7 @@ /* The array of function pointers for syscalls. */ extern void * const sys_call_table[]; +extern void * const compat_sys_call_table[]; /* * Only the low 32 bits of orig_r0 are meaningful, so we return int. diff --git a/arch/riscv/include/asm/thread_info.h b/arch/riscv/include/asm/thread_info.h index 74d888c8d631a217c6bf4dfe89d06369b09c016a..78933ac04995b2d22f545bd8d7853743440c5e49 100644 --- a/arch/riscv/include/asm/thread_info.h +++ b/arch/riscv/include/asm/thread_info.h @@ -97,6 +97,7 @@ struct thread_info { #define TIF_SECCOMP 8 /* syscall secure computing */ #define TIF_NOTIFY_SIGNAL 9 /* signal notifications exist */ #define TIF_UPROBE 10 /* uprobe breakpoint or singlestep */ +#define TIF_32BIT 11 /* compat-mode 32bit process */ #define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE) #define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME) diff --git a/arch/riscv/include/asm/unistd.h b/arch/riscv/include/asm/unistd.h index 6c316093a1e59457b0e03d5493cc02a65b50801c..5ddac412b5782505f3d766d474b4c39d8f12f5ce 100644 --- a/arch/riscv/include/asm/unistd.h +++ b/arch/riscv/include/asm/unistd.h @@ -11,6 +11,17 @@ #define __ARCH_WANT_SYS_CLONE #define __ARCH_WANT_MEMFD_SECRET +#ifdef CONFIG_COMPAT +#define __ARCH_WANT_COMPAT_TRUNCATE64 +#define __ARCH_WANT_COMPAT_FTRUNCATE64 +#define __ARCH_WANT_COMPAT_FALLOCATE +#define __ARCH_WANT_COMPAT_PREAD64 +#define __ARCH_WANT_COMPAT_PWRITE64 +#define __ARCH_WANT_COMPAT_SYNC_FILE_RANGE +#define __ARCH_WANT_COMPAT_READAHEAD +#define __ARCH_WANT_COMPAT_FADVISE64_64 +#endif + #include #define NR_syscalls (__NR_syscalls) diff --git a/arch/riscv/include/asm/vdso.h b/arch/riscv/include/asm/vdso.h index bc6f75f3a199fb53852f232cc717a7263f3e48a8..af981426fe0ff7b5c43b63d54670eac0c7f1cf7f 100644 --- a/arch/riscv/include/asm/vdso.h +++ b/arch/riscv/include/asm/vdso.h @@ -21,6 +21,15 @@ #define VDSO_SYMBOL(base, name) \ (void __user *)((unsigned long)(base) + __vdso_##name##_offset) + +#ifdef CONFIG_COMPAT +#include + +#define COMPAT_VDSO_SYMBOL(base, name) \ + (void __user *)((unsigned long)(base) + compat__vdso_##name##_offset) + +#endif /* CONFIG_COMPAT */ + #endif /* !__ASSEMBLY__ */ #endif /* CONFIG_MMU */ diff --git a/arch/riscv/include/asm/vendorid_list.h b/arch/riscv/include/asm/vendorid_list.h index 9d934215b3c8519b67c5df2e9b3fefeb1c0bca8a..cb89af3f070471cab0c4dec0850202ea2e07e90d 100644 --- a/arch/riscv/include/asm/vendorid_list.h +++ b/arch/riscv/include/asm/vendorid_list.h @@ -6,5 +6,6 @@ #define ASM_VENDOR_LIST_H #define SIFIVE_VENDOR_ID 0x489 +#define THEAD_VENDOR_ID 0x5b7 #endif diff --git a/arch/riscv/include/asm/xip_fixup.h b/arch/riscv/include/asm/xip_fixup.h new file mode 100644 index 0000000000000000000000000000000000000000..d4ffc3c37649ffb1808335417be4b510808ae4bf --- /dev/null +++ b/arch/riscv/include/asm/xip_fixup.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * XIP fixup macros, only useful in assembly. + */ +#ifndef _ASM_RISCV_XIP_FIXUP_H +#define _ASM_RISCV_XIP_FIXUP_H + +#include + +#ifdef CONFIG_XIP_KERNEL +.macro XIP_FIXUP_OFFSET reg + REG_L t0, _xip_fixup + add \reg, \reg, t0 +.endm +.macro XIP_FIXUP_FLASH_OFFSET reg + la t1, __data_loc + REG_L t1, _xip_phys_offset + sub \reg, \reg, t1 + add \reg, \reg, t0 +.endm + +_xip_fixup: .dword CONFIG_PHYS_RAM_BASE - CONFIG_XIP_PHYS_ADDR - XIP_OFFSET +_xip_phys_offset: .dword CONFIG_XIP_PHYS_ADDR + XIP_OFFSET +#else +.macro XIP_FIXUP_OFFSET reg +.endm +.macro XIP_FIXUP_FLASH_OFFSET reg +.endm +#endif /* CONFIG_XIP_KERNEL */ + +#endif diff --git a/arch/riscv/include/uapi/asm/unistd.h b/arch/riscv/include/uapi/asm/unistd.h index 8062996c2dfd077eca892b3ce7bc0fa8a91f2281..c9e50eed14aad7e183b4442b48df49a9e1af4b8e 100644 --- a/arch/riscv/include/uapi/asm/unistd.h +++ b/arch/riscv/include/uapi/asm/unistd.h @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -#ifdef __LP64__ +#if defined(__LP64__) && !defined(__SYSCALL_COMPAT) #define __ARCH_WANT_NEW_STAT #define __ARCH_WANT_SET_GET_RLIMIT #endif /* __LP64__ */ diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile index 87adbe47bc158075030cfacaa9bcbbb68be1121b..c71d6591d53988d1565b2688dd7311fbab5c3b99 100644 --- a/arch/riscv/kernel/Makefile +++ b/arch/riscv/kernel/Makefile @@ -14,10 +14,25 @@ ifdef CONFIG_KEXEC AFLAGS_kexec_relocate.o := -mcmodel=medany $(call cc-option,-mno-relax) endif +# cmodel=medany and notrace when patching early +ifdef CONFIG_RISCV_ALTERNATIVE_EARLY +CFLAGS_alternative.o := -mcmodel=medany +CFLAGS_cpufeature.o := -mcmodel=medany +ifdef CONFIG_FTRACE +CFLAGS_REMOVE_alternative.o = $(CC_FLAGS_FTRACE) +CFLAGS_REMOVE_cpufeature.o = $(CC_FLAGS_FTRACE) +endif +ifdef CONFIG_KASAN +KASAN_SANITIZE_alternative.o := n +KASAN_SANITIZE_cpufeature.o := n +endif +endif + extra-y += head.o extra-y += vmlinux.lds obj-y += soc.o +obj-$(CONFIG_RISCV_ALTERNATIVE) += alternative.o obj-y += cpu.o obj-y += cpufeature.o obj-y += entry.o @@ -64,8 +79,12 @@ endif obj-$(CONFIG_HOTPLUG_CPU) += cpu-hotplug.o obj-$(CONFIG_KGDB) += kgdb.o obj-$(CONFIG_KEXEC) += kexec_relocate.o crash_save_regs.o machine_kexec.o +obj-$(CONFIG_KEXEC_FILE) += elf_kexec.o machine_kexec_file.o obj-$(CONFIG_CRASH_DUMP) += crash_dump.o obj-$(CONFIG_JUMP_LABEL) += jump_label.o obj-$(CONFIG_EFI) += efi.o +obj-$(CONFIG_COMPAT) += compat_syscall_table.o +obj-$(CONFIG_COMPAT) += compat_signal.o +obj-$(CONFIG_COMPAT) += compat_vdso/ diff --git a/arch/riscv/kernel/alternative.c b/arch/riscv/kernel/alternative.c new file mode 100644 index 0000000000000000000000000000000000000000..c9d0d3c532235639cfb680ce2ff95a37907957eb --- /dev/null +++ b/arch/riscv/kernel/alternative.c @@ -0,0 +1,118 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * alternative runtime patching + * inspired by the ARM64 and x86 version + * + * Copyright (C) 2021 Sifive. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct cpu_manufacturer_info_t { + unsigned long vendor_id; + unsigned long arch_id; + unsigned long imp_id; + void (*vendor_patch_func)(struct alt_entry *begin, struct alt_entry *end, + unsigned long archid, unsigned long impid, + unsigned int stage); +}; + +static void __init_or_module riscv_fill_cpu_mfr_info(struct cpu_manufacturer_info_t *cpu_mfr_info) +{ +#ifdef CONFIG_RISCV_M_MODE + cpu_mfr_info->vendor_id = csr_read(CSR_MVENDORID); + cpu_mfr_info->arch_id = csr_read(CSR_MARCHID); + cpu_mfr_info->imp_id = csr_read(CSR_MIMPID); +#else + cpu_mfr_info->vendor_id = sbi_get_mvendorid(); + cpu_mfr_info->arch_id = sbi_get_marchid(); + cpu_mfr_info->imp_id = sbi_get_mimpid(); +#endif + + switch (cpu_mfr_info->vendor_id) { +#ifdef CONFIG_ERRATA_SIFIVE + case SIFIVE_VENDOR_ID: + cpu_mfr_info->vendor_patch_func = sifive_errata_patch_func; + break; +#endif +#ifdef CONFIG_ERRATA_THEAD + case THEAD_VENDOR_ID: + cpu_mfr_info->vendor_patch_func = thead_errata_patch_func; + break; +#endif + default: + cpu_mfr_info->vendor_patch_func = NULL; + } +} + +/* + * This is called very early in the boot process (directly after we run + * a feature detect on the boot CPU). No need to worry about other CPUs + * here. + */ +static void __init_or_module _apply_alternatives(struct alt_entry *begin, + struct alt_entry *end, + unsigned int stage) +{ + struct cpu_manufacturer_info_t cpu_mfr_info; + + riscv_fill_cpu_mfr_info(&cpu_mfr_info); + + riscv_cpufeature_patch_func(begin, end, stage); + + if (!cpu_mfr_info.vendor_patch_func) + return; + + cpu_mfr_info.vendor_patch_func(begin, end, + cpu_mfr_info.arch_id, + cpu_mfr_info.imp_id, + stage); +} + +void __init apply_boot_alternatives(void) +{ + /* If called on non-boot cpu things could go wrong */ + WARN_ON(smp_processor_id() != 0); + + _apply_alternatives((struct alt_entry *)__alt_start, + (struct alt_entry *)__alt_end, + RISCV_ALTERNATIVES_BOOT); +} + +/* + * apply_early_boot_alternatives() is called from setup_vm() with MMU-off. + * + * Following requirements should be honoured for it to work correctly: + * 1) It should use PC-relative addressing for accessing kernel symbols. + * To achieve this we always use GCC cmodel=medany. + * 2) The compiler instrumentation for FTRACE will not work for setup_vm() + * so disable compiler instrumentation when FTRACE is enabled. + * + * Currently, the above requirements are honoured by using custom CFLAGS + * for alternative.o in kernel/Makefile. + */ +void __init apply_early_boot_alternatives(void) +{ +#ifdef CONFIG_RISCV_ALTERNATIVE_EARLY + _apply_alternatives((struct alt_entry *)__alt_start, + (struct alt_entry *)__alt_end, + RISCV_ALTERNATIVES_EARLY_BOOT); +#endif +} + +#ifdef CONFIG_MODULES +void apply_module_alternatives(void *start, size_t length) +{ + _apply_alternatives((struct alt_entry *)start, + (struct alt_entry *)(start + length), + RISCV_ALTERNATIVES_MODULE); +} +#endif diff --git a/arch/riscv/kernel/compat_signal.c b/arch/riscv/kernel/compat_signal.c new file mode 100644 index 0000000000000000000000000000000000000000..6ec4e34255a9abdcdb18fb126f83bbf7a80b9aeb --- /dev/null +++ b/arch/riscv/kernel/compat_signal.c @@ -0,0 +1,243 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#define COMPAT_DEBUG_SIG 0 + +struct compat_sigcontext { + struct compat_user_regs_struct sc_regs; + union __riscv_fp_state sc_fpregs; +}; + +struct compat_ucontext { + compat_ulong_t uc_flags; + struct compat_ucontext *uc_link; + compat_stack_t uc_stack; + sigset_t uc_sigmask; + /* There's some padding here to allow sigset_t to be expanded in the + * future. Though this is unlikely, other architectures put uc_sigmask + * at the end of this structure and explicitly state it can be + * expanded, so we didn't want to box ourselves in here. */ + __u8 __unused[1024 / 8 - sizeof(sigset_t)]; + /* We can't put uc_sigmask at the end of this structure because we need + * to be able to expand sigcontext in the future. For example, the + * vector ISA extension will almost certainly add ISA state. We want + * to ensure all user-visible ISA state can be saved and restored via a + * ucontext, so we're putting this at the end in order to allow for + * infinite extensibility. Since we know this will be extended and we + * assume sigset_t won't be extended an extreme amount, we're + * prioritizing this. */ + struct compat_sigcontext uc_mcontext; +}; + +struct compat_rt_sigframe { + struct compat_siginfo info; + struct compat_ucontext uc; +}; + +#ifdef CONFIG_FPU +static long compat_restore_fp_state(struct pt_regs *regs, + union __riscv_fp_state __user *sc_fpregs) +{ + long err; + struct __riscv_d_ext_state __user *state = &sc_fpregs->d; + size_t i; + + err = __copy_from_user(¤t->thread.fstate, state, sizeof(*state)); + if (unlikely(err)) + return err; + + fstate_restore(current, regs); + + /* We support no other extension state at this time. */ + for (i = 0; i < ARRAY_SIZE(sc_fpregs->q.reserved); i++) { + u32 value; + + err = __get_user(value, &sc_fpregs->q.reserved[i]); + if (unlikely(err)) + break; + if (value != 0) + return -EINVAL; + } + + return err; +} + +static long compat_save_fp_state(struct pt_regs *regs, + union __riscv_fp_state __user *sc_fpregs) +{ + long err; + struct __riscv_d_ext_state __user *state = &sc_fpregs->d; + size_t i; + + fstate_save(current, regs); + err = __copy_to_user(state, ¤t->thread.fstate, sizeof(*state)); + if (unlikely(err)) + return err; + + /* We support no other extension state at this time. */ + for (i = 0; i < ARRAY_SIZE(sc_fpregs->q.reserved); i++) { + err = __put_user(0, &sc_fpregs->q.reserved[i]); + if (unlikely(err)) + break; + } + + return err; +} +#else +#define compat_save_fp_state(task, regs) (0) +#define compat_restore_fp_state(task, regs) (0) +#endif + +static long compat_restore_sigcontext(struct pt_regs *regs, + struct compat_sigcontext __user *sc) +{ + long err; + struct compat_user_regs_struct cregs; + + /* sc_regs is structured the same as the start of pt_regs */ + err = __copy_from_user(&cregs, &sc->sc_regs, sizeof(sc->sc_regs)); + + cregs_to_regs(&cregs, regs); + + /* Restore the floating-point state. */ + if (has_fpu()) + err |= compat_restore_fp_state(regs, &sc->sc_fpregs); + return err; +} + +COMPAT_SYSCALL_DEFINE0(rt_sigreturn) +{ + struct pt_regs *regs = current_pt_regs(); + struct compat_rt_sigframe __user *frame; + struct task_struct *task; + sigset_t set; + + /* Always make any pending restarted system calls return -EINTR */ + current->restart_block.fn = do_no_restart_syscall; + + frame = (struct compat_rt_sigframe __user *)regs->sp; + + if (!access_ok(frame, sizeof(*frame))) + goto badframe; + + if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) + goto badframe; + + set_current_blocked(&set); + + if (compat_restore_sigcontext(regs, &frame->uc.uc_mcontext)) + goto badframe; + + if (compat_restore_altstack(&frame->uc.uc_stack)) + goto badframe; + + return regs->a0; + +badframe: + task = current; + if (show_unhandled_signals) { + pr_info_ratelimited( + "%s[%d]: bad frame in %s: frame=%p pc=%p sp=%p\n", + task->comm, task_pid_nr(task), __func__, + frame, (void *)regs->epc, (void *)regs->sp); + } + force_sig(SIGSEGV); + return 0; +} + +static long compat_setup_sigcontext(struct compat_rt_sigframe __user *frame, + struct pt_regs *regs) +{ + struct compat_sigcontext __user *sc = &frame->uc.uc_mcontext; + struct compat_user_regs_struct cregs; + long err; + + regs_to_cregs(&cregs, regs); + + /* sc_regs is structured the same as the start of pt_regs */ + err = __copy_to_user(&sc->sc_regs, &cregs, sizeof(sc->sc_regs)); + /* Save the floating-point state. */ + if (has_fpu()) + err |= compat_save_fp_state(regs, &sc->sc_fpregs); + return err; +} + +static inline void __user *compat_get_sigframe(struct ksignal *ksig, + struct pt_regs *regs, size_t framesize) +{ + unsigned long sp; + /* Default to using normal stack */ + sp = regs->sp; + + /* + * If we are on the alternate signal stack and would overflow it, don't. + * Return an always-bogus address instead so we will die with SIGSEGV. + */ + if (on_sig_stack(sp) && !likely(on_sig_stack(sp - framesize))) + return (void __user __force *)(-1UL); + + /* This is the X/Open sanctioned signal stack switching. */ + sp = sigsp(sp, ksig) - framesize; + + /* Align the stack frame. */ + sp &= ~0xfUL; + + return (void __user *)sp; +} + +int compat_setup_rt_frame(struct ksignal *ksig, sigset_t *set, + struct pt_regs *regs) +{ + struct compat_rt_sigframe __user *frame; + long err = 0; + + frame = compat_get_sigframe(ksig, regs, sizeof(*frame)); + if (!access_ok(frame, sizeof(*frame))) + return -EFAULT; + + err |= copy_siginfo_to_user32(&frame->info, &ksig->info); + + /* Create the ucontext. */ + err |= __put_user(0, &frame->uc.uc_flags); + err |= __put_user(NULL, &frame->uc.uc_link); + err |= __compat_save_altstack(&frame->uc.uc_stack, regs->sp); + err |= compat_setup_sigcontext(frame, regs); + err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); + if (err) + return -EFAULT; + + regs->ra = (unsigned long)COMPAT_VDSO_SYMBOL( + current->mm->context.vdso, rt_sigreturn); + + /* + * Set up registers for signal handler. + * Registers that we don't modify keep the value they had from + * user-space at the time we took the signal. + * We always pass siginfo and mcontext, regardless of SA_SIGINFO, + * since some things rely on this (e.g. glibc's debug/segfault.c). + */ + regs->epc = (unsigned long)ksig->ka.sa.sa_handler; + regs->sp = (unsigned long)frame; + regs->a0 = ksig->sig; /* a0: signal number */ + regs->a1 = (unsigned long)(&frame->info); /* a1: siginfo pointer */ + regs->a2 = (unsigned long)(&frame->uc); /* a2: ucontext pointer */ + +#if COMPAT_DEBUG_SIG + pr_info("SIG deliver (%s:%d): sig=%d pc=%p ra=%p sp=%p\n", + current->comm, task_pid_nr(current), ksig->sig, + (void *)regs->epc, (void *)regs->ra, frame); +#endif + + return 0; +} diff --git a/arch/riscv/kernel/compat_syscall_table.c b/arch/riscv/kernel/compat_syscall_table.c new file mode 100644 index 0000000000000000000000000000000000000000..651f2b009c2812c6af75d0acce89b45ceaefd835 --- /dev/null +++ b/arch/riscv/kernel/compat_syscall_table.c @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#define __SYSCALL_COMPAT + +#include +#include +#include +#include +#include + +#undef __SYSCALL +#define __SYSCALL(nr, call) [nr] = (call), + +asmlinkage long compat_sys_rt_sigreturn(void); + +void * const compat_sys_call_table[__NR_syscalls] = { + [0 ... __NR_syscalls - 1] = sys_ni_syscall, +#include +}; diff --git a/arch/riscv/kernel/compat_vdso/.gitignore b/arch/riscv/kernel/compat_vdso/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..19d83d846c1e687c3df29f1b381e9e5fa4afc5b8 --- /dev/null +++ b/arch/riscv/kernel/compat_vdso/.gitignore @@ -0,0 +1,2 @@ +# SPDX-License-Identifier: GPL-2.0-only +compat_vdso.lds diff --git a/arch/riscv/kernel/compat_vdso/Makefile b/arch/riscv/kernel/compat_vdso/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..260daf3236d3a8dd08ac046410170c59f5d09b29 --- /dev/null +++ b/arch/riscv/kernel/compat_vdso/Makefile @@ -0,0 +1,78 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# Makefile for compat_vdso +# + +# Symbols present in the compat_vdso +compat_vdso-syms = rt_sigreturn +compat_vdso-syms += getcpu +compat_vdso-syms += flush_icache + +COMPAT_CC := $(CC) +COMPAT_LD := $(LD) + +COMPAT_CC_FLAGS := -march=rv32g -mabi=ilp32 +COMPAT_LD_FLAGS := -melf32lriscv + +# Files to link into the compat_vdso +obj-compat_vdso = $(patsubst %, %.o, $(compat_vdso-syms)) note.o + +# Build rules +targets := $(obj-compat_vdso) compat_vdso.so compat_vdso.so.dbg compat_vdso.lds +obj-compat_vdso := $(addprefix $(obj)/, $(obj-compat_vdso)) + +obj-y += compat_vdso.o +CPPFLAGS_compat_vdso.lds += -P -C -U$(ARCH) + +# Disable profiling and instrumentation for VDSO code +GCOV_PROFILE := n +KCOV_INSTRUMENT := n +KASAN_SANITIZE := n +UBSAN_SANITIZE := n + +# Force dependency +$(obj)/compat_vdso.o: $(obj)/compat_vdso.so + +# link rule for the .so file, .lds has to be first +$(obj)/compat_vdso.so.dbg: $(obj)/compat_vdso.lds $(obj-compat_vdso) FORCE + $(call if_changed,compat_vdsold) +LDFLAGS_compat_vdso.so.dbg = -shared -S -soname=linux-compat_vdso.so.1 \ + --build-id=sha1 --hash-style=both --eh-frame-hdr + +$(obj-compat_vdso): %.o: %.S FORCE + $(call if_changed_dep,compat_vdsoas) + +# strip rule for the .so file +$(obj)/%.so: OBJCOPYFLAGS := -S +$(obj)/%.so: $(obj)/%.so.dbg FORCE + $(call if_changed,objcopy) + +# Generate VDSO offsets using helper script +gen-compat_vdsosym := $(srctree)/$(src)/gen_compat_vdso_offsets.sh +quiet_cmd_compat_vdsosym = VDSOSYM $@ + cmd_compat_vdsosym = $(NM) $< | $(gen-compat_vdsosym) | LC_ALL=C sort > $@ + +include/generated/compat_vdso-offsets.h: $(obj)/compat_vdso.so.dbg FORCE + $(call if_changed,compat_vdsosym) + +# actual build commands +# The DSO images are built using a special linker script +# Make sure only to export the intended __compat_vdso_xxx symbol offsets. +quiet_cmd_compat_vdsold = VDSOLD $@ + cmd_compat_vdsold = $(COMPAT_LD) $(ld_flags) $(COMPAT_LD_FLAGS) -T $(filter-out FORCE,$^) -o $@.tmp && \ + $(OBJCOPY) $(patsubst %, -G __compat_vdso_%, $(compat_vdso-syms)) $@.tmp $@ && \ + rm $@.tmp + +# actual build commands +quiet_cmd_compat_vdsoas = VDSOAS $@ + cmd_compat_vdsoas = $(COMPAT_CC) $(a_flags) $(COMPAT_CC_FLAGS) -c -o $@ $< + +# install commands for the unstripped file +quiet_cmd_compat_vdso_install = INSTALL $@ + cmd_compat_vdso_install = cp $(obj)/$@.dbg $(MODLIB)/compat_vdso/$@ + +compat_vdso.so: $(obj)/compat_vdso.so.dbg + @mkdir -p $(MODLIB)/compat_vdso + $(call cmd,compat_vdso_install) + +compat_vdso_install: compat_vdso.so diff --git a/arch/riscv/kernel/compat_vdso/compat_vdso.S b/arch/riscv/kernel/compat_vdso/compat_vdso.S new file mode 100644 index 0000000000000000000000000000000000000000..ffd66237e091ee77958d02cf25a32ffc2eaaa8a7 --- /dev/null +++ b/arch/riscv/kernel/compat_vdso/compat_vdso.S @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#define vdso_start compat_vdso_start +#define vdso_end compat_vdso_end + +#define __VDSO_PATH "arch/riscv/kernel/compat_vdso/compat_vdso.so" + +#include "../vdso/vdso.S" diff --git a/arch/riscv/kernel/compat_vdso/compat_vdso.lds.S b/arch/riscv/kernel/compat_vdso/compat_vdso.lds.S new file mode 100644 index 0000000000000000000000000000000000000000..c7c9355d311e31467542e7c692f71340df6bc002 --- /dev/null +++ b/arch/riscv/kernel/compat_vdso/compat_vdso.lds.S @@ -0,0 +1,3 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include "../vdso/vdso.lds.S" diff --git a/arch/riscv/kernel/compat_vdso/flush_icache.S b/arch/riscv/kernel/compat_vdso/flush_icache.S new file mode 100644 index 0000000000000000000000000000000000000000..523dd8b96045e06266a8e2b37b73f0d3528a45ec --- /dev/null +++ b/arch/riscv/kernel/compat_vdso/flush_icache.S @@ -0,0 +1,3 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include "../vdso/flush_icache.S" diff --git a/arch/riscv/kernel/compat_vdso/gen_compat_vdso_offsets.sh b/arch/riscv/kernel/compat_vdso/gen_compat_vdso_offsets.sh new file mode 100755 index 0000000000000000000000000000000000000000..8ac070c783b378ab8c25bb89ef7ca7fbf2af9dfa --- /dev/null +++ b/arch/riscv/kernel/compat_vdso/gen_compat_vdso_offsets.sh @@ -0,0 +1,5 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 + +LC_ALL=C +sed -n -e 's/^[0]\+\(0[0-9a-fA-F]*\) . \(__vdso_[a-zA-Z0-9_]*\)$/\#define compat\2_offset\t0x\1/p' diff --git a/arch/riscv/kernel/compat_vdso/getcpu.S b/arch/riscv/kernel/compat_vdso/getcpu.S new file mode 100644 index 0000000000000000000000000000000000000000..10f463efe27108842ce586d9d52f4c6446656ea0 --- /dev/null +++ b/arch/riscv/kernel/compat_vdso/getcpu.S @@ -0,0 +1,3 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include "../vdso/getcpu.S" diff --git a/arch/riscv/kernel/compat_vdso/note.S b/arch/riscv/kernel/compat_vdso/note.S new file mode 100644 index 0000000000000000000000000000000000000000..b10312907542335ff2e6905d0d3f9a4ae467cd0d --- /dev/null +++ b/arch/riscv/kernel/compat_vdso/note.S @@ -0,0 +1,3 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include "../vdso/note.S" diff --git a/arch/riscv/kernel/compat_vdso/rt_sigreturn.S b/arch/riscv/kernel/compat_vdso/rt_sigreturn.S new file mode 100644 index 0000000000000000000000000000000000000000..884aada4facc5d660e6302b0d5adc44101e78d27 --- /dev/null +++ b/arch/riscv/kernel/compat_vdso/rt_sigreturn.S @@ -0,0 +1,3 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include "../vdso/rt_sigreturn.S" diff --git a/arch/riscv/kernel/cpu.c b/arch/riscv/kernel/cpu.c index ccb617791e561a40f8a05da88bdf61d126a62d20..fba9e9f46a8c7aa4cc54c681341caaab368f9f1a 100644 --- a/arch/riscv/kernel/cpu.c +++ b/arch/riscv/kernel/cpu.c @@ -88,6 +88,7 @@ int riscv_of_parent_hartid(struct device_node *node) */ static struct riscv_isa_ext_data isa_ext_arr[] = { __RISCV_ISA_EXT_DATA(sscofpmf, RISCV_ISA_EXT_SSCOFPMF), + __RISCV_ISA_EXT_DATA(svpbmt, RISCV_ISA_EXT_SVPBMT), __RISCV_ISA_EXT_DATA("", RISCV_ISA_EXT_MAX), }; @@ -138,6 +139,7 @@ static void print_mmu(struct seq_file *f) { char sv_type[16]; +#ifdef CONFIG_MMU #if defined(CONFIG_32BIT) strncpy(sv_type, "sv32", 5); #elif defined(CONFIG_64BIT) @@ -148,6 +150,9 @@ static void print_mmu(struct seq_file *f) else strncpy(sv_type, "sv39", 5); #endif +#else + strncpy(sv_type, "none", 5); +#endif /* CONFIG_MMU */ seq_printf(f, "mmu\t\t: %s\n", sv_type); } diff --git a/arch/riscv/kernel/cpufeature.c b/arch/riscv/kernel/cpufeature.c index 1b2d42d7f589775a4c040acf2917cb28c459952f..dea3ea19deeefec89c74af2255fd19aaf32f4717 100644 --- a/arch/riscv/kernel/cpufeature.c +++ b/arch/riscv/kernel/cpufeature.c @@ -8,9 +8,15 @@ #include #include +#include +#include #include -#include +#include +#include #include +#include +#include +#include #include #include @@ -192,6 +198,7 @@ void __init riscv_fill_hwcap(void) set_bit(*ext - 'a', this_isa); } else { SET_ISA_EXT_MAP("sscofpmf", RISCV_ISA_EXT_SSCOFPMF); + SET_ISA_EXT_MAP("svpbmt", RISCV_ISA_EXT_SVPBMT); } #undef SET_ISA_EXT_MAP } @@ -237,3 +244,74 @@ void __init riscv_fill_hwcap(void) static_branch_enable(&cpu_hwcap_fpu); #endif } + +#ifdef CONFIG_RISCV_ALTERNATIVE +struct cpufeature_info { + char name[ERRATA_STRING_LENGTH_MAX]; + bool (*check_func)(unsigned int stage); +}; + +static bool __init_or_module cpufeature_svpbmt_check_func(unsigned int stage) +{ +#ifdef CONFIG_RISCV_ISA_SVPBMT + switch (stage) { + case RISCV_ALTERNATIVES_EARLY_BOOT: + return false; + default: + return riscv_isa_extension_available(NULL, SVPBMT); + } +#endif + + return false; +} + +static const struct cpufeature_info __initdata_or_module +cpufeature_list[CPUFEATURE_NUMBER] = { + { + .name = "svpbmt", + .check_func = cpufeature_svpbmt_check_func + }, +}; + +static u32 __init_or_module cpufeature_probe(unsigned int stage) +{ + const struct cpufeature_info *info; + u32 cpu_req_feature = 0; + int idx; + + for (idx = 0; idx < CPUFEATURE_NUMBER; idx++) { + info = &cpufeature_list[idx]; + + if (info->check_func(stage)) + cpu_req_feature |= (1U << idx); + } + + return cpu_req_feature; +} + +void __init_or_module riscv_cpufeature_patch_func(struct alt_entry *begin, + struct alt_entry *end, + unsigned int stage) +{ + u32 cpu_req_feature = cpufeature_probe(stage); + u32 cpu_apply_feature = 0; + struct alt_entry *alt; + u32 tmp; + + for (alt = begin; alt < end; alt++) { + if (alt->vendor_id != 0) + continue; + if (alt->errata_id >= CPUFEATURE_NUMBER) { + WARN(1, "This feature id:%d is not in kernel cpufeature list", + alt->errata_id); + continue; + } + + tmp = (1U << alt->errata_id); + if (cpu_req_feature & tmp) { + patch_text_nosync(alt->old_ptr, alt->alt_ptr, alt->alt_len); + cpu_apply_feature |= tmp; + } + } +} +#endif diff --git a/arch/riscv/kernel/elf_kexec.c b/arch/riscv/kernel/elf_kexec.c new file mode 100644 index 0000000000000000000000000000000000000000..9cb85095fd459fb5e9cea5d1d6e62e8c4b076128 --- /dev/null +++ b/arch/riscv/kernel/elf_kexec.c @@ -0,0 +1,448 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Load ELF vmlinux file for the kexec_file_load syscall. + * + * Copyright (C) 2021 Huawei Technologies Co, Ltd. + * + * Author: Liao Chang (liaochang1@huawei.com) + * + * Based on kexec-tools' kexec-elf-riscv.c, heavily modified + * for kernel. + */ + +#define pr_fmt(fmt) "kexec_image: " fmt + +#include +#include +#include +#include +#include +#include +#include +#include + +static int riscv_kexec_elf_load(struct kimage *image, struct elfhdr *ehdr, + struct kexec_elf_info *elf_info, unsigned long old_pbase, + unsigned long new_pbase) +{ + int i; + int ret = 0; + size_t size; + struct kexec_buf kbuf; + const struct elf_phdr *phdr; + + kbuf.image = image; + + for (i = 0; i < ehdr->e_phnum; i++) { + phdr = &elf_info->proghdrs[i]; + if (phdr->p_type != PT_LOAD) + continue; + + size = phdr->p_filesz; + if (size > phdr->p_memsz) + size = phdr->p_memsz; + + kbuf.buffer = (void *) elf_info->buffer + phdr->p_offset; + kbuf.bufsz = size; + kbuf.buf_align = phdr->p_align; + kbuf.mem = phdr->p_paddr - old_pbase + new_pbase; + kbuf.memsz = phdr->p_memsz; + kbuf.top_down = false; + ret = kexec_add_buffer(&kbuf); + if (ret) + break; + } + + return ret; +} + +/* + * Go through the available phsyical memory regions and find one that hold + * an image of the specified size. + */ +static int elf_find_pbase(struct kimage *image, unsigned long kernel_len, + struct elfhdr *ehdr, struct kexec_elf_info *elf_info, + unsigned long *old_pbase, unsigned long *new_pbase) +{ + int i; + int ret; + struct kexec_buf kbuf; + const struct elf_phdr *phdr; + unsigned long lowest_paddr = ULONG_MAX; + unsigned long lowest_vaddr = ULONG_MAX; + + for (i = 0; i < ehdr->e_phnum; i++) { + phdr = &elf_info->proghdrs[i]; + if (phdr->p_type != PT_LOAD) + continue; + + if (lowest_paddr > phdr->p_paddr) + lowest_paddr = phdr->p_paddr; + + if (lowest_vaddr > phdr->p_vaddr) + lowest_vaddr = phdr->p_vaddr; + } + + kbuf.image = image; + kbuf.buf_min = lowest_paddr; + kbuf.buf_max = ULONG_MAX; + kbuf.buf_align = PAGE_SIZE; + kbuf.mem = KEXEC_BUF_MEM_UNKNOWN; + kbuf.memsz = ALIGN(kernel_len, PAGE_SIZE); + kbuf.top_down = false; + ret = arch_kexec_locate_mem_hole(&kbuf); + if (!ret) { + *old_pbase = lowest_paddr; + *new_pbase = kbuf.mem; + image->start = ehdr->e_entry - lowest_vaddr + kbuf.mem; + } + return ret; +} + +static int get_nr_ram_ranges_callback(struct resource *res, void *arg) +{ + unsigned int *nr_ranges = arg; + + (*nr_ranges)++; + return 0; +} + +static int prepare_elf64_ram_headers_callback(struct resource *res, void *arg) +{ + struct crash_mem *cmem = arg; + + cmem->ranges[cmem->nr_ranges].start = res->start; + cmem->ranges[cmem->nr_ranges].end = res->end; + cmem->nr_ranges++; + + return 0; +} + +static int prepare_elf_headers(void **addr, unsigned long *sz) +{ + struct crash_mem *cmem; + unsigned int nr_ranges; + int ret; + + nr_ranges = 1; /* For exclusion of crashkernel region */ + walk_system_ram_res(0, -1, &nr_ranges, get_nr_ram_ranges_callback); + + cmem = kmalloc(struct_size(cmem, ranges, nr_ranges), GFP_KERNEL); + if (!cmem) + return -ENOMEM; + + cmem->max_nr_ranges = nr_ranges; + cmem->nr_ranges = 0; + ret = walk_system_ram_res(0, -1, cmem, prepare_elf64_ram_headers_callback); + if (ret) + goto out; + + /* Exclude crashkernel region */ + ret = crash_exclude_mem_range(cmem, crashk_res.start, crashk_res.end); + if (!ret) + ret = crash_prepare_elf64_headers(cmem, true, addr, sz); + +out: + kfree(cmem); + return ret; +} + +static char *setup_kdump_cmdline(struct kimage *image, char *cmdline, + unsigned long cmdline_len) +{ + int elfcorehdr_strlen; + char *cmdline_ptr; + + cmdline_ptr = kzalloc(COMMAND_LINE_SIZE, GFP_KERNEL); + if (!cmdline_ptr) + return NULL; + + elfcorehdr_strlen = sprintf(cmdline_ptr, "elfcorehdr=0x%lx ", + image->elf_load_addr); + + if (elfcorehdr_strlen + cmdline_len > COMMAND_LINE_SIZE) { + pr_err("Appending elfcorehdr= exceeds cmdline size\n"); + kfree(cmdline_ptr); + return NULL; + } + + memcpy(cmdline_ptr + elfcorehdr_strlen, cmdline, cmdline_len); + /* Ensure it's nul terminated */ + cmdline_ptr[COMMAND_LINE_SIZE - 1] = '\0'; + return cmdline_ptr; +} + +static void *elf_kexec_load(struct kimage *image, char *kernel_buf, + unsigned long kernel_len, char *initrd, + unsigned long initrd_len, char *cmdline, + unsigned long cmdline_len) +{ + int ret; + unsigned long old_kernel_pbase = ULONG_MAX; + unsigned long new_kernel_pbase = 0UL; + unsigned long initrd_pbase = 0UL; + unsigned long headers_sz; + unsigned long kernel_start; + void *fdt, *headers; + struct elfhdr ehdr; + struct kexec_buf kbuf; + struct kexec_elf_info elf_info; + char *modified_cmdline = NULL; + + ret = kexec_build_elf_info(kernel_buf, kernel_len, &ehdr, &elf_info); + if (ret) + return ERR_PTR(ret); + + ret = elf_find_pbase(image, kernel_len, &ehdr, &elf_info, + &old_kernel_pbase, &new_kernel_pbase); + if (ret) + goto out; + kernel_start = image->start; + pr_notice("The entry point of kernel at 0x%lx\n", image->start); + + /* Add the kernel binary to the image */ + ret = riscv_kexec_elf_load(image, &ehdr, &elf_info, + old_kernel_pbase, new_kernel_pbase); + if (ret) + goto out; + + kbuf.image = image; + kbuf.buf_min = new_kernel_pbase + kernel_len; + kbuf.buf_max = ULONG_MAX; + + /* Add elfcorehdr */ + if (image->type == KEXEC_TYPE_CRASH) { + ret = prepare_elf_headers(&headers, &headers_sz); + if (ret) { + pr_err("Preparing elf core header failed\n"); + goto out; + } + + kbuf.buffer = headers; + kbuf.bufsz = headers_sz; + kbuf.mem = KEXEC_BUF_MEM_UNKNOWN; + kbuf.memsz = headers_sz; + kbuf.buf_align = ELF_CORE_HEADER_ALIGN; + kbuf.top_down = true; + + ret = kexec_add_buffer(&kbuf); + if (ret) { + vfree(headers); + goto out; + } + image->elf_headers = headers; + image->elf_load_addr = kbuf.mem; + image->elf_headers_sz = headers_sz; + + pr_debug("Loaded elf core header at 0x%lx bufsz=0x%lx memsz=0x%lx\n", + image->elf_load_addr, kbuf.bufsz, kbuf.memsz); + + /* Setup cmdline for kdump kernel case */ + modified_cmdline = setup_kdump_cmdline(image, cmdline, + cmdline_len); + if (!modified_cmdline) { + pr_err("Setting up cmdline for kdump kernel failed\n"); + ret = -EINVAL; + goto out; + } + cmdline = modified_cmdline; + } + +#ifdef CONFIG_ARCH_HAS_KEXEC_PURGATORY + /* Add purgatory to the image */ + kbuf.top_down = true; + kbuf.mem = KEXEC_BUF_MEM_UNKNOWN; + ret = kexec_load_purgatory(image, &kbuf); + if (ret) { + pr_err("Error loading purgatory ret=%d\n", ret); + goto out; + } + ret = kexec_purgatory_get_set_symbol(image, "riscv_kernel_entry", + &kernel_start, + sizeof(kernel_start), 0); + if (ret) + pr_err("Error update purgatory ret=%d\n", ret); +#endif /* CONFIG_ARCH_HAS_KEXEC_PURGATORY */ + + /* Add the initrd to the image */ + if (initrd != NULL) { + kbuf.buffer = initrd; + kbuf.bufsz = kbuf.memsz = initrd_len; + kbuf.buf_align = PAGE_SIZE; + kbuf.top_down = false; + kbuf.mem = KEXEC_BUF_MEM_UNKNOWN; + ret = kexec_add_buffer(&kbuf); + if (ret) + goto out; + initrd_pbase = kbuf.mem; + pr_notice("Loaded initrd at 0x%lx\n", initrd_pbase); + } + + /* Add the DTB to the image */ + fdt = of_kexec_alloc_and_setup_fdt(image, initrd_pbase, + initrd_len, cmdline, 0); + if (!fdt) { + pr_err("Error setting up the new device tree.\n"); + ret = -EINVAL; + goto out; + } + + fdt_pack(fdt); + kbuf.buffer = fdt; + kbuf.bufsz = kbuf.memsz = fdt_totalsize(fdt); + kbuf.buf_align = PAGE_SIZE; + kbuf.mem = KEXEC_BUF_MEM_UNKNOWN; + kbuf.top_down = true; + ret = kexec_add_buffer(&kbuf); + if (ret) { + pr_err("Error add DTB kbuf ret=%d\n", ret); + goto out_free_fdt; + } + pr_notice("Loaded device tree at 0x%lx\n", kbuf.mem); + goto out; + +out_free_fdt: + kvfree(fdt); +out: + kfree(modified_cmdline); + kexec_free_elf_info(&elf_info); + return ret ? ERR_PTR(ret) : NULL; +} + +#define RV_X(x, s, n) (((x) >> (s)) & ((1 << (n)) - 1)) +#define RISCV_IMM_BITS 12 +#define RISCV_IMM_REACH (1LL << RISCV_IMM_BITS) +#define RISCV_CONST_HIGH_PART(x) \ + (((x) + (RISCV_IMM_REACH >> 1)) & ~(RISCV_IMM_REACH - 1)) +#define RISCV_CONST_LOW_PART(x) ((x) - RISCV_CONST_HIGH_PART(x)) + +#define ENCODE_ITYPE_IMM(x) \ + (RV_X(x, 0, 12) << 20) +#define ENCODE_BTYPE_IMM(x) \ + ((RV_X(x, 1, 4) << 8) | (RV_X(x, 5, 6) << 25) | \ + (RV_X(x, 11, 1) << 7) | (RV_X(x, 12, 1) << 31)) +#define ENCODE_UTYPE_IMM(x) \ + (RV_X(x, 12, 20) << 12) +#define ENCODE_JTYPE_IMM(x) \ + ((RV_X(x, 1, 10) << 21) | (RV_X(x, 11, 1) << 20) | \ + (RV_X(x, 12, 8) << 12) | (RV_X(x, 20, 1) << 31)) +#define ENCODE_CBTYPE_IMM(x) \ + ((RV_X(x, 1, 2) << 3) | (RV_X(x, 3, 2) << 10) | (RV_X(x, 5, 1) << 2) | \ + (RV_X(x, 6, 2) << 5) | (RV_X(x, 8, 1) << 12)) +#define ENCODE_CJTYPE_IMM(x) \ + ((RV_X(x, 1, 3) << 3) | (RV_X(x, 4, 1) << 11) | (RV_X(x, 5, 1) << 2) | \ + (RV_X(x, 6, 1) << 7) | (RV_X(x, 7, 1) << 6) | (RV_X(x, 8, 2) << 9) | \ + (RV_X(x, 10, 1) << 8) | (RV_X(x, 11, 1) << 12)) +#define ENCODE_UJTYPE_IMM(x) \ + (ENCODE_UTYPE_IMM(RISCV_CONST_HIGH_PART(x)) | \ + (ENCODE_ITYPE_IMM(RISCV_CONST_LOW_PART(x)) << 32)) +#define ENCODE_UITYPE_IMM(x) \ + (ENCODE_UTYPE_IMM(x) | (ENCODE_ITYPE_IMM(x) << 32)) + +#define CLEAN_IMM(type, x) \ + ((~ENCODE_##type##_IMM((uint64_t)(-1))) & (x)) + +int arch_kexec_apply_relocations_add(struct purgatory_info *pi, + Elf_Shdr *section, + const Elf_Shdr *relsec, + const Elf_Shdr *symtab) +{ + const char *strtab, *name, *shstrtab; + const Elf_Shdr *sechdrs; + Elf_Rela *relas; + int i, r_type; + + /* String & section header string table */ + sechdrs = (void *)pi->ehdr + pi->ehdr->e_shoff; + strtab = (char *)pi->ehdr + sechdrs[symtab->sh_link].sh_offset; + shstrtab = (char *)pi->ehdr + sechdrs[pi->ehdr->e_shstrndx].sh_offset; + + relas = (void *)pi->ehdr + relsec->sh_offset; + + for (i = 0; i < relsec->sh_size / sizeof(*relas); i++) { + const Elf_Sym *sym; /* symbol to relocate */ + unsigned long addr; /* final location after relocation */ + unsigned long val; /* relocated symbol value */ + unsigned long sec_base; /* relocated symbol value */ + void *loc; /* tmp location to modify */ + + sym = (void *)pi->ehdr + symtab->sh_offset; + sym += ELF64_R_SYM(relas[i].r_info); + + if (sym->st_name) + name = strtab + sym->st_name; + else + name = shstrtab + sechdrs[sym->st_shndx].sh_name; + + loc = pi->purgatory_buf; + loc += section->sh_offset; + loc += relas[i].r_offset; + + if (sym->st_shndx == SHN_ABS) + sec_base = 0; + else if (sym->st_shndx >= pi->ehdr->e_shnum) { + pr_err("Invalid section %d for symbol %s\n", + sym->st_shndx, name); + return -ENOEXEC; + } else + sec_base = pi->sechdrs[sym->st_shndx].sh_addr; + + val = sym->st_value; + val += sec_base; + val += relas[i].r_addend; + + addr = section->sh_addr + relas[i].r_offset; + + r_type = ELF64_R_TYPE(relas[i].r_info); + + switch (r_type) { + case R_RISCV_BRANCH: + *(u32 *)loc = CLEAN_IMM(BTYPE, *(u32 *)loc) | + ENCODE_BTYPE_IMM(val - addr); + break; + case R_RISCV_JAL: + *(u32 *)loc = CLEAN_IMM(JTYPE, *(u32 *)loc) | + ENCODE_JTYPE_IMM(val - addr); + break; + /* + * With no R_RISCV_PCREL_LO12_S, R_RISCV_PCREL_LO12_I + * sym is expected to be next to R_RISCV_PCREL_HI20 + * in purgatory relsec. Handle it like R_RISCV_CALL + * sym, instead of searching the whole relsec. + */ + case R_RISCV_PCREL_HI20: + case R_RISCV_CALL: + *(u64 *)loc = CLEAN_IMM(UITYPE, *(u64 *)loc) | + ENCODE_UJTYPE_IMM(val - addr); + break; + case R_RISCV_RVC_BRANCH: + *(u32 *)loc = CLEAN_IMM(CBTYPE, *(u32 *)loc) | + ENCODE_CBTYPE_IMM(val - addr); + break; + case R_RISCV_RVC_JUMP: + *(u32 *)loc = CLEAN_IMM(CJTYPE, *(u32 *)loc) | + ENCODE_CJTYPE_IMM(val - addr); + break; + case R_RISCV_ADD32: + *(u32 *)loc += val; + break; + case R_RISCV_SUB32: + *(u32 *)loc -= val; + break; + /* It has been applied by R_RISCV_PCREL_HI20 sym */ + case R_RISCV_PCREL_LO12_I: + case R_RISCV_ALIGN: + case R_RISCV_RELAX: + break; + default: + pr_err("Unknown rela relocation: %d\n", r_type); + return -ENOEXEC; + } + } + return 0; +} + +const struct kexec_file_ops elf_kexec_ops = { + .probe = kexec_elf_probe, + .load = elf_kexec_load, +}; diff --git a/arch/riscv/kernel/entry.S b/arch/riscv/kernel/entry.S index c8b9ce274b9ab8783fa3c6b8447b62ef4d3cf2af..2e5b88ca11ce1728bc4b49f304901ab4d05157e4 100644 --- a/arch/riscv/kernel/entry.S +++ b/arch/riscv/kernel/entry.S @@ -207,13 +207,27 @@ check_syscall_nr: * Syscall number held in a7. * If syscall number is above allowed value, redirect to ni_syscall. */ - bgeu a7, t0, 1f + bgeu a7, t0, 3f +#ifdef CONFIG_COMPAT + REG_L s0, PT_STATUS(sp) + srli s0, s0, SR_UXL_SHIFT + andi s0, s0, (SR_UXL >> SR_UXL_SHIFT) + li t0, (SR_UXL_32 >> SR_UXL_SHIFT) + sub t0, s0, t0 + bnez t0, 1f + + /* Call compat_syscall */ + la s0, compat_sys_call_table + j 2f +1: +#endif /* Call syscall */ la s0, sys_call_table +2: slli t0, a7, RISCV_LGPTR add s0, s0, t0 REG_L s0, 0(s0) -1: +3: jalr s0 ret_from_syscall: diff --git a/arch/riscv/kernel/ftrace.c b/arch/riscv/kernel/ftrace.c index 4716f4cdc03804ed944d707910594ff565b50de9..2086f65857737300db14d24b17b0439e9f182069 100644 --- a/arch/riscv/kernel/ftrace.c +++ b/arch/riscv/kernel/ftrace.c @@ -12,16 +12,14 @@ #include #ifdef CONFIG_DYNAMIC_FTRACE -int ftrace_arch_code_modify_prepare(void) __acquires(&text_mutex) +void ftrace_arch_code_modify_prepare(void) __acquires(&text_mutex) { mutex_lock(&text_mutex); - return 0; } -int ftrace_arch_code_modify_post_process(void) __releases(&text_mutex) +void ftrace_arch_code_modify_post_process(void) __releases(&text_mutex) { mutex_unlock(&text_mutex); - return 0; } static int ftrace_check_current_call(unsigned long hook_pos, diff --git a/arch/riscv/kernel/head.S b/arch/riscv/kernel/head.S index 893b8bb693912e1c92cb2bd908a26a98a14db40b..273eb0fa1f508bf072860fd6131ee6efbce21890 100644 --- a/arch/riscv/kernel/head.S +++ b/arch/riscv/kernel/head.S @@ -14,6 +14,7 @@ #include #include #include +#include #include "efi-header.S" __HEAD diff --git a/arch/riscv/kernel/machine_kexec.c b/arch/riscv/kernel/machine_kexec.c index cbef0fc73afa8f45c2c1027d9ff6e9f3c3acb3fb..df8e24559035c455d0aa49e615c42b9dfdd109c1 100644 --- a/arch/riscv/kernel/machine_kexec.c +++ b/arch/riscv/kernel/machine_kexec.c @@ -65,7 +65,9 @@ machine_kexec_prepare(struct kimage *image) if (image->segment[i].memsz <= sizeof(fdt)) continue; - if (copy_from_user(&fdt, image->segment[i].buf, sizeof(fdt))) + if (image->file_mode) + memcpy(&fdt, image->segment[i].buf, sizeof(fdt)); + else if (copy_from_user(&fdt, image->segment[i].buf, sizeof(fdt))) continue; if (fdt_check_header(&fdt)) diff --git a/arch/riscv/kernel/machine_kexec_file.c b/arch/riscv/kernel/machine_kexec_file.c new file mode 100644 index 0000000000000000000000000000000000000000..b0bf8c1722c0ccf2e5fd0f95d7345ef7f15e98ad --- /dev/null +++ b/arch/riscv/kernel/machine_kexec_file.c @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * kexec_file for riscv, use vmlinux as the dump-capture kernel image. + * + * Copyright (C) 2021 Huawei Technologies Co, Ltd. + * + * Author: Liao Chang (liaochang1@huawei.com) + */ +#include + +const struct kexec_file_ops * const kexec_file_loaders[] = { + &elf_kexec_ops, + NULL +}; diff --git a/arch/riscv/kernel/module.c b/arch/riscv/kernel/module.c index c29cef90d1ddf64a8b8692961a478acb7150dda0..91fe16bfaa07c0b47fa61dba68adee618db2bfe6 100644 --- a/arch/riscv/kernel/module.c +++ b/arch/riscv/kernel/module.c @@ -11,6 +11,7 @@ #include #include #include +#include #include /* @@ -427,3 +428,31 @@ void *module_alloc(unsigned long size) __builtin_return_address(0)); } #endif + +static const Elf_Shdr *find_section(const Elf_Ehdr *hdr, + const Elf_Shdr *sechdrs, + const char *name) +{ + const Elf_Shdr *s, *se; + const char *secstrs = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; + + for (s = sechdrs, se = sechdrs + hdr->e_shnum; s < se; s++) { + if (strcmp(name, secstrs + s->sh_name) == 0) + return s; + } + + return NULL; +} + +int module_finalize(const Elf_Ehdr *hdr, + const Elf_Shdr *sechdrs, + struct module *me) +{ + const Elf_Shdr *s; + + s = find_section(hdr, sechdrs, ".alternative"); + if (s) + apply_module_alternatives((void *)s->sh_addr, s->sh_size); + + return 0; +} diff --git a/arch/riscv/kernel/process.c b/arch/riscv/kernel/process.c index 504b496787aa4d384e5bae04dc35bf5f104123d7..1c7be865ab317676c497c0fcda5085f921fab1d8 100644 --- a/arch/riscv/kernel/process.c +++ b/arch/riscv/kernel/process.c @@ -84,6 +84,34 @@ void show_regs(struct pt_regs *regs) dump_backtrace(regs, NULL, KERN_DEFAULT); } +#ifdef CONFIG_COMPAT +static bool compat_mode_supported __read_mostly; + +bool compat_elf_check_arch(Elf32_Ehdr *hdr) +{ + return compat_mode_supported && + hdr->e_machine == EM_RISCV && + hdr->e_ident[EI_CLASS] == ELFCLASS32; +} + +static int __init compat_mode_detect(void) +{ + unsigned long tmp = csr_read(CSR_STATUS); + + csr_write(CSR_STATUS, (tmp & ~SR_UXL) | SR_UXL_32); + compat_mode_supported = + (csr_read(CSR_STATUS) & SR_UXL) == SR_UXL_32; + + csr_write(CSR_STATUS, tmp); + + pr_info("riscv: ELF compat mode %s", + compat_mode_supported ? "supported" : "failed"); + + return 0; +} +early_initcall(compat_mode_detect); +#endif + void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long sp) { @@ -98,6 +126,15 @@ void start_thread(struct pt_regs *regs, unsigned long pc, } regs->epc = pc; regs->sp = sp; + +#ifdef CONFIG_64BIT + regs->status &= ~SR_UXL; + + if (is_compat_task()) + regs->status |= SR_UXL_32; + else + regs->status |= SR_UXL_64; +#endif } void flush_thread(void) diff --git a/arch/riscv/kernel/ptrace.c b/arch/riscv/kernel/ptrace.c index 793c7da0554b9974a50dbbc8545807c837aac3e4..2ae8280ae4759d9be510bf182aec523ce301f400 100644 --- a/arch/riscv/kernel/ptrace.c +++ b/arch/riscv/kernel/ptrace.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -110,11 +111,6 @@ static const struct user_regset_view riscv_user_native_view = { .n = ARRAY_SIZE(riscv_user_regset), }; -const struct user_regset_view *task_user_regset_view(struct task_struct *task) -{ - return &riscv_user_native_view; -} - struct pt_regs_offset { const char *name; int offset; @@ -272,3 +268,84 @@ __visible void do_syscall_trace_exit(struct pt_regs *regs) trace_sys_exit(regs, regs_return_value(regs)); #endif } + +#ifdef CONFIG_COMPAT +static int compat_riscv_gpr_get(struct task_struct *target, + const struct user_regset *regset, + struct membuf to) +{ + struct compat_user_regs_struct cregs; + + regs_to_cregs(&cregs, task_pt_regs(target)); + + return membuf_write(&to, &cregs, + sizeof(struct compat_user_regs_struct)); +} + +static int compat_riscv_gpr_set(struct task_struct *target, + const struct user_regset *regset, + unsigned int pos, unsigned int count, + const void *kbuf, const void __user *ubuf) +{ + int ret; + struct compat_user_regs_struct cregs; + + ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &cregs, 0, -1); + + cregs_to_regs(&cregs, task_pt_regs(target)); + + return ret; +} + +static const struct user_regset compat_riscv_user_regset[] = { + [REGSET_X] = { + .core_note_type = NT_PRSTATUS, + .n = ELF_NGREG, + .size = sizeof(compat_elf_greg_t), + .align = sizeof(compat_elf_greg_t), + .regset_get = compat_riscv_gpr_get, + .set = compat_riscv_gpr_set, + }, +#ifdef CONFIG_FPU + [REGSET_F] = { + .core_note_type = NT_PRFPREG, + .n = ELF_NFPREG, + .size = sizeof(elf_fpreg_t), + .align = sizeof(elf_fpreg_t), + .regset_get = riscv_fpr_get, + .set = riscv_fpr_set, + }, +#endif +}; + +static const struct user_regset_view compat_riscv_user_native_view = { + .name = "riscv", + .e_machine = EM_RISCV, + .regsets = compat_riscv_user_regset, + .n = ARRAY_SIZE(compat_riscv_user_regset), +}; + +long compat_arch_ptrace(struct task_struct *child, compat_long_t request, + compat_ulong_t caddr, compat_ulong_t cdata) +{ + long ret = -EIO; + + switch (request) { + default: + ret = compat_ptrace_request(child, request, caddr, cdata); + break; + } + + return ret; +} +#endif /* CONFIG_COMPAT */ + +const struct user_regset_view *task_user_regset_view(struct task_struct *task) +{ +#ifdef CONFIG_COMPAT + if (test_tsk_thread_flag(task, TIF_32BIT)) + return &compat_riscv_user_native_view; + else +#endif + return &riscv_user_native_view; +} diff --git a/arch/riscv/kernel/reset.c b/arch/riscv/kernel/reset.c index 9c842c41684acd79adc2b9bceb5bb08e7abe6d3e..9122885722265c4b9cc79523ec69815a3d58d4eb 100644 --- a/arch/riscv/kernel/reset.c +++ b/arch/riscv/kernel/reset.c @@ -23,16 +23,12 @@ void machine_restart(char *cmd) void machine_halt(void) { - if (pm_power_off != NULL) - pm_power_off(); - else - default_power_off(); + do_kernel_power_off(); + default_power_off(); } void machine_power_off(void) { - if (pm_power_off != NULL) - pm_power_off(); - else - default_power_off(); + do_kernel_power_off(); + default_power_off(); } diff --git a/arch/riscv/kernel/setup.c b/arch/riscv/kernel/setup.c index 834eb652a7b9d6046c0c054b9c58815e03e464c6..e0373a3056e8da1cede33f02d115c7d0dc3f05e3 100644 --- a/arch/riscv/kernel/setup.c +++ b/arch/riscv/kernel/setup.c @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -295,6 +296,7 @@ void __init setup_arch(char **cmdline_p) #endif riscv_fill_hwcap(); + apply_boot_alternatives(); } static int __init topology_init(void) diff --git a/arch/riscv/kernel/signal.c b/arch/riscv/kernel/signal.c index 9f4e59f80551b81a9ad13801e0854fe4cd720083..38b05ca6fe66983426e7bfba231c0775ae8c81d4 100644 --- a/arch/riscv/kernel/signal.c +++ b/arch/riscv/kernel/signal.c @@ -6,6 +6,7 @@ * Copyright (C) 2012 Regents of the University of California */ +#include #include #include #include @@ -14,6 +15,7 @@ #include #include +#include #include #include @@ -261,7 +263,10 @@ static void handle_signal(struct ksignal *ksig, struct pt_regs *regs) rseq_signal_deliver(ksig, regs); /* Set up the stack frame */ - ret = setup_rt_frame(ksig, oldset, regs); + if (is_compat_task()) + ret = compat_setup_rt_frame(ksig, oldset, regs); + else + ret = setup_rt_frame(ksig, oldset, regs); signal_setup_done(ret, ksig, 0); } diff --git a/arch/riscv/kernel/smpboot.c b/arch/riscv/kernel/smpboot.c index 622f226454d53d81cbc5cda9fd735fb6ed41d588..f1e4948a4b525208b88cac211d68536a53f506f7 100644 --- a/arch/riscv/kernel/smpboot.c +++ b/arch/riscv/kernel/smpboot.c @@ -32,7 +32,6 @@ #include #include #include -#include #include "head.h" @@ -41,9 +40,6 @@ static DECLARE_COMPLETION(cpu_running); void __init smp_prepare_boot_cpu(void) { init_cpu_topology(); -#ifdef CONFIG_RISCV_ERRATA_ALTERNATIVE - apply_boot_alternatives(); -#endif } void __init smp_prepare_cpus(unsigned int max_cpus) diff --git a/arch/riscv/kernel/suspend_entry.S b/arch/riscv/kernel/suspend_entry.S index 4b07b809a2b8c47f387a5a51b7e5997824171a84..aafcca58c19de5c50f977622e5cb8443c35fe654 100644 --- a/arch/riscv/kernel/suspend_entry.S +++ b/arch/riscv/kernel/suspend_entry.S @@ -8,6 +8,7 @@ #include #include #include +#include .text .altmacro diff --git a/arch/riscv/kernel/sys_riscv.c b/arch/riscv/kernel/sys_riscv.c index 12f8a7fce78b1d8821c4a29fd6fb8008bcafd3d8..9c0194f176fc09e556a28fb250c2440ada28dbf4 100644 --- a/arch/riscv/kernel/sys_riscv.c +++ b/arch/riscv/kernel/sys_riscv.c @@ -33,7 +33,9 @@ SYSCALL_DEFINE6(mmap, unsigned long, addr, unsigned long, len, { return riscv_sys_mmap(addr, len, prot, flags, fd, offset, 0); } -#else +#endif + +#if defined(CONFIG_32BIT) || defined(CONFIG_COMPAT) SYSCALL_DEFINE6(mmap2, unsigned long, addr, unsigned long, len, unsigned long, prot, unsigned long, flags, unsigned long, fd, off_t, offset) @@ -44,7 +46,7 @@ SYSCALL_DEFINE6(mmap2, unsigned long, addr, unsigned long, len, */ return riscv_sys_mmap(addr, len, prot, flags, fd, offset, 12); } -#endif /* !CONFIG_64BIT */ +#endif /* * Allows the instruction cache to be flushed from userspace. Despite RISC-V diff --git a/arch/riscv/kernel/traps.c b/arch/riscv/kernel/traps.c index fe92e119e6a3332e4d997176961bac6d0e439dd8..b404265092447ca8e349a89412e363b0199b73d2 100644 --- a/arch/riscv/kernel/traps.c +++ b/arch/riscv/kernel/traps.c @@ -86,7 +86,7 @@ static void do_trap_error(struct pt_regs *regs, int signo, int code, } } -#if defined (CONFIG_XIP_KERNEL) && defined (CONFIG_RISCV_ERRATA_ALTERNATIVE) +#if defined(CONFIG_XIP_KERNEL) && defined(CONFIG_RISCV_ALTERNATIVE) #define __trap_section __section(".xip.traps") #else #define __trap_section diff --git a/arch/riscv/kernel/vdso.c b/arch/riscv/kernel/vdso.c index a9436a65161a4f29b048e88343107792345ebfec..69b05b6c181b6d252c6d95d11605b76154619c0c 100644 --- a/arch/riscv/kernel/vdso.c +++ b/arch/riscv/kernel/vdso.c @@ -23,6 +23,9 @@ struct vdso_data { #endif extern char vdso_start[], vdso_end[]; +#ifdef CONFIG_COMPAT +extern char compat_vdso_start[], compat_vdso_end[]; +#endif enum vvar_pages { VVAR_DATA_PAGE_OFFSET, @@ -30,6 +33,11 @@ enum vvar_pages { VVAR_NR_PAGES, }; +enum rv_vdso_map { + RV_VDSO_MAP_VVAR, + RV_VDSO_MAP_VDSO, +}; + #define VVAR_SIZE (VVAR_NR_PAGES << PAGE_SHIFT) /* @@ -52,12 +60,6 @@ struct __vdso_info { struct vm_special_mapping *cm; }; -static struct __vdso_info vdso_info __ro_after_init = { - .name = "vdso", - .vdso_code_start = vdso_start, - .vdso_code_end = vdso_end, -}; - static int vdso_mremap(const struct vm_special_mapping *sm, struct vm_area_struct *new_vma) { @@ -66,37 +68,33 @@ static int vdso_mremap(const struct vm_special_mapping *sm, return 0; } -static int __init __vdso_init(void) +static void __init __vdso_init(struct __vdso_info *vdso_info) { unsigned int i; struct page **vdso_pagelist; unsigned long pfn; - if (memcmp(vdso_info.vdso_code_start, "\177ELF", 4)) { - pr_err("vDSO is not a valid ELF object!\n"); - return -EINVAL; - } + if (memcmp(vdso_info->vdso_code_start, "\177ELF", 4)) + panic("vDSO is not a valid ELF object!\n"); - vdso_info.vdso_pages = ( - vdso_info.vdso_code_end - - vdso_info.vdso_code_start) >> + vdso_info->vdso_pages = ( + vdso_info->vdso_code_end - + vdso_info->vdso_code_start) >> PAGE_SHIFT; - vdso_pagelist = kcalloc(vdso_info.vdso_pages, + vdso_pagelist = kcalloc(vdso_info->vdso_pages, sizeof(struct page *), GFP_KERNEL); if (vdso_pagelist == NULL) - return -ENOMEM; + panic("vDSO kcalloc failed!\n"); /* Grab the vDSO code pages. */ - pfn = sym_to_pfn(vdso_info.vdso_code_start); + pfn = sym_to_pfn(vdso_info->vdso_code_start); - for (i = 0; i < vdso_info.vdso_pages; i++) + for (i = 0; i < vdso_info->vdso_pages; i++) vdso_pagelist[i] = pfn_to_page(pfn + i); - vdso_info.cm->pages = vdso_pagelist; - - return 0; + vdso_info->cm->pages = vdso_pagelist; } #ifdef CONFIG_TIME_NS @@ -116,13 +114,14 @@ int vdso_join_timens(struct task_struct *task, struct time_namespace *ns) { struct mm_struct *mm = task->mm; struct vm_area_struct *vma; + struct __vdso_info *vdso_info = mm->context.vdso_info; mmap_read_lock(mm); for (vma = mm->mmap; vma; vma = vma->vm_next) { unsigned long size = vma->vm_end - vma->vm_start; - if (vma_is_special_mapping(vma, vdso_info.dm)) + if (vma_is_special_mapping(vma, vdso_info->dm)) zap_page_range(vma, vma->vm_start, size); } @@ -187,12 +186,27 @@ static vm_fault_t vvar_fault(const struct vm_special_mapping *sm, return vmf_insert_pfn(vma, vmf->address, pfn); } -enum rv_vdso_map { - RV_VDSO_MAP_VVAR, - RV_VDSO_MAP_VDSO, +static struct vm_special_mapping rv_vdso_maps[] __ro_after_init = { + [RV_VDSO_MAP_VVAR] = { + .name = "[vvar]", + .fault = vvar_fault, + }, + [RV_VDSO_MAP_VDSO] = { + .name = "[vdso]", + .mremap = vdso_mremap, + }, }; -static struct vm_special_mapping rv_vdso_maps[] __ro_after_init = { +static struct __vdso_info vdso_info __ro_after_init = { + .name = "vdso", + .vdso_code_start = vdso_start, + .vdso_code_end = vdso_end, + .dm = &rv_vdso_maps[RV_VDSO_MAP_VVAR], + .cm = &rv_vdso_maps[RV_VDSO_MAP_VDSO], +}; + +#ifdef CONFIG_COMPAT +static struct vm_special_mapping rv_compat_vdso_maps[] __ro_after_init = { [RV_VDSO_MAP_VVAR] = { .name = "[vvar]", .fault = vvar_fault, @@ -203,25 +217,37 @@ static struct vm_special_mapping rv_vdso_maps[] __ro_after_init = { }, }; +static struct __vdso_info compat_vdso_info __ro_after_init = { + .name = "compat_vdso", + .vdso_code_start = compat_vdso_start, + .vdso_code_end = compat_vdso_end, + .dm = &rv_compat_vdso_maps[RV_VDSO_MAP_VVAR], + .cm = &rv_compat_vdso_maps[RV_VDSO_MAP_VDSO], +}; +#endif + static int __init vdso_init(void) { - vdso_info.dm = &rv_vdso_maps[RV_VDSO_MAP_VVAR]; - vdso_info.cm = &rv_vdso_maps[RV_VDSO_MAP_VDSO]; + __vdso_init(&vdso_info); +#ifdef CONFIG_COMPAT + __vdso_init(&compat_vdso_info); +#endif - return __vdso_init(); + return 0; } arch_initcall(vdso_init); static int __setup_additional_pages(struct mm_struct *mm, struct linux_binprm *bprm, - int uses_interp) + int uses_interp, + struct __vdso_info *vdso_info) { unsigned long vdso_base, vdso_text_len, vdso_mapping_len; void *ret; BUILD_BUG_ON(VVAR_NR_PAGES != __VVAR_PAGES); - vdso_text_len = vdso_info.vdso_pages << PAGE_SHIFT; + vdso_text_len = vdso_info->vdso_pages << PAGE_SHIFT; /* Be sure to map the data page */ vdso_mapping_len = vdso_text_len + VVAR_SIZE; @@ -232,16 +258,18 @@ static int __setup_additional_pages(struct mm_struct *mm, } ret = _install_special_mapping(mm, vdso_base, VVAR_SIZE, - (VM_READ | VM_MAYREAD | VM_PFNMAP), vdso_info.dm); + (VM_READ | VM_MAYREAD | VM_PFNMAP), vdso_info->dm); if (IS_ERR(ret)) goto up_fail; vdso_base += VVAR_SIZE; mm->context.vdso = (void *)vdso_base; + mm->context.vdso_info = (void *)vdso_info; + ret = _install_special_mapping(mm, vdso_base, vdso_text_len, (VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC), - vdso_info.cm); + vdso_info->cm); if (IS_ERR(ret)) goto up_fail; @@ -253,6 +281,24 @@ up_fail: return PTR_ERR(ret); } +#ifdef CONFIG_COMPAT +int compat_arch_setup_additional_pages(struct linux_binprm *bprm, + int uses_interp) +{ + struct mm_struct *mm = current->mm; + int ret; + + if (mmap_write_lock_killable(mm)) + return -EINTR; + + ret = __setup_additional_pages(mm, bprm, uses_interp, + &compat_vdso_info); + mmap_write_unlock(mm); + + return ret; +} +#endif + int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) { struct mm_struct *mm = current->mm; @@ -261,7 +307,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) if (mmap_write_lock_killable(mm)) return -EINTR; - ret = __setup_additional_pages(mm, bprm, uses_interp); + ret = __setup_additional_pages(mm, bprm, uses_interp, &vdso_info); mmap_write_unlock(mm); return ret; diff --git a/arch/riscv/kernel/vdso/vdso.S b/arch/riscv/kernel/vdso/vdso.S index df222245be0572ede4a2f6f2a6983685ed9bbf32..83f1c899e8d82e646701676f7b85ad4eb0712995 100644 --- a/arch/riscv/kernel/vdso/vdso.S +++ b/arch/riscv/kernel/vdso/vdso.S @@ -7,12 +7,16 @@ #include #include +#ifndef __VDSO_PATH +#define __VDSO_PATH "arch/riscv/kernel/vdso/vdso.so" +#endif + __PAGE_ALIGNED_DATA .globl vdso_start, vdso_end .balign PAGE_SIZE vdso_start: - .incbin "arch/riscv/kernel/vdso/vdso.so" + .incbin __VDSO_PATH .balign PAGE_SIZE vdso_end: diff --git a/arch/riscv/mm/fault.c b/arch/riscv/mm/fault.c index 4e9efbe46d5fc2583302100096eb8f4d4982ff71..40694f0cab9e51c8f4cb1a6dae6d7545e48d8dd6 100644 --- a/arch/riscv/mm/fault.c +++ b/arch/riscv/mm/fault.c @@ -102,9 +102,9 @@ static inline void bad_area(struct pt_regs *regs, struct mm_struct *mm, int code static inline void vmalloc_fault(struct pt_regs *regs, int code, unsigned long addr) { pgd_t *pgd, *pgd_k; - pud_t *pud, *pud_k; - p4d_t *p4d, *p4d_k; - pmd_t *pmd, *pmd_k; + pud_t *pud_k; + p4d_t *p4d_k; + pmd_t *pmd_k; pte_t *pte_k; int index; unsigned long pfn; @@ -132,14 +132,12 @@ static inline void vmalloc_fault(struct pt_regs *regs, int code, unsigned long a } set_pgd(pgd, *pgd_k); - p4d = p4d_offset(pgd, addr); p4d_k = p4d_offset(pgd_k, addr); if (!p4d_present(*p4d_k)) { no_context(regs, addr); return; } - pud = pud_offset(p4d, addr); pud_k = pud_offset(p4d_k, addr); if (!pud_present(*pud_k)) { no_context(regs, addr); @@ -150,13 +148,11 @@ static inline void vmalloc_fault(struct pt_regs *regs, int code, unsigned long a * Since the vmalloc area is global, it is unnecessary * to copy individual PTEs */ - pmd = pmd_offset(pud, addr); pmd_k = pmd_offset(pud_k, addr); if (!pmd_present(*pmd_k)) { no_context(regs, addr); return; } - set_pmd(pmd, *pmd_k); /* * Make sure the actual PTE exists as well to diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c index 180d6a3e2a05f157ce9f0d590d5ac61dc977bacd..eed613599ba67a36490c6c4af13f502718ed75cc 100644 --- a/arch/riscv/mm/init.c +++ b/arch/riscv/mm/init.c @@ -578,9 +578,9 @@ static void __init create_p4d_mapping(p4d_t *p4dp, create_pte_mapping(__nextp, __va, __pa, __sz, __prot) #define fixmap_pgd_next ((uintptr_t)fixmap_pte) #define early_dtb_pgd_next ((uintptr_t)early_dtb_pmd) -#define create_p4d_mapping(__pmdp, __va, __pa, __sz, __prot) -#define create_pud_mapping(__pmdp, __va, __pa, __sz, __prot) -#define create_pmd_mapping(__pmdp, __va, __pa, __sz, __prot) +#define create_p4d_mapping(__pmdp, __va, __pa, __sz, __prot) do {} while(0) +#define create_pud_mapping(__pmdp, __va, __pa, __sz, __prot) do {} while(0) +#define create_pmd_mapping(__pmdp, __va, __pa, __sz, __prot) do {} while(0) #endif /* __PAGETABLE_PMD_FOLDED */ void __init create_pgd_mapping(pgd_t *pgdp, @@ -671,7 +671,7 @@ static __init pgprot_t pgprot_from_va(uintptr_t va) } #endif /* CONFIG_STRICT_KERNEL_RWX */ -#ifdef CONFIG_64BIT +#if defined(CONFIG_64BIT) && !defined(CONFIG_XIP_KERNEL) static void __init disable_pgtable_l5(void) { pgtable_l5_enabled = false; @@ -947,6 +947,7 @@ asmlinkage void __init setup_vm(uintptr_t dtb_pa) BUG_ON((kernel_map.virt_addr + kernel_map.size) > ADDRESS_SPACE_END - SZ_4K); #endif + apply_early_boot_alternatives(); pt_ops_set_early(); /* Setup early PGD for fixmap */ diff --git a/arch/riscv/purgatory/.gitignore b/arch/riscv/purgatory/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..38d7d1bda4d7c2671d99087b8b9345d8d647543c --- /dev/null +++ b/arch/riscv/purgatory/.gitignore @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0-only +purgatory.chk +purgatory.ro +kexec-purgatory.c diff --git a/arch/riscv/purgatory/Makefile b/arch/riscv/purgatory/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..d4df200f7edf9d97fc842d46246bc974947ec8ef --- /dev/null +++ b/arch/riscv/purgatory/Makefile @@ -0,0 +1,95 @@ +# SPDX-License-Identifier: GPL-2.0 +OBJECT_FILES_NON_STANDARD := y + +purgatory-y := purgatory.o sha256.o entry.o string.o ctype.o memcpy.o memset.o + +targets += $(purgatory-y) +PURGATORY_OBJS = $(addprefix $(obj)/,$(purgatory-y)) + +$(obj)/string.o: $(srctree)/lib/string.c FORCE + $(call if_changed_rule,cc_o_c) + +$(obj)/ctype.o: $(srctree)/lib/ctype.c FORCE + $(call if_changed_rule,cc_o_c) + +$(obj)/memcpy.o: $(srctree)/arch/riscv/lib/memcpy.S FORCE + $(call if_changed_rule,as_o_S) + +$(obj)/memset.o: $(srctree)/arch/riscv/lib/memset.S FORCE + $(call if_changed_rule,as_o_S) + +$(obj)/sha256.o: $(srctree)/lib/crypto/sha256.c FORCE + $(call if_changed_rule,cc_o_c) + +CFLAGS_sha256.o := -D__DISABLE_EXPORTS +CFLAGS_string.o := -D__DISABLE_EXPORTS +CFLAGS_ctype.o := -D__DISABLE_EXPORTS + +# When linking purgatory.ro with -r unresolved symbols are not checked, +# also link a purgatory.chk binary without -r to check for unresolved symbols. +PURGATORY_LDFLAGS := -e purgatory_start -z nodefaultlib +LDFLAGS_purgatory.ro := -r $(PURGATORY_LDFLAGS) +LDFLAGS_purgatory.chk := $(PURGATORY_LDFLAGS) +targets += purgatory.ro purgatory.chk + +# Sanitizer, etc. runtimes are unavailable and cannot be linked here. +GCOV_PROFILE := n +KASAN_SANITIZE := n +UBSAN_SANITIZE := n +KCSAN_SANITIZE := n +KCOV_INSTRUMENT := n + +# These are adjustments to the compiler flags used for objects that +# make up the standalone purgatory.ro + +PURGATORY_CFLAGS_REMOVE := -mcmodel=kernel +PURGATORY_CFLAGS := -mcmodel=medany -ffreestanding -fno-zero-initialized-in-bss +PURGATORY_CFLAGS += $(DISABLE_STACKLEAK_PLUGIN) -DDISABLE_BRANCH_PROFILING +PURGATORY_CFLAGS += -fno-stack-protector -g0 + +# Default KBUILD_CFLAGS can have -pg option set when FTRACE is enabled. That +# in turn leaves some undefined symbols like __fentry__ in purgatory and not +# sure how to relocate those. +ifdef CONFIG_FUNCTION_TRACER +PURGATORY_CFLAGS_REMOVE += $(CC_FLAGS_FTRACE) +endif + +ifdef CONFIG_STACKPROTECTOR +PURGATORY_CFLAGS_REMOVE += -fstack-protector +endif + +ifdef CONFIG_STACKPROTECTOR_STRONG +PURGATORY_CFLAGS_REMOVE += -fstack-protector-strong +endif + +CFLAGS_REMOVE_purgatory.o += $(PURGATORY_CFLAGS_REMOVE) +CFLAGS_purgatory.o += $(PURGATORY_CFLAGS) + +CFLAGS_REMOVE_sha256.o += $(PURGATORY_CFLAGS_REMOVE) +CFLAGS_sha256.o += $(PURGATORY_CFLAGS) + +CFLAGS_REMOVE_string.o += $(PURGATORY_CFLAGS_REMOVE) +CFLAGS_string.o += $(PURGATORY_CFLAGS) + +CFLAGS_REMOVE_ctype.o += $(PURGATORY_CFLAGS_REMOVE) +CFLAGS_ctype.o += $(PURGATORY_CFLAGS) + +AFLAGS_REMOVE_entry.o += -Wa,-gdwarf-2 +AFLAGS_REMOVE_memcpy.o += -Wa,-gdwarf-2 +AFLAGS_REMOVE_memset.o += -Wa,-gdwarf-2 + +$(obj)/purgatory.ro: $(PURGATORY_OBJS) FORCE + $(call if_changed,ld) + +$(obj)/purgatory.chk: $(obj)/purgatory.ro FORCE + $(call if_changed,ld) + +targets += kexec-purgatory.c + +quiet_cmd_bin2c = BIN2C $@ + cmd_bin2c = $(objtree)/scripts/bin2c kexec_purgatory < $< > $@ + +$(obj)/kexec-purgatory.c: $(obj)/purgatory.ro $(obj)/purgatory.chk FORCE + $(call if_changed,bin2c) + +obj-$(CONFIG_ARCH_HAS_KEXEC_PURGATORY) += kexec-purgatory.o diff --git a/arch/riscv/purgatory/entry.S b/arch/riscv/purgatory/entry.S new file mode 100644 index 0000000000000000000000000000000000000000..0194f4554130ae6b89cf5db97a069a65bc2c6fc1 --- /dev/null +++ b/arch/riscv/purgatory/entry.S @@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * purgatory: Runs between two kernels + * + * Copyright (C) 2022 Huawei Technologies Co, Ltd. + * + * Author: Li Zhengyu (lizhengyu3@huawei.com) + * + */ + +.macro size, sym:req + .size \sym, . - \sym +.endm + +.text + +.globl purgatory_start +purgatory_start: + + lla sp, .Lstack + mv s0, a0 /* The hartid of the current hart */ + mv s1, a1 /* Phys address of the FDT image */ + + jal purgatory + + /* Start new image. */ + mv a0, s0 + mv a1, s1 + ld a2, riscv_kernel_entry + jr a2 + +size purgatory_start + +.align 4 + .rept 256 + .quad 0 + .endr +.Lstack: + +.data + +.globl riscv_kernel_entry +riscv_kernel_entry: + .quad 0 +size riscv_kernel_entry + +.end diff --git a/arch/riscv/purgatory/purgatory.c b/arch/riscv/purgatory/purgatory.c new file mode 100644 index 0000000000000000000000000000000000000000..80596ab5fb6228fc69447f7ef1266721102cc396 --- /dev/null +++ b/arch/riscv/purgatory/purgatory.c @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * purgatory: Runs between two kernels + * + * Copyright (C) 2022 Huawei Technologies Co, Ltd. + * + * Author: Li Zhengyu (lizhengyu3@huawei.com) + * + */ + +#include +#include +#include +#include + +u8 purgatory_sha256_digest[SHA256_DIGEST_SIZE] __section(".kexec-purgatory"); + +struct kexec_sha_region purgatory_sha_regions[KEXEC_SEGMENT_MAX] __section(".kexec-purgatory"); + +static int verify_sha256_digest(void) +{ + struct kexec_sha_region *ptr, *end; + struct sha256_state ss; + u8 digest[SHA256_DIGEST_SIZE]; + + sha256_init(&ss); + end = purgatory_sha_regions + ARRAY_SIZE(purgatory_sha_regions); + for (ptr = purgatory_sha_regions; ptr < end; ptr++) + sha256_update(&ss, (uint8_t *)(ptr->start), ptr->len); + sha256_final(&ss, digest); + if (memcmp(digest, purgatory_sha256_digest, sizeof(digest)) != 0) + return 1; + return 0; +} + +/* workaround for a warning with -Wmissing-prototypes */ +void purgatory(void); + +void purgatory(void) +{ + if (verify_sha256_digest()) + for (;;) + /* loop forever */ + ; +} diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 5886e039e16d3b0a18844f2be585f7c47c8cca11..b17239ae7bd4ad780e08c8cb671bd3f708a1a304 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -418,9 +418,6 @@ config COMPAT (and some other stuff like libraries and such) is needed for executing 31 bit applications. It is safe to say "Y". -config SYSVIPC_COMPAT - def_bool y if COMPAT && SYSVIPC - config SMP def_bool y diff --git a/arch/s390/crypto/chacha-glue.c b/arch/s390/crypto/chacha-glue.c index ccfff73e2c93674134fc07440652c22cb278f6bd..2ec51f339cec44462550d3629de7f79ac95cc260 100644 --- a/arch/s390/crypto/chacha-glue.c +++ b/arch/s390/crypto/chacha-glue.c @@ -62,6 +62,34 @@ static int chacha20_s390(struct skcipher_request *req) return rc; } +void hchacha_block_arch(const u32 *state, u32 *stream, int nrounds) +{ + /* TODO: implement hchacha_block_arch() in assembly */ + hchacha_block_generic(state, stream, nrounds); +} +EXPORT_SYMBOL(hchacha_block_arch); + +void chacha_init_arch(u32 *state, const u32 *key, const u8 *iv) +{ + chacha_init_generic(state, key, iv); +} +EXPORT_SYMBOL(chacha_init_arch); + +void chacha_crypt_arch(u32 *state, u8 *dst, const u8 *src, + unsigned int bytes, int nrounds) +{ + /* s390 chacha20 implementation has 20 rounds hard-coded, + * it cannot handle a block of data or less, but otherwise + * it can handle data of arbitrary size + */ + if (bytes <= CHACHA_BLOCK_SIZE || nrounds != 20) + chacha_crypt_generic(state, dst, src, bytes, nrounds); + else + chacha20_crypt_s390(state, dst, src, bytes, + &state[4], &state[12]); +} +EXPORT_SYMBOL(chacha_crypt_arch); + static struct skcipher_alg chacha_algs[] = { { .base.cra_name = "chacha20", @@ -83,12 +111,14 @@ static struct skcipher_alg chacha_algs[] = { static int __init chacha_mod_init(void) { - return crypto_register_skciphers(chacha_algs, ARRAY_SIZE(chacha_algs)); + return IS_REACHABLE(CONFIG_CRYPTO_SKCIPHER) ? + crypto_register_skciphers(chacha_algs, ARRAY_SIZE(chacha_algs)) : 0; } static void __exit chacha_mod_fini(void) { - crypto_unregister_skciphers(chacha_algs, ARRAY_SIZE(chacha_algs)); + if (IS_REACHABLE(CONFIG_CRYPTO_SKCIPHER)) + crypto_unregister_skciphers(chacha_algs, ARRAY_SIZE(chacha_algs)); } module_cpu_feature_match(VXRS, chacha_mod_init); diff --git a/arch/s390/include/asm/compat.h b/arch/s390/include/asm/compat.h index 7d6fe813ac39ee03110e4706bc60b5f9ca9b8839..a386070f1d5653a97bf2aa075b21c23e83eac436 100644 --- a/arch/s390/include/asm/compat.h +++ b/arch/s390/include/asm/compat.h @@ -13,6 +13,18 @@ #define compat_mode_t compat_mode_t typedef u16 compat_mode_t; +#define __compat_uid_t __compat_uid_t +typedef u16 __compat_uid_t; +typedef u16 __compat_gid_t; + +#define compat_dev_t compat_dev_t +typedef u16 compat_dev_t; + +#define compat_ipc_pid_t compat_ipc_pid_t +typedef u16 compat_ipc_pid_t; + +#define compat_statfs compat_statfs + #include #define __TYPE_IS_PTR(t) (!__builtin_types_compatible_p( \ @@ -30,15 +42,9 @@ typedef u16 compat_mode_t; PSW32_MASK_MCHECK | PSW32_MASK_PSTATE | \ PSW32_ASC_PRIMARY) -#define COMPAT_USER_HZ 100 #define COMPAT_UTS_MACHINE "s390\0\0\0\0" -typedef u16 __compat_uid_t; -typedef u16 __compat_gid_t; -typedef u16 compat_dev_t; typedef u16 compat_nlink_t; -typedef u16 compat_ipc_pid_t; -typedef __kernel_fsid_t compat_fsid_t; typedef struct { u32 mask; @@ -79,26 +85,6 @@ struct compat_stat { u32 __unused5; }; -struct compat_flock { - short l_type; - short l_whence; - compat_off_t l_start; - compat_off_t l_len; - compat_pid_t l_pid; -}; - -#define F_GETLK64 12 -#define F_SETLK64 13 -#define F_SETLKW64 14 - -struct compat_flock64 { - short l_type; - short l_whence; - compat_loff_t l_start; - compat_loff_t l_len; - compat_pid_t l_pid; -}; - struct compat_statfs { u32 f_type; u32 f_bsize; @@ -129,10 +115,6 @@ struct compat_statfs64 { u32 f_spare[4]; }; -#define COMPAT_RLIM_INFINITY 0xffffffff - -#define COMPAT_OFF_T_MAX 0x7fffffff - /* * A pointer passed in from user mode. This should not * be used for syscall parameters, just declare them @@ -155,61 +137,4 @@ static inline int is_compat_task(void) #endif -struct compat_ipc64_perm { - compat_key_t key; - __compat_uid32_t uid; - __compat_gid32_t gid; - __compat_uid32_t cuid; - __compat_gid32_t cgid; - compat_mode_t mode; - unsigned short __pad1; - unsigned short seq; - unsigned short __pad2; - unsigned int __unused1; - unsigned int __unused2; -}; - -struct compat_semid64_ds { - struct compat_ipc64_perm sem_perm; - compat_ulong_t sem_otime; - compat_ulong_t sem_otime_high; - compat_ulong_t sem_ctime; - compat_ulong_t sem_ctime_high; - compat_ulong_t sem_nsems; - compat_ulong_t __unused1; - compat_ulong_t __unused2; -}; - -struct compat_msqid64_ds { - struct compat_ipc64_perm msg_perm; - compat_ulong_t msg_stime; - compat_ulong_t msg_stime_high; - compat_ulong_t msg_rtime; - compat_ulong_t msg_rtime_high; - compat_ulong_t msg_ctime; - compat_ulong_t msg_ctime_high; - compat_ulong_t msg_cbytes; - compat_ulong_t msg_qnum; - compat_ulong_t msg_qbytes; - compat_pid_t msg_lspid; - compat_pid_t msg_lrpid; - compat_ulong_t __unused1; - compat_ulong_t __unused2; -}; - -struct compat_shmid64_ds { - struct compat_ipc64_perm shm_perm; - compat_size_t shm_segsz; - compat_ulong_t shm_atime; - compat_ulong_t shm_atime_high; - compat_ulong_t shm_dtime; - compat_ulong_t shm_dtime_high; - compat_ulong_t shm_ctime; - compat_ulong_t shm_ctime_high; - compat_pid_t shm_cpid; - compat_pid_t shm_lpid; - compat_ulong_t shm_nattch; - compat_ulong_t __unused1; - compat_ulong_t __unused2; -}; #endif /* _ASM_S390X_COMPAT_H */ diff --git a/arch/s390/include/asm/unistd.h b/arch/s390/include/asm/unistd.h index 9e9f75ef046a8f533c78d1927bc0e6701ff822ca..4260bc5ce7f8134d7aed6a3e9df21d7f7680847d 100644 --- a/arch/s390/include/asm/unistd.h +++ b/arch/s390/include/asm/unistd.h @@ -28,6 +28,7 @@ #define __ARCH_WANT_SYS_SIGPENDING #define __ARCH_WANT_SYS_SIGPROCMASK # ifdef CONFIG_COMPAT +# define __ARCH_WANT_COMPAT_STAT # define __ARCH_WANT_SYS_TIME32 # define __ARCH_WANT_SYS_UTIME32 # endif diff --git a/arch/s390/kernel/ftrace.c b/arch/s390/kernel/ftrace.c index 1852d46babb1552b3d504e9c48d669c70941d33e..416b5a94353db0a45174f8f21f55c85e39b07c25 100644 --- a/arch/s390/kernel/ftrace.c +++ b/arch/s390/kernel/ftrace.c @@ -225,14 +225,13 @@ void arch_ftrace_update_code(int command) ftrace_modify_all_code(command); } -int ftrace_arch_code_modify_post_process(void) +void ftrace_arch_code_modify_post_process(void) { /* * Flush any pre-fetched instructions on all * CPUs to make the new code visible. */ text_poke_sync_lock(); - return 0; } #ifdef CONFIG_MODULES diff --git a/arch/sh/kernel/reboot.c b/arch/sh/kernel/reboot.c index 5c33f036418be2e00d3de5516d2a3a3e9eb9333b..e8eeedc9b1822d5963cb2df4ce17439835f88e81 100644 --- a/arch/sh/kernel/reboot.c +++ b/arch/sh/kernel/reboot.c @@ -46,8 +46,7 @@ static void native_machine_shutdown(void) static void native_machine_power_off(void) { - if (pm_power_off) - pm_power_off(); + do_kernel_power_off(); } static void native_machine_halt(void) diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index 85b573643af61f5baa3f239bbae63719030d246d..ba449c47effd8d975abf2f1130acef46e46662f9 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig @@ -489,9 +489,4 @@ config COMPAT select ARCH_WANT_OLD_COMPAT_IPC select COMPAT_OLD_SIGACTION -config SYSVIPC_COMPAT - bool - depends on COMPAT && SYSVIPC - default y - source "drivers/sbus/char/Kconfig" diff --git a/arch/sparc/include/asm/compat.h b/arch/sparc/include/asm/compat.h index bd949fcf9d63be98852b3cd873c6a0f282c42940..e4382d2efa569b9da7e88af51fa6e5c8a19f69e0 100644 --- a/arch/sparc/include/asm/compat.h +++ b/arch/sparc/include/asm/compat.h @@ -9,17 +9,25 @@ #define compat_mode_t compat_mode_t typedef u16 compat_mode_t; +#define __compat_uid_t __compat_uid_t +typedef u16 __compat_uid_t; +typedef u16 __compat_gid_t; + +#define compat_dev_t compat_dev_t +typedef u16 compat_dev_t; + +#define compat_ipc_pid_t compat_ipc_pid_t +typedef u16 compat_ipc_pid_t; + +#define compat_ipc64_perm compat_ipc64_perm + +#define COMPAT_RLIM_INFINITY 0x7fffffff + #include -#define COMPAT_USER_HZ 100 #define COMPAT_UTS_MACHINE "sparc\0\0" -typedef u16 __compat_uid_t; -typedef u16 __compat_gid_t; -typedef u16 compat_dev_t; typedef s16 compat_nlink_t; -typedef u16 compat_ipc_pid_t; -typedef __kernel_fsid_t compat_fsid_t; struct compat_stat { compat_dev_t st_dev; @@ -75,46 +83,7 @@ struct compat_stat64 { unsigned int __unused5; }; -struct compat_flock { - short l_type; - short l_whence; - compat_off_t l_start; - compat_off_t l_len; - compat_pid_t l_pid; - short __unused; -}; - -#define F_GETLK64 12 -#define F_SETLK64 13 -#define F_SETLKW64 14 - -struct compat_flock64 { - short l_type; - short l_whence; - compat_loff_t l_start; - compat_loff_t l_len; - compat_pid_t l_pid; - short __unused; -}; - -struct compat_statfs { - int f_type; - int f_bsize; - int f_blocks; - int f_bfree; - int f_bavail; - int f_files; - int f_ffree; - compat_fsid_t f_fsid; - int f_namelen; /* SunOS ignores this field. */ - int f_frsize; - int f_flags; - int f_spare[4]; -}; - -#define COMPAT_RLIM_INFINITY 0x7fffffff - -#define COMPAT_OFF_T_MAX 0x7fffffff +#define __ARCH_COMPAT_FLOCK_PAD short __unused; struct compat_ipc64_perm { compat_key_t key; diff --git a/arch/sparc/include/asm/unistd.h b/arch/sparc/include/asm/unistd.h index 1e66278ba4a5fdb0db181ad7791853704513c602..d6bc76706a7aa416dab25cdb6e6e82f54cb9891e 100644 --- a/arch/sparc/include/asm/unistd.h +++ b/arch/sparc/include/asm/unistd.h @@ -46,6 +46,7 @@ #define __ARCH_WANT_SYS_TIME #define __ARCH_WANT_SYS_UTIME #define __ARCH_WANT_COMPAT_SYS_SENDFILE +#define __ARCH_WANT_COMPAT_STAT #endif #ifdef __32bit_syscall_numbers__ diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index cf531fbcd2295ec2a77007274ad529180c84cd0b..a293a30e4cdde9d3a399bd70141f04c6276a7290 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -2870,10 +2870,6 @@ config COMPAT if COMPAT config COMPAT_FOR_U64_ALIGNMENT def_bool y - -config SYSVIPC_COMPAT - def_bool y - depends on SYSVIPC endif endmenu diff --git a/arch/x86/crypto/blowfish_glue.c b/arch/x86/crypto/blowfish_glue.c index fda6066437aa346b878a6f2ce371529cf97b0951..ba06322c1e3963094dea80ff7f2a1a02474ff82b 100644 --- a/arch/x86/crypto/blowfish_glue.c +++ b/arch/x86/crypto/blowfish_glue.c @@ -303,7 +303,7 @@ static int force; module_param(force, int, 0); MODULE_PARM_DESC(force, "Force module load, ignore CPU blacklist"); -static int __init init(void) +static int __init blowfish_init(void) { int err; @@ -327,15 +327,15 @@ static int __init init(void) return err; } -static void __exit fini(void) +static void __exit blowfish_fini(void) { crypto_unregister_alg(&bf_cipher_alg); crypto_unregister_skciphers(bf_skcipher_algs, ARRAY_SIZE(bf_skcipher_algs)); } -module_init(init); -module_exit(fini); +module_init(blowfish_init); +module_exit(blowfish_fini); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Blowfish Cipher Algorithm, asm optimized"); diff --git a/arch/x86/crypto/camellia_glue.c b/arch/x86/crypto/camellia_glue.c index 66c435ba9d3da0a6ffde0b114bde995631ab1b33..d45e9c0c42acf7b072f08a8d823f194c8a4a8756 100644 --- a/arch/x86/crypto/camellia_glue.c +++ b/arch/x86/crypto/camellia_glue.c @@ -1377,7 +1377,7 @@ static int force; module_param(force, int, 0); MODULE_PARM_DESC(force, "Force module load, ignore CPU blacklist"); -static int __init init(void) +static int __init camellia_init(void) { int err; @@ -1401,15 +1401,15 @@ static int __init init(void) return err; } -static void __exit fini(void) +static void __exit camellia_fini(void) { crypto_unregister_alg(&camellia_cipher_alg); crypto_unregister_skciphers(camellia_skcipher_algs, ARRAY_SIZE(camellia_skcipher_algs)); } -module_init(init); -module_exit(fini); +module_init(camellia_init); +module_exit(camellia_fini); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Camellia Cipher Algorithm, asm optimized"); diff --git a/arch/x86/crypto/serpent_avx2_glue.c b/arch/x86/crypto/serpent_avx2_glue.c index ccf0b5fa4933066c054c2269a40cbbf6b9d3a08a..347e97f4b713b9d9e64c6d16f66c6b34db7b0b00 100644 --- a/arch/x86/crypto/serpent_avx2_glue.c +++ b/arch/x86/crypto/serpent_avx2_glue.c @@ -96,7 +96,7 @@ static struct skcipher_alg serpent_algs[] = { static struct simd_skcipher_alg *serpent_simd_algs[ARRAY_SIZE(serpent_algs)]; -static int __init init(void) +static int __init serpent_avx2_init(void) { const char *feature_name; @@ -115,14 +115,14 @@ static int __init init(void) serpent_simd_algs); } -static void __exit fini(void) +static void __exit serpent_avx2_fini(void) { simd_unregister_skciphers(serpent_algs, ARRAY_SIZE(serpent_algs), serpent_simd_algs); } -module_init(init); -module_exit(fini); +module_init(serpent_avx2_init); +module_exit(serpent_avx2_fini); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Serpent Cipher Algorithm, AVX2 optimized"); diff --git a/arch/x86/crypto/twofish_glue.c b/arch/x86/crypto/twofish_glue.c index 77e06c2da83d0ec5a9e468759727c0c25baca5b5..f9c4adc274040a605718890689e018e81affd422 100644 --- a/arch/x86/crypto/twofish_glue.c +++ b/arch/x86/crypto/twofish_glue.c @@ -81,18 +81,18 @@ static struct crypto_alg alg = { } }; -static int __init init(void) +static int __init twofish_glue_init(void) { return crypto_register_alg(&alg); } -static void __exit fini(void) +static void __exit twofish_glue_fini(void) { crypto_unregister_alg(&alg); } -module_init(init); -module_exit(fini); +module_init(twofish_glue_init); +module_exit(twofish_glue_fini); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION ("Twofish Cipher Algorithm, asm optimized"); diff --git a/arch/x86/crypto/twofish_glue_3way.c b/arch/x86/crypto/twofish_glue_3way.c index 3507cf2064f107bd2363aabe56c17210db41d9eb..90454cf18e0defa2d0825c18a1c6d0466c14592a 100644 --- a/arch/x86/crypto/twofish_glue_3way.c +++ b/arch/x86/crypto/twofish_glue_3way.c @@ -140,7 +140,7 @@ static int force; module_param(force, int, 0); MODULE_PARM_DESC(force, "Force module load, ignore CPU blacklist"); -static int __init init(void) +static int __init twofish_3way_init(void) { if (!force && is_blacklisted_cpu()) { printk(KERN_INFO @@ -154,13 +154,13 @@ static int __init init(void) ARRAY_SIZE(tf_skciphers)); } -static void __exit fini(void) +static void __exit twofish_3way_fini(void) { crypto_unregister_skciphers(tf_skciphers, ARRAY_SIZE(tf_skciphers)); } -module_init(init); -module_exit(fini); +module_init(twofish_3way_init); +module_exit(twofish_3way_fini); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Twofish Cipher Algorithm, 3-way parallel asm optimized"); diff --git a/arch/x86/include/asm/compat.h b/arch/x86/include/asm/compat.h index 20fd0acd7d800b58a8b95b2ff807899af94cfae1..b1221da477b7438bf7a562fbbec3069b254addc0 100644 --- a/arch/x86/include/asm/compat.h +++ b/arch/x86/include/asm/compat.h @@ -15,17 +15,23 @@ #define compat_mode_t compat_mode_t typedef u16 compat_mode_t; +#define __compat_uid_t __compat_uid_t +typedef u16 __compat_uid_t; +typedef u16 __compat_gid_t; + +#define compat_dev_t compat_dev_t +typedef u16 compat_dev_t; + +#define compat_ipc_pid_t compat_ipc_pid_t +typedef u16 compat_ipc_pid_t; + +#define compat_statfs compat_statfs + #include -#define COMPAT_USER_HZ 100 #define COMPAT_UTS_MACHINE "i686\0\0" -typedef u16 __compat_uid_t; -typedef u16 __compat_gid_t; -typedef u16 compat_dev_t; typedef u16 compat_nlink_t; -typedef u16 compat_ipc_pid_t; -typedef __kernel_fsid_t compat_fsid_t; struct compat_stat { u32 st_dev; @@ -48,29 +54,11 @@ struct compat_stat { u32 __unused5; }; -struct compat_flock { - short l_type; - short l_whence; - compat_off_t l_start; - compat_off_t l_len; - compat_pid_t l_pid; -}; - -#define F_GETLK64 12 /* using 'struct flock64' */ -#define F_SETLK64 13 -#define F_SETLKW64 14 - /* - * IA32 uses 4 byte alignment for 64 bit quantities, - * so we need to pack this structure. + * IA32 uses 4 byte alignment for 64 bit quantities, so we need to pack the + * compat flock64 structure. */ -struct compat_flock64 { - short l_type; - short l_whence; - compat_loff_t l_start; - compat_loff_t l_len; - compat_pid_t l_pid; -} __attribute__((packed)); +#define __ARCH_NEED_COMPAT_FLOCK64_PACKED struct compat_statfs { int f_type; @@ -87,68 +75,6 @@ struct compat_statfs { int f_spare[4]; }; -#define COMPAT_RLIM_INFINITY 0xffffffff - -#define COMPAT_OFF_T_MAX 0x7fffffff - -struct compat_ipc64_perm { - compat_key_t key; - __compat_uid32_t uid; - __compat_gid32_t gid; - __compat_uid32_t cuid; - __compat_gid32_t cgid; - unsigned short mode; - unsigned short __pad1; - unsigned short seq; - unsigned short __pad2; - compat_ulong_t unused1; - compat_ulong_t unused2; -}; - -struct compat_semid64_ds { - struct compat_ipc64_perm sem_perm; - compat_ulong_t sem_otime; - compat_ulong_t sem_otime_high; - compat_ulong_t sem_ctime; - compat_ulong_t sem_ctime_high; - compat_ulong_t sem_nsems; - compat_ulong_t __unused3; - compat_ulong_t __unused4; -}; - -struct compat_msqid64_ds { - struct compat_ipc64_perm msg_perm; - compat_ulong_t msg_stime; - compat_ulong_t msg_stime_high; - compat_ulong_t msg_rtime; - compat_ulong_t msg_rtime_high; - compat_ulong_t msg_ctime; - compat_ulong_t msg_ctime_high; - compat_ulong_t msg_cbytes; - compat_ulong_t msg_qnum; - compat_ulong_t msg_qbytes; - compat_pid_t msg_lspid; - compat_pid_t msg_lrpid; - compat_ulong_t __unused4; - compat_ulong_t __unused5; -}; - -struct compat_shmid64_ds { - struct compat_ipc64_perm shm_perm; - compat_size_t shm_segsz; - compat_ulong_t shm_atime; - compat_ulong_t shm_atime_high; - compat_ulong_t shm_dtime; - compat_ulong_t shm_dtime_high; - compat_ulong_t shm_ctime; - compat_ulong_t shm_ctime_high; - compat_pid_t shm_cpid; - compat_pid_t shm_lpid; - compat_ulong_t shm_nattch; - compat_ulong_t __unused4; - compat_ulong_t __unused5; -}; - #ifdef CONFIG_X86_X32_ABI #define COMPAT_USE_64BIT_TIME \ (!!(task_pt_regs(current)->orig_ax & __X32_SYSCALL_BIT)) diff --git a/arch/x86/include/asm/ftrace.h b/arch/x86/include/asm/ftrace.h index 024d9797646ee1abdfc99e0b12f75576603c9371..b5ef474be858d4278f05e778bf8985ed5636b998 100644 --- a/arch/x86/include/asm/ftrace.h +++ b/arch/x86/include/asm/ftrace.h @@ -9,6 +9,13 @@ # define MCOUNT_ADDR ((unsigned long)(__fentry__)) #define MCOUNT_INSN_SIZE 5 /* sizeof mcount call */ +/* Ignore unused weak functions which will have non zero offsets */ +#ifdef CONFIG_HAVE_FENTRY +# include +/* Add offset for endbr64 if IBT enabled */ +# define FTRACE_MCOUNT_MAX_OFFSET ENDBR_INSN_SIZE +#endif + #ifdef CONFIG_DYNAMIC_FTRACE #define ARCH_SUPPORTS_FTRACE_OPS 1 #endif diff --git a/arch/x86/include/asm/set_memory.h b/arch/x86/include/asm/set_memory.h index 78ca53512486421d17c0a684181972c3fc17a9c4..b45c4d27fd46e5f129876f8dac416b0ee33bc0af 100644 --- a/arch/x86/include/asm/set_memory.h +++ b/arch/x86/include/asm/set_memory.h @@ -86,56 +86,4 @@ bool kernel_page_present(struct page *page); extern int kernel_set_to_readonly; -#ifdef CONFIG_X86_64 -/* - * Prevent speculative access to the page by either unmapping - * it (if we do not require access to any part of the page) or - * marking it uncacheable (if we want to try to retrieve data - * from non-poisoned lines in the page). - */ -static inline int set_mce_nospec(unsigned long pfn, bool unmap) -{ - unsigned long decoy_addr; - int rc; - - /* SGX pages are not in the 1:1 map */ - if (arch_is_platform_page(pfn << PAGE_SHIFT)) - return 0; - /* - * We would like to just call: - * set_memory_XX((unsigned long)pfn_to_kaddr(pfn), 1); - * but doing that would radically increase the odds of a - * speculative access to the poison page because we'd have - * the virtual address of the kernel 1:1 mapping sitting - * around in registers. - * Instead we get tricky. We create a non-canonical address - * that looks just like the one we want, but has bit 63 flipped. - * This relies on set_memory_XX() properly sanitizing any __pa() - * results with __PHYSICAL_MASK or PTE_PFN_MASK. - */ - decoy_addr = (pfn << PAGE_SHIFT) + (PAGE_OFFSET ^ BIT(63)); - - if (unmap) - rc = set_memory_np(decoy_addr, 1); - else - rc = set_memory_uc(decoy_addr, 1); - if (rc) - pr_warn("Could not invalidate pfn=0x%lx from 1:1 map\n", pfn); - return rc; -} -#define set_mce_nospec set_mce_nospec - -/* Restore full speculative operation to the pfn. */ -static inline int clear_mce_nospec(unsigned long pfn) -{ - return set_memory_wb((unsigned long) pfn_to_kaddr(pfn), 1); -} -#define clear_mce_nospec clear_mce_nospec -#else -/* - * Few people would run a 32-bit kernel on a machine that supports - * recoverable errors because they have too much memory to boot 32-bit. - */ -#endif - #endif /* _ASM_X86_SET_MEMORY_H */ diff --git a/arch/x86/include/asm/unistd.h b/arch/x86/include/asm/unistd.h index 80e9d5206a7152da0fb1c0cd723d6f461e74f2ff..761173ccc33cab5b29664afc0655e57ea0a0487f 100644 --- a/arch/x86/include/asm/unistd.h +++ b/arch/x86/include/asm/unistd.h @@ -22,6 +22,7 @@ # include # define __ARCH_WANT_SYS_TIME # define __ARCH_WANT_SYS_UTIME +# define __ARCH_WANT_COMPAT_STAT # define __ARCH_WANT_COMPAT_SYS_PREADV64 # define __ARCH_WANT_COMPAT_SYS_PWRITEV64 # define __ARCH_WANT_COMPAT_SYS_PREADV64V2 diff --git a/arch/x86/kernel/cpu/mce/core.c b/arch/x86/kernel/cpu/mce/core.c index d775fcd74e98d268d4251402d10c1cbf5a52e66f..2c8ec5c71712191486000cf3d0e34ebe24f18eb2 100644 --- a/arch/x86/kernel/cpu/mce/core.c +++ b/arch/x86/kernel/cpu/mce/core.c @@ -581,7 +581,7 @@ static int uc_decode_notifier(struct notifier_block *nb, unsigned long val, pfn = mce->addr >> PAGE_SHIFT; if (!memory_failure(pfn, 0)) { - set_mce_nospec(pfn, whole_page(mce)); + set_mce_nospec(pfn); mce->kflags |= MCE_HANDLED_UC; } @@ -1318,7 +1318,7 @@ static void kill_me_maybe(struct callback_head *cb) ret = memory_failure(p->mce_addr >> PAGE_SHIFT, flags); if (!ret) { - set_mce_nospec(p->mce_addr >> PAGE_SHIFT, p->mce_whole_page); + set_mce_nospec(p->mce_addr >> PAGE_SHIFT); sync_core(); return; } @@ -1344,7 +1344,7 @@ static void kill_me_never(struct callback_head *cb) p->mce_count = 0; pr_err("Kernel accessed poison in user space at %llx\n", p->mce_addr); if (!memory_failure(p->mce_addr >> PAGE_SHIFT, 0)) - set_mce_nospec(p->mce_addr >> PAGE_SHIFT, p->mce_whole_page); + set_mce_nospec(p->mce_addr >> PAGE_SHIFT); } static void queue_task_work(struct mce *m, char *msg, void (*func)(struct callback_head *)) diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c index 5b8f2c357160116335a93a1dd30947602a642a1e..831613959a92af177a621ce507d18f671daeed86 100644 --- a/arch/x86/kernel/cpu/mshyperv.c +++ b/arch/x86/kernel/cpu/mshyperv.c @@ -457,6 +457,8 @@ static void __init ms_hyperv_init_platform(void) */ if (!(ms_hyperv.features & HV_ACCESS_TSC_INVARIANT)) mark_tsc_unstable("running on Hyper-V"); + + hardlockup_detector_disable(); } static bool __init ms_hyperv_x2apic_available(void) diff --git a/arch/x86/kernel/ftrace.c b/arch/x86/kernel/ftrace.c index b09d73c2ba897610ff6f8d69cc527c2e56c684a7..5b4efc927d808b68d5d5a18adaf1991dcd6fef52 100644 --- a/arch/x86/kernel/ftrace.c +++ b/arch/x86/kernel/ftrace.c @@ -37,7 +37,7 @@ static int ftrace_poke_late = 0; -int ftrace_arch_code_modify_prepare(void) +void ftrace_arch_code_modify_prepare(void) __acquires(&text_mutex) { /* @@ -47,10 +47,9 @@ int ftrace_arch_code_modify_prepare(void) */ mutex_lock(&text_mutex); ftrace_poke_late = 1; - return 0; } -int ftrace_arch_code_modify_post_process(void) +void ftrace_arch_code_modify_post_process(void) __releases(&text_mutex) { /* @@ -61,7 +60,6 @@ int ftrace_arch_code_modify_post_process(void) text_poke_finish(); ftrace_poke_late = 0; mutex_unlock(&text_mutex); - return 0; } static const char *ftrace_nop_replace(void) diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c index fa700b46588e04df189adb60c17ccac36bca33df..c3636ea4aa71f47e79af3699a657d7586cd85077 100644 --- a/arch/x86/kernel/reboot.c +++ b/arch/x86/kernel/reboot.c @@ -739,10 +739,10 @@ static void native_machine_halt(void) static void native_machine_power_off(void) { - if (pm_power_off) { + if (kernel_can_power_off()) { if (!reboot_force) machine_shutdown(); - pm_power_off(); + do_kernel_power_off(); } /* A fallback in case there is no PM info available */ tboot_shutdown(TB_SHUTDOWN_HALT); diff --git a/arch/x86/kernel/tracepoint.c b/arch/x86/kernel/tracepoint.c index fcfc077afe2dcf86915a1e493bf8ff9048cb5235..03ae1caaa878df00ec5901824e1cc30cbec0f201 100644 --- a/arch/x86/kernel/tracepoint.c +++ b/arch/x86/kernel/tracepoint.c @@ -1,17 +1,11 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Code for supporting irq vector tracepoints. - * * Copyright (C) 2013 Seiji Aguchi - * */ #include #include -#include -#include #include -#include DEFINE_STATIC_KEY_FALSE(trace_pagefault_key); diff --git a/arch/x86/mm/pat/set_memory.c b/arch/x86/mm/pat/set_memory.c index 0656db33574d390e73d2af31ab6815fad1b9922d..1abd5438f1269553cbb5dd7a4a55425a5abfbd60 100644 --- a/arch/x86/mm/pat/set_memory.c +++ b/arch/x86/mm/pat/set_memory.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -29,7 +30,6 @@ #include #include #include -#include #include #include @@ -1805,7 +1805,7 @@ static inline int cpa_clear_pages_array(struct page **pages, int numpages, } /* - * _set_memory_prot is an internal helper for callers that have been passed + * __set_memory_prot is an internal helper for callers that have been passed * a pgprot_t value from upper layers and a reservation has already been taken. * If you want to set the pgprot to a specific page protocol, use the * set_memory_xx() functions. @@ -1914,6 +1914,51 @@ int set_memory_wb(unsigned long addr, int numpages) } EXPORT_SYMBOL(set_memory_wb); +/* Prevent speculative access to a page by marking it not-present */ +#ifdef CONFIG_X86_64 +int set_mce_nospec(unsigned long pfn) +{ + unsigned long decoy_addr; + int rc; + + /* SGX pages are not in the 1:1 map */ + if (arch_is_platform_page(pfn << PAGE_SHIFT)) + return 0; + /* + * We would like to just call: + * set_memory_XX((unsigned long)pfn_to_kaddr(pfn), 1); + * but doing that would radically increase the odds of a + * speculative access to the poison page because we'd have + * the virtual address of the kernel 1:1 mapping sitting + * around in registers. + * Instead we get tricky. We create a non-canonical address + * that looks just like the one we want, but has bit 63 flipped. + * This relies on set_memory_XX() properly sanitizing any __pa() + * results with __PHYSICAL_MASK or PTE_PFN_MASK. + */ + decoy_addr = (pfn << PAGE_SHIFT) + (PAGE_OFFSET ^ BIT(63)); + + rc = set_memory_np(decoy_addr, 1); + if (rc) + pr_warn("Could not invalidate pfn=0x%lx from 1:1 map\n", pfn); + return rc; +} + +static int set_memory_present(unsigned long *addr, int numpages) +{ + return change_page_attr_set(addr, numpages, __pgprot(_PAGE_PRESENT), 0); +} + +/* Restore full speculative operation to the pfn. */ +int clear_mce_nospec(unsigned long pfn) +{ + unsigned long addr = (unsigned long) pfn_to_kaddr(pfn); + + return set_memory_present(&addr, 1); +} +EXPORT_SYMBOL_GPL(clear_mce_nospec); +#endif /* CONFIG_X86_64 */ + int set_memory_x(unsigned long addr, int numpages) { if (!(__supported_pte_mask & _PAGE_NX)) diff --git a/arch/x86/xen/enlighten_pv.c b/arch/x86/xen/enlighten_pv.c index ca85d1409917aeb62b63f215e88c8ddbaf318c46..f33a4421e7cd6def0c956736707b5d14c3899f7d 100644 --- a/arch/x86/xen/enlighten_pv.c +++ b/arch/x86/xen/enlighten_pv.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -1069,8 +1070,7 @@ static void xen_machine_halt(void) static void xen_machine_power_off(void) { - if (pm_power_off) - pm_power_off(); + do_kernel_power_off(); xen_reboot(SHUTDOWN_poweroff); } diff --git a/crypto/Kconfig b/crypto/Kconfig index 41068811fd0e1d8facff621a9116b7d1e1b59ef7..19197469cfab3d7c6d5c10a53afbf239c88b0044 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -274,7 +274,7 @@ config CRYPTO_ECRDSA config CRYPTO_SM2 tristate "SM2 algorithm" - select CRYPTO_LIB_SM3 + select CRYPTO_SM3 select CRYPTO_AKCIPHER select CRYPTO_MANAGER select MPILIB @@ -1010,9 +1010,12 @@ config CRYPTO_SHA3 http://keccak.noekeon.org/ config CRYPTO_SM3 + tristate + +config CRYPTO_SM3_GENERIC tristate "SM3 digest algorithm" select CRYPTO_HASH - select CRYPTO_LIB_SM3 + select CRYPTO_SM3 help SM3 secure hash function as defined by OSCCA GM/T 0004-2012 SM3). It is part of the Chinese Commercial Cryptography suite. @@ -1025,7 +1028,7 @@ config CRYPTO_SM3_AVX_X86_64 tristate "SM3 digest algorithm (x86_64/AVX)" depends on X86 && 64BIT select CRYPTO_HASH - select CRYPTO_LIB_SM3 + select CRYPTO_SM3 help SM3 secure hash function as defined by OSCCA GM/T 0004-2012 SM3). It is part of the Chinese Commercial Cryptography suite. This is @@ -1572,9 +1575,12 @@ config CRYPTO_SERPENT_AVX2_X86_64 config CRYPTO_SM4 + tristate + +config CRYPTO_SM4_GENERIC tristate "SM4 cipher algorithm" select CRYPTO_ALGAPI - select CRYPTO_LIB_SM4 + select CRYPTO_SM4 help SM4 cipher algorithms (OSCCA GB/T 32907-2016). @@ -1603,7 +1609,7 @@ config CRYPTO_SM4_AESNI_AVX_X86_64 select CRYPTO_SKCIPHER select CRYPTO_SIMD select CRYPTO_ALGAPI - select CRYPTO_LIB_SM4 + select CRYPTO_SM4 help SM4 cipher algorithms (OSCCA GB/T 32907-2016) (x86_64/AES-NI/AVX). @@ -1624,7 +1630,7 @@ config CRYPTO_SM4_AESNI_AVX2_X86_64 select CRYPTO_SKCIPHER select CRYPTO_SIMD select CRYPTO_ALGAPI - select CRYPTO_LIB_SM4 + select CRYPTO_SM4 select CRYPTO_SM4_AESNI_AVX_X86_64 help SM4 cipher algorithms (OSCCA GB/T 32907-2016) (x86_64/AES-NI/AVX2). diff --git a/crypto/Makefile b/crypto/Makefile index f754c4d17d6bdb5df40e2b9e697623a9d95d0745..43bc33e247d19ffb09613f2678a3743364b84d23 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -78,7 +78,8 @@ obj-$(CONFIG_CRYPTO_SHA1) += sha1_generic.o obj-$(CONFIG_CRYPTO_SHA256) += sha256_generic.o obj-$(CONFIG_CRYPTO_SHA512) += sha512_generic.o obj-$(CONFIG_CRYPTO_SHA3) += sha3_generic.o -obj-$(CONFIG_CRYPTO_SM3) += sm3_generic.o +obj-$(CONFIG_CRYPTO_SM3) += sm3.o +obj-$(CONFIG_CRYPTO_SM3_GENERIC) += sm3_generic.o obj-$(CONFIG_CRYPTO_STREEBOG) += streebog_generic.o obj-$(CONFIG_CRYPTO_WP512) += wp512.o CFLAGS_wp512.o := $(call cc-option,-fno-schedule-insns) # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79149 @@ -134,7 +135,8 @@ obj-$(CONFIG_CRYPTO_SERPENT) += serpent_generic.o CFLAGS_serpent_generic.o := $(call cc-option,-fsched-pressure) # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79149 obj-$(CONFIG_CRYPTO_AES) += aes_generic.o CFLAGS_aes_generic.o := $(call cc-option,-fno-code-hoisting) # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83356 -obj-$(CONFIG_CRYPTO_SM4) += sm4_generic.o +obj-$(CONFIG_CRYPTO_SM4) += sm4.o +obj-$(CONFIG_CRYPTO_SM4_GENERIC) += sm4_generic.o obj-$(CONFIG_CRYPTO_AES_TI) += aes_ti.o obj-$(CONFIG_CRYPTO_CAMELLIA) += camellia_generic.o obj-$(CONFIG_CRYPTO_CAST_COMMON) += cast_common.o diff --git a/crypto/cryptd.c b/crypto/cryptd.c index a1bea0f4baa881b73422618669634b77abe1f68c..668095eca0fafb52137e33ee70a97c2695b3180b 100644 --- a/crypto/cryptd.c +++ b/crypto/cryptd.c @@ -39,6 +39,10 @@ struct cryptd_cpu_queue { }; struct cryptd_queue { + /* + * Protected by disabling BH to allow enqueueing from softinterrupt and + * dequeuing from kworker (cryptd_queue_worker()). + */ struct cryptd_cpu_queue __percpu *cpu_queue; }; @@ -125,28 +129,28 @@ static void cryptd_fini_queue(struct cryptd_queue *queue) static int cryptd_enqueue_request(struct cryptd_queue *queue, struct crypto_async_request *request) { - int cpu, err; + int err; struct cryptd_cpu_queue *cpu_queue; refcount_t *refcnt; - cpu = get_cpu(); + local_bh_disable(); cpu_queue = this_cpu_ptr(queue->cpu_queue); err = crypto_enqueue_request(&cpu_queue->queue, request); refcnt = crypto_tfm_ctx(request->tfm); if (err == -ENOSPC) - goto out_put_cpu; + goto out; - queue_work_on(cpu, cryptd_wq, &cpu_queue->work); + queue_work_on(smp_processor_id(), cryptd_wq, &cpu_queue->work); if (!refcount_read(refcnt)) - goto out_put_cpu; + goto out; refcount_inc(refcnt); -out_put_cpu: - put_cpu(); +out: + local_bh_enable(); return err; } @@ -162,15 +166,10 @@ static void cryptd_queue_worker(struct work_struct *work) cpu_queue = container_of(work, struct cryptd_cpu_queue, work); /* * Only handle one request at a time to avoid hogging crypto workqueue. - * preempt_disable/enable is used to prevent being preempted by - * cryptd_enqueue_request(). local_bh_disable/enable is used to prevent - * cryptd_enqueue_request() being accessed from software interrupts. */ local_bh_disable(); - preempt_disable(); backlog = crypto_get_backlog(&cpu_queue->queue); req = crypto_dequeue_request(&cpu_queue->queue); - preempt_enable(); local_bh_enable(); if (!req) diff --git a/crypto/crypto_engine.c b/crypto/crypto_engine.c index 6056a990c9f2c61b95bd5269f755d3da00f35304..bb8e77077f020ce9b6ee9de194d47ad9e0258cc0 100644 --- a/crypto/crypto_engine.c +++ b/crypto/crypto_engine.c @@ -253,6 +253,7 @@ static void crypto_pump_work(struct kthread_work *work) * crypto_transfer_request - transfer the new request into the engine queue * @engine: the hardware engine * @req: the request need to be listed into the engine queue + * @need_pump: indicates whether queue the pump of request to kthread_work */ static int crypto_transfer_request(struct crypto_engine *engine, struct crypto_async_request *req, diff --git a/crypto/ecrdsa.c b/crypto/ecrdsa.c index b32ffcaad9adfcf49ac67c53af668d10aea3ab88..f3c6b5e15e75baf2e6e72df193efba8c7653d012 100644 --- a/crypto/ecrdsa.c +++ b/crypto/ecrdsa.c @@ -113,15 +113,15 @@ static int ecrdsa_verify(struct akcipher_request *req) /* Step 1: verify that 0 < r < q, 0 < s < q */ if (vli_is_zero(r, ndigits) || - vli_cmp(r, ctx->curve->n, ndigits) == 1 || + vli_cmp(r, ctx->curve->n, ndigits) >= 0 || vli_is_zero(s, ndigits) || - vli_cmp(s, ctx->curve->n, ndigits) == 1) + vli_cmp(s, ctx->curve->n, ndigits) >= 0) return -EKEYREJECTED; /* Step 2: calculate hash (h) of the message (passed as input) */ /* Step 3: calculate e = h \mod q */ vli_from_le64(e, digest, ndigits); - if (vli_cmp(e, ctx->curve->n, ndigits) == 1) + if (vli_cmp(e, ctx->curve->n, ndigits) >= 0) vli_sub(e, e, ctx->curve->n, ndigits); if (vli_is_zero(e, ndigits)) e[0] = 1; @@ -137,7 +137,7 @@ static int ecrdsa_verify(struct akcipher_request *req) /* Step 6: calculate point C = z_1P + z_2Q, and R = x_c \mod q */ ecc_point_mult_shamir(&cc, z1, &ctx->curve->g, z2, &ctx->pub_key, ctx->curve); - if (vli_cmp(cc.x, ctx->curve->n, ndigits) == 1) + if (vli_cmp(cc.x, ctx->curve->n, ndigits) >= 0) vli_sub(cc.x, cc.x, ctx->curve->n, ndigits); /* Step 7: if R == r signature is valid */ diff --git a/lib/crypto/sm3.c b/crypto/sm3.c similarity index 100% rename from lib/crypto/sm3.c rename to crypto/sm3.c diff --git a/lib/crypto/sm4.c b/crypto/sm4.c similarity index 94% rename from lib/crypto/sm4.c rename to crypto/sm4.c index 284e62576d0c621692b368bed91936bfaeb6fe4b..2c44193bc27e4a0369a795ed641a6e32ca33cb6b 100644 --- a/lib/crypto/sm4.c +++ b/crypto/sm4.c @@ -11,7 +11,7 @@ #include #include -static const u32 fk[4] = { +static const u32 ____cacheline_aligned fk[4] = { 0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc }; @@ -61,6 +61,14 @@ static const u8 ____cacheline_aligned sbox[256] = { 0x79, 0xee, 0x5f, 0x3e, 0xd7, 0xcb, 0x39, 0x48 }; +extern const u32 crypto_sm4_fk[4] __alias(fk); +extern const u32 crypto_sm4_ck[32] __alias(ck); +extern const u8 crypto_sm4_sbox[256] __alias(sbox); + +EXPORT_SYMBOL(crypto_sm4_fk); +EXPORT_SYMBOL(crypto_sm4_ck); +EXPORT_SYMBOL(crypto_sm4_sbox); + static inline u32 sm4_t_non_lin_sub(u32 x) { u32 out; diff --git a/crypto/testmgr.c b/crypto/testmgr.c index 4948201065cc481049549271bb9678b9dd226a48..5801a8f9f713475ffd23441de62deb202469efc1 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c @@ -232,6 +232,20 @@ enum finalization_type { FINALIZATION_TYPE_DIGEST, /* use digest() */ }; +/* + * Whether the crypto operation will occur in-place, and if so whether the + * source and destination scatterlist pointers will coincide (req->src == + * req->dst), or whether they'll merely point to two separate scatterlists + * (req->src != req->dst) that reference the same underlying memory. + * + * This is only relevant for algorithm types that support in-place operation. + */ +enum inplace_mode { + OUT_OF_PLACE, + INPLACE_ONE_SGLIST, + INPLACE_TWO_SGLISTS, +}; + #define TEST_SG_TOTAL 10000 /** @@ -265,7 +279,7 @@ struct test_sg_division { * crypto test vector can be tested. * * @name: name of this config, logged for debugging purposes if a test fails - * @inplace: operate on the data in-place, if applicable for the algorithm type? + * @inplace_mode: whether and how to operate on the data in-place, if applicable * @req_flags: extra request_flags, e.g. CRYPTO_TFM_REQ_MAY_SLEEP * @src_divs: description of how to arrange the source scatterlist * @dst_divs: description of how to arrange the dst scatterlist, if applicable @@ -282,7 +296,7 @@ struct test_sg_division { */ struct testvec_config { const char *name; - bool inplace; + enum inplace_mode inplace_mode; u32 req_flags; struct test_sg_division src_divs[XBUFSIZE]; struct test_sg_division dst_divs[XBUFSIZE]; @@ -307,11 +321,16 @@ struct testvec_config { /* Configs for skciphers and aeads */ static const struct testvec_config default_cipher_testvec_configs[] = { { - .name = "in-place", - .inplace = true, + .name = "in-place (one sglist)", + .inplace_mode = INPLACE_ONE_SGLIST, + .src_divs = { { .proportion_of_total = 10000 } }, + }, { + .name = "in-place (two sglists)", + .inplace_mode = INPLACE_TWO_SGLISTS, .src_divs = { { .proportion_of_total = 10000 } }, }, { .name = "out-of-place", + .inplace_mode = OUT_OF_PLACE, .src_divs = { { .proportion_of_total = 10000 } }, }, { .name = "unaligned buffer, offset=1", @@ -349,7 +368,7 @@ static const struct testvec_config default_cipher_testvec_configs[] = { .key_offset = 3, }, { .name = "misaligned splits crossing pages, inplace", - .inplace = true, + .inplace_mode = INPLACE_ONE_SGLIST, .src_divs = { { .proportion_of_total = 7500, @@ -749,18 +768,39 @@ static int build_cipher_test_sglists(struct cipher_test_sglists *tsgls, iov_iter_kvec(&input, WRITE, inputs, nr_inputs, src_total_len); err = build_test_sglist(&tsgls->src, cfg->src_divs, alignmask, - cfg->inplace ? + cfg->inplace_mode != OUT_OF_PLACE ? max(dst_total_len, src_total_len) : src_total_len, &input, NULL); if (err) return err; - if (cfg->inplace) { + /* + * In-place crypto operations can use the same scatterlist for both the + * source and destination (req->src == req->dst), or can use separate + * scatterlists (req->src != req->dst) which point to the same + * underlying memory. Make sure to test both cases. + */ + if (cfg->inplace_mode == INPLACE_ONE_SGLIST) { tsgls->dst.sgl_ptr = tsgls->src.sgl; tsgls->dst.nents = tsgls->src.nents; return 0; } + if (cfg->inplace_mode == INPLACE_TWO_SGLISTS) { + /* + * For now we keep it simple and only test the case where the + * two scatterlists have identical entries, rather than + * different entries that split up the same memory differently. + */ + memcpy(tsgls->dst.sgl, tsgls->src.sgl, + tsgls->src.nents * sizeof(tsgls->src.sgl[0])); + memcpy(tsgls->dst.sgl_saved, tsgls->src.sgl, + tsgls->src.nents * sizeof(tsgls->src.sgl[0])); + tsgls->dst.sgl_ptr = tsgls->dst.sgl; + tsgls->dst.nents = tsgls->src.nents; + return 0; + } + /* Out of place */ return build_test_sglist(&tsgls->dst, cfg->dst_divs[0].proportion_of_total ? cfg->dst_divs : cfg->src_divs, @@ -995,9 +1035,19 @@ static void generate_random_testvec_config(struct testvec_config *cfg, p += scnprintf(p, end - p, "random:"); - if (prandom_u32() % 2 == 0) { - cfg->inplace = true; - p += scnprintf(p, end - p, " inplace"); + switch (prandom_u32() % 4) { + case 0: + case 1: + cfg->inplace_mode = OUT_OF_PLACE; + break; + case 2: + cfg->inplace_mode = INPLACE_ONE_SGLIST; + p += scnprintf(p, end - p, " inplace_one_sglist"); + break; + default: + cfg->inplace_mode = INPLACE_TWO_SGLISTS; + p += scnprintf(p, end - p, " inplace_two_sglists"); + break; } if (prandom_u32() % 2 == 0) { @@ -1034,7 +1084,7 @@ static void generate_random_testvec_config(struct testvec_config *cfg, cfg->req_flags); p += scnprintf(p, end - p, "]"); - if (!cfg->inplace && prandom_u32() % 2 == 0) { + if (cfg->inplace_mode == OUT_OF_PLACE && prandom_u32() % 2 == 0) { p += scnprintf(p, end - p, " dst_divs=["); p = generate_random_sgl_divisions(cfg->dst_divs, ARRAY_SIZE(cfg->dst_divs), @@ -2085,7 +2135,8 @@ static int test_aead_vec_cfg(int enc, const struct aead_testvec *vec, /* Check for the correct output (ciphertext or plaintext) */ err = verify_correct_output(&tsgls->dst, enc ? vec->ctext : vec->ptext, enc ? vec->clen : vec->plen, - vec->alen, enc || !cfg->inplace); + vec->alen, + enc || cfg->inplace_mode == OUT_OF_PLACE); if (err == -EOVERFLOW) { pr_err("alg: aead: %s %s overran dst buffer on test vector %s, cfg=\"%s\"\n", driver, op, vec_name, cfg->name); diff --git a/drivers/Makefile b/drivers/Makefile index 020780b6b4d221c4dd18cd0af9ec21b4590715ad..f735c49551432a442e3de4cb06884f9c2b42ff03 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -72,9 +72,9 @@ obj-$(CONFIG_PARPORT) += parport/ obj-y += base/ block/ misc/ mfd/ nfc/ obj-$(CONFIG_LIBNVDIMM) += nvdimm/ obj-$(CONFIG_DAX) += dax/ -obj-$(CONFIG_CXL_BUS) += cxl/ obj-$(CONFIG_DMA_SHARED_BUFFER) += dma-buf/ obj-$(CONFIG_NUBUS) += nubus/ +obj-y += cxl/ obj-y += macintosh/ obj-y += scsi/ obj-y += nvme/ diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c index db487ff9dd1b6313e66061f391350258a1858bf7..c29e41bfcf35d1f1d78f3738a33923162dd394b4 100644 --- a/drivers/acpi/ac.c +++ b/drivers/acpi/ac.c @@ -32,7 +32,6 @@ MODULE_AUTHOR("Paul Diefenbaugh"); MODULE_DESCRIPTION("ACPI AC Adapter Driver"); MODULE_LICENSE("GPL"); - static int acpi_ac_add(struct acpi_device *device); static int acpi_ac_remove(struct acpi_device *device); static void acpi_ac_notify(struct acpi_device *device, u32 event); @@ -125,6 +124,7 @@ static int get_ac_property(struct power_supply *psy, default: return -EINVAL; } + return 0; } @@ -286,6 +286,7 @@ static int acpi_ac_resume(struct device *dev) return 0; if (old_state != ac->state) kobject_uevent(&ac->charger->dev.kobj, KOBJ_CHANGE); + return 0; } #else @@ -296,7 +297,6 @@ static int acpi_ac_remove(struct acpi_device *device) { struct acpi_ac *ac = NULL; - if (!device || !acpi_driver_data(device)) return -EINVAL; diff --git a/drivers/acpi/acpi_video.c b/drivers/acpi/acpi_video.c index 990ff5b0aeb875d919efad799aa36fb6d5183f8e..e07782b1fbb68eb6ca3d7a7552387266519f1d83 100644 --- a/drivers/acpi/acpi_video.c +++ b/drivers/acpi/acpi_video.c @@ -1707,24 +1707,23 @@ static int acpi_video_resume(struct notifier_block *nb, int i; switch (val) { - case PM_HIBERNATION_PREPARE: - case PM_SUSPEND_PREPARE: - case PM_RESTORE_PREPARE: - return NOTIFY_DONE; - } - - video = container_of(nb, struct acpi_video_bus, pm_nb); - - dev_info(&video->device->dev, "Restoring backlight state\n"); + case PM_POST_HIBERNATION: + case PM_POST_SUSPEND: + case PM_POST_RESTORE: + video = container_of(nb, struct acpi_video_bus, pm_nb); + + dev_info(&video->device->dev, "Restoring backlight state\n"); + + for (i = 0; i < video->attached_count; i++) { + video_device = video->attached_array[i].bind_info; + if (video_device && video_device->brightness) + acpi_video_device_lcd_set_level(video_device, + video_device->brightness->curr); + } - for (i = 0; i < video->attached_count; i++) { - video_device = video->attached_array[i].bind_info; - if (video_device && video_device->brightness) - acpi_video_device_lcd_set_level(video_device, - video_device->brightness->curr); + return NOTIFY_OK; } - - return NOTIFY_OK; + return NOTIFY_DONE; } static acpi_status diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index dc208f5f5a1f7893f55ef6a835cd3c80a6094970..306513fec1e1f71ca0c0bb0464d44e4fb3926967 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -52,7 +52,6 @@ static bool battery_driver_registered; static int battery_bix_broken_package; static int battery_notification_delay_ms; static int battery_ac_is_broken; -static int battery_quirk_notcharging; static unsigned int cache_time = 1000; module_param(cache_time, uint, 0644); MODULE_PARM_DESC(cache_time, "cache time in milliseconds"); @@ -216,10 +215,8 @@ static int acpi_battery_get_property(struct power_supply *psy, val->intval = POWER_SUPPLY_STATUS_CHARGING; else if (acpi_battery_is_charged(battery)) val->intval = POWER_SUPPLY_STATUS_FULL; - else if (battery_quirk_notcharging) - val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING; else - val->intval = POWER_SUPPLY_STATUS_UNKNOWN; + val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING; break; case POWER_SUPPLY_PROP_PRESENT: val->intval = acpi_battery_present(battery); @@ -1105,12 +1102,6 @@ battery_ac_is_broken_quirk(const struct dmi_system_id *d) return 0; } -static int __init battery_quirk_not_charging(const struct dmi_system_id *d) -{ - battery_quirk_notcharging = 1; - return 0; -} - static const struct dmi_system_id bat_dmi_table[] __initconst = { { /* NEC LZ750/LS */ @@ -1139,19 +1130,6 @@ static const struct dmi_system_id bat_dmi_table[] __initconst = { DMI_MATCH(DMI_BIOS_DATE, "08/22/2014"), }, }, - { - /* - * On Lenovo ThinkPads the BIOS specification defines - * a state when the bits for charging and discharging - * are both set to 0. That state is "Not Charging". - */ - .callback = battery_quirk_not_charging, - .ident = "Lenovo ThinkPad", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad"), - }, - }, { /* Microsoft Surface Go 3 */ .callback = battery_notification_delay_quirk, diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index b67d2ee77cd136eeab5e1b0485d1a26b1be2b607..86fa61a21826c3f25d7eef67255aa065da402bb6 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -443,7 +443,7 @@ static void acpi_bus_osc_negotiate_usb_control(void) } osc_sb_native_usb4_control = - control & ((u32 *)context.ret.pointer)[OSC_CONTROL_DWORD]; + control & acpi_osc_ctx_get_pci_control(&context); acpi_bus_decode_usb_osc("USB4 _OSC: OS supports", control); acpi_bus_decode_usb_osc("USB4 _OSC: OS controls", diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c index 3b299b28a8afe66f83ff3676674bd687877dd006..903528f7e187e4bc1698e4d24ed5d2693f080527 100644 --- a/drivers/acpi/cppc_acpi.c +++ b/drivers/acpi/cppc_acpi.c @@ -315,7 +315,7 @@ static int send_pcc_cmd(int pcc_ss_id, u16 cmd) goto end; } - /* wait for completion and check for PCC errro bit */ + /* wait for completion and check for PCC error bit */ ret = check_pcc_chan(pcc_ss_id, true); if (pcc_ss_data->pcc_mrtt) diff --git a/drivers/acpi/dptf/dptf_pch_fivr.c b/drivers/acpi/dptf/dptf_pch_fivr.c index c0da24c9f8c36bb526ad3958fc6438198a228b31..4919e7abe93f47280157dcc91f10f09434951255 100644 --- a/drivers/acpi/dptf/dptf_pch_fivr.c +++ b/drivers/acpi/dptf/dptf_pch_fivr.c @@ -151,6 +151,7 @@ static int pch_fivr_remove(struct platform_device *pdev) static const struct acpi_device_id pch_fivr_device_ids[] = { {"INTC1045", 0}, {"INTC1049", 0}, + {"INTC1064", 0}, {"INTC10A3", 0}, {"", 0}, }; diff --git a/drivers/acpi/dptf/dptf_power.c b/drivers/acpi/dptf/dptf_power.c index 407b89d8a2ce17a718235a750c4e3bcaaa9acb06..86561eda939f7953b21ebd4b85366ee15094a4fa 100644 --- a/drivers/acpi/dptf/dptf_power.c +++ b/drivers/acpi/dptf/dptf_power.c @@ -232,6 +232,8 @@ static const struct acpi_device_id int3407_device_ids[] = { {"INTC1050", 0}, {"INTC1060", 0}, {"INTC1061", 0}, + {"INTC1065", 0}, + {"INTC1066", 0}, {"INTC10A4", 0}, {"INTC10A5", 0}, {"", 0}, diff --git a/drivers/acpi/dptf/int340x_thermal.c b/drivers/acpi/dptf/int340x_thermal.c index 42a5563465484aedf742c75464b2406c62bcf319..b7113fa92fa68503ff683fca441b9c7d546037b1 100644 --- a/drivers/acpi/dptf/int340x_thermal.c +++ b/drivers/acpi/dptf/int340x_thermal.c @@ -27,6 +27,7 @@ static const struct acpi_device_id int340x_thermal_device_ids[] = { {"INT3532"}, {"INTC1040"}, {"INTC1041"}, + {"INTC1042"}, {"INTC1043"}, {"INTC1044"}, {"INTC1045"}, @@ -37,6 +38,11 @@ static const struct acpi_device_id int340x_thermal_device_ids[] = { {"INTC1050"}, {"INTC1060"}, {"INTC1061"}, + {"INTC1062"}, + {"INTC1063"}, + {"INTC1064"}, + {"INTC1065"}, + {"INTC1066"}, {"INTC10A0"}, {"INTC10A1"}, {"INTC10A2"}, diff --git a/drivers/acpi/fan.h b/drivers/acpi/fan.h index 44728529a5b6bca99c19367b156cbadbea71433d..e7b4b4e4a55e487740ec1a2acac68cd6ba689053 100644 --- a/drivers/acpi/fan.h +++ b/drivers/acpi/fan.h @@ -14,6 +14,7 @@ {"INT3404", }, /* Fan */ \ {"INTC1044", }, /* Fan for Tiger Lake generation */ \ {"INTC1048", }, /* Fan for Alder Lake generation */ \ + {"INTC1063", }, /* Fan for Meteor Lake generation */ \ {"INTC10A2", }, /* Fan for Raptor Lake generation */ \ {"PNP0C0B", } /* Generic ACPI fan */ diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index ef104809f27b17415758cff0d3793a8d7193b070..8d769114a0487013e6635e88139ce8fb96aaa5bf 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c @@ -79,17 +79,17 @@ static struct acpi_bus_type *acpi_get_bus_type(struct device *dev) static int find_child_checks(struct acpi_device *adev, bool check_children) { - bool sta_present = true; unsigned long long sta; acpi_status status; + if (check_children && list_empty(&adev->children)) + return -ENODEV; + status = acpi_evaluate_integer(adev->handle, "_STA", NULL, &sta); if (status == AE_NOT_FOUND) - sta_present = false; - else if (ACPI_FAILURE(status) || !(sta & ACPI_STA_DEVICE_ENABLED)) - return -ENODEV; + return FIND_CHILD_MIN_SCORE; - if (check_children && list_empty(&adev->children)) + if (ACPI_FAILURE(status) || !(sta & ACPI_STA_DEVICE_ENABLED)) return -ENODEV; /* @@ -99,8 +99,10 @@ static int find_child_checks(struct acpi_device *adev, bool check_children) * matched going forward. [This means a second spec violation in a row, * so whatever we do here is best effort anyway.] */ - return sta_present && !adev->pnp.type.platform_id ? - FIND_CHILD_MAX_SCORE : FIND_CHILD_MIN_SCORE; + if (adev->pnp.type.platform_id) + return FIND_CHILD_MIN_SCORE; + + return FIND_CHILD_MAX_SCORE; } struct acpi_device *acpi_find_child_device(struct acpi_device *parent, diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c index fe61f617a943bd4640e08f6e5f5b684df1780871..ae5f4acf2675390f58c38aee79c7a0e68e14d47c 100644 --- a/drivers/acpi/nfit/core.c +++ b/drivers/acpi/nfit/core.c @@ -1230,7 +1230,7 @@ static ssize_t hw_error_scrub_store(struct device *dev, if (rc) return rc; - nfit_device_lock(dev); + device_lock(dev); nd_desc = dev_get_drvdata(dev); if (nd_desc) { struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc); @@ -1247,7 +1247,7 @@ static ssize_t hw_error_scrub_store(struct device *dev, break; } } - nfit_device_unlock(dev); + device_unlock(dev); if (rc) return rc; return size; @@ -1267,10 +1267,10 @@ static ssize_t scrub_show(struct device *dev, ssize_t rc = -ENXIO; bool busy; - nfit_device_lock(dev); + device_lock(dev); nd_desc = dev_get_drvdata(dev); if (!nd_desc) { - nfit_device_unlock(dev); + device_unlock(dev); return rc; } acpi_desc = to_acpi_desc(nd_desc); @@ -1287,7 +1287,7 @@ static ssize_t scrub_show(struct device *dev, } mutex_unlock(&acpi_desc->init_mutex); - nfit_device_unlock(dev); + device_unlock(dev); return rc; } @@ -1304,14 +1304,14 @@ static ssize_t scrub_store(struct device *dev, if (val != 1) return -EINVAL; - nfit_device_lock(dev); + device_lock(dev); nd_desc = dev_get_drvdata(dev); if (nd_desc) { struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc); rc = acpi_nfit_ars_rescan(acpi_desc, ARS_REQ_LONG); } - nfit_device_unlock(dev); + device_unlock(dev); if (rc) return rc; return size; @@ -1697,9 +1697,9 @@ static void acpi_nvdimm_notify(acpi_handle handle, u32 event, void *data) struct acpi_device *adev = data; struct device *dev = &adev->dev; - nfit_device_lock(dev->parent); + device_lock(dev->parent); __acpi_nvdimm_notify(dev, event); - nfit_device_unlock(dev->parent); + device_unlock(dev->parent); } static bool acpi_nvdimm_has_method(struct acpi_device *adev, char *method) @@ -3152,8 +3152,8 @@ static int acpi_nfit_flush_probe(struct nvdimm_bus_descriptor *nd_desc) struct device *dev = acpi_desc->dev; /* Bounce the device lock to flush acpi_nfit_add / acpi_nfit_notify */ - nfit_device_lock(dev); - nfit_device_unlock(dev); + device_lock(dev); + device_unlock(dev); /* Bounce the init_mutex to complete initial registration */ mutex_lock(&acpi_desc->init_mutex); @@ -3305,8 +3305,8 @@ void acpi_nfit_shutdown(void *data) * acpi_nfit_ars_rescan() submissions have had a chance to * either submit or see ->cancel set. */ - nfit_device_lock(bus_dev); - nfit_device_unlock(bus_dev); + device_lock(bus_dev); + device_unlock(bus_dev); flush_workqueue(nfit_wq); } @@ -3449,9 +3449,9 @@ EXPORT_SYMBOL_GPL(__acpi_nfit_notify); static void acpi_nfit_notify(struct acpi_device *adev, u32 event) { - nfit_device_lock(&adev->dev); + device_lock(&adev->dev); __acpi_nfit_notify(&adev->dev, adev->handle, event); - nfit_device_unlock(&adev->dev); + device_unlock(&adev->dev); } static const struct acpi_device_id acpi_nfit_ids[] = { diff --git a/drivers/acpi/nfit/mce.c b/drivers/acpi/nfit/mce.c index ee8d9973f60b885de1efce97d0b31fc68fec1091..d48a388b796ed0608296f17d9b435d50e261ac44 100644 --- a/drivers/acpi/nfit/mce.c +++ b/drivers/acpi/nfit/mce.c @@ -32,6 +32,7 @@ static int nfit_handle_mce(struct notifier_block *nb, unsigned long val, */ mutex_lock(&acpi_desc_lock); list_for_each_entry(acpi_desc, &acpi_descs, list) { + unsigned int align = 1UL << MCI_MISC_ADDR_LSB(mce->misc); struct device *dev = acpi_desc->dev; int found_match = 0; @@ -63,8 +64,7 @@ static int nfit_handle_mce(struct notifier_block *nb, unsigned long val, /* If this fails due to an -ENOMEM, there is little we can do */ nvdimm_bus_add_badrange(acpi_desc->nvdimm_bus, - ALIGN(mce->addr, L1_CACHE_BYTES), - L1_CACHE_BYTES); + ALIGN_DOWN(mce->addr, align), align); nvdimm_region_notify(nfit_spa->nd_region, NVDIMM_REVALIDATE_POISON); diff --git a/drivers/acpi/nfit/nfit.h b/drivers/acpi/nfit/nfit.h index 50882bdbeb96e42312c39262007b7f4015a2b922..6023ad61831aa3a1d7f1d9c12c65dad20775bc70 100644 --- a/drivers/acpi/nfit/nfit.h +++ b/drivers/acpi/nfit/nfit.h @@ -337,30 +337,6 @@ static inline struct acpi_nfit_desc *to_acpi_desc( return container_of(nd_desc, struct acpi_nfit_desc, nd_desc); } -#ifdef CONFIG_PROVE_LOCKING -static inline void nfit_device_lock(struct device *dev) -{ - device_lock(dev); - mutex_lock(&dev->lockdep_mutex); -} - -static inline void nfit_device_unlock(struct device *dev) -{ - mutex_unlock(&dev->lockdep_mutex); - device_unlock(dev); -} -#else -static inline void nfit_device_lock(struct device *dev) -{ - device_lock(dev); -} - -static inline void nfit_device_unlock(struct device *dev) -{ - device_unlock(dev); -} -#endif - const guid_t *to_nfit_uuid(enum nfit_uuids id); int acpi_nfit_init(struct acpi_nfit_desc *acpi_desc, void *nfit, acpi_size sz); void acpi_nfit_shutdown(void *data); diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 7a70c4bfc23c6684a68c9e517dfc64700c92d98b..3269a888fb7a97a3566be8eaa76ad17eb0843805 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -36,7 +36,6 @@ #include #include "acpica/accommon.h" -#include "acpica/acnamesp.h" #include "internal.h" /* Definitions for ACPI_DEBUG_PRINT() */ @@ -1496,91 +1495,6 @@ int acpi_check_region(resource_size_t start, resource_size_t n, } EXPORT_SYMBOL(acpi_check_region); -static acpi_status acpi_deactivate_mem_region(acpi_handle handle, u32 level, - void *_res, void **return_value) -{ - struct acpi_mem_space_context **mem_ctx; - union acpi_operand_object *handler_obj; - union acpi_operand_object *region_obj2; - union acpi_operand_object *region_obj; - struct resource *res = _res; - acpi_status status; - - region_obj = acpi_ns_get_attached_object(handle); - if (!region_obj) - return AE_OK; - - handler_obj = region_obj->region.handler; - if (!handler_obj) - return AE_OK; - - if (region_obj->region.space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) - return AE_OK; - - if (!(region_obj->region.flags & AOPOBJ_SETUP_COMPLETE)) - return AE_OK; - - region_obj2 = acpi_ns_get_secondary_object(region_obj); - if (!region_obj2) - return AE_OK; - - mem_ctx = (void *)®ion_obj2->extra.region_context; - - if (!(mem_ctx[0]->address >= res->start && - mem_ctx[0]->address < res->end)) - return AE_OK; - - status = handler_obj->address_space.setup(region_obj, - ACPI_REGION_DEACTIVATE, - NULL, (void **)mem_ctx); - if (ACPI_SUCCESS(status)) - region_obj->region.flags &= ~(AOPOBJ_SETUP_COMPLETE); - - return status; -} - -/** - * acpi_release_memory - Release any mappings done to a memory region - * @handle: Handle to namespace node - * @res: Memory resource - * @level: A level that terminates the search - * - * Walks through @handle and unmaps all SystemMemory Operation Regions that - * overlap with @res and that have already been activated (mapped). - * - * This is a helper that allows drivers to place special requirements on memory - * region that may overlap with operation regions, primarily allowing them to - * safely map the region as non-cached memory. - * - * The unmapped Operation Regions will be automatically remapped next time they - * are called, so the drivers do not need to do anything else. - */ -acpi_status acpi_release_memory(acpi_handle handle, struct resource *res, - u32 level) -{ - acpi_status status; - - if (!(res->flags & IORESOURCE_MEM)) - return AE_TYPE; - - status = acpi_walk_namespace(ACPI_TYPE_REGION, handle, level, - acpi_deactivate_mem_region, NULL, - res, NULL); - if (ACPI_FAILURE(status)) - return status; - - /* - * Wait for all of the mappings queued up for removal by - * acpi_deactivate_mem_region() to actually go away. - */ - synchronize_rcu(); - rcu_barrier(); - flush_scheduled_work(); - - return AE_OK; -} -EXPORT_SYMBOL_GPL(acpi_release_memory); - /* * Let drivers know whether the resource checks are effective */ diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index b3b507f20e87edf061ca9099fac1070de1be3255..d57cf8454b93e3be6a67546a3a654458c8e71ddf 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -140,6 +140,17 @@ static struct pci_osc_bit_struct pci_osc_control_bit[] = { { OSC_PCI_EXPRESS_DPC_CONTROL, "DPC" }, }; +static struct pci_osc_bit_struct cxl_osc_support_bit[] = { + { OSC_CXL_1_1_PORT_REG_ACCESS_SUPPORT, "CXL11PortRegAccess" }, + { OSC_CXL_2_0_PORT_DEV_REG_ACCESS_SUPPORT, "CXL20PortDevRegAccess" }, + { OSC_CXL_PROTOCOL_ERR_REPORTING_SUPPORT, "CXLProtocolErrorReporting" }, + { OSC_CXL_NATIVE_HP_SUPPORT, "CXLNativeHotPlug" }, +}; + +static struct pci_osc_bit_struct cxl_osc_control_bit[] = { + { OSC_CXL_ERROR_REPORTING_CONTROL, "CXLMemErrorReporting" }, +}; + static void decode_osc_bits(struct acpi_pci_root *root, char *msg, u32 word, struct pci_osc_bit_struct *table, int size) { @@ -168,33 +179,73 @@ static void decode_osc_control(struct acpi_pci_root *root, char *msg, u32 word) ARRAY_SIZE(pci_osc_control_bit)); } +static void decode_cxl_osc_support(struct acpi_pci_root *root, char *msg, u32 word) +{ + decode_osc_bits(root, msg, word, cxl_osc_support_bit, + ARRAY_SIZE(cxl_osc_support_bit)); +} + +static void decode_cxl_osc_control(struct acpi_pci_root *root, char *msg, u32 word) +{ + decode_osc_bits(root, msg, word, cxl_osc_control_bit, + ARRAY_SIZE(cxl_osc_control_bit)); +} + +static inline bool is_pcie(struct acpi_pci_root *root) +{ + return root->bridge_type == ACPI_BRIDGE_TYPE_PCIE; +} + +static inline bool is_cxl(struct acpi_pci_root *root) +{ + return root->bridge_type == ACPI_BRIDGE_TYPE_CXL; +} + static u8 pci_osc_uuid_str[] = "33DB4D5B-1FF7-401C-9657-7441C03DD766"; +static u8 cxl_osc_uuid_str[] = "68F2D50B-C469-4d8A-BD3D-941A103FD3FC"; -static acpi_status acpi_pci_run_osc(acpi_handle handle, - const u32 *capbuf, u32 *retval) +static char *to_uuid(struct acpi_pci_root *root) +{ + if (is_cxl(root)) + return cxl_osc_uuid_str; + return pci_osc_uuid_str; +} + +static int cap_length(struct acpi_pci_root *root) +{ + if (is_cxl(root)) + return sizeof(u32) * OSC_CXL_CAPABILITY_DWORDS; + return sizeof(u32) * OSC_PCI_CAPABILITY_DWORDS; +} + +static acpi_status acpi_pci_run_osc(struct acpi_pci_root *root, + const u32 *capbuf, u32 *pci_control, + u32 *cxl_control) { struct acpi_osc_context context = { - .uuid_str = pci_osc_uuid_str, + .uuid_str = to_uuid(root), .rev = 1, - .cap.length = 12, + .cap.length = cap_length(root), .cap.pointer = (void *)capbuf, }; acpi_status status; - status = acpi_run_osc(handle, &context); + status = acpi_run_osc(root->device->handle, &context); if (ACPI_SUCCESS(status)) { - *retval = *((u32 *)(context.ret.pointer + 8)); + *pci_control = acpi_osc_ctx_get_pci_control(&context); + if (is_cxl(root)) + *cxl_control = acpi_osc_ctx_get_cxl_control(&context); kfree(context.ret.pointer); } return status; } -static acpi_status acpi_pci_query_osc(struct acpi_pci_root *root, - u32 support, - u32 *control) +static acpi_status acpi_pci_query_osc(struct acpi_pci_root *root, u32 support, + u32 *control, u32 cxl_support, + u32 *cxl_control) { acpi_status status; - u32 result, capbuf[3]; + u32 pci_result, cxl_result, capbuf[OSC_CXL_CAPABILITY_DWORDS]; support |= root->osc_support_set; @@ -202,10 +253,28 @@ static acpi_status acpi_pci_query_osc(struct acpi_pci_root *root, capbuf[OSC_SUPPORT_DWORD] = support; capbuf[OSC_CONTROL_DWORD] = *control | root->osc_control_set; - status = acpi_pci_run_osc(root->device->handle, capbuf, &result); + if (is_cxl(root)) { + cxl_support |= root->osc_ext_support_set; + capbuf[OSC_EXT_SUPPORT_DWORD] = cxl_support; + capbuf[OSC_EXT_CONTROL_DWORD] = *cxl_control | root->osc_ext_control_set; + } + +retry: + status = acpi_pci_run_osc(root, capbuf, &pci_result, &cxl_result); if (ACPI_SUCCESS(status)) { root->osc_support_set = support; - *control = result; + *control = pci_result; + if (is_cxl(root)) { + root->osc_ext_support_set = cxl_support; + *cxl_control = cxl_result; + } + } else if (is_cxl(root)) { + /* + * CXL _OSC is optional on CXL 1.1 hosts. Fall back to PCIe _OSC + * upon any failure using CXL _OSC. + */ + root->bridge_type = ACPI_BRIDGE_TYPE_PCIE; + goto retry; } return status; } @@ -321,6 +390,8 @@ EXPORT_SYMBOL_GPL(acpi_get_pci_dev); * @handle: ACPI handle of a PCI root bridge (or PCIe Root Complex). * @mask: Mask of _OSC bits to request control of, place to store control mask. * @support: _OSC supported capability. + * @cxl_mask: Mask of CXL _OSC control bits, place to store control mask. + * @cxl_support: CXL _OSC supported capability. * * Run _OSC query for @mask and if that is successful, compare the returned * mask of control bits with @req. If all of the @req bits are set in the @@ -331,12 +402,14 @@ EXPORT_SYMBOL_GPL(acpi_get_pci_dev); * _OSC bits the BIOS has granted control of, but its contents are meaningless * on failure. **/ -static acpi_status acpi_pci_osc_control_set(acpi_handle handle, u32 *mask, u32 support) +static acpi_status acpi_pci_osc_control_set(acpi_handle handle, u32 *mask, + u32 support, u32 *cxl_mask, + u32 cxl_support) { u32 req = OSC_PCI_EXPRESS_CAPABILITY_CONTROL; struct acpi_pci_root *root; acpi_status status; - u32 ctrl, capbuf[3]; + u32 ctrl, cxl_ctrl = 0, capbuf[OSC_CXL_CAPABILITY_DWORDS]; if (!mask) return AE_BAD_PARAMETER; @@ -348,20 +421,42 @@ static acpi_status acpi_pci_osc_control_set(acpi_handle handle, u32 *mask, u32 s ctrl = *mask; *mask |= root->osc_control_set; + if (is_cxl(root)) { + cxl_ctrl = *cxl_mask; + *cxl_mask |= root->osc_ext_control_set; + } + /* Need to check the available controls bits before requesting them. */ do { - status = acpi_pci_query_osc(root, support, mask); + u32 pci_missing = 0, cxl_missing = 0; + + status = acpi_pci_query_osc(root, support, mask, cxl_support, + cxl_mask); if (ACPI_FAILURE(status)) return status; - if (ctrl == *mask) - break; - decode_osc_control(root, "platform does not support", - ctrl & ~(*mask)); + if (is_cxl(root)) { + if (ctrl == *mask && cxl_ctrl == *cxl_mask) + break; + pci_missing = ctrl & ~(*mask); + cxl_missing = cxl_ctrl & ~(*cxl_mask); + } else { + if (ctrl == *mask) + break; + pci_missing = ctrl & ~(*mask); + } + if (pci_missing) + decode_osc_control(root, "platform does not support", + pci_missing); + if (cxl_missing) + decode_cxl_osc_control(root, "CXL platform does not support", + cxl_missing); ctrl = *mask; - } while (*mask); + cxl_ctrl = *cxl_mask; + } while (*mask || *cxl_mask); /* No need to request _OSC if the control was already granted. */ - if ((root->osc_control_set & ctrl) == ctrl) + if ((root->osc_control_set & ctrl) == ctrl && + (root->osc_ext_control_set & cxl_ctrl) == cxl_ctrl) return AE_OK; if ((ctrl & req) != req) { @@ -373,11 +468,17 @@ static acpi_status acpi_pci_osc_control_set(acpi_handle handle, u32 *mask, u32 s capbuf[OSC_QUERY_DWORD] = 0; capbuf[OSC_SUPPORT_DWORD] = root->osc_support_set; capbuf[OSC_CONTROL_DWORD] = ctrl; - status = acpi_pci_run_osc(handle, capbuf, mask); + if (is_cxl(root)) { + capbuf[OSC_EXT_SUPPORT_DWORD] = root->osc_ext_support_set; + capbuf[OSC_EXT_CONTROL_DWORD] = cxl_ctrl; + } + + status = acpi_pci_run_osc(root, capbuf, mask, cxl_mask); if (ACPI_FAILURE(status)) return status; root->osc_control_set = *mask; + root->osc_ext_control_set = *cxl_mask; return AE_OK; } @@ -403,6 +504,53 @@ static u32 calculate_support(void) return support; } +/* + * Background on hotplug support, and making it depend on only + * CONFIG_HOTPLUG_PCI_PCIE vs. also considering CONFIG_MEMORY_HOTPLUG: + * + * CONFIG_ACPI_HOTPLUG_MEMORY does depend on CONFIG_MEMORY_HOTPLUG, but + * there is no existing _OSC for memory hotplug support. The reason is that + * ACPI memory hotplug requires the OS to acknowledge / coordinate with + * memory plug events via a scan handler. On the CXL side the equivalent + * would be if Linux supported the Mechanical Retention Lock [1], or + * otherwise had some coordination for the driver of a PCI device + * undergoing hotplug to be consulted on whether the hotplug should + * proceed or not. + * + * The concern is that if Linux says no to supporting CXL hotplug then + * the BIOS may say no to giving the OS hotplug control of any other PCIe + * device. So the question here is not whether hotplug is enabled, it's + * whether it is handled natively by the at all OS, and if + * CONFIG_HOTPLUG_PCI_PCIE is enabled then the answer is "yes". + * + * Otherwise, the plan for CXL coordinated remove, since the kernel does + * not support blocking hotplug, is to require the memory device to be + * disabled before hotplug is attempted. When CONFIG_MEMORY_HOTPLUG is + * disabled that step will fail and the remove attempt cancelled by the + * user. If that is not honored and the card is removed anyway then it + * does not matter if CONFIG_MEMORY_HOTPLUG is enabled or not, it will + * cause a crash and other badness. + * + * Therefore, just say yes to CXL hotplug and require removal to + * be coordinated by userspace unless and until the kernel grows better + * mechanisms for doing "managed" removal of devices in consultation with + * the driver. + * + * [1]: https://lore.kernel.org/all/20201122014203.4706-1-ashok.raj@intel.com/ + */ +static u32 calculate_cxl_support(void) +{ + u32 support; + + support = OSC_CXL_2_0_PORT_DEV_REG_ACCESS_SUPPORT; + if (pci_aer_available()) + support |= OSC_CXL_PROTOCOL_ERR_REPORTING_SUPPORT; + if (IS_ENABLED(CONFIG_HOTPLUG_PCI_PCIE)) + support |= OSC_CXL_NATIVE_HP_SUPPORT; + + return support; +} + static u32 calculate_control(void) { u32 control; @@ -434,6 +582,16 @@ static u32 calculate_control(void) return control; } +static u32 calculate_cxl_control(void) +{ + u32 control = 0; + + if (IS_ENABLED(CONFIG_MEMORY_FAILURE)) + control |= OSC_CXL_ERROR_REPORTING_CONTROL; + + return control; +} + static bool os_control_query_checks(struct acpi_pci_root *root, u32 support) { struct acpi_device *device = root->device; @@ -452,10 +610,10 @@ static bool os_control_query_checks(struct acpi_pci_root *root, u32 support) return true; } -static void negotiate_os_control(struct acpi_pci_root *root, int *no_aspm, - bool is_pcie) +static void negotiate_os_control(struct acpi_pci_root *root, int *no_aspm) { u32 support, control = 0, requested = 0; + u32 cxl_support = 0, cxl_control = 0, cxl_requested = 0; acpi_status status; struct acpi_device *device = root->device; acpi_handle handle = device->handle; @@ -479,10 +637,20 @@ static void negotiate_os_control(struct acpi_pci_root *root, int *no_aspm, if (os_control_query_checks(root, support)) requested = control = calculate_control(); - status = acpi_pci_osc_control_set(handle, &control, support); + if (is_cxl(root)) { + cxl_support = calculate_cxl_support(); + decode_cxl_osc_support(root, "OS supports", cxl_support); + cxl_requested = cxl_control = calculate_cxl_control(); + } + + status = acpi_pci_osc_control_set(handle, &control, support, + &cxl_control, cxl_support); if (ACPI_SUCCESS(status)) { if (control) decode_osc_control(root, "OS now controls", control); + if (cxl_control) + decode_cxl_osc_control(root, "OS now controls", + cxl_control); if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM) { /* @@ -504,13 +672,18 @@ static void negotiate_os_control(struct acpi_pci_root *root, int *no_aspm, *no_aspm = 1; /* _OSC is optional for PCI host bridges */ - if ((status == AE_NOT_FOUND) && !is_pcie) + if (status == AE_NOT_FOUND && !is_pcie(root)) return; if (control) { decode_osc_control(root, "OS requested", requested); decode_osc_control(root, "platform willing to grant", control); } + if (cxl_control) { + decode_cxl_osc_control(root, "OS requested", cxl_requested); + decode_cxl_osc_control(root, "platform willing to grant", + cxl_control); + } dev_info(&device->dev, "_OSC: platform retains control of PCIe features (%s)\n", acpi_format_exception(status)); @@ -527,7 +700,7 @@ static int acpi_pci_root_add(struct acpi_device *device, acpi_handle handle = device->handle; int no_aspm = 0; bool hotadd = system_state == SYSTEM_RUNNING; - bool is_pcie; + const char *acpi_hid; root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL); if (!root) @@ -585,8 +758,15 @@ static int acpi_pci_root_add(struct acpi_device *device, root->mcfg_addr = acpi_pci_root_get_mcfg_addr(handle); - is_pcie = strcmp(acpi_device_hid(device), "PNP0A08") == 0; - negotiate_os_control(root, &no_aspm, is_pcie); + acpi_hid = acpi_device_hid(root->device); + if (strcmp(acpi_hid, "PNP0A08") == 0) + root->bridge_type = ACPI_BRIDGE_TYPE_PCIE; + else if (strcmp(acpi_hid, "ACPI0016") == 0) + root->bridge_type = ACPI_BRIDGE_TYPE_CXL; + else + dev_dbg(&device->dev, "Assuming non-PCIe host bridge\n"); + + negotiate_os_control(root, &no_aspm); /* * TBD: Need PCI interface for enumeration/configuration of roots. diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index e9c84d0ac55bd8d901f03905f0ce3dc71c9b4fef..6a5572a1a80ccfba497c95ca96d00ecf6badf4a1 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -38,11 +38,11 @@ #define ACPI_IDLE_STATE_START (IS_ENABLED(CONFIG_ARCH_HAS_CPU_RELAX) ? 1 : 0) static unsigned int max_cstate __read_mostly = ACPI_PROCESSOR_MAX_POWER; -module_param(max_cstate, uint, 0000); -static unsigned int nocst __read_mostly; -module_param(nocst, uint, 0000); -static int bm_check_disable __read_mostly; -module_param(bm_check_disable, uint, 0000); +module_param(max_cstate, uint, 0400); +static bool nocst __read_mostly; +module_param(nocst, bool, 0400); +static bool bm_check_disable __read_mostly; +module_param(bm_check_disable, bool, 0400); static unsigned int latency_factor __read_mostly = 2; module_param(latency_factor, uint, 0644); diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 3147702710afe51d5715c1e3c0b1d7b903cc6451..04ea1569df789c5a56a36d5c7fbdea742f6c7619 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -1035,20 +1035,22 @@ static void acpi_sleep_hibernate_setup(void) static inline void acpi_sleep_hibernate_setup(void) {} #endif /* !CONFIG_HIBERNATION */ -static void acpi_power_off_prepare(void) +static int acpi_power_off_prepare(struct sys_off_data *data) { /* Prepare to power off the system */ acpi_sleep_prepare(ACPI_STATE_S5); acpi_disable_all_gpes(); acpi_os_wait_events_complete(); + return NOTIFY_DONE; } -static void acpi_power_off(void) +static int acpi_power_off(struct sys_off_data *data) { /* acpi_sleep_prepare(ACPI_STATE_S5) should have already been called */ pr_debug("%s called\n", __func__); local_irq_disable(); acpi_enter_sleep_state(ACPI_STATE_S5); + return NOTIFY_DONE; } int __init acpi_sleep_init(void) @@ -1067,8 +1069,14 @@ int __init acpi_sleep_init(void) if (acpi_sleep_state_supported(ACPI_STATE_S5)) { sleep_states[ACPI_STATE_S5] = 1; - pm_power_off_prepare = acpi_power_off_prepare; - pm_power_off = acpi_power_off; + + register_sys_off_handler(SYS_OFF_MODE_POWER_OFF_PREPARE, + SYS_OFF_PRIO_FIRMWARE, + acpi_power_off_prepare, NULL); + + register_sys_off_handler(SYS_OFF_MODE_POWER_OFF, + SYS_OFF_PRIO_FIRMWARE, + acpi_power_off, NULL); } else { acpi_no_s5 = true; } diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c index 7e775ba6fdd905ea766c3e0a9d113fef47d48e26..3a2adeaef5ce4069e8af014cfc08c53a3280c365 100644 --- a/drivers/amba/bus.c +++ b/drivers/amba/bus.c @@ -20,6 +20,10 @@ #include #include #include +#include +#include +#include +#include #define to_amba_driver(d) container_of(d, struct amba_driver, drv) @@ -273,6 +277,36 @@ static void amba_shutdown(struct device *dev) drv->shutdown(to_amba_device(dev)); } +static int amba_dma_configure(struct device *dev) +{ + struct amba_driver *drv = to_amba_driver(dev->driver); + enum dev_dma_attr attr; + int ret = 0; + + if (dev->of_node) { + ret = of_dma_configure(dev, dev->of_node, true); + } else if (has_acpi_companion(dev)) { + attr = acpi_get_dma_attr(to_acpi_device_node(dev->fwnode)); + ret = acpi_dma_configure(dev, attr); + } + + if (!ret && !drv->driver_managed_dma) { + ret = iommu_device_use_default_domain(dev); + if (ret) + arch_teardown_dma_ops(dev); + } + + return ret; +} + +static void amba_dma_cleanup(struct device *dev) +{ + struct amba_driver *drv = to_amba_driver(dev->driver); + + if (!drv->driver_managed_dma) + iommu_device_unuse_default_domain(dev); +} + #ifdef CONFIG_PM /* * Hooks to provide runtime PM of the pclk (bus clock). It is safe to @@ -341,7 +375,8 @@ struct bus_type amba_bustype = { .probe = amba_probe, .remove = amba_remove, .shutdown = amba_shutdown, - .dma_configure = platform_dma_configure, + .dma_configure = amba_dma_configure, + .dma_cleanup = amba_dma_cleanup, .pm = &amba_pm, }; EXPORT_SYMBOL_GPL(amba_bustype); diff --git a/drivers/base/core.c b/drivers/base/core.c index f711a6fd34fb383243ec4940923d5b114e5fe5e4..d7b6d2533e898de00d772b92269879094452ee90 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -2864,9 +2864,6 @@ void device_initialize(struct device *dev) kobject_init(&dev->kobj, &device_ktype); INIT_LIST_HEAD(&dev->dma_pools); mutex_init(&dev->mutex); -#ifdef CONFIG_PROVE_LOCKING - mutex_init(&dev->lockdep_mutex); -#endif lockdep_set_novalidate_class(&dev->mutex); spin_lock_init(&dev->devres_lock); INIT_LIST_HEAD(&dev->devres_head); diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 3fc3b5940bb31983d1fc0b1f65dede25c5b2c090..94b7ac9bf4596a3c210f0be62a4e4e44a760cb29 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -671,6 +671,8 @@ sysfs_failed: if (dev->bus) blocking_notifier_call_chain(&dev->bus->p->bus_notifier, BUS_NOTIFY_DRIVER_NOT_BOUND, dev); + if (dev->bus && dev->bus->dma_cleanup) + dev->bus->dma_cleanup(dev); pinctrl_bind_failed: device_links_no_driver(dev); device_unbind_cleanup(dev); @@ -1199,6 +1201,9 @@ static void __device_release_driver(struct device *dev, struct device *parent) device_remove(dev); + if (dev->bus && dev->bus->dma_cleanup) + dev->bus->dma_cleanup(dev); + device_links_driver_cleanup(dev); device_unbind_cleanup(dev); diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 8cc272fd5c99aefb601c312e87632288e1ad7382..70bc30cf575c5131d85d80ebc466148cdc49910f 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -30,6 +30,8 @@ #include #include #include +#include +#include #include "base.h" #include "power/power.h" @@ -1454,9 +1456,9 @@ static void platform_shutdown(struct device *_dev) drv->shutdown(dev); } - -int platform_dma_configure(struct device *dev) +static int platform_dma_configure(struct device *dev) { + struct platform_driver *drv = to_platform_driver(dev->driver); enum dev_dma_attr attr; int ret = 0; @@ -1467,9 +1469,23 @@ int platform_dma_configure(struct device *dev) ret = acpi_dma_configure(dev, attr); } + if (!ret && !drv->driver_managed_dma) { + ret = iommu_device_use_default_domain(dev); + if (ret) + arch_teardown_dma_ops(dev); + } + return ret; } +static void platform_dma_cleanup(struct device *dev) +{ + struct platform_driver *drv = to_platform_driver(dev->driver); + + if (!drv->driver_managed_dma) + iommu_device_unuse_default_domain(dev); +} + static const struct dev_pm_ops platform_dev_pm_ops = { SET_RUNTIME_PM_OPS(pm_generic_runtime_suspend, pm_generic_runtime_resume, NULL) USE_PLATFORM_PM_SLEEP_OPS @@ -1484,6 +1500,7 @@ struct bus_type platform_bus_type = { .remove = platform_remove, .shutdown = platform_shutdown, .dma_configure = platform_dma_configure, + .dma_cleanup = platform_dma_cleanup, .pm = &platform_dev_pm_ops, }; EXPORT_SYMBOL_GPL(platform_bus_type); diff --git a/drivers/bus/fsl-mc/fsl-mc-bus.c b/drivers/bus/fsl-mc/fsl-mc-bus.c index 8fd4a356a86ec0b1cff2b830c6c1bf78924682f0..76648c4fdaf4be187d7b0e78e8f2d9a6a5db1ede 100644 --- a/drivers/bus/fsl-mc/fsl-mc-bus.c +++ b/drivers/bus/fsl-mc/fsl-mc-bus.c @@ -21,6 +21,7 @@ #include #include #include +#include #include "fsl-mc-private.h" @@ -140,15 +141,33 @@ static int fsl_mc_dma_configure(struct device *dev) { struct device *dma_dev = dev; struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); + struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(dev->driver); u32 input_id = mc_dev->icid; + int ret; while (dev_is_fsl_mc(dma_dev)) dma_dev = dma_dev->parent; if (dev_of_node(dma_dev)) - return of_dma_configure_id(dev, dma_dev->of_node, 0, &input_id); + ret = of_dma_configure_id(dev, dma_dev->of_node, 0, &input_id); + else + ret = acpi_dma_configure_id(dev, DEV_DMA_COHERENT, &input_id); + + if (!ret && !mc_drv->driver_managed_dma) { + ret = iommu_device_use_default_domain(dev); + if (ret) + arch_teardown_dma_ops(dev); + } + + return ret; +} + +static void fsl_mc_dma_cleanup(struct device *dev) +{ + struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(dev->driver); - return acpi_dma_configure_id(dev, DEV_DMA_COHERENT, &input_id); + if (!mc_drv->driver_managed_dma) + iommu_device_unuse_default_domain(dev); } static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, @@ -312,6 +331,7 @@ struct bus_type fsl_mc_bus_type = { .match = fsl_mc_bus_match, .uevent = fsl_mc_bus_uevent, .dma_configure = fsl_mc_dma_configure, + .dma_cleanup = fsl_mc_dma_cleanup, .dev_groups = fsl_mc_dev_groups, .bus_groups = fsl_mc_bus_groups, }; diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig index a087156a58186ab13f0f8491b23e4b504e48b76d..b3f2d55dc551b38835d631e3c60ebd3761c98767 100644 --- a/drivers/char/hw_random/Kconfig +++ b/drivers/char/hw_random/Kconfig @@ -385,6 +385,19 @@ config HW_RANDOM_PIC32 If unsure, say Y. +config HW_RANDOM_POLARFIRE_SOC + tristate "Microchip PolarFire SoC Random Number Generator support" + depends on HW_RANDOM && POLARFIRE_SOC_SYS_CTRL + help + This driver provides kernel-side support for the Random Number + Generator hardware found on PolarFire SoC (MPFS). + + To compile this driver as a module, choose M here. The + module will be called mfps_rng. + + If unsure, say N. + + config HW_RANDOM_MESON tristate "Amlogic Meson Random Number Generator support" depends on HW_RANDOM @@ -527,7 +540,7 @@ config HW_RANDOM_ARM_SMCCC_TRNG config HW_RANDOM_CN10K tristate "Marvell CN10K Random Number Generator support" - depends on HW_RANDOM && PCI && ARM64 + depends on HW_RANDOM && PCI && (ARM64 || (64BIT && COMPILE_TEST)) default HW_RANDOM help This driver provides support for the True Random Number diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile index 584d47ba32f7677b4e56229588837b1f0597d840..3e948cf044762cd4fd6b5ca94cb6a4ff9940cae4 100644 --- a/drivers/char/hw_random/Makefile +++ b/drivers/char/hw_random/Makefile @@ -46,3 +46,4 @@ obj-$(CONFIG_HW_RANDOM_CCTRNG) += cctrng.o obj-$(CONFIG_HW_RANDOM_XIPHERA) += xiphera-trng.o obj-$(CONFIG_HW_RANDOM_ARM_SMCCC_TRNG) += arm_smccc_trng.o obj-$(CONFIG_HW_RANDOM_CN10K) += cn10k-rng.o +obj-$(CONFIG_HW_RANDOM_POLARFIRE_SOC) += mpfs-rng.o diff --git a/drivers/char/hw_random/cn10k-rng.c b/drivers/char/hw_random/cn10k-rng.c index 35001c63648bba63977411932166ba8b94901dd1..a01e9307737c5e11eea9ccd9dd5c10fe724ac04b 100644 --- a/drivers/char/hw_random/cn10k-rng.c +++ b/drivers/char/hw_random/cn10k-rng.c @@ -31,26 +31,23 @@ struct cn10k_rng { #define PLAT_OCTEONTX_RESET_RNG_EBG_HEALTH_STATE 0xc2000b0f -static int reset_rng_health_state(struct cn10k_rng *rng) +static unsigned long reset_rng_health_state(struct cn10k_rng *rng) { struct arm_smccc_res res; /* Send SMC service call to reset EBG health state */ arm_smccc_smc(PLAT_OCTEONTX_RESET_RNG_EBG_HEALTH_STATE, 0, 0, 0, 0, 0, 0, 0, &res); - if (res.a0 != 0UL) - return -EIO; - - return 0; + return res.a0; } static int check_rng_health(struct cn10k_rng *rng) { u64 status; - int err; + unsigned long err; /* Skip checking health */ if (!rng->reg_base) - return 0; + return -ENODEV; status = readq(rng->reg_base + RNM_PF_EBG_HEALTH); if (status & BIT_ULL(20)) { @@ -58,7 +55,9 @@ static int check_rng_health(struct cn10k_rng *rng) if (err) { dev_err(&rng->pdev->dev, "HWRNG: Health test failed (status=%llx)\n", status); - dev_err(&rng->pdev->dev, "HWRNG: error during reset\n"); + dev_err(&rng->pdev->dev, "HWRNG: error during reset (error=%lx)\n", + err); + return -EIO; } } return 0; @@ -90,6 +89,7 @@ static int cn10k_rng_read(struct hwrng *hwrng, void *data, { struct cn10k_rng *rng = (struct cn10k_rng *)hwrng->priv; unsigned int size; + u8 *pos = data; int err = 0; u64 value; @@ -102,17 +102,20 @@ static int cn10k_rng_read(struct hwrng *hwrng, void *data, while (size >= 8) { cn10k_read_trng(rng, &value); - *((u64 *)data) = (u64)value; + *((u64 *)pos) = value; size -= 8; - data += 8; + pos += 8; } - while (size > 0) { + if (size > 0) { cn10k_read_trng(rng, &value); - *((u8 *)data) = (u8)value; - size--; - data++; + while (size > 0) { + *pos = (u8)value; + value >>= 8; + size--; + pos++; + } } return max - size; diff --git a/drivers/char/hw_random/mpfs-rng.c b/drivers/char/hw_random/mpfs-rng.c new file mode 100644 index 0000000000000000000000000000000000000000..5813da617a485e9afb5b4840a691b34e23b4bd16 --- /dev/null +++ b/drivers/char/hw_random/mpfs-rng.c @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Microchip PolarFire SoC (MPFS) hardware random driver + * + * Copyright (c) 2020-2022 Microchip Corporation. All rights reserved. + * + * Author: Conor Dooley + */ + +#include +#include +#include +#include + +#define CMD_OPCODE 0x21 +#define CMD_DATA_SIZE 0U +#define CMD_DATA NULL +#define MBOX_OFFSET 0U +#define RESP_OFFSET 0U +#define RNG_RESP_BYTES 32U + +struct mpfs_rng { + struct mpfs_sys_controller *sys_controller; + struct hwrng rng; +}; + +static int mpfs_rng_read(struct hwrng *rng, void *buf, size_t max, bool wait) +{ + struct mpfs_rng *rng_priv = container_of(rng, struct mpfs_rng, rng); + u32 response_msg[RNG_RESP_BYTES / sizeof(u32)]; + unsigned int count = 0, copy_size_bytes; + int ret; + + struct mpfs_mss_response response = { + .resp_status = 0U, + .resp_msg = (u32 *)response_msg, + .resp_size = RNG_RESP_BYTES + }; + struct mpfs_mss_msg msg = { + .cmd_opcode = CMD_OPCODE, + .cmd_data_size = CMD_DATA_SIZE, + .response = &response, + .cmd_data = CMD_DATA, + .mbox_offset = MBOX_OFFSET, + .resp_offset = RESP_OFFSET + }; + + while (count < max) { + ret = mpfs_blocking_transaction(rng_priv->sys_controller, &msg); + if (ret) + return ret; + + copy_size_bytes = max - count > RNG_RESP_BYTES ? RNG_RESP_BYTES : max - count; + memcpy(buf + count, response_msg, copy_size_bytes); + + count += copy_size_bytes; + if (!wait) + break; + } + + return count; +} + +static int mpfs_rng_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct mpfs_rng *rng_priv; + int ret; + + rng_priv = devm_kzalloc(dev, sizeof(*rng_priv), GFP_KERNEL); + if (!rng_priv) + return -ENOMEM; + + rng_priv->sys_controller = mpfs_sys_controller_get(&pdev->dev); + if (IS_ERR(rng_priv->sys_controller)) + return dev_err_probe(dev, PTR_ERR(rng_priv->sys_controller), + "Failed to register system controller hwrng sub device\n"); + + rng_priv->rng.read = mpfs_rng_read; + rng_priv->rng.name = pdev->name; + rng_priv->rng.quality = 1024; + + platform_set_drvdata(pdev, rng_priv); + + ret = devm_hwrng_register(&pdev->dev, &rng_priv->rng); + if (ret) + return dev_err_probe(&pdev->dev, ret, "Failed to register MPFS hwrng\n"); + + dev_info(&pdev->dev, "Registered MPFS hwrng\n"); + + return 0; +} + +static struct platform_driver mpfs_rng_driver = { + .driver = { + .name = "mpfs-rng", + }, + .probe = mpfs_rng_probe, +}; +module_platform_driver(mpfs_rng_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Conor Dooley "); +MODULE_DESCRIPTION("PolarFire SoC (MPFS) hardware random driver"); diff --git a/drivers/char/hw_random/omap3-rom-rng.c b/drivers/char/hw_random/omap3-rom-rng.c index e0d77fa048fb6caa81bbbddfb0e1678320da2ffe..f06e4f95114f91b8c6dcbf7664e3ad5b1e327356 100644 --- a/drivers/char/hw_random/omap3-rom-rng.c +++ b/drivers/char/hw_random/omap3-rom-rng.c @@ -92,7 +92,7 @@ static int __maybe_unused omap_rom_rng_runtime_resume(struct device *dev) r = ddata->rom_rng_call(0, 0, RNG_GEN_PRNG_HW_INIT); if (r != 0) { - clk_disable(ddata->clk); + clk_disable_unprepare(ddata->clk); dev_err(dev, "HW init failed: %d\n", r); return -EIO; diff --git a/drivers/char/hw_random/optee-rng.c b/drivers/char/hw_random/optee-rng.c index a948c0727b2bcb18970e1fa3b5b012ccd9961652..96b5d546d136adaecb5af8fd78b4afbb9aeee511 100644 --- a/drivers/char/hw_random/optee-rng.c +++ b/drivers/char/hw_random/optee-rng.c @@ -115,7 +115,7 @@ static size_t get_optee_rng_data(struct optee_rng_private *pvt_data, static int optee_rng_read(struct hwrng *rng, void *buf, size_t max, bool wait) { struct optee_rng_private *pvt_data = to_optee_rng_private(rng); - size_t read = 0, rng_size = 0; + size_t read = 0, rng_size; int timeout = 1; u8 *data = buf; diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 5d596e778ff49d52f90d8aac0934d477dbf3b962..48f8f4221e21d038f0c2e65f6b505bf49da995e5 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -210,6 +210,15 @@ config COMMON_CLK_CS2000_CP help If you say yes here you get support for the CS2000 clock multiplier. +config COMMON_CLK_EN7523 + bool "Clock driver for Airoha EN7523 SoC system clocks" + depends on OF + depends on ARCH_AIROHA || COMPILE_TEST + default ARCH_AIROHA + help + This driver provides the fixed clocks and gates present on Airoha + ARM silicon. + config COMMON_CLK_FSL_FLEXSPI tristate "Clock driver for FlexSPI on Layerscape SoCs" depends on ARCH_LAYERSCAPE || COMPILE_TEST @@ -368,6 +377,11 @@ config COMMON_CLK_VC5 This driver supports the IDT VersaClock 5 and VersaClock 6 programmable clock generators. +config COMMON_CLK_STM32MP135 + def_bool COMMON_CLK && MACH_STM32MP13 + help + Support for stm32mp135 SoC family clocks + config COMMON_CLK_STM32MP157 def_bool COMMON_CLK && MACH_STM32MP157 help diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 21cb96b022e61bcddd229042794b93e761d4ab55..d5db170d38d2d9c96085f45f6f0ca2011d46acd8 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -30,6 +30,7 @@ obj-$(CONFIG_COMMON_CLK_CDCE925) += clk-cdce925.o obj-$(CONFIG_ARCH_CLPS711X) += clk-clps711x.o obj-$(CONFIG_COMMON_CLK_CS2000_CP) += clk-cs2000-cp.o obj-$(CONFIG_ARCH_SPARX5) += clk-sparx5.o +obj-$(CONFIG_COMMON_CLK_EN7523) += clk-en7523.o obj-$(CONFIG_COMMON_CLK_FIXED_MMIO) += clk-fixed-mmio.o obj-$(CONFIG_COMMON_CLK_FSL_FLEXSPI) += clk-fsl-flexspi.o obj-$(CONFIG_COMMON_CLK_FSL_SAI) += clk-fsl-sai.o @@ -114,6 +115,7 @@ obj-y += socfpga/ obj-$(CONFIG_PLAT_SPEAR) += spear/ obj-y += sprd/ obj-$(CONFIG_ARCH_STI) += st/ +obj-$(CONFIG_ARCH_STM32) += stm32/ obj-$(CONFIG_SOC_STARFIVE) += starfive/ obj-$(CONFIG_ARCH_SUNXI) += sunxi/ obj-y += sunxi-ng/ diff --git a/drivers/clk/actions/owl-pll.c b/drivers/clk/actions/owl-pll.c index 02437bdedf4dbfe931026e4cd55c779e89e79eb3..155f313986b40f15b7c426f4d49b1ed560acf9c3 100644 --- a/drivers/clk/actions/owl-pll.c +++ b/drivers/clk/actions/owl-pll.c @@ -25,7 +25,7 @@ static u32 owl_pll_calculate_mul(struct owl_pll_hw *pll_hw, unsigned long rate) else if (mul > pll_hw->max_mul) mul = pll_hw->max_mul; - return mul &= mul_mask(pll_hw); + return mul & mul_mask(pll_hw); } static unsigned long _get_table_rate(const struct clk_pll_table *table, diff --git a/drivers/clk/bcm/clk-raspberrypi.c b/drivers/clk/bcm/clk-raspberrypi.c index 9d09621549b9b93360603b4b5bad6a53498bffe1..73518009a0f204d61e9e177a79d57d66fce2a611 100644 --- a/drivers/clk/bcm/clk-raspberrypi.c +++ b/drivers/clk/bcm/clk-raspberrypi.c @@ -345,7 +345,7 @@ static int raspberrypi_discover_clocks(struct raspberrypi_clk *rpi, int ret; clks = devm_kcalloc(rpi->dev, - sizeof(*clks), RPI_FIRMWARE_NUM_CLK_ID, + RPI_FIRMWARE_NUM_CLK_ID, sizeof(*clks), GFP_KERNEL); if (!clks) return -ENOMEM; diff --git a/drivers/clk/clk-cdce706.c b/drivers/clk/clk-cdce706.c index c91e9096b070e96de87f3f1ae6926b8d2431d539..5467d941ddfd0b97decc993f5127b30cf68e46a7 100644 --- a/drivers/clk/clk-cdce706.c +++ b/drivers/clk/clk-cdce706.c @@ -627,8 +627,7 @@ of_clk_cdce_get(struct of_phandle_args *clkspec, void *data) return &cdce->clkout[idx].hw; } -static int cdce706_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int cdce706_probe(struct i2c_client *client) { struct i2c_adapter *adapter = client->adapter; struct cdce706_dev_data *cdce; @@ -692,7 +691,7 @@ static struct i2c_driver cdce706_i2c_driver = { .name = "cdce706", .of_match_table = of_match_ptr(cdce706_dt_match), }, - .probe = cdce706_probe, + .probe_new = cdce706_probe, .remove = cdce706_remove, .id_table = cdce706_id, }; diff --git a/drivers/clk/clk-cdce925.c b/drivers/clk/clk-cdce925.c index 308b353815e170ad22d2fc1a2416c05e06458084..ef9a2d44e40c3670d205975bc2435f2204431711 100644 --- a/drivers/clk/clk-cdce925.c +++ b/drivers/clk/clk-cdce925.c @@ -634,11 +634,20 @@ static struct regmap_bus regmap_cdce925_bus = { .read = cdce925_regmap_i2c_read, }; -static int cdce925_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static const struct i2c_device_id cdce925_id[] = { + { "cdce913", CDCE913 }, + { "cdce925", CDCE925 }, + { "cdce937", CDCE937 }, + { "cdce949", CDCE949 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, cdce925_id); + +static int cdce925_probe(struct i2c_client *client) { struct clk_cdce925_chip *data; struct device_node *node = client->dev.of_node; + const struct i2c_device_id *id = i2c_match_id(cdce925_id, client); const char *parent_name; const char *pll_clk_name[MAX_NUMBER_OF_PLLS] = {NULL,}; struct clk_init_data init; @@ -814,15 +823,6 @@ error: return err; } -static const struct i2c_device_id cdce925_id[] = { - { "cdce913", CDCE913 }, - { "cdce925", CDCE925 }, - { "cdce937", CDCE937 }, - { "cdce949", CDCE949 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, cdce925_id); - static const struct of_device_id clk_cdce925_of_match[] = { { .compatible = "ti,cdce913" }, { .compatible = "ti,cdce925" }, @@ -837,7 +837,7 @@ static struct i2c_driver cdce925_driver = { .name = "cdce925", .of_match_table = of_match_ptr(clk_cdce925_of_match), }, - .probe = cdce925_probe, + .probe_new = cdce925_probe, .id_table = cdce925_id, }; module_i2c_driver(cdce925_driver); diff --git a/drivers/clk/clk-cs2000-cp.c b/drivers/clk/clk-cs2000-cp.c index dc5040a84dcc91fe66c4d60169a216257020a2a8..aa5c72bab83ea5689f115c0e641997d6a22890c7 100644 --- a/drivers/clk/clk-cs2000-cp.c +++ b/drivers/clk/clk-cs2000-cp.c @@ -570,8 +570,7 @@ static int cs2000_remove(struct i2c_client *client) return 0; } -static int cs2000_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int cs2000_probe(struct i2c_client *client) { struct cs2000_priv *priv; struct device *dev = &client->dev; @@ -625,7 +624,7 @@ static struct i2c_driver cs2000_driver = { .pm = &cs2000_pm_ops, .of_match_table = cs2000_of_match, }, - .probe = cs2000_probe, + .probe_new = cs2000_probe, .remove = cs2000_remove, .id_table = cs2000_id, }; diff --git a/drivers/clk/clk-en7523.c b/drivers/clk/clk-en7523.c new file mode 100644 index 0000000000000000000000000000000000000000..29f0126cbd05bc77227d523deb7adaebf9744dc6 --- /dev/null +++ b/drivers/clk/clk-en7523.c @@ -0,0 +1,351 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include +#include +#include +#include +#include +#include +#include + +#define REG_PCI_CONTROL 0x88 +#define REG_PCI_CONTROL_PERSTOUT BIT(29) +#define REG_PCI_CONTROL_PERSTOUT1 BIT(26) +#define REG_PCI_CONTROL_REFCLK_EN1 BIT(22) +#define REG_GSW_CLK_DIV_SEL 0x1b4 +#define REG_EMI_CLK_DIV_SEL 0x1b8 +#define REG_BUS_CLK_DIV_SEL 0x1bc +#define REG_SPI_CLK_DIV_SEL 0x1c4 +#define REG_SPI_CLK_FREQ_SEL 0x1c8 +#define REG_NPU_CLK_DIV_SEL 0x1fc +#define REG_CRYPTO_CLKSRC 0x200 +#define REG_RESET_CONTROL 0x834 +#define REG_RESET_CONTROL_PCIEHB BIT(29) +#define REG_RESET_CONTROL_PCIE1 BIT(27) +#define REG_RESET_CONTROL_PCIE2 BIT(26) + +struct en_clk_desc { + int id; + const char *name; + u32 base_reg; + u8 base_bits; + u8 base_shift; + union { + const unsigned int *base_values; + unsigned int base_value; + }; + size_t n_base_values; + + u16 div_reg; + u8 div_bits; + u8 div_shift; + u16 div_val0; + u8 div_step; +}; + +struct en_clk_gate { + void __iomem *base; + struct clk_hw hw; +}; + +static const u32 gsw_base[] = { 400000000, 500000000 }; +static const u32 emi_base[] = { 333000000, 400000000 }; +static const u32 bus_base[] = { 500000000, 540000000 }; +static const u32 slic_base[] = { 100000000, 3125000 }; +static const u32 npu_base[] = { 333000000, 400000000, 500000000 }; + +static const struct en_clk_desc en7523_base_clks[] = { + { + .id = EN7523_CLK_GSW, + .name = "gsw", + + .base_reg = REG_GSW_CLK_DIV_SEL, + .base_bits = 1, + .base_shift = 8, + .base_values = gsw_base, + .n_base_values = ARRAY_SIZE(gsw_base), + + .div_bits = 3, + .div_shift = 0, + .div_step = 1, + }, { + .id = EN7523_CLK_EMI, + .name = "emi", + + .base_reg = REG_EMI_CLK_DIV_SEL, + .base_bits = 1, + .base_shift = 8, + .base_values = emi_base, + .n_base_values = ARRAY_SIZE(emi_base), + + .div_bits = 3, + .div_shift = 0, + .div_step = 1, + }, { + .id = EN7523_CLK_BUS, + .name = "bus", + + .base_reg = REG_BUS_CLK_DIV_SEL, + .base_bits = 1, + .base_shift = 8, + .base_values = bus_base, + .n_base_values = ARRAY_SIZE(bus_base), + + .div_bits = 3, + .div_shift = 0, + .div_step = 1, + }, { + .id = EN7523_CLK_SLIC, + .name = "slic", + + .base_reg = REG_SPI_CLK_FREQ_SEL, + .base_bits = 1, + .base_shift = 0, + .base_values = slic_base, + .n_base_values = ARRAY_SIZE(slic_base), + + .div_reg = REG_SPI_CLK_DIV_SEL, + .div_bits = 5, + .div_shift = 24, + .div_val0 = 20, + .div_step = 2, + }, { + .id = EN7523_CLK_SPI, + .name = "spi", + + .base_reg = REG_SPI_CLK_DIV_SEL, + + .base_value = 400000000, + + .div_bits = 5, + .div_shift = 8, + .div_val0 = 40, + .div_step = 2, + }, { + .id = EN7523_CLK_NPU, + .name = "npu", + + .base_reg = REG_NPU_CLK_DIV_SEL, + .base_bits = 2, + .base_shift = 8, + .base_values = npu_base, + .n_base_values = ARRAY_SIZE(npu_base), + + .div_bits = 3, + .div_shift = 0, + .div_step = 1, + }, { + .id = EN7523_CLK_CRYPTO, + .name = "crypto", + + .base_reg = REG_CRYPTO_CLKSRC, + .base_bits = 1, + .base_shift = 8, + .base_values = emi_base, + .n_base_values = ARRAY_SIZE(emi_base), + } +}; + +static const struct of_device_id of_match_clk_en7523[] = { + { .compatible = "airoha,en7523-scu", }, + { /* sentinel */ } +}; + +static unsigned int en7523_get_base_rate(void __iomem *base, unsigned int i) +{ + const struct en_clk_desc *desc = &en7523_base_clks[i]; + u32 val; + + if (!desc->base_bits) + return desc->base_value; + + val = readl(base + desc->base_reg); + val >>= desc->base_shift; + val &= (1 << desc->base_bits) - 1; + + if (val >= desc->n_base_values) + return 0; + + return desc->base_values[val]; +} + +static u32 en7523_get_div(void __iomem *base, int i) +{ + const struct en_clk_desc *desc = &en7523_base_clks[i]; + u32 reg, val; + + if (!desc->div_bits) + return 1; + + reg = desc->div_reg ? desc->div_reg : desc->base_reg; + val = readl(base + reg); + val >>= desc->div_shift; + val &= (1 << desc->div_bits) - 1; + + if (!val && desc->div_val0) + return desc->div_val0; + + return (val + 1) * desc->div_step; +} + +static int en7523_pci_is_enabled(struct clk_hw *hw) +{ + struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw); + + return !!(readl(cg->base + REG_PCI_CONTROL) & REG_PCI_CONTROL_REFCLK_EN1); +} + +static int en7523_pci_prepare(struct clk_hw *hw) +{ + struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw); + void __iomem *np_base = cg->base; + u32 val, mask; + + /* Need to pull device low before reset */ + val = readl(np_base + REG_PCI_CONTROL); + val &= ~(REG_PCI_CONTROL_PERSTOUT1 | REG_PCI_CONTROL_PERSTOUT); + writel(val, np_base + REG_PCI_CONTROL); + usleep_range(1000, 2000); + + /* Enable PCIe port 1 */ + val |= REG_PCI_CONTROL_REFCLK_EN1; + writel(val, np_base + REG_PCI_CONTROL); + usleep_range(1000, 2000); + + /* Reset to default */ + val = readl(np_base + REG_RESET_CONTROL); + mask = REG_RESET_CONTROL_PCIE1 | REG_RESET_CONTROL_PCIE2 | + REG_RESET_CONTROL_PCIEHB; + writel(val & ~mask, np_base + REG_RESET_CONTROL); + usleep_range(1000, 2000); + writel(val | mask, np_base + REG_RESET_CONTROL); + msleep(100); + writel(val & ~mask, np_base + REG_RESET_CONTROL); + usleep_range(5000, 10000); + + /* Release device */ + mask = REG_PCI_CONTROL_PERSTOUT1 | REG_PCI_CONTROL_PERSTOUT; + val = readl(np_base + REG_PCI_CONTROL); + writel(val & ~mask, np_base + REG_PCI_CONTROL); + usleep_range(1000, 2000); + writel(val | mask, np_base + REG_PCI_CONTROL); + msleep(250); + + return 0; +} + +static void en7523_pci_unprepare(struct clk_hw *hw) +{ + struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw); + void __iomem *np_base = cg->base; + u32 val; + + val = readl(np_base + REG_PCI_CONTROL); + val &= ~REG_PCI_CONTROL_REFCLK_EN1; + writel(val, np_base + REG_PCI_CONTROL); +} + +static struct clk_hw *en7523_register_pcie_clk(struct device *dev, + void __iomem *np_base) +{ + static const struct clk_ops pcie_gate_ops = { + .is_enabled = en7523_pci_is_enabled, + .prepare = en7523_pci_prepare, + .unprepare = en7523_pci_unprepare, + }; + struct clk_init_data init = { + .name = "pcie", + .ops = &pcie_gate_ops, + }; + struct en_clk_gate *cg; + + cg = devm_kzalloc(dev, sizeof(*cg), GFP_KERNEL); + if (!cg) + return NULL; + + cg->base = np_base; + cg->hw.init = &init; + en7523_pci_unprepare(&cg->hw); + + if (clk_hw_register(dev, &cg->hw)) + return NULL; + + return &cg->hw; +} + +static void en7523_register_clocks(struct device *dev, struct clk_hw_onecell_data *clk_data, + void __iomem *base, void __iomem *np_base) +{ + struct clk_hw *hw; + u32 rate; + int i; + + for (i = 0; i < ARRAY_SIZE(en7523_base_clks); i++) { + const struct en_clk_desc *desc = &en7523_base_clks[i]; + + rate = en7523_get_base_rate(base, i); + rate /= en7523_get_div(base, i); + + hw = clk_hw_register_fixed_rate(dev, desc->name, NULL, 0, rate); + if (IS_ERR(hw)) { + pr_err("Failed to register clk %s: %ld\n", + desc->name, PTR_ERR(hw)); + continue; + } + + clk_data->hws[desc->id] = hw; + } + + hw = en7523_register_pcie_clk(dev, np_base); + clk_data->hws[EN7523_CLK_PCIE] = hw; + + clk_data->num = EN7523_NUM_CLOCKS; +} + +static int en7523_clk_probe(struct platform_device *pdev) +{ + struct device_node *node = pdev->dev.of_node; + struct clk_hw_onecell_data *clk_data; + void __iomem *base, *np_base; + int r; + + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) + return PTR_ERR(base); + + np_base = devm_platform_ioremap_resource(pdev, 1); + if (IS_ERR(np_base)) + return PTR_ERR(np_base); + + clk_data = devm_kzalloc(&pdev->dev, + struct_size(clk_data, hws, EN7523_NUM_CLOCKS), + GFP_KERNEL); + if (!clk_data) + return -ENOMEM; + + en7523_register_clocks(&pdev->dev, clk_data, base, np_base); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) + dev_err(&pdev->dev, + "could not register clock provider: %s: %d\n", + pdev->name, r); + + return r; +} + +static struct platform_driver clk_en7523_drv = { + .probe = en7523_clk_probe, + .driver = { + .name = "clk-en7523", + .of_match_table = of_match_clk_en7523, + .suppress_bind_attrs = true, + }, +}; + +static int __init clk_en7523_init(void) +{ + return platform_driver_register(&clk_en7523_drv); +} + +arch_initcall(clk_en7523_init); diff --git a/drivers/clk/clk-fixed-rate.c b/drivers/clk/clk-fixed-rate.c index 45501637705c30f88317e1cf70bba8d4dcc92cfd..ac68a6b40f0e5d0d0b238844a2fd1d6cae88353c 100644 --- a/drivers/clk/clk-fixed-rate.c +++ b/drivers/clk/clk-fixed-rate.c @@ -87,7 +87,7 @@ struct clk_hw *__clk_hw_register_fixed_rate(struct device *dev, hw = &fixed->hw; if (dev || !np) ret = clk_hw_register(dev, hw); - else if (np) + else ret = of_clk_hw_register(np, hw); if (ret) { kfree(fixed); diff --git a/drivers/clk/clk-max9485.c b/drivers/clk/clk-max9485.c index 5e80f3d090f34f1602b7bf7a97d7b5ed28b2fffe..5f85b0a32872ae4887d0bffdc32e30fbb76f4659 100644 --- a/drivers/clk/clk-max9485.c +++ b/drivers/clk/clk-max9485.c @@ -254,8 +254,7 @@ max9485_of_clk_get(struct of_phandle_args *clkspec, void *data) return &drvdata->hw[idx].hw; } -static int max9485_i2c_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int max9485_i2c_probe(struct i2c_client *client) { struct max9485_driver_data *drvdata; struct device *dev = &client->dev; @@ -377,7 +376,7 @@ static struct i2c_driver max9485_driver = { .pm = &max9485_pm_ops, .of_match_table = max9485_dt_ids, }, - .probe = max9485_i2c_probe, + .probe_new = max9485_i2c_probe, .id_table = max9485_i2c_ids, }; module_i2c_driver(max9485_driver); diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c index 214045f6e9895719c3490b14cd158fae74b2c387..fa817c317c2a9bd13e7c2eb42d0fd34aae06bcf5 100644 --- a/drivers/clk/clk-mux.c +++ b/drivers/clk/clk-mux.c @@ -157,11 +157,11 @@ struct clk_hw *__clk_hw_register_mux(struct device *dev, struct device_node *np, struct clk_mux *mux; struct clk_hw *hw; struct clk_init_data init = {}; - u8 width = 0; int ret = -EINVAL; if (clk_mux_flags & CLK_MUX_HIWORD_MASK) { - width = fls(mask) - ffs(mask) + 1; + u8 width = fls(mask) - ffs(mask) + 1; + if (width + shift > 16) { pr_err("mux value exceeds LOWORD field\n"); return ERR_PTR(-EINVAL); diff --git a/drivers/clk/clk-renesas-pcie.c b/drivers/clk/clk-renesas-pcie.c index 59d9cf0053ebb07f0c5768ae7c90b397f3d276fa..4f5df1fc74b46d2dabdc89da02af14468fc47192 100644 --- a/drivers/clk/clk-renesas-pcie.c +++ b/drivers/clk/clk-renesas-pcie.c @@ -213,7 +213,7 @@ rs9_of_clk_get(struct of_phandle_args *clkspec, void *data) return rs9->clk_dif[idx]; } -static int rs9_probe(struct i2c_client *client, const struct i2c_device_id *id) +static int rs9_probe(struct i2c_client *client) { unsigned char name[5] = "DIF0"; struct rs9_driver_data *rs9; @@ -312,7 +312,7 @@ static struct i2c_driver rs9_driver = { .pm = &rs9_pm_ops, .of_match_table = clk_rs9_of_match, }, - .probe = rs9_probe, + .probe_new = rs9_probe, .id_table = rs9_id, }; module_i2c_driver(rs9_driver); diff --git a/drivers/clk/clk-si514.c b/drivers/clk/clk-si514.c index 364b62b9928d3a00981b50f71e9874361b54e19c..4481c4303534f49960f5b9cedbafd9bb7c1d4d1d 100644 --- a/drivers/clk/clk-si514.c +++ b/drivers/clk/clk-si514.c @@ -327,8 +327,7 @@ static const struct regmap_config si514_regmap_config = { .volatile_reg = si514_regmap_is_volatile, }; -static int si514_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int si514_probe(struct i2c_client *client) { struct clk_si514 *data; struct clk_init_data init; @@ -394,7 +393,7 @@ static struct i2c_driver si514_driver = { .name = "si514", .of_match_table = clk_si514_of_match, }, - .probe = si514_probe, + .probe_new = si514_probe, .remove = si514_remove, .id_table = si514_id, }; diff --git a/drivers/clk/clk-si5341.c b/drivers/clk/clk-si5341.c index 41851f41b68211a6dab2b076403ad3b4965f42a1..4bca73212662876224c6d57932e8558a431279ae 100644 --- a/drivers/clk/clk-si5341.c +++ b/drivers/clk/clk-si5341.c @@ -1547,8 +1547,7 @@ static const struct attribute *si5341_attributes[] = { NULL }; -static int si5341_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int si5341_probe(struct i2c_client *client) { struct clk_si5341 *data; struct clk_init_data init; @@ -1837,7 +1836,7 @@ static struct i2c_driver si5341_driver = { .name = "si5341", .of_match_table = clk_si5341_of_match, }, - .probe = si5341_probe, + .probe_new = si5341_probe, .remove = si5341_remove, .id_table = si5341_id, }; diff --git a/drivers/clk/clk-si5351.c b/drivers/clk/clk-si5351.c index 93fa8c9e11be004e64a3736249633d568d82bfe4..b9f088c4ba2f54f458307979d0ef57f74f618e0b 100644 --- a/drivers/clk/clk-si5351.c +++ b/drivers/clk/clk-si5351.c @@ -1367,9 +1367,18 @@ si53351_of_clk_get(struct of_phandle_args *clkspec, void *data) } #endif /* CONFIG_OF */ -static int si5351_i2c_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static const struct i2c_device_id si5351_i2c_ids[] = { + { "si5351a", SI5351_VARIANT_A }, + { "si5351a-msop", SI5351_VARIANT_A3 }, + { "si5351b", SI5351_VARIANT_B }, + { "si5351c", SI5351_VARIANT_C }, + { } +}; +MODULE_DEVICE_TABLE(i2c, si5351_i2c_ids); + +static int si5351_i2c_probe(struct i2c_client *client) { + const struct i2c_device_id *id = i2c_match_id(si5351_i2c_ids, client); enum si5351_variant variant = (enum si5351_variant)id->driver_data; struct si5351_platform_data *pdata; struct si5351_driver_data *drvdata; @@ -1649,21 +1658,12 @@ static int si5351_i2c_remove(struct i2c_client *client) return 0; } -static const struct i2c_device_id si5351_i2c_ids[] = { - { "si5351a", SI5351_VARIANT_A }, - { "si5351a-msop", SI5351_VARIANT_A3 }, - { "si5351b", SI5351_VARIANT_B }, - { "si5351c", SI5351_VARIANT_C }, - { } -}; -MODULE_DEVICE_TABLE(i2c, si5351_i2c_ids); - static struct i2c_driver si5351_driver = { .driver = { .name = "si5351", .of_match_table = of_match_ptr(si5351_dt_ids), }, - .probe = si5351_i2c_probe, + .probe_new = si5351_i2c_probe, .remove = si5351_i2c_remove, .id_table = si5351_i2c_ids, }; diff --git a/drivers/clk/clk-si544.c b/drivers/clk/clk-si544.c index d9ec9086184df5468c429dc6001e8c0b74589953..089786907641ebd8aa3256c261c9c6af1f199714 100644 --- a/drivers/clk/clk-si544.c +++ b/drivers/clk/clk-si544.c @@ -451,11 +451,19 @@ static const struct regmap_config si544_regmap_config = { .volatile_reg = si544_regmap_is_volatile, }; -static int si544_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static const struct i2c_device_id si544_id[] = { + { "si544a", si544a }, + { "si544b", si544b }, + { "si544c", si544c }, + { } +}; +MODULE_DEVICE_TABLE(i2c, si544_id); + +static int si544_probe(struct i2c_client *client) { struct clk_si544 *data; struct clk_init_data init; + const struct i2c_device_id *id = i2c_match_id(si544_id, client); int err; data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL); @@ -499,14 +507,6 @@ static int si544_probe(struct i2c_client *client, return 0; } -static const struct i2c_device_id si544_id[] = { - { "si544a", si544a }, - { "si544b", si544b }, - { "si544c", si544c }, - { } -}; -MODULE_DEVICE_TABLE(i2c, si544_id); - static const struct of_device_id clk_si544_of_match[] = { { .compatible = "silabs,si544a" }, { .compatible = "silabs,si544b" }, @@ -520,7 +520,7 @@ static struct i2c_driver si544_driver = { .name = "si544", .of_match_table = clk_si544_of_match, }, - .probe = si544_probe, + .probe_new = si544_probe, .id_table = si544_id, }; module_i2c_driver(si544_driver); diff --git a/drivers/clk/clk-si570.c b/drivers/clk/clk-si570.c index eea50121718a69996287483ea37f62476a99ba7b..1ff8f32f734dcd959d534dc6f79cdd2cb050058f 100644 --- a/drivers/clk/clk-si570.c +++ b/drivers/clk/clk-si570.c @@ -398,11 +398,20 @@ static const struct regmap_config si570_regmap_config = { .volatile_reg = si570_regmap_is_volatile, }; -static int si570_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static const struct i2c_device_id si570_id[] = { + { "si570", si57x }, + { "si571", si57x }, + { "si598", si59x }, + { "si599", si59x }, + { } +}; +MODULE_DEVICE_TABLE(i2c, si570_id); + +static int si570_probe(struct i2c_client *client) { struct clk_si570 *data; struct clk_init_data init; + const struct i2c_device_id *id = i2c_match_id(si570_id, client); u32 initial_fout, factory_fout, stability; bool skip_recall; int err; @@ -495,15 +504,6 @@ static int si570_remove(struct i2c_client *client) return 0; } -static const struct i2c_device_id si570_id[] = { - { "si570", si57x }, - { "si571", si57x }, - { "si598", si59x }, - { "si599", si59x }, - { } -}; -MODULE_DEVICE_TABLE(i2c, si570_id); - static const struct of_device_id clk_si570_of_match[] = { { .compatible = "silabs,si570" }, { .compatible = "silabs,si571" }, @@ -518,7 +518,7 @@ static struct i2c_driver si570_driver = { .name = "si570", .of_match_table = clk_si570_of_match, }, - .probe = si570_probe, + .probe_new = si570_probe, .remove = si570_remove, .id_table = si570_id, }; diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 4ce256b805909e8cf59d4bfbba291c489132a4fb..777f56b210dc11d99662766b0ceeb96484fcebee 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -110,17 +110,10 @@ struct clk { /*** runtime pm ***/ static int clk_pm_runtime_get(struct clk_core *core) { - int ret; - if (!core->rpm_enabled) return 0; - ret = pm_runtime_get_sync(core->dev); - if (ret < 0) { - pm_runtime_put_noidle(core->dev); - return ret; - } - return 0; + return pm_runtime_resume_and_get(core->dev); } static void clk_pm_runtime_put(struct clk_core *core) diff --git a/drivers/clk/imx/clk-composite-8m.c b/drivers/clk/imx/clk-composite-8m.c index 2dfd6149e52828d69a611c8d20660fe4e5543751..cbf0d7955a00ae1b5dbb11921054c94f82a11f5d 100644 --- a/drivers/clk/imx/clk-composite-8m.c +++ b/drivers/clk/imx/clk-composite-8m.c @@ -178,7 +178,7 @@ struct clk_hw *__imx8m_clk_hw_composite(const char *name, unsigned long flags) { struct clk_hw *hw = ERR_PTR(-ENOMEM), *mux_hw; - struct clk_hw *div_hw, *gate_hw; + struct clk_hw *div_hw, *gate_hw = NULL; struct clk_divider *div = NULL; struct clk_gate *gate = NULL; struct clk_mux *mux = NULL; @@ -223,14 +223,17 @@ struct clk_hw *__imx8m_clk_hw_composite(const char *name, div->lock = &imx_ccm_lock; div->flags = CLK_DIVIDER_ROUND_CLOSEST; - gate = kzalloc(sizeof(*gate), GFP_KERNEL); - if (!gate) - goto fail; + /* skip registering the gate ops if M4 is enabled */ + if (!mcore_booted) { + gate = kzalloc(sizeof(*gate), GFP_KERNEL); + if (!gate) + goto fail; - gate_hw = &gate->hw; - gate->reg = reg; - gate->bit_idx = PCG_CGC_SHIFT; - gate->lock = &imx_ccm_lock; + gate_hw = &gate->hw; + gate->reg = reg; + gate->bit_idx = PCG_CGC_SHIFT; + gate->lock = &imx_ccm_lock; + } hw = clk_hw_register_composite(NULL, name, parent_names, num_parents, mux_hw, mux_ops, div_hw, diff --git a/drivers/clk/imx/clk-imx7d.c b/drivers/clk/imx/clk-imx7d.c index 3f6fd7ef2a68fcca4c38de27afcbfaafa61af218..cbf8131c63f7e1f085c57ca286e800e5ad79126e 100644 --- a/drivers/clk/imx/clk-imx7d.c +++ b/drivers/clk/imx/clk-imx7d.c @@ -782,7 +782,6 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node) hws[IMX7D_DRAM_PHYM_ALT_ROOT_CLK] = imx_clk_hw_gate2_flags("dram_phym_alt_root_clk", "dram_phym_alt_post_div", base + 0x4130, 0, CLK_IS_CRITICAL | CLK_OPS_PARENT_ENABLE); hws[IMX7D_DRAM_ALT_ROOT_CLK] = imx_clk_hw_gate2_flags("dram_alt_root_clk", "dram_alt_post_div", base + 0x4130, 0, CLK_IS_CRITICAL | CLK_OPS_PARENT_ENABLE); hws[IMX7D_OCOTP_CLK] = imx_clk_hw_gate4("ocotp_clk", "ipg_root_clk", base + 0x4230, 0); - hws[IMX7D_SNVS_CLK] = imx_clk_hw_gate4("snvs_clk", "ipg_root_clk", base + 0x4250, 0); hws[IMX7D_MU_ROOT_CLK] = imx_clk_hw_gate4("mu_root_clk", "ipg_root_clk", base + 0x4270, 0); hws[IMX7D_CAAM_CLK] = imx_clk_hw_gate4("caam_clk", "ipg_root_clk", base + 0x4240, 0); hws[IMX7D_USB_HSIC_ROOT_CLK] = imx_clk_hw_gate4("usb_hsic_root_clk", "usb_hsic_post_div", base + 0x4690, 0); diff --git a/drivers/clk/imx/clk-imx8mm.c b/drivers/clk/imx/clk-imx8mm.c index e8cbe181ec06d6dfe4739bf42da669e7539a44fa..b6d275855b36b730b960fbe3db1d9d3cceac6556 100644 --- a/drivers/clk/imx/clk-imx8mm.c +++ b/drivers/clk/imx/clk-imx8mm.c @@ -560,7 +560,6 @@ static int imx8mm_clocks_probe(struct platform_device *pdev) hws[IMX8MM_CLK_SAI5_IPG] = imx_clk_hw_gate2_shared2("sai5_ipg_clk", "ipg_audio_root", base + 0x4370, 0, &share_count_sai5); hws[IMX8MM_CLK_SAI6_ROOT] = imx_clk_hw_gate2_shared2("sai6_root_clk", "sai6", base + 0x4380, 0, &share_count_sai6); hws[IMX8MM_CLK_SAI6_IPG] = imx_clk_hw_gate2_shared2("sai6_ipg_clk", "ipg_audio_root", base + 0x4380, 0, &share_count_sai6); - hws[IMX8MM_CLK_SNVS_ROOT] = imx_clk_hw_gate4("snvs_root_clk", "ipg_root", base + 0x4470, 0); hws[IMX8MM_CLK_UART1_ROOT] = imx_clk_hw_gate4("uart1_root_clk", "uart1", base + 0x4490, 0); hws[IMX8MM_CLK_UART2_ROOT] = imx_clk_hw_gate4("uart2_root_clk", "uart2", base + 0x44a0, 0); hws[IMX8MM_CLK_UART3_ROOT] = imx_clk_hw_gate4("uart3_root_clk", "uart3", base + 0x44b0, 0); @@ -639,6 +638,8 @@ static struct platform_driver imx8mm_clk_driver = { }, }; module_platform_driver(imx8mm_clk_driver); +module_param(mcore_booted, bool, S_IRUGO); +MODULE_PARM_DESC(mcore_booted, "See Cortex-M core is booted or not"); MODULE_AUTHOR("Bai Ping "); MODULE_DESCRIPTION("NXP i.MX8MM clock driver"); diff --git a/drivers/clk/imx/clk-imx8mn.c b/drivers/clk/imx/clk-imx8mn.c index 92fcbab4f5bee3747e0695c0b23ce9f2fbbc5079..d37c45b676abe4da6b7fcf76a0b024543d7dc70d 100644 --- a/drivers/clk/imx/clk-imx8mn.c +++ b/drivers/clk/imx/clk-imx8mn.c @@ -227,6 +227,30 @@ static const char * const imx8mn_pwm4_sels[] = {"osc_24m", "sys_pll2_100m", "sys "sys_pll1_40m", "sys_pll3_out", "clk_ext2", "sys_pll1_80m", "video_pll1_out", }; +static const char * const imx8mn_gpt1_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_400m", + "sys_pll1_40m", "video_pll1_out", "sys_pll1_80m", + "audio_pll1_out", "clk_ext1", }; + +static const char * const imx8mn_gpt2_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_400m", + "sys_pll1_40m", "video_pll1_out", "sys_pll1_80m", + "audio_pll1_out", "clk_ext1", }; + +static const char * const imx8mn_gpt3_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_400m", + "sys_pll1_40m", "video_pll1_out", "sys_pll1_80m", + "audio_pll1_out", "clk_ext1", }; + +static const char * const imx8mn_gpt4_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_400m", + "sys_pll1_40m", "video_pll1_out", "sys_pll1_80m", + "audio_pll1_out", "clk_ext1", }; + +static const char * const imx8mn_gpt5_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_400m", + "sys_pll1_40m", "video_pll1_out", "sys_pll1_80m", + "audio_pll1_out", "clk_ext1", }; + +static const char * const imx8mn_gpt6_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_400m", + "sys_pll1_40m", "video_pll1_out", "sys_pll1_80m", + "audio_pll1_out", "clk_ext1", }; + static const char * const imx8mn_wdog_sels[] = {"osc_24m", "sys_pll1_133m", "sys_pll1_160m", "vpu_pll_out", "sys_pll2_125m", "sys_pll3_out", "sys_pll1_80m", "sys_pll2_166m", }; @@ -476,6 +500,12 @@ static int imx8mn_clocks_probe(struct platform_device *pdev) hws[IMX8MN_CLK_PWM2] = imx8m_clk_hw_composite("pwm2", imx8mn_pwm2_sels, base + 0xb400); hws[IMX8MN_CLK_PWM3] = imx8m_clk_hw_composite("pwm3", imx8mn_pwm3_sels, base + 0xb480); hws[IMX8MN_CLK_PWM4] = imx8m_clk_hw_composite("pwm4", imx8mn_pwm4_sels, base + 0xb500); + hws[IMX8MN_CLK_GPT1] = imx8m_clk_hw_composite("gpt1", imx8mn_gpt1_sels, base + 0xb580); + hws[IMX8MN_CLK_GPT2] = imx8m_clk_hw_composite("gpt2", imx8mn_gpt2_sels, base + 0xb600); + hws[IMX8MN_CLK_GPT3] = imx8m_clk_hw_composite("gpt3", imx8mn_gpt3_sels, base + 0xb680); + hws[IMX8MN_CLK_GPT4] = imx8m_clk_hw_composite("gpt4", imx8mn_gpt4_sels, base + 0xb700); + hws[IMX8MN_CLK_GPT5] = imx8m_clk_hw_composite("gpt5", imx8mn_gpt5_sels, base + 0xb780); + hws[IMX8MN_CLK_GPT6] = imx8m_clk_hw_composite("gpt6", imx8mn_gpt6_sels, base + 0xb800); hws[IMX8MN_CLK_WDOG] = imx8m_clk_hw_composite("wdog", imx8mn_wdog_sels, base + 0xb900); hws[IMX8MN_CLK_WRCLK] = imx8m_clk_hw_composite("wrclk", imx8mn_wrclk_sels, base + 0xb980); hws[IMX8MN_CLK_CLKO1] = imx8m_clk_hw_composite("clko1", imx8mn_clko1_sels, base + 0xba00); @@ -501,6 +531,12 @@ static int imx8mn_clocks_probe(struct platform_device *pdev) hws[IMX8MN_CLK_GPIO3_ROOT] = imx_clk_hw_gate4("gpio3_root_clk", "ipg_root", base + 0x40d0, 0); hws[IMX8MN_CLK_GPIO4_ROOT] = imx_clk_hw_gate4("gpio4_root_clk", "ipg_root", base + 0x40e0, 0); hws[IMX8MN_CLK_GPIO5_ROOT] = imx_clk_hw_gate4("gpio5_root_clk", "ipg_root", base + 0x40f0, 0); + hws[IMX8MN_CLK_GPT1_ROOT] = imx_clk_hw_gate4("gpt1_root_clk", "gpt1", base + 0x4100, 0); + hws[IMX8MN_CLK_GPT2_ROOT] = imx_clk_hw_gate4("gpt2_root_clk", "gpt2", base + 0x4110, 0); + hws[IMX8MN_CLK_GPT3_ROOT] = imx_clk_hw_gate4("gpt3_root_clk", "gpt3", base + 0x4120, 0); + hws[IMX8MN_CLK_GPT4_ROOT] = imx_clk_hw_gate4("gpt4_root_clk", "gpt4", base + 0x4130, 0); + hws[IMX8MN_CLK_GPT5_ROOT] = imx_clk_hw_gate4("gpt5_root_clk", "gpt5", base + 0x4140, 0); + hws[IMX8MN_CLK_GPT6_ROOT] = imx_clk_hw_gate4("gpt6_root_clk", "gpt6", base + 0x4150, 0); hws[IMX8MN_CLK_I2C1_ROOT] = imx_clk_hw_gate4("i2c1_root_clk", "i2c1", base + 0x4170, 0); hws[IMX8MN_CLK_I2C2_ROOT] = imx_clk_hw_gate4("i2c2_root_clk", "i2c2", base + 0x4180, 0); hws[IMX8MN_CLK_I2C3_ROOT] = imx_clk_hw_gate4("i2c3_root_clk", "i2c3", base + 0x4190, 0); @@ -522,7 +558,6 @@ static int imx8mn_clocks_probe(struct platform_device *pdev) hws[IMX8MN_CLK_SAI5_IPG] = imx_clk_hw_gate2_shared2("sai5_ipg_clk", "ipg_audio_root", base + 0x4370, 0, &share_count_sai5); hws[IMX8MN_CLK_SAI6_ROOT] = imx_clk_hw_gate2_shared2("sai6_root_clk", "sai6", base + 0x4380, 0, &share_count_sai6); hws[IMX8MN_CLK_SAI6_IPG] = imx_clk_hw_gate2_shared2("sai6_ipg_clk", "ipg_audio_root", base + 0x4380, 0, &share_count_sai6); - hws[IMX8MN_CLK_SNVS_ROOT] = imx_clk_hw_gate4("snvs_root_clk", "ipg_root", base + 0x4470, 0); hws[IMX8MN_CLK_UART1_ROOT] = imx_clk_hw_gate4("uart1_root_clk", "uart1", base + 0x4490, 0); hws[IMX8MN_CLK_UART2_ROOT] = imx_clk_hw_gate4("uart2_root_clk", "uart2", base + 0x44a0, 0); hws[IMX8MN_CLK_UART3_ROOT] = imx_clk_hw_gate4("uart3_root_clk", "uart3", base + 0x44b0, 0); @@ -549,6 +584,8 @@ static int imx8mn_clocks_probe(struct platform_device *pdev) hws[IMX8MN_CLK_SDMA3_ROOT] = imx_clk_hw_gate4("sdma3_clk", "ipg_audio_root", base + 0x45f0, 0); hws[IMX8MN_CLK_SAI7_ROOT] = imx_clk_hw_gate2_shared2("sai7_root_clk", "sai7", base + 0x4650, 0, &share_count_sai7); + hws[IMX8MN_CLK_GPT_3M] = imx_clk_hw_fixed_factor("gpt_3m", "osc_24m", 1, 8); + hws[IMX8MN_CLK_DRAM_ALT_ROOT] = imx_clk_hw_fixed_factor("dram_alt_root", "dram_alt", 1, 4); hws[IMX8MN_CLK_ARM] = imx_clk_hw_cpu("arm", "arm_a53_core", @@ -594,6 +631,8 @@ static struct platform_driver imx8mn_clk_driver = { }, }; module_platform_driver(imx8mn_clk_driver); +module_param(mcore_booted, bool, S_IRUGO); +MODULE_PARM_DESC(mcore_booted, "See Cortex-M core is booted or not"); MODULE_AUTHOR("Anson Huang "); MODULE_DESCRIPTION("NXP i.MX8MN clock driver"); diff --git a/drivers/clk/imx/clk-imx8mp.c b/drivers/clk/imx/clk-imx8mp.c index 18f5b7c3ca9d878f35f9390de38396165618c977..e89db568f5a897d8f93a825fbbc0ea0bbe5beb91 100644 --- a/drivers/clk/imx/clk-imx8mp.c +++ b/drivers/clk/imx/clk-imx8mp.c @@ -358,7 +358,7 @@ static const char * const imx8mp_media_mipi_phy1_ref_sels[] = {"osc_24m", "sys_p "clk_ext2", "audio_pll2_out", "video_pll1_out", }; -static const char * const imx8mp_media_disp1_pix_sels[] = {"osc_24m", "video_pll1_out", "audio_pll2_out", +static const char * const imx8mp_media_disp_pix_sels[] = {"osc_24m", "video_pll1_out", "audio_pll2_out", "audio_pll1_out", "sys_pll1_800m", "sys_pll2_1000m", "sys_pll3_out", "clk_ext4", }; @@ -399,6 +399,11 @@ static const char * const imx8mp_sai7_sels[] = {"osc_24m", "audio_pll1_out", "au static const char * const imx8mp_dram_core_sels[] = {"dram_pll_out", "dram_alt_root", }; +static const char * const imx8mp_clkout_sels[] = {"audio_pll1_out", "audio_pll2_out", "video_pll1_out", + "dummy", "dummy", "gpu_pll_out", "vpu_pll_out", + "arm_pll_out", "sys_pll1", "sys_pll2", "sys_pll3", + "dummy", "dummy", "osc_24m", "dummy", "osc_32k"}; + static struct clk_hw **hws; static struct clk_hw_onecell_data *clk_hw_data; @@ -504,6 +509,15 @@ static int imx8mp_clocks_probe(struct platform_device *pdev) hws[IMX8MP_SYS_PLL2_500M] = imx_clk_hw_fixed_factor("sys_pll2_500m", "sys_pll2_out", 1, 2); hws[IMX8MP_SYS_PLL2_1000M] = imx_clk_hw_fixed_factor("sys_pll2_1000m", "sys_pll2_out", 1, 1); + hws[IMX8MP_CLK_CLKOUT1_SEL] = imx_clk_hw_mux2("clkout1_sel", anatop_base + 0x128, 4, 4, + imx8mp_clkout_sels, ARRAY_SIZE(imx8mp_clkout_sels)); + hws[IMX8MP_CLK_CLKOUT1_DIV] = imx_clk_hw_divider("clkout1_div", "clkout1_sel", anatop_base + 0x128, 0, 4); + hws[IMX8MP_CLK_CLKOUT1] = imx_clk_hw_gate("clkout1", "clkout1_div", anatop_base + 0x128, 8); + hws[IMX8MP_CLK_CLKOUT2_SEL] = imx_clk_hw_mux2("clkout2_sel", anatop_base + 0x128, 20, 4, + imx8mp_clkout_sels, ARRAY_SIZE(imx8mp_clkout_sels)); + hws[IMX8MP_CLK_CLKOUT2_DIV] = imx_clk_hw_divider("clkout2_div", "clkout2_sel", anatop_base + 0x128, 16, 4); + hws[IMX8MP_CLK_CLKOUT2] = imx_clk_hw_gate("clkout2", "clkout2_div", anatop_base + 0x128, 24); + hws[IMX8MP_CLK_A53_DIV] = imx8m_clk_hw_composite_core("arm_a53_div", imx8mp_a53_sels, ccm_base + 0x8000); hws[IMX8MP_CLK_A53_SRC] = hws[IMX8MP_CLK_A53_DIV]; hws[IMX8MP_CLK_A53_CG] = hws[IMX8MP_CLK_A53_DIV]; @@ -538,6 +552,7 @@ static int imx8mp_clocks_probe(struct platform_device *pdev) hws[IMX8MP_CLK_AHB] = imx8m_clk_hw_composite_bus_critical("ahb_root", imx8mp_ahb_sels, ccm_base + 0x9000); hws[IMX8MP_CLK_AUDIO_AHB] = imx8m_clk_hw_composite_bus("audio_ahb", imx8mp_audio_ahb_sels, ccm_base + 0x9100); hws[IMX8MP_CLK_MIPI_DSI_ESC_RX] = imx8m_clk_hw_composite_bus("mipi_dsi_esc_rx", imx8mp_mipi_dsi_esc_rx_sels, ccm_base + 0x9200); + hws[IMX8MP_CLK_MEDIA_DISP2_PIX] = imx8m_clk_hw_composite("media_disp2_pix", imx8mp_media_disp_pix_sels, ccm_base + 0x9300); hws[IMX8MP_CLK_IPG_ROOT] = imx_clk_hw_divider2("ipg_root", "ahb_root", ccm_base + 0x9080, 0, 1); @@ -600,7 +615,7 @@ static int imx8mp_clocks_probe(struct platform_device *pdev) hws[IMX8MP_CLK_USDHC3] = imx8m_clk_hw_composite("usdhc3", imx8mp_usdhc3_sels, ccm_base + 0xbc80); hws[IMX8MP_CLK_MEDIA_CAM1_PIX] = imx8m_clk_hw_composite("media_cam1_pix", imx8mp_media_cam1_pix_sels, ccm_base + 0xbd00); hws[IMX8MP_CLK_MEDIA_MIPI_PHY1_REF] = imx8m_clk_hw_composite("media_mipi_phy1_ref", imx8mp_media_mipi_phy1_ref_sels, ccm_base + 0xbd80); - hws[IMX8MP_CLK_MEDIA_DISP1_PIX] = imx8m_clk_hw_composite("media_disp1_pix", imx8mp_media_disp1_pix_sels, ccm_base + 0xbe00); + hws[IMX8MP_CLK_MEDIA_DISP1_PIX] = imx8m_clk_hw_composite("media_disp1_pix", imx8mp_media_disp_pix_sels, ccm_base + 0xbe00); hws[IMX8MP_CLK_MEDIA_CAM2_PIX] = imx8m_clk_hw_composite("media_cam2_pix", imx8mp_media_cam2_pix_sels, ccm_base + 0xbe80); hws[IMX8MP_CLK_MEDIA_LDB] = imx8m_clk_hw_composite("media_ldb", imx8mp_media_ldb_sels, ccm_base + 0xbf00); hws[IMX8MP_CLK_MEMREPAIR] = imx8m_clk_hw_composite_critical("mem_repair", imx8mp_memrepair_sels, ccm_base + 0xbf80); @@ -654,12 +669,11 @@ static int imx8mp_clocks_probe(struct platform_device *pdev) hws[IMX8MP_CLK_SIM_ENET_ROOT] = imx_clk_hw_gate4("sim_enet_root_clk", "enet_axi", ccm_base + 0x4400, 0); hws[IMX8MP_CLK_GPU2D_ROOT] = imx_clk_hw_gate4("gpu2d_root_clk", "gpu2d_core", ccm_base + 0x4450, 0); hws[IMX8MP_CLK_GPU3D_ROOT] = imx_clk_hw_gate4("gpu3d_root_clk", "gpu3d_core", ccm_base + 0x4460, 0); - hws[IMX8MP_CLK_SNVS_ROOT] = imx_clk_hw_gate4("snvs_root_clk", "ipg_root", ccm_base + 0x4470, 0); hws[IMX8MP_CLK_UART1_ROOT] = imx_clk_hw_gate4("uart1_root_clk", "uart1", ccm_base + 0x4490, 0); hws[IMX8MP_CLK_UART2_ROOT] = imx_clk_hw_gate4("uart2_root_clk", "uart2", ccm_base + 0x44a0, 0); hws[IMX8MP_CLK_UART3_ROOT] = imx_clk_hw_gate4("uart3_root_clk", "uart3", ccm_base + 0x44b0, 0); hws[IMX8MP_CLK_UART4_ROOT] = imx_clk_hw_gate4("uart4_root_clk", "uart4", ccm_base + 0x44c0, 0); - hws[IMX8MP_CLK_USB_ROOT] = imx_clk_hw_gate4("usb_root_clk", "osc_32k", ccm_base + 0x44d0, 0); + hws[IMX8MP_CLK_USB_ROOT] = imx_clk_hw_gate4("usb_root_clk", "hsio_axi", ccm_base + 0x44d0, 0); hws[IMX8MP_CLK_USB_PHY_ROOT] = imx_clk_hw_gate4("usb_phy_root_clk", "usb_phy_ref", ccm_base + 0x44f0, 0); hws[IMX8MP_CLK_USDHC1_ROOT] = imx_clk_hw_gate4("usdhc1_root_clk", "usdhc1", ccm_base + 0x4510, 0); hws[IMX8MP_CLK_USDHC2_ROOT] = imx_clk_hw_gate4("usdhc2_root_clk", "usdhc2", ccm_base + 0x4520, 0); @@ -721,6 +735,8 @@ static struct platform_driver imx8mp_clk_driver = { }, }; module_platform_driver(imx8mp_clk_driver); +module_param(mcore_booted, bool, S_IRUGO); +MODULE_PARM_DESC(mcore_booted, "See Cortex-M core is booted or not"); MODULE_AUTHOR("Anson Huang "); MODULE_DESCRIPTION("NXP i.MX8MP clock driver"); diff --git a/drivers/clk/imx/clk-imx8mq.c b/drivers/clk/imx/clk-imx8mq.c index 83cc2b1c32947089a3999ef88cda655ffe9be03e..882dcad4817d7efcf7c45a20a35a3df990a2a0d0 100644 --- a/drivers/clk/imx/clk-imx8mq.c +++ b/drivers/clk/imx/clk-imx8mq.c @@ -25,7 +25,7 @@ static u32 share_count_sai6; static u32 share_count_dcss; static u32 share_count_nand; -static const char * const pll_ref_sels[] = { "osc_25m", "osc_27m", "dummy", "dummy", }; +static const char * const pll_ref_sels[] = { "osc_25m", "osc_27m", "hdmi_phy_27m", "dummy", }; static const char * const arm_pll_bypass_sels[] = {"arm_pll", "arm_pll_ref_sel", }; static const char * const gpu_pll_bypass_sels[] = {"gpu_pll", "gpu_pll_ref_sel", }; static const char * const vpu_pll_bypass_sels[] = {"vpu_pll", "vpu_pll_ref_sel", }; @@ -557,7 +557,6 @@ static int imx8mq_clocks_probe(struct platform_device *pdev) hws[IMX8MQ_CLK_SAI5_IPG] = imx_clk_hw_gate2_shared2("sai5_ipg_clk", "ipg_audio_root", base + 0x4370, 0, &share_count_sai5); hws[IMX8MQ_CLK_SAI6_ROOT] = imx_clk_hw_gate2_shared2("sai6_root_clk", "sai6", base + 0x4380, 0, &share_count_sai6); hws[IMX8MQ_CLK_SAI6_IPG] = imx_clk_hw_gate2_shared2("sai6_ipg_clk", "ipg_audio_root", base + 0x4380, 0, &share_count_sai6); - hws[IMX8MQ_CLK_SNVS_ROOT] = imx_clk_hw_gate4("snvs_root_clk", "ipg_root", base + 0x4470, 0); hws[IMX8MQ_CLK_UART1_ROOT] = imx_clk_hw_gate4("uart1_root_clk", "uart1", base + 0x4490, 0); hws[IMX8MQ_CLK_UART2_ROOT] = imx_clk_hw_gate4("uart2_root_clk", "uart2", base + 0x44a0, 0); hws[IMX8MQ_CLK_UART3_ROOT] = imx_clk_hw_gate4("uart3_root_clk", "uart3", base + 0x44b0, 0); @@ -632,6 +631,8 @@ static struct platform_driver imx8mq_clk_driver = { }, }; module_platform_driver(imx8mq_clk_driver); +module_param(mcore_booted, bool, S_IRUGO); +MODULE_PARM_DESC(mcore_booted, "See Cortex-M core is booted or not"); MODULE_AUTHOR("Abel Vesa "); MODULE_DESCRIPTION("NXP i.MX8MQ clock driver"); diff --git a/drivers/clk/imx/clk-scu.c b/drivers/clk/imx/clk-scu.c index 083da31dc3ead77a824091f033fbb2fe1f18a4f0..5b022eeb838baa8f20ecfc9385dbbbc753665d52 100644 --- a/drivers/clk/imx/clk-scu.c +++ b/drivers/clk/imx/clk-scu.c @@ -528,7 +528,7 @@ static int imx_clk_scu_probe(struct platform_device *pdev) pm_runtime_use_autosuspend(&pdev->dev); pm_runtime_enable(dev); - ret = pm_runtime_get_sync(dev); + ret = pm_runtime_resume_and_get(dev); if (ret) { pm_genpd_remove_device(dev); pm_runtime_disable(dev); @@ -837,8 +837,10 @@ struct clk_hw *__imx_clk_gpr_scu(const char *name, const char * const *parent_na if (!clk_node) return ERR_PTR(-ENOMEM); - if (!imx_scu_clk_is_valid(rsrc_id)) + if (!imx_scu_clk_is_valid(rsrc_id)) { + kfree(clk_node); return ERR_PTR(-EINVAL); + } clk = kzalloc(sizeof(*clk), GFP_KERNEL); if (!clk) { diff --git a/drivers/clk/imx/clk.c b/drivers/clk/imx/clk.c index 7cc669934253a210e300b5e9d597091e9a6b1897..5582f18dd632fced92017c5a00d55b030128b5dd 100644 --- a/drivers/clk/imx/clk.c +++ b/drivers/clk/imx/clk.c @@ -17,6 +17,9 @@ DEFINE_SPINLOCK(imx_ccm_lock); EXPORT_SYMBOL_GPL(imx_ccm_lock); +bool mcore_booted; +EXPORT_SYMBOL_GPL(mcore_booted); + void imx_unregister_clocks(struct clk *clks[], unsigned int count) { unsigned int i; @@ -173,6 +176,8 @@ void imx_register_uart_clocks(unsigned int clk_count) int i; imx_uart_clocks = kcalloc(clk_count, sizeof(struct clk *), GFP_KERNEL); + if (!imx_uart_clocks) + return; if (!of_stdout) return; diff --git a/drivers/clk/imx/clk.h b/drivers/clk/imx/clk.h index a7cbbcd1a3f46b5e74107920edd0f0275f92b1a4..5061a06468df8d0bc78329179b30a323ba87eb0a 100644 --- a/drivers/clk/imx/clk.h +++ b/drivers/clk/imx/clk.h @@ -7,6 +7,7 @@ #include extern spinlock_t imx_ccm_lock; +extern bool mcore_booted; void imx_check_clocks(struct clk *clks[], unsigned int count); void imx_check_clk_hws(struct clk_hw *clks[], unsigned int count); diff --git a/drivers/clk/ingenic/cgu.c b/drivers/clk/ingenic/cgu.c index af31633a8862e18f7e20bd25ad3b916713ae831c..861c50d6cb244bce0cebdae84f4380f406b6fa18 100644 --- a/drivers/clk/ingenic/cgu.c +++ b/drivers/clk/ingenic/cgu.c @@ -660,7 +660,7 @@ static int ingenic_register_clock(struct ingenic_cgu *cgu, unsigned idx) ingenic_clk->idx = idx; clk_init.name = clk_info->name; - clk_init.flags = 0; + clk_init.flags = clk_info->flags; clk_init.parent_names = parent_names; caps = clk_info->type; diff --git a/drivers/clk/ingenic/cgu.h b/drivers/clk/ingenic/cgu.h index bfc2b9c38a4180db08518fa972089313c52fdbca..147b7df0d657377bca62af28c810ebd36fd16efa 100644 --- a/drivers/clk/ingenic/cgu.h +++ b/drivers/clk/ingenic/cgu.h @@ -136,6 +136,7 @@ struct ingenic_cgu_custom_info { * struct ingenic_cgu_clk_info - information about a clock * @name: name of the clock * @type: a bitmask formed from CGU_CLK_* values + * @flags: common clock flags to set on this clock * @parents: an array of the indices of potential parents of this clock * within the clock_info array of the CGU, or -1 in entries * which correspond to no valid parent @@ -161,6 +162,8 @@ struct ingenic_cgu_clk_info { CGU_CLK_CUSTOM = BIT(7), } type; + unsigned long flags; + int parents[4]; union { diff --git a/drivers/clk/ingenic/jz4725b-cgu.c b/drivers/clk/ingenic/jz4725b-cgu.c index 15d61793f53b13729a2a37a67e1e1c3519b37f78..590e9c85cb25b78e06747e8d9abbdda59d0a669e 100644 --- a/drivers/clk/ingenic/jz4725b-cgu.c +++ b/drivers/clk/ingenic/jz4725b-cgu.c @@ -87,6 +87,11 @@ static const struct ingenic_cgu_clk_info jz4725b_cgu_clocks[] = { [JZ4725B_CLK_CCLK] = { "cclk", CGU_CLK_DIV, + /* + * Disabling the CPU clock or any parent clocks will hang the + * system; mark it critical. + */ + .flags = CLK_IS_CRITICAL, .parents = { JZ4725B_CLK_PLL, -1, -1, -1 }, .div = { CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1, 0, @@ -114,6 +119,11 @@ static const struct ingenic_cgu_clk_info jz4725b_cgu_clocks[] = { [JZ4725B_CLK_MCLK] = { "mclk", CGU_CLK_DIV, + /* + * Disabling MCLK or its parents will render DRAM + * inaccessible; mark it critical. + */ + .flags = CLK_IS_CRITICAL, .parents = { JZ4725B_CLK_PLL, -1, -1, -1 }, .div = { CGU_REG_CPCCR, 12, 1, 4, 22, -1, -1, 0, diff --git a/drivers/clk/ingenic/jz4740-cgu.c b/drivers/clk/ingenic/jz4740-cgu.c index 43ffb62c42bb0078868f709f923527146268349b..3e0a30574ebb35c0115151b54ab01caf698d87f7 100644 --- a/drivers/clk/ingenic/jz4740-cgu.c +++ b/drivers/clk/ingenic/jz4740-cgu.c @@ -102,6 +102,11 @@ static const struct ingenic_cgu_clk_info jz4740_cgu_clocks[] = { [JZ4740_CLK_CCLK] = { "cclk", CGU_CLK_DIV, + /* + * Disabling the CPU clock or any parent clocks will hang the + * system; mark it critical. + */ + .flags = CLK_IS_CRITICAL, .parents = { JZ4740_CLK_PLL, -1, -1, -1 }, .div = { CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1, 0, @@ -129,6 +134,11 @@ static const struct ingenic_cgu_clk_info jz4740_cgu_clocks[] = { [JZ4740_CLK_MCLK] = { "mclk", CGU_CLK_DIV, + /* + * Disabling MCLK or its parents will render DRAM + * inaccessible; mark it critical. + */ + .flags = CLK_IS_CRITICAL, .parents = { JZ4740_CLK_PLL, -1, -1, -1 }, .div = { CGU_REG_CPCCR, 12, 1, 4, 22, -1, -1, 0, diff --git a/drivers/clk/ingenic/jz4760-cgu.c b/drivers/clk/ingenic/jz4760-cgu.c index 8fdd383560fbc770e5932c1ddd26bf4eecfd0359..ecd395ac8a28d4fa8c80cc0cc6fe23c798dd56aa 100644 --- a/drivers/clk/ingenic/jz4760-cgu.c +++ b/drivers/clk/ingenic/jz4760-cgu.c @@ -143,6 +143,11 @@ static const struct ingenic_cgu_clk_info jz4760_cgu_clocks[] = { [JZ4760_CLK_CCLK] = { "cclk", CGU_CLK_DIV, + /* + * Disabling the CPU clock or any parent clocks will hang the + * system; mark it critical. + */ + .flags = CLK_IS_CRITICAL, .parents = { JZ4760_CLK_PLL0, }, .div = { CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1, 0, @@ -175,6 +180,11 @@ static const struct ingenic_cgu_clk_info jz4760_cgu_clocks[] = { }, [JZ4760_CLK_MCLK] = { "mclk", CGU_CLK_DIV, + /* + * Disabling MCLK or its parents will render DRAM + * inaccessible; mark it critical. + */ + .flags = CLK_IS_CRITICAL, .parents = { JZ4760_CLK_PLL0, }, .div = { CGU_REG_CPCCR, 12, 1, 4, 22, -1, -1, 0, diff --git a/drivers/clk/ingenic/jz4770-cgu.c b/drivers/clk/ingenic/jz4770-cgu.c index 7ef91257630e7406175303accdbed2a025c1cb97..6ae1740367f9e37000685dd3a92da0aec764d341 100644 --- a/drivers/clk/ingenic/jz4770-cgu.c +++ b/drivers/clk/ingenic/jz4770-cgu.c @@ -149,6 +149,11 @@ static const struct ingenic_cgu_clk_info jz4770_cgu_clocks[] = { [JZ4770_CLK_CCLK] = { "cclk", CGU_CLK_DIV, + /* + * Disabling the CPU clock or any parent clocks will hang the + * system; mark it critical. + */ + .flags = CLK_IS_CRITICAL, .parents = { JZ4770_CLK_PLL0, }, .div = { CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1, 0, diff --git a/drivers/clk/ingenic/jz4780-cgu.c b/drivers/clk/ingenic/jz4780-cgu.c index e357c228e0f14ddb2bdafd4c18929018914f6f84..b1dadc0a5e7556a8570286344818c2d1157bf9e8 100644 --- a/drivers/clk/ingenic/jz4780-cgu.c +++ b/drivers/clk/ingenic/jz4780-cgu.c @@ -341,12 +341,22 @@ static const struct ingenic_cgu_clk_info jz4780_cgu_clocks[] = { [JZ4780_CLK_CPU] = { "cpu", CGU_CLK_DIV, + /* + * Disabling the CPU clock or any parent clocks will hang the + * system; mark it critical. + */ + .flags = CLK_IS_CRITICAL, .parents = { JZ4780_CLK_CPUMUX, -1, -1, -1 }, .div = { CGU_REG_CLOCKCONTROL, 0, 1, 4, 22, -1, -1 }, }, [JZ4780_CLK_L2CACHE] = { "l2cache", CGU_CLK_DIV, + /* + * The L2 cache clock is critical if caches are enabled and + * disabling it or any parent clocks will hang the system. + */ + .flags = CLK_IS_CRITICAL, .parents = { JZ4780_CLK_CPUMUX, -1, -1, -1 }, .div = { CGU_REG_CLOCKCONTROL, 4, 1, 4, -1, -1, -1 }, }, @@ -380,6 +390,11 @@ static const struct ingenic_cgu_clk_info jz4780_cgu_clocks[] = { [JZ4780_CLK_DDR] = { "ddr", CGU_CLK_MUX | CGU_CLK_DIV, + /* + * Disabling DDR clock or its parents will render DRAM + * inaccessible; mark it critical. + */ + .flags = CLK_IS_CRITICAL, .parents = { -1, JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL, -1 }, .mux = { CGU_REG_DDRCDR, 30, 2 }, .div = { CGU_REG_DDRCDR, 0, 1, 4, 29, 28, 27 }, diff --git a/drivers/clk/ingenic/tcu.c b/drivers/clk/ingenic/tcu.c index 77acfbeb48300ed870c2c3fb2840834541aabe1f..201bf6e6b6e0ffb60cd34c0ecfbd1fa31673dd37 100644 --- a/drivers/clk/ingenic/tcu.c +++ b/drivers/clk/ingenic/tcu.c @@ -31,6 +31,7 @@ struct ingenic_soc_info { unsigned int num_channels; bool has_ost; bool has_tcu_clk; + bool allow_missing_tcu_clk; }; struct ingenic_tcu_clk_info { @@ -320,7 +321,8 @@ static const struct ingenic_soc_info jz4770_soc_info = { static const struct ingenic_soc_info x1000_soc_info = { .num_channels = 8, .has_ost = false, /* X1000 has OST, but it not belong TCU */ - .has_tcu_clk = false, + .has_tcu_clk = true, + .allow_missing_tcu_clk = true, }; static const struct of_device_id __maybe_unused ingenic_tcu_of_match[] __initconst = { @@ -355,14 +357,27 @@ static int __init ingenic_tcu_probe(struct device_node *np) tcu->clk = of_clk_get_by_name(np, "tcu"); if (IS_ERR(tcu->clk)) { ret = PTR_ERR(tcu->clk); - pr_crit("Cannot get TCU clock\n"); - goto err_free_tcu; - } - ret = clk_prepare_enable(tcu->clk); - if (ret) { - pr_crit("Unable to enable TCU clock\n"); - goto err_put_clk; + /* + * Old device trees for some SoCs did not include the + * TCU clock because this driver (incorrectly) didn't + * use it. In this case we complain loudly and attempt + * to continue without the clock, which might work if + * booting with workarounds like "clk_ignore_unused". + */ + if (tcu->soc_info->allow_missing_tcu_clk && ret == -EINVAL) { + pr_warn("TCU clock missing from device tree, please update your device tree\n"); + tcu->clk = NULL; + } else { + pr_crit("Cannot get TCU clock from device tree\n"); + goto err_free_tcu; + } + } else { + ret = clk_prepare_enable(tcu->clk); + if (ret) { + pr_crit("Unable to enable TCU clock\n"); + goto err_put_clk; + } } } @@ -432,10 +447,10 @@ err_unregister_timer_clocks: clk_hw_unregister(tcu->clocks->hws[i]); kfree(tcu->clocks); err_clk_disable: - if (tcu->soc_info->has_tcu_clk) + if (tcu->clk) clk_disable_unprepare(tcu->clk); err_put_clk: - if (tcu->soc_info->has_tcu_clk) + if (tcu->clk) clk_put(tcu->clk); err_free_tcu: kfree(tcu); diff --git a/drivers/clk/ingenic/x1000-cgu.c b/drivers/clk/ingenic/x1000-cgu.c index 3c4d5a77ccbd1f125e249c3eb69402f756a7fb42..b2ce3fb83f544fbace8cdd10d8c0da0d0af6b4fe 100644 --- a/drivers/clk/ingenic/x1000-cgu.c +++ b/drivers/clk/ingenic/x1000-cgu.c @@ -251,6 +251,11 @@ static const struct ingenic_cgu_clk_info x1000_cgu_clocks[] = { [X1000_CLK_CPU] = { "cpu", CGU_CLK_DIV | CGU_CLK_GATE, + /* + * Disabling the CPU clock or any parent clocks will hang the + * system; mark it critical. + */ + .flags = CLK_IS_CRITICAL, .parents = { X1000_CLK_CPUMUX, -1, -1, -1 }, .div = { CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1 }, .gate = { CGU_REG_CLKGR, 30 }, @@ -258,6 +263,11 @@ static const struct ingenic_cgu_clk_info x1000_cgu_clocks[] = { [X1000_CLK_L2CACHE] = { "l2cache", CGU_CLK_DIV, + /* + * The L2 cache clock is critical if caches are enabled and + * disabling it or any parent clocks will hang the system. + */ + .flags = CLK_IS_CRITICAL, .parents = { X1000_CLK_CPUMUX, -1, -1, -1 }, .div = { CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1 }, }, @@ -290,6 +300,11 @@ static const struct ingenic_cgu_clk_info x1000_cgu_clocks[] = { [X1000_CLK_DDR] = { "ddr", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE, + /* + * Disabling DDR clock or its parents will render DRAM + * inaccessible; mark it critical. + */ + .flags = CLK_IS_CRITICAL, .parents = { -1, X1000_CLK_SCLKA, X1000_CLK_MPLL, -1 }, .mux = { CGU_REG_DDRCDR, 30, 2 }, .div = { CGU_REG_DDRCDR, 0, 1, 4, 29, 28, 27 }, diff --git a/drivers/clk/ingenic/x1830-cgu.c b/drivers/clk/ingenic/x1830-cgu.c index e01ec2dc7a1a92da55c00ebd800cc826733a35f8..0fd46e50a513fc8ce71a133957c5b437772e7287 100644 --- a/drivers/clk/ingenic/x1830-cgu.c +++ b/drivers/clk/ingenic/x1830-cgu.c @@ -225,6 +225,7 @@ static const struct ingenic_cgu_clk_info x1830_cgu_clocks[] = { [X1830_CLK_CPU] = { "cpu", CGU_CLK_DIV | CGU_CLK_GATE, + .flags = CLK_IS_CRITICAL, .parents = { X1830_CLK_CPUMUX, -1, -1, -1 }, .div = { CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1 }, .gate = { CGU_REG_CLKGR1, 15 }, @@ -232,6 +233,11 @@ static const struct ingenic_cgu_clk_info x1830_cgu_clocks[] = { [X1830_CLK_L2CACHE] = { "l2cache", CGU_CLK_DIV, + /* + * The L2 cache clock is critical if caches are enabled and + * disabling it or any parent clocks will hang the system. + */ + .flags = CLK_IS_CRITICAL, .parents = { X1830_CLK_CPUMUX, -1, -1, -1 }, .div = { CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1 }, }, @@ -264,6 +270,11 @@ static const struct ingenic_cgu_clk_info x1830_cgu_clocks[] = { [X1830_CLK_DDR] = { "ddr", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE, + /* + * Disabling DDR clock or its parents will render DRAM + * inaccessible; mark it critical. + */ + .flags = CLK_IS_CRITICAL, .parents = { -1, X1830_CLK_SCLKA, X1830_CLK_MPLL, -1 }, .mux = { CGU_REG_DDRCDR, 30, 2 }, .div = { CGU_REG_DDRCDR, 0, 1, 4, 29, 28, 27 }, diff --git a/drivers/clk/keystone/syscon-clk.c b/drivers/clk/keystone/syscon-clk.c index aae1a4076281943346cd5855de615a037a454d77..19198325b909ccbfb5c6f578559ecb53b7ecc55c 100644 --- a/drivers/clk/keystone/syscon-clk.c +++ b/drivers/clk/keystone/syscon-clk.c @@ -162,6 +162,13 @@ static const struct ti_syscon_gate_clk_data am64_clk_data[] = { { /* Sentinel */ }, }; +static const struct ti_syscon_gate_clk_data am62_clk_data[] = { + TI_SYSCON_CLK_GATE("epwm_tbclk0", 0x0, 0), + TI_SYSCON_CLK_GATE("epwm_tbclk1", 0x0, 1), + TI_SYSCON_CLK_GATE("epwm_tbclk2", 0x0, 2), + { /* Sentinel */ }, +}; + static const struct of_device_id ti_syscon_gate_clk_ids[] = { { .compatible = "ti,am654-ehrpwm-tbclk", @@ -171,6 +178,10 @@ static const struct of_device_id ti_syscon_gate_clk_ids[] = { .compatible = "ti,am64-epwm-tbclk", .data = &am64_clk_data, }, + { + .compatible = "ti,am62-epwm-tbclk", + .data = &am62_clk_data, + }, { } }; MODULE_DEVICE_TABLE(of, ti_syscon_gate_clk_ids); diff --git a/drivers/clk/mediatek/Kconfig b/drivers/clk/mediatek/Kconfig index 01ef02c547251f637d2f69683898964d9be07dc5..d5936cfb3beeee582fb885f354b1f8e839061452 100644 --- a/drivers/clk/mediatek/Kconfig +++ b/drivers/clk/mediatek/Kconfig @@ -512,6 +512,14 @@ config COMMON_CLK_MT8183_VENCSYS help This driver supports MediaTek MT8183 vencsys clocks. +config COMMON_CLK_MT8186 + bool "Clock driver for MediaTek MT8186" + depends on ARM64 || COMPILE_TEST + select COMMON_CLK_MEDIATEK + default ARCH_MEDIATEK + help + This driver supports MediaTek MT8186 clocks. + config COMMON_CLK_MT8192 bool "Clock driver for MediaTek MT8192" depends on ARM64 || COMPILE_TEST diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile index 7b0c2646ce4aea79767222529e02ce89282e830c..caf2ce93d6668c21b80f71434420459131279be1 100644 --- a/drivers/clk/mediatek/Makefile +++ b/drivers/clk/mediatek/Makefile @@ -71,6 +71,11 @@ obj-$(CONFIG_COMMON_CLK_MT8183_MFGCFG) += clk-mt8183-mfgcfg.o obj-$(CONFIG_COMMON_CLK_MT8183_MMSYS) += clk-mt8183-mm.o obj-$(CONFIG_COMMON_CLK_MT8183_VDECSYS) += clk-mt8183-vdec.o obj-$(CONFIG_COMMON_CLK_MT8183_VENCSYS) += clk-mt8183-venc.o +obj-$(CONFIG_COMMON_CLK_MT8186) += clk-mt8186-mcu.o clk-mt8186-topckgen.o clk-mt8186-infra_ao.o \ + clk-mt8186-apmixedsys.o clk-mt8186-imp_iic_wrap.o \ + clk-mt8186-mfg.o clk-mt8186-mm.o clk-mt8186-wpe.o \ + clk-mt8186-img.o clk-mt8186-vdec.o clk-mt8186-venc.o \ + clk-mt8186-cam.o clk-mt8186-mdp.o clk-mt8186-ipe.o obj-$(CONFIG_COMMON_CLK_MT8192) += clk-mt8192.o obj-$(CONFIG_COMMON_CLK_MT8192_AUDSYS) += clk-mt8192-aud.o obj-$(CONFIG_COMMON_CLK_MT8192_CAMSYS) += clk-mt8192-cam.o diff --git a/drivers/clk/mediatek/clk-apmixed.c b/drivers/clk/mediatek/clk-apmixed.c index a29339cc26c44d200698930ea2732e72603c0c3c..fc3d4146f4827e4504156f8e1320155249b66faa 100644 --- a/drivers/clk/mediatek/clk-apmixed.c +++ b/drivers/clk/mediatek/clk-apmixed.c @@ -70,12 +70,12 @@ static const struct clk_ops mtk_ref2usb_tx_ops = { .unprepare = mtk_ref2usb_tx_unprepare, }; -struct clk * __init mtk_clk_register_ref2usb_tx(const char *name, +struct clk_hw * __init mtk_clk_register_ref2usb_tx(const char *name, const char *parent_name, void __iomem *reg) { struct mtk_ref2usb_tx *tx; struct clk_init_data init = {}; - struct clk *clk; + int ret; tx = kzalloc(sizeof(*tx), GFP_KERNEL); if (!tx) @@ -89,14 +89,14 @@ struct clk * __init mtk_clk_register_ref2usb_tx(const char *name, init.parent_names = &parent_name; init.num_parents = 1; - clk = clk_register(NULL, &tx->hw); + ret = clk_hw_register(NULL, &tx->hw); - if (IS_ERR(clk)) { - pr_err("Failed to register clk %s: %pe\n", name, clk); + if (ret) { kfree(tx); + return ERR_PTR(ret); } - return clk; + return &tx->hw; } MODULE_LICENSE("GPL"); diff --git a/drivers/clk/mediatek/clk-cpumux.c b/drivers/clk/mediatek/clk-cpumux.c index c11b3fae622e40b54d52fc493ccbc38e3baf3654..2b5d48591738830c37b77e98b0b01224298ed0a1 100644 --- a/drivers/clk/mediatek/clk-cpumux.c +++ b/drivers/clk/mediatek/clk-cpumux.c @@ -57,12 +57,12 @@ static const struct clk_ops clk_cpumux_ops = { .set_parent = clk_cpumux_set_parent, }; -static struct clk * +static struct clk_hw * mtk_clk_register_cpumux(const struct mtk_composite *mux, struct regmap *regmap) { struct mtk_clk_cpumux *cpumux; - struct clk *clk; + int ret; struct clk_init_data init; cpumux = kzalloc(sizeof(*cpumux), GFP_KERNEL); @@ -81,34 +81,33 @@ mtk_clk_register_cpumux(const struct mtk_composite *mux, cpumux->regmap = regmap; cpumux->hw.init = &init; - clk = clk_register(NULL, &cpumux->hw); - if (IS_ERR(clk)) + ret = clk_hw_register(NULL, &cpumux->hw); + if (ret) { kfree(cpumux); + return ERR_PTR(ret); + } - return clk; + return &cpumux->hw; } -static void mtk_clk_unregister_cpumux(struct clk *clk) +static void mtk_clk_unregister_cpumux(struct clk_hw *hw) { struct mtk_clk_cpumux *cpumux; - struct clk_hw *hw; - - hw = __clk_get_hw(clk); if (!hw) return; cpumux = to_mtk_clk_cpumux(hw); - clk_unregister(clk); + clk_hw_unregister(hw); kfree(cpumux); } int mtk_clk_register_cpumuxes(struct device_node *node, const struct mtk_composite *clks, int num, - struct clk_onecell_data *clk_data) + struct clk_hw_onecell_data *clk_data) { int i; - struct clk *clk; + struct clk_hw *hw; struct regmap *regmap; regmap = device_node_to_regmap(node); @@ -120,19 +119,20 @@ int mtk_clk_register_cpumuxes(struct device_node *node, for (i = 0; i < num; i++) { const struct mtk_composite *mux = &clks[i]; - if (!IS_ERR_OR_NULL(clk_data->clks[mux->id])) { + if (!IS_ERR_OR_NULL(clk_data->hws[mux->id])) { pr_warn("%pOF: Trying to register duplicate clock ID: %d\n", node, mux->id); continue; } - clk = mtk_clk_register_cpumux(mux, regmap); - if (IS_ERR(clk)) { - pr_err("Failed to register clk %s: %pe\n", mux->name, clk); + hw = mtk_clk_register_cpumux(mux, regmap); + if (IS_ERR(hw)) { + pr_err("Failed to register clk %s: %pe\n", mux->name, + hw); goto err; } - clk_data->clks[mux->id] = clk; + clk_data->hws[mux->id] = hw; } return 0; @@ -141,29 +141,29 @@ err: while (--i >= 0) { const struct mtk_composite *mux = &clks[i]; - if (IS_ERR_OR_NULL(clk_data->clks[mux->id])) + if (IS_ERR_OR_NULL(clk_data->hws[mux->id])) continue; - mtk_clk_unregister_cpumux(clk_data->clks[mux->id]); - clk_data->clks[mux->id] = ERR_PTR(-ENOENT); + mtk_clk_unregister_cpumux(clk_data->hws[mux->id]); + clk_data->hws[mux->id] = ERR_PTR(-ENOENT); } - return PTR_ERR(clk); + return PTR_ERR(hw); } void mtk_clk_unregister_cpumuxes(const struct mtk_composite *clks, int num, - struct clk_onecell_data *clk_data) + struct clk_hw_onecell_data *clk_data) { int i; for (i = num; i > 0; i--) { const struct mtk_composite *mux = &clks[i - 1]; - if (IS_ERR_OR_NULL(clk_data->clks[mux->id])) + if (IS_ERR_OR_NULL(clk_data->hws[mux->id])) continue; - mtk_clk_unregister_cpumux(clk_data->clks[mux->id]); - clk_data->clks[mux->id] = ERR_PTR(-ENOENT); + mtk_clk_unregister_cpumux(clk_data->hws[mux->id]); + clk_data->hws[mux->id] = ERR_PTR(-ENOENT); } } diff --git a/drivers/clk/mediatek/clk-cpumux.h b/drivers/clk/mediatek/clk-cpumux.h index b07e89f7c2832de5610c91795527bc4f3cb24ebf..325adbef25d13a1c2f5c2f9ad5de0ca87f64d8e4 100644 --- a/drivers/clk/mediatek/clk-cpumux.h +++ b/drivers/clk/mediatek/clk-cpumux.h @@ -7,15 +7,15 @@ #ifndef __DRV_CLK_CPUMUX_H #define __DRV_CLK_CPUMUX_H -struct clk_onecell_data; +struct clk_hw_onecell_data; struct device_node; struct mtk_composite; int mtk_clk_register_cpumuxes(struct device_node *node, const struct mtk_composite *clks, int num, - struct clk_onecell_data *clk_data); + struct clk_hw_onecell_data *clk_data); void mtk_clk_unregister_cpumuxes(const struct mtk_composite *clks, int num, - struct clk_onecell_data *clk_data); + struct clk_hw_onecell_data *clk_data); #endif /* __DRV_CLK_CPUMUX_H */ diff --git a/drivers/clk/mediatek/clk-gate.c b/drivers/clk/mediatek/clk-gate.c index da52023f845588b1a9a4b252664a616498dfde1e..421806236228f466b665627edde942803f956a06 100644 --- a/drivers/clk/mediatek/clk-gate.c +++ b/drivers/clk/mediatek/clk-gate.c @@ -152,7 +152,7 @@ const struct clk_ops mtk_clk_gate_ops_no_setclr_inv = { }; EXPORT_SYMBOL_GPL(mtk_clk_gate_ops_no_setclr_inv); -static struct clk *mtk_clk_register_gate(const char *name, +static struct clk_hw *mtk_clk_register_gate(const char *name, const char *parent_name, struct regmap *regmap, int set_ofs, int clr_ofs, int sta_ofs, u8 bit, @@ -160,7 +160,7 @@ static struct clk *mtk_clk_register_gate(const char *name, unsigned long flags, struct device *dev) { struct mtk_clk_gate *cg; - struct clk *clk; + int ret; struct clk_init_data init = {}; cg = kzalloc(sizeof(*cg), GFP_KERNEL); @@ -181,35 +181,34 @@ static struct clk *mtk_clk_register_gate(const char *name, cg->hw.init = &init; - clk = clk_register(dev, &cg->hw); - if (IS_ERR(clk)) + ret = clk_hw_register(dev, &cg->hw); + if (ret) { kfree(cg); + return ERR_PTR(ret); + } - return clk; + return &cg->hw; } -static void mtk_clk_unregister_gate(struct clk *clk) +static void mtk_clk_unregister_gate(struct clk_hw *hw) { struct mtk_clk_gate *cg; - struct clk_hw *hw; - - hw = __clk_get_hw(clk); if (!hw) return; cg = to_mtk_clk_gate(hw); - clk_unregister(clk); + clk_hw_unregister(hw); kfree(cg); } int mtk_clk_register_gates_with_dev(struct device_node *node, const struct mtk_gate *clks, int num, - struct clk_onecell_data *clk_data, + struct clk_hw_onecell_data *clk_data, struct device *dev) { int i; - struct clk *clk; + struct clk_hw *hw; struct regmap *regmap; if (!clk_data) @@ -224,13 +223,13 @@ int mtk_clk_register_gates_with_dev(struct device_node *node, for (i = 0; i < num; i++) { const struct mtk_gate *gate = &clks[i]; - if (!IS_ERR_OR_NULL(clk_data->clks[gate->id])) { + if (!IS_ERR_OR_NULL(clk_data->hws[gate->id])) { pr_warn("%pOF: Trying to register duplicate clock ID: %d\n", node, gate->id); continue; } - clk = mtk_clk_register_gate(gate->name, gate->parent_name, + hw = mtk_clk_register_gate(gate->name, gate->parent_name, regmap, gate->regs->set_ofs, gate->regs->clr_ofs, @@ -238,12 +237,13 @@ int mtk_clk_register_gates_with_dev(struct device_node *node, gate->shift, gate->ops, gate->flags, dev); - if (IS_ERR(clk)) { - pr_err("Failed to register clk %s: %pe\n", gate->name, clk); + if (IS_ERR(hw)) { + pr_err("Failed to register clk %s: %pe\n", gate->name, + hw); goto err; } - clk_data->clks[gate->id] = clk; + clk_data->hws[gate->id] = hw; } return 0; @@ -252,26 +252,26 @@ err: while (--i >= 0) { const struct mtk_gate *gate = &clks[i]; - if (IS_ERR_OR_NULL(clk_data->clks[gate->id])) + if (IS_ERR_OR_NULL(clk_data->hws[gate->id])) continue; - mtk_clk_unregister_gate(clk_data->clks[gate->id]); - clk_data->clks[gate->id] = ERR_PTR(-ENOENT); + mtk_clk_unregister_gate(clk_data->hws[gate->id]); + clk_data->hws[gate->id] = ERR_PTR(-ENOENT); } - return PTR_ERR(clk); + return PTR_ERR(hw); } int mtk_clk_register_gates(struct device_node *node, const struct mtk_gate *clks, int num, - struct clk_onecell_data *clk_data) + struct clk_hw_onecell_data *clk_data) { return mtk_clk_register_gates_with_dev(node, clks, num, clk_data, NULL); } EXPORT_SYMBOL_GPL(mtk_clk_register_gates); void mtk_clk_unregister_gates(const struct mtk_gate *clks, int num, - struct clk_onecell_data *clk_data) + struct clk_hw_onecell_data *clk_data) { int i; @@ -281,11 +281,11 @@ void mtk_clk_unregister_gates(const struct mtk_gate *clks, int num, for (i = num; i > 0; i--) { const struct mtk_gate *gate = &clks[i - 1]; - if (IS_ERR_OR_NULL(clk_data->clks[gate->id])) + if (IS_ERR_OR_NULL(clk_data->hws[gate->id])) continue; - mtk_clk_unregister_gate(clk_data->clks[gate->id]); - clk_data->clks[gate->id] = ERR_PTR(-ENOENT); + mtk_clk_unregister_gate(clk_data->hws[gate->id]); + clk_data->hws[gate->id] = ERR_PTR(-ENOENT); } } EXPORT_SYMBOL_GPL(mtk_clk_unregister_gates); diff --git a/drivers/clk/mediatek/clk-gate.h b/drivers/clk/mediatek/clk-gate.h index 6b5738826a223ac646bf9589bc6c0720f2367182..d9897ef5352844badc0b8107693aa6751b292ef1 100644 --- a/drivers/clk/mediatek/clk-gate.h +++ b/drivers/clk/mediatek/clk-gate.h @@ -10,7 +10,7 @@ #include struct clk; -struct clk_onecell_data; +struct clk_hw_onecell_data; struct clk_ops; struct device; struct device_node; @@ -52,14 +52,14 @@ struct mtk_gate { int mtk_clk_register_gates(struct device_node *node, const struct mtk_gate *clks, int num, - struct clk_onecell_data *clk_data); + struct clk_hw_onecell_data *clk_data); int mtk_clk_register_gates_with_dev(struct device_node *node, const struct mtk_gate *clks, int num, - struct clk_onecell_data *clk_data, + struct clk_hw_onecell_data *clk_data, struct device *dev); void mtk_clk_unregister_gates(const struct mtk_gate *clks, int num, - struct clk_onecell_data *clk_data); + struct clk_hw_onecell_data *clk_data); #endif /* __DRV_CLK_GATE_H */ diff --git a/drivers/clk/mediatek/clk-mt2701-aud.c b/drivers/clk/mediatek/clk-mt2701-aud.c index e66896a44fad8854243cccd5c9ada89911aa0edb..6ba398eb7df9158339402553585cae6d9e2a66a4 100644 --- a/drivers/clk/mediatek/clk-mt2701-aud.c +++ b/drivers/clk/mediatek/clk-mt2701-aud.c @@ -145,7 +145,7 @@ static const struct of_device_id of_match_clk_mt2701_aud[] = { static int clk_mt2701_aud_probe(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; struct device_node *node = pdev->dev.of_node; int r; @@ -154,7 +154,7 @@ static int clk_mt2701_aud_probe(struct platform_device *pdev) mtk_clk_register_gates(node, audio_clks, ARRAY_SIZE(audio_clks), clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r) { dev_err(&pdev->dev, "could not register clock provider: %s: %d\n", diff --git a/drivers/clk/mediatek/clk-mt2701-bdp.c b/drivers/clk/mediatek/clk-mt2701-bdp.c index ffa09cfbfd51a0eee611ad95742ba9e4097bb492..662a8ab3fbb18a828048edf3241a12cb90d4df58 100644 --- a/drivers/clk/mediatek/clk-mt2701-bdp.c +++ b/drivers/clk/mediatek/clk-mt2701-bdp.c @@ -101,7 +101,7 @@ static const struct of_device_id of_match_clk_mt2701_bdp[] = { static int clk_mt2701_bdp_probe(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; int r; struct device_node *node = pdev->dev.of_node; @@ -110,7 +110,7 @@ static int clk_mt2701_bdp_probe(struct platform_device *pdev) mtk_clk_register_gates(node, bdp_clks, ARRAY_SIZE(bdp_clks), clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r) dev_err(&pdev->dev, "could not register clock provider: %s: %d\n", diff --git a/drivers/clk/mediatek/clk-mt2701-eth.c b/drivers/clk/mediatek/clk-mt2701-eth.c index 100ff6ca609e86c0d239178be136f68a7997b024..47c2289f3d1df9e438f0a014fb4251bba637209b 100644 --- a/drivers/clk/mediatek/clk-mt2701-eth.c +++ b/drivers/clk/mediatek/clk-mt2701-eth.c @@ -43,7 +43,7 @@ static const struct of_device_id of_match_clk_mt2701_eth[] = { static int clk_mt2701_eth_probe(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; int r; struct device_node *node = pdev->dev.of_node; @@ -52,7 +52,7 @@ static int clk_mt2701_eth_probe(struct platform_device *pdev) mtk_clk_register_gates(node, eth_clks, ARRAY_SIZE(eth_clks), clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r) dev_err(&pdev->dev, "could not register clock provider: %s: %d\n", diff --git a/drivers/clk/mediatek/clk-mt2701-g3d.c b/drivers/clk/mediatek/clk-mt2701-g3d.c index 1328c112a38fed702d3a1526155a1bc2643b9bb8..79929ed37f83830531a8d7602ab3747f9b679c77 100644 --- a/drivers/clk/mediatek/clk-mt2701-g3d.c +++ b/drivers/clk/mediatek/clk-mt2701-g3d.c @@ -37,7 +37,7 @@ static const struct mtk_gate g3d_clks[] = { static int clk_mt2701_g3dsys_init(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; struct device_node *node = pdev->dev.of_node; int r; @@ -46,7 +46,7 @@ static int clk_mt2701_g3dsys_init(struct platform_device *pdev) mtk_clk_register_gates(node, g3d_clks, ARRAY_SIZE(g3d_clks), clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r) dev_err(&pdev->dev, "could not register clock provider: %s: %d\n", diff --git a/drivers/clk/mediatek/clk-mt2701-hif.c b/drivers/clk/mediatek/clk-mt2701-hif.c index 61444881c53910692ed1782c698acd292b8537ce..1aa36cb93ad0ab210d5aa4cd82beef5dfc3d64cb 100644 --- a/drivers/clk/mediatek/clk-mt2701-hif.c +++ b/drivers/clk/mediatek/clk-mt2701-hif.c @@ -40,7 +40,7 @@ static const struct of_device_id of_match_clk_mt2701_hif[] = { static int clk_mt2701_hif_probe(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; int r; struct device_node *node = pdev->dev.of_node; @@ -49,7 +49,7 @@ static int clk_mt2701_hif_probe(struct platform_device *pdev) mtk_clk_register_gates(node, hif_clks, ARRAY_SIZE(hif_clks), clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r) { dev_err(&pdev->dev, "could not register clock provider: %s: %d\n", diff --git a/drivers/clk/mediatek/clk-mt2701-img.c b/drivers/clk/mediatek/clk-mt2701-img.c index 631e80f0fc7df439f92d4fa2267a5748cebae42b..c4f3cd26df60b51b2fd744fb5a7fa261fb750f55 100644 --- a/drivers/clk/mediatek/clk-mt2701-img.c +++ b/drivers/clk/mediatek/clk-mt2701-img.c @@ -43,7 +43,7 @@ static const struct of_device_id of_match_clk_mt2701_img[] = { static int clk_mt2701_img_probe(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; int r; struct device_node *node = pdev->dev.of_node; @@ -52,7 +52,7 @@ static int clk_mt2701_img_probe(struct platform_device *pdev) mtk_clk_register_gates(node, img_clks, ARRAY_SIZE(img_clks), clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r) dev_err(&pdev->dev, "could not register clock provider: %s: %d\n", diff --git a/drivers/clk/mediatek/clk-mt2701-mm.c b/drivers/clk/mediatek/clk-mt2701-mm.c index cb18e1849492cc612f951978f22dce7ca6a90cbf..9ea7abad99d23a8bca69ec7910a2274a84f0663d 100644 --- a/drivers/clk/mediatek/clk-mt2701-mm.c +++ b/drivers/clk/mediatek/clk-mt2701-mm.c @@ -83,7 +83,7 @@ static int clk_mt2701_mm_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct device_node *node = dev->parent->of_node; - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; int r; clk_data = mtk_alloc_clk_data(CLK_MM_NR); @@ -91,7 +91,7 @@ static int clk_mt2701_mm_probe(struct platform_device *pdev) mtk_clk_register_gates(node, mm_clks, ARRAY_SIZE(mm_clks), clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r) dev_err(&pdev->dev, "could not register clock provider: %s: %d\n", diff --git a/drivers/clk/mediatek/clk-mt2701-vdec.c b/drivers/clk/mediatek/clk-mt2701-vdec.c index c9def728ad1e828499ae42bc6868e187dc907b81..a2f18117f27a602ef312e723799a9edb8d32ddb6 100644 --- a/drivers/clk/mediatek/clk-mt2701-vdec.c +++ b/drivers/clk/mediatek/clk-mt2701-vdec.c @@ -54,7 +54,7 @@ static const struct of_device_id of_match_clk_mt2701_vdec[] = { static int clk_mt2701_vdec_probe(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; int r; struct device_node *node = pdev->dev.of_node; @@ -63,7 +63,7 @@ static int clk_mt2701_vdec_probe(struct platform_device *pdev) mtk_clk_register_gates(node, vdec_clks, ARRAY_SIZE(vdec_clks), clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r) dev_err(&pdev->dev, "could not register clock provider: %s: %d\n", diff --git a/drivers/clk/mediatek/clk-mt2701.c b/drivers/clk/mediatek/clk-mt2701.c index 1eb3e4563c3fb09010cbc5b76eb21ec651e1f9a3..04ba356db2d7eb62ecbc0962eec419759765dd61 100644 --- a/drivers/clk/mediatek/clk-mt2701.c +++ b/drivers/clk/mediatek/clk-mt2701.c @@ -666,7 +666,7 @@ static const struct mtk_gate top_clks[] = { static int mtk_topckgen_init(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; void __iomem *base; struct device_node *node = pdev->dev.of_node; struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -692,7 +692,7 @@ static int mtk_topckgen_init(struct platform_device *pdev) mtk_clk_register_gates(node, top_clks, ARRAY_SIZE(top_clks), clk_data); - return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); } static const struct mtk_gate_regs infra_cg_regs = { @@ -735,7 +735,7 @@ static const struct mtk_fixed_factor infra_fixed_divs[] = { FACTOR(CLK_INFRA_CLK_13M, "clk13m", "clk26m", 1, 2), }; -static struct clk_onecell_data *infra_clk_data; +static struct clk_hw_onecell_data *infra_clk_data; static void __init mtk_infrasys_init_early(struct device_node *node) { @@ -745,7 +745,7 @@ static void __init mtk_infrasys_init_early(struct device_node *node) infra_clk_data = mtk_alloc_clk_data(CLK_INFRA_NR); for (i = 0; i < CLK_INFRA_NR; i++) - infra_clk_data->clks[i] = ERR_PTR(-EPROBE_DEFER); + infra_clk_data->hws[i] = ERR_PTR(-EPROBE_DEFER); } mtk_clk_register_factors(infra_fixed_divs, ARRAY_SIZE(infra_fixed_divs), @@ -754,7 +754,8 @@ static void __init mtk_infrasys_init_early(struct device_node *node) mtk_clk_register_cpumuxes(node, cpu_muxes, ARRAY_SIZE(cpu_muxes), infra_clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, infra_clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, + infra_clk_data); if (r) pr_err("%s(): could not register clock provider: %d\n", __func__, r); @@ -771,8 +772,8 @@ static int mtk_infrasys_init(struct platform_device *pdev) infra_clk_data = mtk_alloc_clk_data(CLK_INFRA_NR); } else { for (i = 0; i < CLK_INFRA_NR; i++) { - if (infra_clk_data->clks[i] == ERR_PTR(-EPROBE_DEFER)) - infra_clk_data->clks[i] = ERR_PTR(-ENOENT); + if (infra_clk_data->hws[i] == ERR_PTR(-EPROBE_DEFER)) + infra_clk_data->hws[i] = ERR_PTR(-ENOENT); } } @@ -781,7 +782,8 @@ static int mtk_infrasys_init(struct platform_device *pdev) mtk_clk_register_factors(infra_fixed_divs, ARRAY_SIZE(infra_fixed_divs), infra_clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, infra_clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, + infra_clk_data); if (r) return r; @@ -886,7 +888,7 @@ static const struct mtk_composite peri_muxs[] = { static int mtk_pericfg_init(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; void __iomem *base; int r; struct device_node *node = pdev->dev.of_node; @@ -904,7 +906,7 @@ static int mtk_pericfg_init(struct platform_device *pdev) mtk_clk_register_composites(peri_muxs, ARRAY_SIZE(peri_muxs), base, &mt2701_clk_lock, clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r) return r; @@ -935,13 +937,13 @@ static int mtk_pericfg_init(struct platform_device *pdev) } static const struct mtk_pll_data apmixed_plls[] = { - PLL(CLK_APMIXED_ARMPLL, "armpll", 0x200, 0x20c, 0x80000001, + PLL(CLK_APMIXED_ARMPLL, "armpll", 0x200, 0x20c, 0x80000000, PLL_AO, 21, 0x204, 24, 0x0, 0x204, 0), - PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x210, 0x21c, 0xf0000001, + PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x210, 0x21c, 0xf0000000, HAVE_RST_BAR, 21, 0x210, 4, 0x0, 0x214, 0), - PLL(CLK_APMIXED_UNIVPLL, "univpll", 0x220, 0x22c, 0xf3000001, + PLL(CLK_APMIXED_UNIVPLL, "univpll", 0x220, 0x22c, 0xf3000000, HAVE_RST_BAR, 7, 0x220, 4, 0x0, 0x224, 14), - PLL(CLK_APMIXED_MMPLL, "mmpll", 0x230, 0x23c, 0x00000001, 0, + PLL(CLK_APMIXED_MMPLL, "mmpll", 0x230, 0x23c, 0, 0, 21, 0x230, 4, 0x0, 0x234, 0), PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x240, 0x24c, 0x00000001, 0, 21, 0x240, 4, 0x0, 0x244, 0), @@ -969,7 +971,7 @@ static const struct mtk_fixed_factor apmixed_fixed_divs[] = { static int mtk_apmixedsys_init(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; struct device_node *node = pdev->dev.of_node; clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR); @@ -981,7 +983,7 @@ static int mtk_apmixedsys_init(struct platform_device *pdev) mtk_clk_register_factors(apmixed_fixed_divs, ARRAY_SIZE(apmixed_fixed_divs), clk_data); - return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); } static const struct of_device_id of_match_clk_mt2701[] = { diff --git a/drivers/clk/mediatek/clk-mt2712-bdp.c b/drivers/clk/mediatek/clk-mt2712-bdp.c index a200714001d825d7dbd487a0b18fad7301787c67..9acab43571337c9d39e3e22943a3d36ae042499d 100644 --- a/drivers/clk/mediatek/clk-mt2712-bdp.c +++ b/drivers/clk/mediatek/clk-mt2712-bdp.c @@ -60,7 +60,7 @@ static const struct mtk_gate bdp_clks[] = { static int clk_mt2712_bdp_probe(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; int r; struct device_node *node = pdev->dev.of_node; @@ -69,7 +69,7 @@ static int clk_mt2712_bdp_probe(struct platform_device *pdev) mtk_clk_register_gates(node, bdp_clks, ARRAY_SIZE(bdp_clks), clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r != 0) pr_err("%s(): could not register clock provider: %d\n", diff --git a/drivers/clk/mediatek/clk-mt2712-img.c b/drivers/clk/mediatek/clk-mt2712-img.c index 89b2a7197b020eeba1ea332dc5bbed5462149579..5cc143e65e423dfab458fb02146e9f3e0ceb36cf 100644 --- a/drivers/clk/mediatek/clk-mt2712-img.c +++ b/drivers/clk/mediatek/clk-mt2712-img.c @@ -38,7 +38,7 @@ static const struct mtk_gate img_clks[] = { static int clk_mt2712_img_probe(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; int r; struct device_node *node = pdev->dev.of_node; @@ -47,7 +47,7 @@ static int clk_mt2712_img_probe(struct platform_device *pdev) mtk_clk_register_gates(node, img_clks, ARRAY_SIZE(img_clks), clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r != 0) pr_err("%s(): could not register clock provider: %d\n", diff --git a/drivers/clk/mediatek/clk-mt2712-jpgdec.c b/drivers/clk/mediatek/clk-mt2712-jpgdec.c index 58813c38ab4d173115362daaa0465f8eaa274155..31fc30370d9831c1e6fd6744a3adeb6a9e1bf573 100644 --- a/drivers/clk/mediatek/clk-mt2712-jpgdec.c +++ b/drivers/clk/mediatek/clk-mt2712-jpgdec.c @@ -34,7 +34,7 @@ static const struct mtk_gate jpgdec_clks[] = { static int clk_mt2712_jpgdec_probe(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; int r; struct device_node *node = pdev->dev.of_node; @@ -43,7 +43,7 @@ static int clk_mt2712_jpgdec_probe(struct platform_device *pdev) mtk_clk_register_gates(node, jpgdec_clks, ARRAY_SIZE(jpgdec_clks), clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r != 0) pr_err("%s(): could not register clock provider: %d\n", diff --git a/drivers/clk/mediatek/clk-mt2712-mfg.c b/drivers/clk/mediatek/clk-mt2712-mfg.c index a6b827db17bc9041f6561d9fb68d76e9f3edfab9..a4d09675bf18e0d80d8dd067603421e414a5cdd6 100644 --- a/drivers/clk/mediatek/clk-mt2712-mfg.c +++ b/drivers/clk/mediatek/clk-mt2712-mfg.c @@ -33,7 +33,7 @@ static const struct mtk_gate mfg_clks[] = { static int clk_mt2712_mfg_probe(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; int r; struct device_node *node = pdev->dev.of_node; @@ -42,7 +42,7 @@ static int clk_mt2712_mfg_probe(struct platform_device *pdev) mtk_clk_register_gates(node, mfg_clks, ARRAY_SIZE(mfg_clks), clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r != 0) pr_err("%s(): could not register clock provider: %d\n", diff --git a/drivers/clk/mediatek/clk-mt2712-mm.c b/drivers/clk/mediatek/clk-mt2712-mm.c index 5519c3d68c1f5e2c4f6fb09ad529d4788e6e41f3..7d44b09b8a0a793abe14818e52647ba16d0c8239 100644 --- a/drivers/clk/mediatek/clk-mt2712-mm.c +++ b/drivers/clk/mediatek/clk-mt2712-mm.c @@ -130,7 +130,7 @@ static int clk_mt2712_mm_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct device_node *node = dev->parent->of_node; - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; int r; clk_data = mtk_alloc_clk_data(CLK_MM_NR_CLK); @@ -138,7 +138,7 @@ static int clk_mt2712_mm_probe(struct platform_device *pdev) mtk_clk_register_gates(node, mm_clks, ARRAY_SIZE(mm_clks), clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r != 0) pr_err("%s(): could not register clock provider: %d\n", diff --git a/drivers/clk/mediatek/clk-mt2712-vdec.c b/drivers/clk/mediatek/clk-mt2712-vdec.c index 4987ad9d3b1161b8b72a3676534b17670bf5f25a..af13f43dd83198b6c54878db5894f88d678c4030 100644 --- a/drivers/clk/mediatek/clk-mt2712-vdec.c +++ b/drivers/clk/mediatek/clk-mt2712-vdec.c @@ -52,7 +52,7 @@ static const struct mtk_gate vdec_clks[] = { static int clk_mt2712_vdec_probe(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; int r; struct device_node *node = pdev->dev.of_node; @@ -61,7 +61,7 @@ static int clk_mt2712_vdec_probe(struct platform_device *pdev) mtk_clk_register_gates(node, vdec_clks, ARRAY_SIZE(vdec_clks), clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r != 0) pr_err("%s(): could not register clock provider: %d\n", diff --git a/drivers/clk/mediatek/clk-mt2712-venc.c b/drivers/clk/mediatek/clk-mt2712-venc.c index 07c29daa1ad6e139771fc5faa32e8a5badb3284e..abc08a02975353c83640cf35bf3b3c5deed3a281 100644 --- a/drivers/clk/mediatek/clk-mt2712-venc.c +++ b/drivers/clk/mediatek/clk-mt2712-venc.c @@ -35,7 +35,7 @@ static const struct mtk_gate venc_clks[] = { static int clk_mt2712_venc_probe(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; int r; struct device_node *node = pdev->dev.of_node; @@ -44,7 +44,7 @@ static int clk_mt2712_venc_probe(struct platform_device *pdev) mtk_clk_register_gates(node, venc_clks, ARRAY_SIZE(venc_clks), clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r != 0) pr_err("%s(): could not register clock provider: %d\n", diff --git a/drivers/clk/mediatek/clk-mt2712.c b/drivers/clk/mediatek/clk-mt2712.c index ff72b9ab945bd1577b9a08a90801cbbc5f8e6f8d..410b059727ea1e683b63d81a3955b9bfef8cedc9 100644 --- a/drivers/clk/mediatek/clk-mt2712.c +++ b/drivers/clk/mediatek/clk-mt2712.c @@ -1223,44 +1223,44 @@ static const struct mtk_pll_div_table mmpll_div_table[] = { }; static const struct mtk_pll_data plls[] = { - PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x0230, 0x023C, 0xf0000101, + PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x0230, 0x023C, 0xf0000100, HAVE_RST_BAR, 31, 0x0230, 4, 0, 0, 0, 0x0234, 0), - PLL(CLK_APMIXED_UNIVPLL, "univpll", 0x0240, 0x024C, 0xfe000101, + PLL(CLK_APMIXED_UNIVPLL, "univpll", 0x0240, 0x024C, 0xfe000100, HAVE_RST_BAR, 31, 0x0240, 4, 0, 0, 0, 0x0244, 0), - PLL(CLK_APMIXED_VCODECPLL, "vcodecpll", 0x0320, 0x032C, 0xc0000101, + PLL(CLK_APMIXED_VCODECPLL, "vcodecpll", 0x0320, 0x032C, 0xc0000100, 0, 31, 0x0320, 4, 0, 0, 0, 0x0324, 0), - PLL(CLK_APMIXED_VENCPLL, "vencpll", 0x0280, 0x028C, 0x00000101, + PLL(CLK_APMIXED_VENCPLL, "vencpll", 0x0280, 0x028C, 0x00000100, 0, 31, 0x0280, 4, 0, 0, 0, 0x0284, 0), - PLL(CLK_APMIXED_APLL1, "apll1", 0x0330, 0x0340, 0x00000101, + PLL(CLK_APMIXED_APLL1, "apll1", 0x0330, 0x0340, 0x00000100, 0, 31, 0x0330, 4, 0x0338, 0x0014, 0, 0x0334, 0), - PLL(CLK_APMIXED_APLL2, "apll2", 0x0350, 0x0360, 0x00000101, + PLL(CLK_APMIXED_APLL2, "apll2", 0x0350, 0x0360, 0x00000100, 0, 31, 0x0350, 4, 0x0358, 0x0014, 1, 0x0354, 0), - PLL(CLK_APMIXED_LVDSPLL, "lvdspll", 0x0370, 0x037c, 0x00000101, + PLL(CLK_APMIXED_LVDSPLL, "lvdspll", 0x0370, 0x037c, 0x00000100, 0, 31, 0x0370, 4, 0, 0, 0, 0x0374, 0), - PLL(CLK_APMIXED_LVDSPLL2, "lvdspll2", 0x0390, 0x039C, 0x00000101, + PLL(CLK_APMIXED_LVDSPLL2, "lvdspll2", 0x0390, 0x039C, 0x00000100, 0, 31, 0x0390, 4, 0, 0, 0, 0x0394, 0), - PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x0270, 0x027C, 0x00000101, + PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x0270, 0x027C, 0x00000100, 0, 31, 0x0270, 4, 0, 0, 0, 0x0274, 0), - PLL(CLK_APMIXED_MSDCPLL2, "msdcpll2", 0x0410, 0x041C, 0x00000101, + PLL(CLK_APMIXED_MSDCPLL2, "msdcpll2", 0x0410, 0x041C, 0x00000100, 0, 31, 0x0410, 4, 0, 0, 0, 0x0414, 0), - PLL(CLK_APMIXED_TVDPLL, "tvdpll", 0x0290, 0x029C, 0xc0000101, + PLL(CLK_APMIXED_TVDPLL, "tvdpll", 0x0290, 0x029C, 0xc0000100, 0, 31, 0x0290, 4, 0, 0, 0, 0x0294, 0), - PLL_B(CLK_APMIXED_MMPLL, "mmpll", 0x0250, 0x0260, 0x00000101, + PLL_B(CLK_APMIXED_MMPLL, "mmpll", 0x0250, 0x0260, 0x00000100, 0, 31, 0x0250, 4, 0, 0, 0, 0x0254, 0, mmpll_div_table), - PLL_B(CLK_APMIXED_ARMCA35PLL, "armca35pll", 0x0100, 0x0110, 0xf0000101, + PLL_B(CLK_APMIXED_ARMCA35PLL, "armca35pll", 0x0100, 0x0110, 0xf0000100, HAVE_RST_BAR, 31, 0x0100, 4, 0, 0, 0, 0x0104, 0, armca35pll_div_table), - PLL_B(CLK_APMIXED_ARMCA72PLL, "armca72pll", 0x0210, 0x0220, 0x00000101, + PLL_B(CLK_APMIXED_ARMCA72PLL, "armca72pll", 0x0210, 0x0220, 0x00000100, 0, 31, 0x0210, 4, 0, 0, 0, 0x0214, 0, armca72pll_div_table), - PLL(CLK_APMIXED_ETHERPLL, "etherpll", 0x0300, 0x030C, 0xc0000101, + PLL(CLK_APMIXED_ETHERPLL, "etherpll", 0x0300, 0x030C, 0xc0000100, 0, 31, 0x0300, 4, 0, 0, 0, 0x0304, 0), }; static int clk_mt2712_apmixed_probe(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; int r; struct device_node *node = pdev->dev.of_node; @@ -1268,7 +1268,7 @@ static int clk_mt2712_apmixed_probe(struct platform_device *pdev) mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r != 0) pr_err("%s(): could not register clock provider: %d\n", @@ -1277,7 +1277,7 @@ static int clk_mt2712_apmixed_probe(struct platform_device *pdev) return r; } -static struct clk_onecell_data *top_clk_data; +static struct clk_hw_onecell_data *top_clk_data; static void clk_mt2712_top_init_early(struct device_node *node) { @@ -1287,13 +1287,13 @@ static void clk_mt2712_top_init_early(struct device_node *node) top_clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK); for (i = 0; i < CLK_TOP_NR_CLK; i++) - top_clk_data->clks[i] = ERR_PTR(-EPROBE_DEFER); + top_clk_data->hws[i] = ERR_PTR(-EPROBE_DEFER); } mtk_clk_register_factors(top_early_divs, ARRAY_SIZE(top_early_divs), top_clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, top_clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, top_clk_data); if (r) pr_err("%s(): could not register clock provider: %d\n", __func__, r); @@ -1318,8 +1318,8 @@ static int clk_mt2712_top_probe(struct platform_device *pdev) top_clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK); } else { for (i = 0; i < CLK_TOP_NR_CLK; i++) { - if (top_clk_data->clks[i] == ERR_PTR(-EPROBE_DEFER)) - top_clk_data->clks[i] = ERR_PTR(-ENOENT); + if (top_clk_data->hws[i] == ERR_PTR(-EPROBE_DEFER)) + top_clk_data->hws[i] = ERR_PTR(-ENOENT); } } @@ -1335,7 +1335,7 @@ static int clk_mt2712_top_probe(struct platform_device *pdev) mtk_clk_register_gates(node, top_clks, ARRAY_SIZE(top_clks), top_clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, top_clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, top_clk_data); if (r != 0) pr_err("%s(): could not register clock provider: %d\n", @@ -1346,7 +1346,7 @@ static int clk_mt2712_top_probe(struct platform_device *pdev) static int clk_mt2712_infra_probe(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; int r; struct device_node *node = pdev->dev.of_node; @@ -1355,7 +1355,7 @@ static int clk_mt2712_infra_probe(struct platform_device *pdev) mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks), clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r != 0) pr_err("%s(): could not register clock provider: %d\n", @@ -1368,7 +1368,7 @@ static int clk_mt2712_infra_probe(struct platform_device *pdev) static int clk_mt2712_peri_probe(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; int r; struct device_node *node = pdev->dev.of_node; @@ -1377,7 +1377,7 @@ static int clk_mt2712_peri_probe(struct platform_device *pdev) mtk_clk_register_gates(node, peri_clks, ARRAY_SIZE(peri_clks), clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r != 0) pr_err("%s(): could not register clock provider: %d\n", @@ -1390,7 +1390,7 @@ static int clk_mt2712_peri_probe(struct platform_device *pdev) static int clk_mt2712_mcu_probe(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; int r; struct device_node *node = pdev->dev.of_node; void __iomem *base; @@ -1406,7 +1406,7 @@ static int clk_mt2712_mcu_probe(struct platform_device *pdev) mtk_clk_register_composites(mcu_muxes, ARRAY_SIZE(mcu_muxes), base, &mt2712_clk_lock, clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r != 0) pr_err("%s(): could not register clock provider: %d\n", diff --git a/drivers/clk/mediatek/clk-mt6765-audio.c b/drivers/clk/mediatek/clk-mt6765-audio.c index 4c989165d795059968e07e2c7320857240d4abff..9c6e9caad5972e04e623868b9e84fe2118a0cd81 100644 --- a/drivers/clk/mediatek/clk-mt6765-audio.c +++ b/drivers/clk/mediatek/clk-mt6765-audio.c @@ -66,7 +66,7 @@ static const struct mtk_gate audio_clks[] = { static int clk_mt6765_audio_probe(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; int r; struct device_node *node = pdev->dev.of_node; @@ -75,7 +75,7 @@ static int clk_mt6765_audio_probe(struct platform_device *pdev) mtk_clk_register_gates(node, audio_clks, ARRAY_SIZE(audio_clks), clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r) pr_err("%s(): could not register clock provider: %d\n", diff --git a/drivers/clk/mediatek/clk-mt6765-cam.c b/drivers/clk/mediatek/clk-mt6765-cam.c index c96394893bcfda6b1ae6a238c46f184433da4418..2586d3ac4cd45fd7d3210ab0d48262084b16f0a9 100644 --- a/drivers/clk/mediatek/clk-mt6765-cam.c +++ b/drivers/clk/mediatek/clk-mt6765-cam.c @@ -41,7 +41,7 @@ static const struct mtk_gate cam_clks[] = { static int clk_mt6765_cam_probe(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; int r; struct device_node *node = pdev->dev.of_node; @@ -49,7 +49,7 @@ static int clk_mt6765_cam_probe(struct platform_device *pdev) mtk_clk_register_gates(node, cam_clks, ARRAY_SIZE(cam_clks), clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r) pr_err("%s(): could not register clock provider: %d\n", diff --git a/drivers/clk/mediatek/clk-mt6765-img.c b/drivers/clk/mediatek/clk-mt6765-img.c index 6fd8bf8030fc703e6415d0e67863474f4d0dbb66..8cc95b98921e1909121833f757c0ebca9b790aca 100644 --- a/drivers/clk/mediatek/clk-mt6765-img.c +++ b/drivers/clk/mediatek/clk-mt6765-img.c @@ -37,7 +37,7 @@ static const struct mtk_gate img_clks[] = { static int clk_mt6765_img_probe(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; int r; struct device_node *node = pdev->dev.of_node; @@ -45,7 +45,7 @@ static int clk_mt6765_img_probe(struct platform_device *pdev) mtk_clk_register_gates(node, img_clks, ARRAY_SIZE(img_clks), clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r) pr_err("%s(): could not register clock provider: %d\n", diff --git a/drivers/clk/mediatek/clk-mt6765-mipi0a.c b/drivers/clk/mediatek/clk-mt6765-mipi0a.c index 81744d0f95a0f555017f884c206c2be10b21fd0c..c816e26a95f99de84e0d2449323291f584285042 100644 --- a/drivers/clk/mediatek/clk-mt6765-mipi0a.c +++ b/drivers/clk/mediatek/clk-mt6765-mipi0a.c @@ -34,7 +34,7 @@ static const struct mtk_gate mipi0a_clks[] = { static int clk_mt6765_mipi0a_probe(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; int r; struct device_node *node = pdev->dev.of_node; @@ -43,7 +43,7 @@ static int clk_mt6765_mipi0a_probe(struct platform_device *pdev) mtk_clk_register_gates(node, mipi0a_clks, ARRAY_SIZE(mipi0a_clks), clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r) pr_err("%s(): could not register clock provider: %d\n", diff --git a/drivers/clk/mediatek/clk-mt6765-mm.c b/drivers/clk/mediatek/clk-mt6765-mm.c index 6d8214c51684e62e7de4e203ec6772b4abead7fb..ee6d3b859a6ca4a04a6bf8ffd96b6761ab3d7c4c 100644 --- a/drivers/clk/mediatek/clk-mt6765-mm.c +++ b/drivers/clk/mediatek/clk-mt6765-mm.c @@ -63,7 +63,7 @@ static const struct mtk_gate mm_clks[] = { static int clk_mt6765_mm_probe(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; int r; struct device_node *node = pdev->dev.of_node; @@ -71,7 +71,7 @@ static int clk_mt6765_mm_probe(struct platform_device *pdev) mtk_clk_register_gates(node, mm_clks, ARRAY_SIZE(mm_clks), clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r) pr_err("%s(): could not register clock provider: %d\n", diff --git a/drivers/clk/mediatek/clk-mt6765-vcodec.c b/drivers/clk/mediatek/clk-mt6765-vcodec.c index baae665fab31cfcf94f732ca3b85c8a738acb454..d8045979d48a5fb11538b771a001725c6de0f34d 100644 --- a/drivers/clk/mediatek/clk-mt6765-vcodec.c +++ b/drivers/clk/mediatek/clk-mt6765-vcodec.c @@ -36,7 +36,7 @@ static const struct mtk_gate venc_clks[] = { static int clk_mt6765_vcodec_probe(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; int r; struct device_node *node = pdev->dev.of_node; @@ -45,7 +45,7 @@ static int clk_mt6765_vcodec_probe(struct platform_device *pdev) mtk_clk_register_gates(node, venc_clks, ARRAY_SIZE(venc_clks), clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r) pr_err("%s(): could not register clock provider: %d\n", diff --git a/drivers/clk/mediatek/clk-mt6765.c b/drivers/clk/mediatek/clk-mt6765.c index 24829ca3bd1f648ee57e09cb8e20aedd0c03ccea..e9b9e6729733528be28d00af281d1e4b897dbee6 100644 --- a/drivers/clk/mediatek/clk-mt6765.c +++ b/drivers/clk/mediatek/clk-mt6765.c @@ -748,32 +748,32 @@ static const struct mtk_gate apmixed_clks[] = { _pcw_reg, _pcw_shift, NULL) \ static const struct mtk_pll_data plls[] = { - PLL(CLK_APMIXED_ARMPLL_L, "armpll_l", 0x021C, 0x0228, BIT(0), + PLL(CLK_APMIXED_ARMPLL_L, "armpll_l", 0x021C, 0x0228, 0, PLL_AO, 22, 8, 0x0220, 24, 0, 0, 0, 0x0220, 0), - PLL(CLK_APMIXED_ARMPLL, "armpll", 0x020C, 0x0218, BIT(0), + PLL(CLK_APMIXED_ARMPLL, "armpll", 0x020C, 0x0218, 0, PLL_AO, 22, 8, 0x0210, 24, 0, 0, 0, 0x0210, 0), - PLL(CLK_APMIXED_CCIPLL, "ccipll", 0x022C, 0x0238, BIT(0), + PLL(CLK_APMIXED_CCIPLL, "ccipll", 0x022C, 0x0238, 0, PLL_AO, 22, 8, 0x0230, 24, 0, 0, 0, 0x0230, 0), - PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x023C, 0x0248, BIT(0), + PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x023C, 0x0248, 0, (HAVE_RST_BAR | PLL_AO), 22, 8, 0x0240, 24, 0, 0, 0, 0x0240, 0), - PLL(CLK_APMIXED_MFGPLL, "mfgpll", 0x024C, 0x0258, BIT(0), + PLL(CLK_APMIXED_MFGPLL, "mfgpll", 0x024C, 0x0258, 0, 0, 22, 8, 0x0250, 24, 0, 0, 0, 0x0250, 0), - PLL(CLK_APMIXED_MMPLL, "mmpll", 0x025C, 0x0268, BIT(0), + PLL(CLK_APMIXED_MMPLL, "mmpll", 0x025C, 0x0268, 0, 0, 22, 8, 0x0260, 24, 0, 0, 0, 0x0260, 0), - PLL(CLK_APMIXED_UNIV2PLL, "univ2pll", 0x026C, 0x0278, BIT(0), + PLL(CLK_APMIXED_UNIV2PLL, "univ2pll", 0x026C, 0x0278, 0, HAVE_RST_BAR, 22, 8, 0x0270, 24, 0, 0, 0, 0x0270, 0), - PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x027C, 0x0288, BIT(0), + PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x027C, 0x0288, 0, 0, 22, 8, 0x0280, 24, 0, 0, 0, 0x0280, 0), - PLL(CLK_APMIXED_APLL1, "apll1", 0x028C, 0x029C, BIT(0), + PLL(CLK_APMIXED_APLL1, "apll1", 0x028C, 0x029C, 0, 0, 32, 8, 0x0290, 24, 0x0040, 0x000C, 0, 0x0294, 0), - PLL(CLK_APMIXED_MPLL, "mpll", 0x02A0, 0x02AC, BIT(0), + PLL(CLK_APMIXED_MPLL, "mpll", 0x02A0, 0x02AC, 0, PLL_AO, 22, 8, 0x02A4, 24, 0, 0, 0, 0x02A4, 0), }; static int clk_mt6765_apmixed_probe(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; int r; struct device_node *node = pdev->dev.of_node; void __iomem *base; @@ -791,7 +791,7 @@ static int clk_mt6765_apmixed_probe(struct platform_device *pdev) mtk_clk_register_gates(node, apmixed_clks, ARRAY_SIZE(apmixed_clks), clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r) pr_err("%s(): could not register clock provider: %d\n", @@ -811,7 +811,7 @@ static int clk_mt6765_top_probe(struct platform_device *pdev) int r; struct device_node *node = pdev->dev.of_node; void __iomem *base; - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); base = devm_ioremap_resource(&pdev->dev, res); @@ -831,7 +831,7 @@ static int clk_mt6765_top_probe(struct platform_device *pdev) mtk_clk_register_gates(node, top_clks, ARRAY_SIZE(top_clks), clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r) pr_err("%s(): could not register clock provider: %d\n", @@ -848,7 +848,7 @@ static int clk_mt6765_top_probe(struct platform_device *pdev) static int clk_mt6765_ifr_probe(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; int r; struct device_node *node = pdev->dev.of_node; void __iomem *base; @@ -864,7 +864,7 @@ static int clk_mt6765_ifr_probe(struct platform_device *pdev) mtk_clk_register_gates(node, ifr_clks, ARRAY_SIZE(ifr_clks), clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r) pr_err("%s(): could not register clock provider: %d\n", diff --git a/drivers/clk/mediatek/clk-mt6779-aud.c b/drivers/clk/mediatek/clk-mt6779-aud.c index 9e889e4c361a6d46f5af47ea6bbf83c9b14c2223..97e44abb7e8798d42e6b912430f2093fcd7cde99 100644 --- a/drivers/clk/mediatek/clk-mt6779-aud.c +++ b/drivers/clk/mediatek/clk-mt6779-aud.c @@ -96,7 +96,7 @@ static const struct of_device_id of_match_clk_mt6779_aud[] = { static int clk_mt6779_aud_probe(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; struct device_node *node = pdev->dev.of_node; clk_data = mtk_alloc_clk_data(CLK_AUD_NR_CLK); @@ -104,7 +104,7 @@ static int clk_mt6779_aud_probe(struct platform_device *pdev) mtk_clk_register_gates(node, audio_clks, ARRAY_SIZE(audio_clks), clk_data); - return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); } static struct platform_driver clk_mt6779_aud_drv = { diff --git a/drivers/clk/mediatek/clk-mt6779-cam.c b/drivers/clk/mediatek/clk-mt6779-cam.c index 7f07a2a139acf4b1abac0a0e7467d35aa0b9fb81..9c5117aae14689ca01acdc1a477bbc24bd97ec79 100644 --- a/drivers/clk/mediatek/clk-mt6779-cam.c +++ b/drivers/clk/mediatek/clk-mt6779-cam.c @@ -45,7 +45,7 @@ static const struct of_device_id of_match_clk_mt6779_cam[] = { static int clk_mt6779_cam_probe(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; struct device_node *node = pdev->dev.of_node; clk_data = mtk_alloc_clk_data(CLK_CAM_NR_CLK); @@ -53,7 +53,7 @@ static int clk_mt6779_cam_probe(struct platform_device *pdev) mtk_clk_register_gates(node, cam_clks, ARRAY_SIZE(cam_clks), clk_data); - return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); } static struct platform_driver clk_mt6779_cam_drv = { diff --git a/drivers/clk/mediatek/clk-mt6779-img.c b/drivers/clk/mediatek/clk-mt6779-img.c index f0961fa1a28649d7c53c71ffe1214cd3564cc1f8..801271477d46ba2364cee4e2487e5dd425a2558f 100644 --- a/drivers/clk/mediatek/clk-mt6779-img.c +++ b/drivers/clk/mediatek/clk-mt6779-img.c @@ -37,7 +37,7 @@ static const struct of_device_id of_match_clk_mt6779_img[] = { static int clk_mt6779_img_probe(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; struct device_node *node = pdev->dev.of_node; clk_data = mtk_alloc_clk_data(CLK_IMG_NR_CLK); @@ -45,7 +45,7 @@ static int clk_mt6779_img_probe(struct platform_device *pdev) mtk_clk_register_gates(node, img_clks, ARRAY_SIZE(img_clks), clk_data); - return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); } static struct platform_driver clk_mt6779_img_drv = { diff --git a/drivers/clk/mediatek/clk-mt6779-ipe.c b/drivers/clk/mediatek/clk-mt6779-ipe.c index 8c6f3e154bf35506b7826df1ea2626179534f62f..f67814ca7dfba7abdf6f76e65562592043645f75 100644 --- a/drivers/clk/mediatek/clk-mt6779-ipe.c +++ b/drivers/clk/mediatek/clk-mt6779-ipe.c @@ -39,7 +39,7 @@ static const struct of_device_id of_match_clk_mt6779_ipe[] = { static int clk_mt6779_ipe_probe(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; struct device_node *node = pdev->dev.of_node; clk_data = mtk_alloc_clk_data(CLK_IPE_NR_CLK); @@ -47,7 +47,7 @@ static int clk_mt6779_ipe_probe(struct platform_device *pdev) mtk_clk_register_gates(node, ipe_clks, ARRAY_SIZE(ipe_clks), clk_data); - return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); } static struct platform_driver clk_mt6779_ipe_drv = { diff --git a/drivers/clk/mediatek/clk-mt6779-mfg.c b/drivers/clk/mediatek/clk-mt6779-mfg.c index 9f3372886e6b41921c6e0f0399b7d6d736d935cd..fc7387b59758d36220c11f24ab7eea41b3abdb16 100644 --- a/drivers/clk/mediatek/clk-mt6779-mfg.c +++ b/drivers/clk/mediatek/clk-mt6779-mfg.c @@ -29,7 +29,7 @@ static const struct mtk_gate mfg_clks[] = { static int clk_mt6779_mfg_probe(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; struct device_node *node = pdev->dev.of_node; clk_data = mtk_alloc_clk_data(CLK_MFGCFG_NR_CLK); @@ -37,7 +37,7 @@ static int clk_mt6779_mfg_probe(struct platform_device *pdev) mtk_clk_register_gates(node, mfg_clks, ARRAY_SIZE(mfg_clks), clk_data); - return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); } static const struct of_device_id of_match_clk_mt6779_mfg[] = { diff --git a/drivers/clk/mediatek/clk-mt6779-mm.c b/drivers/clk/mediatek/clk-mt6779-mm.c index 33946e6471227e881f30cf746e31feb4948d3395..eda8cbee3d234203fedeb7438c7aa45601184d67 100644 --- a/drivers/clk/mediatek/clk-mt6779-mm.c +++ b/drivers/clk/mediatek/clk-mt6779-mm.c @@ -89,14 +89,14 @@ static int clk_mt6779_mm_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct device_node *node = dev->parent->of_node; - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; clk_data = mtk_alloc_clk_data(CLK_MM_NR_CLK); mtk_clk_register_gates(node, mm_clks, ARRAY_SIZE(mm_clks), clk_data); - return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); } static struct platform_driver clk_mt6779_mm_drv = { diff --git a/drivers/clk/mediatek/clk-mt6779-vdec.c b/drivers/clk/mediatek/clk-mt6779-vdec.c index f4358844c2e08659440c483203566bb0c18ec3e5..7e195b082e86754420e59da6492e7baed6ec0fb6 100644 --- a/drivers/clk/mediatek/clk-mt6779-vdec.c +++ b/drivers/clk/mediatek/clk-mt6779-vdec.c @@ -46,7 +46,7 @@ static const struct of_device_id of_match_clk_mt6779_vdec[] = { static int clk_mt6779_vdec_probe(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; struct device_node *node = pdev->dev.of_node; clk_data = mtk_alloc_clk_data(CLK_VDEC_GCON_NR_CLK); @@ -54,7 +54,7 @@ static int clk_mt6779_vdec_probe(struct platform_device *pdev) mtk_clk_register_gates(node, vdec_clks, ARRAY_SIZE(vdec_clks), clk_data); - return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); } static struct platform_driver clk_mt6779_vdec_drv = { diff --git a/drivers/clk/mediatek/clk-mt6779-venc.c b/drivers/clk/mediatek/clk-mt6779-venc.c index ff67084af5aa11393dafcef50ddce90d3b875c02..573efa87c9bdc0d79a0f61f33406e2f393642439 100644 --- a/drivers/clk/mediatek/clk-mt6779-venc.c +++ b/drivers/clk/mediatek/clk-mt6779-venc.c @@ -37,7 +37,7 @@ static const struct of_device_id of_match_clk_mt6779_venc[] = { static int clk_mt6779_venc_probe(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; struct device_node *node = pdev->dev.of_node; clk_data = mtk_alloc_clk_data(CLK_VENC_GCON_NR_CLK); @@ -45,7 +45,7 @@ static int clk_mt6779_venc_probe(struct platform_device *pdev) mtk_clk_register_gates(node, venc_clks, ARRAY_SIZE(venc_clks), clk_data); - return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); } static struct platform_driver clk_mt6779_venc_drv = { diff --git a/drivers/clk/mediatek/clk-mt6779.c b/drivers/clk/mediatek/clk-mt6779.c index 7b61664da18f1b981130d1d69c31f66158f162a6..0d0a90ee5eb2c1a0a0bae7333382049511921338 100644 --- a/drivers/clk/mediatek/clk-mt6779.c +++ b/drivers/clk/mediatek/clk-mt6779.c @@ -1182,39 +1182,39 @@ static const struct mtk_gate apmixed_clks[] = { _pcw_chg_reg, NULL) static const struct mtk_pll_data plls[] = { - PLL(CLK_APMIXED_ARMPLL_LL, "armpll_ll", 0x0200, 0x020C, BIT(0), + PLL(CLK_APMIXED_ARMPLL_LL, "armpll_ll", 0x0200, 0x020C, 0, PLL_AO, 0, 22, 8, 0x0204, 24, 0, 0, 0, 0x0204, 0, 0), - PLL(CLK_APMIXED_ARMPLL_BL, "armpll_bl", 0x0210, 0x021C, BIT(0), + PLL(CLK_APMIXED_ARMPLL_BL, "armpll_bl", 0x0210, 0x021C, 0, PLL_AO, 0, 22, 8, 0x0214, 24, 0, 0, 0, 0x0214, 0, 0), - PLL(CLK_APMIXED_CCIPLL, "ccipll", 0x02A0, 0x02AC, BIT(0), + PLL(CLK_APMIXED_CCIPLL, "ccipll", 0x02A0, 0x02AC, 0, PLL_AO, 0, 22, 8, 0x02A4, 24, 0, 0, 0, 0x02A4, 0, 0), - PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x0230, 0x023C, BIT(0), + PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x0230, 0x023C, 0, (HAVE_RST_BAR), BIT(24), 22, 8, 0x0234, 24, 0, 0, 0, 0x0234, 0, 0), - PLL(CLK_APMIXED_UNIV2PLL, "univ2pll", 0x0240, 0x024C, BIT(0), + PLL(CLK_APMIXED_UNIV2PLL, "univ2pll", 0x0240, 0x024C, 0, (HAVE_RST_BAR), BIT(24), 22, 8, 0x0244, 24, 0, 0, 0, 0x0244, 0, 0), - PLL(CLK_APMIXED_MFGPLL, "mfgpll", 0x0250, 0x025C, BIT(0), + PLL(CLK_APMIXED_MFGPLL, "mfgpll", 0x0250, 0x025C, 0, 0, 0, 22, 8, 0x0254, 24, 0, 0, 0, 0x0254, 0, 0), - PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x0260, 0x026C, BIT(0), + PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x0260, 0x026C, 0, 0, 0, 22, 8, 0x0264, 24, 0, 0, 0, 0x0264, 0, 0), - PLL(CLK_APMIXED_TVDPLL, "tvdpll", 0x0270, 0x027C, BIT(0), + PLL(CLK_APMIXED_TVDPLL, "tvdpll", 0x0270, 0x027C, 0, 0, 0, 22, 8, 0x0274, 24, 0, 0, 0, 0x0274, 0, 0), - PLL(CLK_APMIXED_ADSPPLL, "adsppll", 0x02b0, 0x02bC, BIT(0), + PLL(CLK_APMIXED_ADSPPLL, "adsppll", 0x02b0, 0x02bC, 0, (HAVE_RST_BAR), BIT(23), 22, 8, 0x02b4, 24, 0, 0, 0, 0x02b4, 0, 0), - PLL(CLK_APMIXED_MMPLL, "mmpll", 0x0280, 0x028C, BIT(0), + PLL(CLK_APMIXED_MMPLL, "mmpll", 0x0280, 0x028C, 0, (HAVE_RST_BAR), BIT(23), 22, 8, 0x0284, 24, 0, 0, 0, 0x0284, 0, 0), - PLL(CLK_APMIXED_APLL1, "apll1", 0x02C0, 0x02D0, BIT(0), + PLL(CLK_APMIXED_APLL1, "apll1", 0x02C0, 0x02D0, 0, 0, 0, 32, 8, 0x02C0, 1, 0, 0x14, 0, 0x02C4, 0, 0x2C0), - PLL(CLK_APMIXED_APLL2, "apll2", 0x02D4, 0x02E4, BIT(0), + PLL(CLK_APMIXED_APLL2, "apll2", 0x02D4, 0x02E4, 0, 0, 0, 32, 8, 0x02D4, 1, 0, 0x14, 1, 0x02D8, 0, 0x02D4), }; static int clk_mt6779_apmixed_probe(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; struct device_node *node = pdev->dev.of_node; clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK); @@ -1224,13 +1224,13 @@ static int clk_mt6779_apmixed_probe(struct platform_device *pdev) mtk_clk_register_gates(node, apmixed_clks, ARRAY_SIZE(apmixed_clks), clk_data); - return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); } static int clk_mt6779_top_probe(struct platform_device *pdev) { void __iomem *base; - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; struct device_node *node = pdev->dev.of_node; base = devm_platform_ioremap_resource(pdev, 0); @@ -1253,12 +1253,12 @@ static int clk_mt6779_top_probe(struct platform_device *pdev) mtk_clk_register_composites(top_aud_divs, ARRAY_SIZE(top_aud_divs), base, &mt6779_clk_lock, clk_data); - return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); } static int clk_mt6779_infra_probe(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; struct device_node *node = pdev->dev.of_node; clk_data = mtk_alloc_clk_data(CLK_INFRA_NR_CLK); @@ -1266,7 +1266,7 @@ static int clk_mt6779_infra_probe(struct platform_device *pdev) mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks), clk_data); - return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); } static const struct of_device_id of_match_clk_mt6779[] = { diff --git a/drivers/clk/mediatek/clk-mt6797-img.c b/drivers/clk/mediatek/clk-mt6797-img.c index 908bf9784f0335122e1235b806146b43f23761ee..25d17db13bac3ca4674617a4a77aa0ab6e6c2cfe 100644 --- a/drivers/clk/mediatek/clk-mt6797-img.c +++ b/drivers/clk/mediatek/clk-mt6797-img.c @@ -39,7 +39,7 @@ static const struct of_device_id of_match_clk_mt6797_img[] = { static int clk_mt6797_img_probe(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; int r; struct device_node *node = pdev->dev.of_node; @@ -48,7 +48,7 @@ static int clk_mt6797_img_probe(struct platform_device *pdev) mtk_clk_register_gates(node, img_clks, ARRAY_SIZE(img_clks), clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r) dev_err(&pdev->dev, "could not register clock provider: %s: %d\n", diff --git a/drivers/clk/mediatek/clk-mt6797-mm.c b/drivers/clk/mediatek/clk-mt6797-mm.c index 01fdce2872477eb73564dba254b9e0f72b450422..0846011fc8943ec00c27fb334ddf7ce08bd32606 100644 --- a/drivers/clk/mediatek/clk-mt6797-mm.c +++ b/drivers/clk/mediatek/clk-mt6797-mm.c @@ -96,7 +96,7 @@ static int clk_mt6797_mm_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct device_node *node = dev->parent->of_node; - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; int r; clk_data = mtk_alloc_clk_data(CLK_MM_NR); @@ -104,7 +104,7 @@ static int clk_mt6797_mm_probe(struct platform_device *pdev) mtk_clk_register_gates(node, mm_clks, ARRAY_SIZE(mm_clks), clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r) dev_err(&pdev->dev, "could not register clock provider: %s: %d\n", diff --git a/drivers/clk/mediatek/clk-mt6797-vdec.c b/drivers/clk/mediatek/clk-mt6797-vdec.c index bbbc8119c3af920bebf2534bd9203709c1a995ee..de857894e0338fdc434e166cad8ae4c8ed68b9a4 100644 --- a/drivers/clk/mediatek/clk-mt6797-vdec.c +++ b/drivers/clk/mediatek/clk-mt6797-vdec.c @@ -56,7 +56,7 @@ static const struct of_device_id of_match_clk_mt6797_vdec[] = { static int clk_mt6797_vdec_probe(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; int r; struct device_node *node = pdev->dev.of_node; @@ -65,7 +65,7 @@ static int clk_mt6797_vdec_probe(struct platform_device *pdev) mtk_clk_register_gates(node, vdec_clks, ARRAY_SIZE(vdec_clks), clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r) dev_err(&pdev->dev, "could not register clock provider: %s: %d\n", diff --git a/drivers/clk/mediatek/clk-mt6797-venc.c b/drivers/clk/mediatek/clk-mt6797-venc.c index 2c75f0cbfb516e3a115451bf0af98e0afad8abfa..78b7ed55f9799d5bdb7acc35c5b10d862b8f7fd3 100644 --- a/drivers/clk/mediatek/clk-mt6797-venc.c +++ b/drivers/clk/mediatek/clk-mt6797-venc.c @@ -41,7 +41,7 @@ static const struct of_device_id of_match_clk_mt6797_venc[] = { static int clk_mt6797_venc_probe(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; int r; struct device_node *node = pdev->dev.of_node; @@ -50,7 +50,7 @@ static int clk_mt6797_venc_probe(struct platform_device *pdev) mtk_clk_register_gates(node, venc_clks, ARRAY_SIZE(venc_clks), clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r) dev_err(&pdev->dev, "could not register clock provider: %s: %d\n", diff --git a/drivers/clk/mediatek/clk-mt6797.c b/drivers/clk/mediatek/clk-mt6797.c index 02259e81625a0b4144f8f055c88f56a7d7d85655..b89f325a4b9b8476074f4fe96786a4b8aa0567be 100644 --- a/drivers/clk/mediatek/clk-mt6797.c +++ b/drivers/clk/mediatek/clk-mt6797.c @@ -383,7 +383,7 @@ static const struct mtk_composite top_muxes[] = { static int mtk_topckgen_init(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; void __iomem *base; struct device_node *node = pdev->dev.of_node; @@ -399,7 +399,7 @@ static int mtk_topckgen_init(struct platform_device *pdev) mtk_clk_register_composites(top_muxes, ARRAY_SIZE(top_muxes), base, &mt6797_clk_lock, clk_data); - return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); } static const struct mtk_gate_regs infra0_cg_regs = { @@ -556,7 +556,7 @@ static const struct mtk_fixed_factor infra_fixed_divs[] = { FACTOR(CLK_INFRA_13M, "clk13m", "clk26m", 1, 2), }; -static struct clk_onecell_data *infra_clk_data; +static struct clk_hw_onecell_data *infra_clk_data; static void mtk_infrasys_init_early(struct device_node *node) { @@ -566,13 +566,14 @@ static void mtk_infrasys_init_early(struct device_node *node) infra_clk_data = mtk_alloc_clk_data(CLK_INFRA_NR); for (i = 0; i < CLK_INFRA_NR; i++) - infra_clk_data->clks[i] = ERR_PTR(-EPROBE_DEFER); + infra_clk_data->hws[i] = ERR_PTR(-EPROBE_DEFER); } mtk_clk_register_factors(infra_fixed_divs, ARRAY_SIZE(infra_fixed_divs), infra_clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, infra_clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, + infra_clk_data); if (r) pr_err("%s(): could not register clock provider: %d\n", __func__, r); @@ -590,8 +591,8 @@ static int mtk_infrasys_init(struct platform_device *pdev) infra_clk_data = mtk_alloc_clk_data(CLK_INFRA_NR); } else { for (i = 0; i < CLK_INFRA_NR; i++) { - if (infra_clk_data->clks[i] == ERR_PTR(-EPROBE_DEFER)) - infra_clk_data->clks[i] = ERR_PTR(-ENOENT); + if (infra_clk_data->hws[i] == ERR_PTR(-EPROBE_DEFER)) + infra_clk_data->hws[i] = ERR_PTR(-ENOENT); } } @@ -600,7 +601,8 @@ static int mtk_infrasys_init(struct platform_device *pdev) mtk_clk_register_factors(infra_fixed_divs, ARRAY_SIZE(infra_fixed_divs), infra_clk_data); - return of_clk_add_provider(node, of_clk_src_onecell_get, infra_clk_data); + return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, + infra_clk_data); } #define MT6797_PLL_FMAX (3000UL * MHZ) @@ -635,31 +637,31 @@ static int mtk_infrasys_init(struct platform_device *pdev) NULL) static const struct mtk_pll_data plls[] = { - PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x0220, 0x022C, 0xF0000101, PLL_AO, + PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x0220, 0x022C, 0xF0000100, PLL_AO, 21, 0x220, 4, 0x0, 0x224, 0), - PLL(CLK_APMIXED_UNIVPLL, "univpll", 0x0230, 0x023C, 0xFE000011, 0, 7, + PLL(CLK_APMIXED_UNIVPLL, "univpll", 0x0230, 0x023C, 0xFE000010, 0, 7, 0x230, 4, 0x0, 0x234, 14), - PLL(CLK_APMIXED_MFGPLL, "mfgpll", 0x0240, 0x024C, 0x00000101, 0, 21, + PLL(CLK_APMIXED_MFGPLL, "mfgpll", 0x0240, 0x024C, 0x00000100, 0, 21, 0x244, 24, 0x0, 0x244, 0), - PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x0250, 0x025C, 0x00000121, 0, 21, + PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x0250, 0x025C, 0x00000120, 0, 21, 0x250, 4, 0x0, 0x254, 0), - PLL(CLK_APMIXED_IMGPLL, "imgpll", 0x0260, 0x026C, 0x00000121, 0, 21, + PLL(CLK_APMIXED_IMGPLL, "imgpll", 0x0260, 0x026C, 0x00000120, 0, 21, 0x260, 4, 0x0, 0x264, 0), - PLL(CLK_APMIXED_TVDPLL, "tvdpll", 0x0270, 0x027C, 0xC0000121, 0, 21, + PLL(CLK_APMIXED_TVDPLL, "tvdpll", 0x0270, 0x027C, 0xC0000120, 0, 21, 0x270, 4, 0x0, 0x274, 0), - PLL(CLK_APMIXED_CODECPLL, "codecpll", 0x0290, 0x029C, 0x00000121, 0, 21, + PLL(CLK_APMIXED_CODECPLL, "codecpll", 0x0290, 0x029C, 0x00000120, 0, 21, 0x290, 4, 0x0, 0x294, 0), - PLL(CLK_APMIXED_VDECPLL, "vdecpll", 0x02E4, 0x02F0, 0x00000121, 0, 21, + PLL(CLK_APMIXED_VDECPLL, "vdecpll", 0x02E4, 0x02F0, 0x00000120, 0, 21, 0x2E4, 4, 0x0, 0x2E8, 0), - PLL(CLK_APMIXED_APLL1, "apll1", 0x02A0, 0x02B0, 0x00000131, 0, 31, + PLL(CLK_APMIXED_APLL1, "apll1", 0x02A0, 0x02B0, 0x00000130, 0, 31, 0x2A0, 4, 0x2A8, 0x2A4, 0), - PLL(CLK_APMIXED_APLL2, "apll2", 0x02B4, 0x02C4, 0x00000131, 0, 31, + PLL(CLK_APMIXED_APLL2, "apll2", 0x02B4, 0x02C4, 0x00000130, 0, 31, 0x2B4, 4, 0x2BC, 0x2B8, 0), }; static int mtk_apmixedsys_init(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; struct device_node *node = pdev->dev.of_node; clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR); @@ -668,7 +670,7 @@ static int mtk_apmixedsys_init(struct platform_device *pdev) mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data); - return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); } static const struct of_device_id of_match_clk_mt6797[] = { diff --git a/drivers/clk/mediatek/clk-mt7622-aud.c b/drivers/clk/mediatek/clk-mt7622-aud.c index 2bd4295bc36be878e0ae803edf91d0ac24d039e3..9f2e5aa7b5d9baae18f37d4326b862df42285b34 100644 --- a/drivers/clk/mediatek/clk-mt7622-aud.c +++ b/drivers/clk/mediatek/clk-mt7622-aud.c @@ -132,7 +132,7 @@ static const struct mtk_gate audio_clks[] = { static int clk_mt7622_audiosys_init(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; struct device_node *node = pdev->dev.of_node; int r; @@ -141,7 +141,7 @@ static int clk_mt7622_audiosys_init(struct platform_device *pdev) mtk_clk_register_gates(node, audio_clks, ARRAY_SIZE(audio_clks), clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r) { dev_err(&pdev->dev, "could not register clock provider: %s: %d\n", diff --git a/drivers/clk/mediatek/clk-mt7622-eth.c b/drivers/clk/mediatek/clk-mt7622-eth.c index c9947dc7ba5a2b4301c9d23368e5d3025a760d38..b12d48705496ece46153a8d989dc2deb42204c13 100644 --- a/drivers/clk/mediatek/clk-mt7622-eth.c +++ b/drivers/clk/mediatek/clk-mt7622-eth.c @@ -67,7 +67,7 @@ static const struct mtk_gate sgmii_clks[] = { static int clk_mt7622_ethsys_init(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; struct device_node *node = pdev->dev.of_node; int r; @@ -76,7 +76,7 @@ static int clk_mt7622_ethsys_init(struct platform_device *pdev) mtk_clk_register_gates(node, eth_clks, ARRAY_SIZE(eth_clks), clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r) dev_err(&pdev->dev, "could not register clock provider: %s: %d\n", @@ -89,7 +89,7 @@ static int clk_mt7622_ethsys_init(struct platform_device *pdev) static int clk_mt7622_sgmiisys_init(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; struct device_node *node = pdev->dev.of_node; int r; @@ -98,7 +98,7 @@ static int clk_mt7622_sgmiisys_init(struct platform_device *pdev) mtk_clk_register_gates(node, sgmii_clks, ARRAY_SIZE(sgmii_clks), clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r) dev_err(&pdev->dev, "could not register clock provider: %s: %d\n", diff --git a/drivers/clk/mediatek/clk-mt7622-hif.c b/drivers/clk/mediatek/clk-mt7622-hif.c index 628be0c9f8888053d3c0d3d8ea494daf91618304..58728e35e80a9d0d3a72707af9383f9bc821efb0 100644 --- a/drivers/clk/mediatek/clk-mt7622-hif.c +++ b/drivers/clk/mediatek/clk-mt7622-hif.c @@ -78,7 +78,7 @@ static const struct mtk_gate pcie_clks[] = { static int clk_mt7622_ssusbsys_init(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; struct device_node *node = pdev->dev.of_node; int r; @@ -87,7 +87,7 @@ static int clk_mt7622_ssusbsys_init(struct platform_device *pdev) mtk_clk_register_gates(node, ssusb_clks, ARRAY_SIZE(ssusb_clks), clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r) dev_err(&pdev->dev, "could not register clock provider: %s: %d\n", @@ -100,7 +100,7 @@ static int clk_mt7622_ssusbsys_init(struct platform_device *pdev) static int clk_mt7622_pciesys_init(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; struct device_node *node = pdev->dev.of_node; int r; @@ -109,7 +109,7 @@ static int clk_mt7622_pciesys_init(struct platform_device *pdev) mtk_clk_register_gates(node, pcie_clks, ARRAY_SIZE(pcie_clks), clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r) dev_err(&pdev->dev, "could not register clock provider: %s: %d\n", diff --git a/drivers/clk/mediatek/clk-mt7622.c b/drivers/clk/mediatek/clk-mt7622.c index 0e1fb30a1e98b611bd9511e2021ada1818e03eda..e4a5e5230861b2a60cadcb58956bdfcc6bdcc1b7 100644 --- a/drivers/clk/mediatek/clk-mt7622.c +++ b/drivers/clk/mediatek/clk-mt7622.c @@ -329,23 +329,23 @@ static const struct mtk_gate_regs peri1_cg_regs = { }; static const struct mtk_pll_data plls[] = { - PLL(CLK_APMIXED_ARMPLL, "armpll", 0x0200, 0x020C, 0x00000001, + PLL(CLK_APMIXED_ARMPLL, "armpll", 0x0200, 0x020C, 0, PLL_AO, 21, 0x0204, 24, 0, 0x0204, 0), - PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x0210, 0x021C, 0x00000001, + PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x0210, 0x021C, 0, HAVE_RST_BAR, 21, 0x0214, 24, 0, 0x0214, 0), - PLL(CLK_APMIXED_UNIV2PLL, "univ2pll", 0x0220, 0x022C, 0x00000001, + PLL(CLK_APMIXED_UNIV2PLL, "univ2pll", 0x0220, 0x022C, 0, HAVE_RST_BAR, 7, 0x0224, 24, 0, 0x0224, 14), - PLL(CLK_APMIXED_ETH1PLL, "eth1pll", 0x0300, 0x0310, 0x00000001, + PLL(CLK_APMIXED_ETH1PLL, "eth1pll", 0x0300, 0x0310, 0, 0, 21, 0x0300, 1, 0, 0x0304, 0), - PLL(CLK_APMIXED_ETH2PLL, "eth2pll", 0x0314, 0x0320, 0x00000001, + PLL(CLK_APMIXED_ETH2PLL, "eth2pll", 0x0314, 0x0320, 0, 0, 21, 0x0314, 1, 0, 0x0318, 0), - PLL(CLK_APMIXED_AUD1PLL, "aud1pll", 0x0324, 0x0330, 0x00000001, + PLL(CLK_APMIXED_AUD1PLL, "aud1pll", 0x0324, 0x0330, 0, 0, 31, 0x0324, 1, 0, 0x0328, 0), - PLL(CLK_APMIXED_AUD2PLL, "aud2pll", 0x0334, 0x0340, 0x00000001, + PLL(CLK_APMIXED_AUD2PLL, "aud2pll", 0x0334, 0x0340, 0, 0, 31, 0x0334, 1, 0, 0x0338, 0), - PLL(CLK_APMIXED_TRGPLL, "trgpll", 0x0344, 0x0354, 0x00000001, + PLL(CLK_APMIXED_TRGPLL, "trgpll", 0x0344, 0x0354, 0, 0, 21, 0x0344, 1, 0, 0x0348, 0), - PLL(CLK_APMIXED_SGMIPLL, "sgmipll", 0x0358, 0x0368, 0x00000001, + PLL(CLK_APMIXED_SGMIPLL, "sgmipll", 0x0358, 0x0368, 0, 0, 21, 0x0358, 1, 0, 0x035C, 0), }; @@ -612,7 +612,7 @@ static struct mtk_composite peri_muxes[] = { static int mtk_topckgen_init(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; void __iomem *base; struct device_node *node = pdev->dev.of_node; @@ -637,17 +637,17 @@ static int mtk_topckgen_init(struct platform_device *pdev) mtk_clk_register_gates(node, top_clks, ARRAY_SIZE(top_clks), clk_data); - clk_prepare_enable(clk_data->clks[CLK_TOP_AXI_SEL]); - clk_prepare_enable(clk_data->clks[CLK_TOP_MEM_SEL]); - clk_prepare_enable(clk_data->clks[CLK_TOP_DDRPHYCFG_SEL]); + clk_prepare_enable(clk_data->hws[CLK_TOP_AXI_SEL]->clk); + clk_prepare_enable(clk_data->hws[CLK_TOP_MEM_SEL]->clk); + clk_prepare_enable(clk_data->hws[CLK_TOP_DDRPHYCFG_SEL]->clk); - return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); } static int mtk_infrasys_init(struct platform_device *pdev) { struct device_node *node = pdev->dev.of_node; - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; int r; clk_data = mtk_alloc_clk_data(CLK_INFRA_NR_CLK); @@ -658,8 +658,8 @@ static int mtk_infrasys_init(struct platform_device *pdev) mtk_clk_register_cpumuxes(node, infra_muxes, ARRAY_SIZE(infra_muxes), clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, - clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, + clk_data); if (r) return r; @@ -670,7 +670,7 @@ static int mtk_infrasys_init(struct platform_device *pdev) static int mtk_apmixedsys_init(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; struct device_node *node = pdev->dev.of_node; clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK); @@ -683,15 +683,15 @@ static int mtk_apmixedsys_init(struct platform_device *pdev) mtk_clk_register_gates(node, apmixed_clks, ARRAY_SIZE(apmixed_clks), clk_data); - clk_prepare_enable(clk_data->clks[CLK_APMIXED_ARMPLL]); - clk_prepare_enable(clk_data->clks[CLK_APMIXED_MAIN_CORE_EN]); + clk_prepare_enable(clk_data->hws[CLK_APMIXED_ARMPLL]->clk); + clk_prepare_enable(clk_data->hws[CLK_APMIXED_MAIN_CORE_EN]->clk); - return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); } static int mtk_pericfg_init(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; void __iomem *base; int r; struct device_node *node = pdev->dev.of_node; @@ -708,11 +708,11 @@ static int mtk_pericfg_init(struct platform_device *pdev) mtk_clk_register_composites(peri_muxes, ARRAY_SIZE(peri_muxes), base, &mt7622_clk_lock, clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r) return r; - clk_prepare_enable(clk_data->clks[CLK_PERI_UART0_PD]); + clk_prepare_enable(clk_data->hws[CLK_PERI_UART0_PD]->clk); mtk_register_reset_controller(node, 2, 0x0); diff --git a/drivers/clk/mediatek/clk-mt7629-eth.c b/drivers/clk/mediatek/clk-mt7629-eth.c index 88279d0ea1a76a49c0f1cc07242bf1ca0490eecf..c49fd732c9b29b0894686eb9beb8a261e837f23a 100644 --- a/drivers/clk/mediatek/clk-mt7629-eth.c +++ b/drivers/clk/mediatek/clk-mt7629-eth.c @@ -78,7 +78,7 @@ static const struct mtk_gate sgmii_clks[2][4] = { static int clk_mt7629_ethsys_init(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; struct device_node *node = pdev->dev.of_node; int r; @@ -86,7 +86,7 @@ static int clk_mt7629_ethsys_init(struct platform_device *pdev) mtk_clk_register_gates(node, eth_clks, CLK_ETH_NR_CLK, clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r) dev_err(&pdev->dev, "could not register clock provider: %s: %d\n", @@ -99,7 +99,7 @@ static int clk_mt7629_ethsys_init(struct platform_device *pdev) static int clk_mt7629_sgmiisys_init(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; struct device_node *node = pdev->dev.of_node; static int id; int r; @@ -109,7 +109,7 @@ static int clk_mt7629_sgmiisys_init(struct platform_device *pdev) mtk_clk_register_gates(node, sgmii_clks[id++], CLK_SGMII_NR_CLK, clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r) dev_err(&pdev->dev, "could not register clock provider: %s: %d\n", diff --git a/drivers/clk/mediatek/clk-mt7629-hif.c b/drivers/clk/mediatek/clk-mt7629-hif.c index 5c5b37207afbd2f01c0dcabadf75035882aec003..acaa97fda331e1a7f8a21572e1f33a3afc5ec4a9 100644 --- a/drivers/clk/mediatek/clk-mt7629-hif.c +++ b/drivers/clk/mediatek/clk-mt7629-hif.c @@ -73,7 +73,7 @@ static const struct mtk_gate pcie_clks[] = { static int clk_mt7629_ssusbsys_init(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; struct device_node *node = pdev->dev.of_node; int r; @@ -82,7 +82,7 @@ static int clk_mt7629_ssusbsys_init(struct platform_device *pdev) mtk_clk_register_gates(node, ssusb_clks, ARRAY_SIZE(ssusb_clks), clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r) dev_err(&pdev->dev, "could not register clock provider: %s: %d\n", @@ -95,7 +95,7 @@ static int clk_mt7629_ssusbsys_init(struct platform_device *pdev) static int clk_mt7629_pciesys_init(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; struct device_node *node = pdev->dev.of_node; int r; @@ -104,7 +104,7 @@ static int clk_mt7629_pciesys_init(struct platform_device *pdev) mtk_clk_register_gates(node, pcie_clks, ARRAY_SIZE(pcie_clks), clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r) dev_err(&pdev->dev, "could not register clock provider: %s: %d\n", diff --git a/drivers/clk/mediatek/clk-mt7629.c b/drivers/clk/mediatek/clk-mt7629.c index c0e023bf31eb5e85eec9502068cf49f5fe6a5ea8..e4a08c811adc279b8b3972e04e162990eec3de67 100644 --- a/drivers/clk/mediatek/clk-mt7629.c +++ b/drivers/clk/mediatek/clk-mt7629.c @@ -336,17 +336,17 @@ static const struct mtk_gate_regs peri1_cg_regs = { }; static const struct mtk_pll_data plls[] = { - PLL(CLK_APMIXED_ARMPLL, "armpll", 0x0200, 0x020C, 0x00000001, + PLL(CLK_APMIXED_ARMPLL, "armpll", 0x0200, 0x020C, 0, 0, 21, 0x0204, 24, 0, 0x0204, 0), - PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x0210, 0x021C, 0x00000001, + PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x0210, 0x021C, 0, HAVE_RST_BAR, 21, 0x0214, 24, 0, 0x0214, 0), - PLL(CLK_APMIXED_UNIV2PLL, "univ2pll", 0x0220, 0x022C, 0x00000001, + PLL(CLK_APMIXED_UNIV2PLL, "univ2pll", 0x0220, 0x022C, 0, HAVE_RST_BAR, 7, 0x0224, 24, 0, 0x0224, 14), - PLL(CLK_APMIXED_ETH1PLL, "eth1pll", 0x0300, 0x0310, 0x00000001, + PLL(CLK_APMIXED_ETH1PLL, "eth1pll", 0x0300, 0x0310, 0, 0, 21, 0x0300, 1, 0, 0x0304, 0), - PLL(CLK_APMIXED_ETH2PLL, "eth2pll", 0x0314, 0x0320, 0x00000001, + PLL(CLK_APMIXED_ETH2PLL, "eth2pll", 0x0314, 0x0320, 0, 0, 21, 0x0314, 1, 0, 0x0318, 0), - PLL(CLK_APMIXED_SGMIPLL, "sgmipll", 0x0358, 0x0368, 0x00000001, + PLL(CLK_APMIXED_SGMIPLL, "sgmipll", 0x0358, 0x0368, 0, 0, 21, 0x0358, 1, 0, 0x035C, 0), }; @@ -572,7 +572,7 @@ static struct mtk_composite peri_muxes[] = { static int mtk_topckgen_init(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; void __iomem *base; struct device_node *node = pdev->dev.of_node; @@ -591,17 +591,17 @@ static int mtk_topckgen_init(struct platform_device *pdev) mtk_clk_register_composites(top_muxes, ARRAY_SIZE(top_muxes), base, &mt7629_clk_lock, clk_data); - clk_prepare_enable(clk_data->clks[CLK_TOP_AXI_SEL]); - clk_prepare_enable(clk_data->clks[CLK_TOP_MEM_SEL]); - clk_prepare_enable(clk_data->clks[CLK_TOP_DDRPHYCFG_SEL]); + clk_prepare_enable(clk_data->hws[CLK_TOP_AXI_SEL]->clk); + clk_prepare_enable(clk_data->hws[CLK_TOP_MEM_SEL]->clk); + clk_prepare_enable(clk_data->hws[CLK_TOP_DDRPHYCFG_SEL]->clk); - return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); } static int mtk_infrasys_init(struct platform_device *pdev) { struct device_node *node = pdev->dev.of_node; - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; clk_data = mtk_alloc_clk_data(CLK_INFRA_NR_CLK); @@ -611,13 +611,13 @@ static int mtk_infrasys_init(struct platform_device *pdev) mtk_clk_register_cpumuxes(node, infra_muxes, ARRAY_SIZE(infra_muxes), clk_data); - return of_clk_add_provider(node, of_clk_src_onecell_get, - clk_data); + return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, + clk_data); } static int mtk_pericfg_init(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; void __iomem *base; int r; struct device_node *node = pdev->dev.of_node; @@ -634,18 +634,18 @@ static int mtk_pericfg_init(struct platform_device *pdev) mtk_clk_register_composites(peri_muxes, ARRAY_SIZE(peri_muxes), base, &mt7629_clk_lock, clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r) return r; - clk_prepare_enable(clk_data->clks[CLK_PERI_UART0_PD]); + clk_prepare_enable(clk_data->hws[CLK_PERI_UART0_PD]->clk); return 0; } static int mtk_apmixedsys_init(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; struct device_node *node = pdev->dev.of_node; clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK); @@ -658,10 +658,10 @@ static int mtk_apmixedsys_init(struct platform_device *pdev) mtk_clk_register_gates(node, apmixed_clks, ARRAY_SIZE(apmixed_clks), clk_data); - clk_prepare_enable(clk_data->clks[CLK_APMIXED_ARMPLL]); - clk_prepare_enable(clk_data->clks[CLK_APMIXED_MAIN_CORE_EN]); + clk_prepare_enable(clk_data->hws[CLK_APMIXED_ARMPLL]->clk); + clk_prepare_enable(clk_data->hws[CLK_APMIXED_MAIN_CORE_EN]->clk); - return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); } diff --git a/drivers/clk/mediatek/clk-mt7986-apmixed.c b/drivers/clk/mediatek/clk-mt7986-apmixed.c index 21d4c82e782ab73067d38d740cd123151f3fdd38..62080ee4dbe35dfd3acb352a8170cbb7eb0fc68c 100644 --- a/drivers/clk/mediatek/clk-mt7986-apmixed.c +++ b/drivers/clk/mediatek/clk-mt7986-apmixed.c @@ -42,21 +42,21 @@ "clkxtal") static const struct mtk_pll_data plls[] = { - PLL(CLK_APMIXED_ARMPLL, "armpll", 0x0200, 0x020C, 0x00000001, 0, 32, + PLL(CLK_APMIXED_ARMPLL, "armpll", 0x0200, 0x020C, 0x0, 0, 32, 0x0200, 4, 0, 0x0204, 0), - PLL(CLK_APMIXED_NET2PLL, "net2pll", 0x0210, 0x021C, 0x00000001, 0, 32, + PLL(CLK_APMIXED_NET2PLL, "net2pll", 0x0210, 0x021C, 0x0, 0, 32, 0x0210, 4, 0, 0x0214, 0), - PLL(CLK_APMIXED_MMPLL, "mmpll", 0x0220, 0x022C, 0x00000001, 0, 32, + PLL(CLK_APMIXED_MMPLL, "mmpll", 0x0220, 0x022C, 0x0, 0, 32, 0x0220, 4, 0, 0x0224, 0), - PLL(CLK_APMIXED_SGMPLL, "sgmpll", 0x0230, 0x023c, 0x00000001, 0, 32, + PLL(CLK_APMIXED_SGMPLL, "sgmpll", 0x0230, 0x023c, 0x0, 0, 32, 0x0230, 4, 0, 0x0234, 0), - PLL(CLK_APMIXED_WEDMCUPLL, "wedmcupll", 0x0240, 0x024c, 0x00000001, 0, + PLL(CLK_APMIXED_WEDMCUPLL, "wedmcupll", 0x0240, 0x024c, 0x0, 0, 32, 0x0240, 4, 0, 0x0244, 0), - PLL(CLK_APMIXED_NET1PLL, "net1pll", 0x0250, 0x025c, 0x00000001, 0, 32, + PLL(CLK_APMIXED_NET1PLL, "net1pll", 0x0250, 0x025c, 0x0, 0, 32, 0x0250, 4, 0, 0x0254, 0), - PLL(CLK_APMIXED_MPLL, "mpll", 0x0260, 0x0270, 0x00000001, 0, 32, 0x0260, + PLL(CLK_APMIXED_MPLL, "mpll", 0x0260, 0x0270, 0x0, 0, 32, 0x0260, 4, 0, 0x0264, 0), - PLL(CLK_APMIXED_APLL2, "apll2", 0x0278, 0x0288, 0x00000001, 0, 32, + PLL(CLK_APMIXED_APLL2, "apll2", 0x0278, 0x0288, 0x0, 0, 32, 0x0278, 4, 0, 0x027c, 0), }; @@ -67,7 +67,7 @@ static const struct of_device_id of_match_clk_mt7986_apmixed[] = { static int clk_mt7986_apmixed_probe(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; struct device_node *node = pdev->dev.of_node; int r; @@ -77,9 +77,9 @@ static int clk_mt7986_apmixed_probe(struct platform_device *pdev) mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data); - clk_prepare_enable(clk_data->clks[CLK_APMIXED_ARMPLL]); + clk_prepare_enable(clk_data->hws[CLK_APMIXED_ARMPLL]->clk); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r) { pr_err("%s(): could not register clock provider: %d\n", __func__, r); diff --git a/drivers/clk/mediatek/clk-mt7986-eth.c b/drivers/clk/mediatek/clk-mt7986-eth.c index 495d023ccad7c64229c1b87573db764146ed7b08..7868c0728e9620c02ef8b8307e54079e7f82b6e6 100644 --- a/drivers/clk/mediatek/clk-mt7986-eth.c +++ b/drivers/clk/mediatek/clk-mt7986-eth.c @@ -79,7 +79,7 @@ static const struct mtk_gate eth_clks[] __initconst = { static void __init mtk_sgmiisys_0_init(struct device_node *node) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; int r; clk_data = mtk_alloc_clk_data(ARRAY_SIZE(sgmii0_clks)); @@ -87,7 +87,7 @@ static void __init mtk_sgmiisys_0_init(struct device_node *node) mtk_clk_register_gates(node, sgmii0_clks, ARRAY_SIZE(sgmii0_clks), clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r) pr_err("%s(): could not register clock provider: %d\n", __func__, r); @@ -97,7 +97,7 @@ CLK_OF_DECLARE(mtk_sgmiisys_0, "mediatek,mt7986-sgmiisys_0", static void __init mtk_sgmiisys_1_init(struct device_node *node) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; int r; clk_data = mtk_alloc_clk_data(ARRAY_SIZE(sgmii1_clks)); @@ -105,7 +105,7 @@ static void __init mtk_sgmiisys_1_init(struct device_node *node) mtk_clk_register_gates(node, sgmii1_clks, ARRAY_SIZE(sgmii1_clks), clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r) pr_err("%s(): could not register clock provider: %d\n", @@ -116,17 +116,17 @@ CLK_OF_DECLARE(mtk_sgmiisys_1, "mediatek,mt7986-sgmiisys_1", static void __init mtk_ethsys_init(struct device_node *node) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; int r; clk_data = mtk_alloc_clk_data(ARRAY_SIZE(eth_clks)); mtk_clk_register_gates(node, eth_clks, ARRAY_SIZE(eth_clks), clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r) pr_err("%s(): could not register clock provider: %d\n", __func__, r); } -CLK_OF_DECLARE(mtk_ethsys, "mediatek,mt7986-ethsys_ck", mtk_ethsys_init); +CLK_OF_DECLARE(mtk_ethsys, "mediatek,mt7986-ethsys", mtk_ethsys_init); diff --git a/drivers/clk/mediatek/clk-mt7986-infracfg.c b/drivers/clk/mediatek/clk-mt7986-infracfg.c index f209c559fbc3ac3f3f8aa104c1fcf93e070caf38..d90727a53283c70e7ac1a627c1387b96c36688e0 100644 --- a/drivers/clk/mediatek/clk-mt7986-infracfg.c +++ b/drivers/clk/mediatek/clk-mt7986-infracfg.c @@ -171,7 +171,7 @@ static const struct mtk_gate infra_clks[] = { static int clk_mt7986_infracfg_probe(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; struct device_node *node = pdev->dev.of_node; int r; void __iomem *base; @@ -195,7 +195,7 @@ static int clk_mt7986_infracfg_probe(struct platform_device *pdev) mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks), clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r) { pr_err("%s(): could not register clock provider: %d\n", __func__, r); diff --git a/drivers/clk/mediatek/clk-mt7986-topckgen.c b/drivers/clk/mediatek/clk-mt7986-topckgen.c index 8f6f79b6e31efb1338661eea5fa529989c925a5c..de5121cf28774f718116015bbbb361071332e1a3 100644 --- a/drivers/clk/mediatek/clk-mt7986-topckgen.c +++ b/drivers/clk/mediatek/clk-mt7986-topckgen.c @@ -283,7 +283,7 @@ static const struct mtk_mux top_muxes[] = { static int clk_mt7986_topckgen_probe(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; struct device_node *node = pdev->dev.of_node; int r; void __iomem *base; @@ -306,14 +306,14 @@ static int clk_mt7986_topckgen_probe(struct platform_device *pdev) mtk_clk_register_muxes(top_muxes, ARRAY_SIZE(top_muxes), node, &mt7986_clk_lock, clk_data); - clk_prepare_enable(clk_data->clks[CLK_TOP_SYSAXI_SEL]); - clk_prepare_enable(clk_data->clks[CLK_TOP_SYSAPB_SEL]); - clk_prepare_enable(clk_data->clks[CLK_TOP_DRAMC_SEL]); - clk_prepare_enable(clk_data->clks[CLK_TOP_DRAMC_MD32_SEL]); - clk_prepare_enable(clk_data->clks[CLK_TOP_F26M_SEL]); - clk_prepare_enable(clk_data->clks[CLK_TOP_SGM_REG_SEL]); + clk_prepare_enable(clk_data->hws[CLK_TOP_SYSAXI_SEL]->clk); + clk_prepare_enable(clk_data->hws[CLK_TOP_SYSAPB_SEL]->clk); + clk_prepare_enable(clk_data->hws[CLK_TOP_DRAMC_SEL]->clk); + clk_prepare_enable(clk_data->hws[CLK_TOP_DRAMC_MD32_SEL]->clk); + clk_prepare_enable(clk_data->hws[CLK_TOP_F26M_SEL]->clk); + clk_prepare_enable(clk_data->hws[CLK_TOP_SGM_REG_SEL]->clk); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r) { pr_err("%s(): could not register clock provider: %d\n", diff --git a/drivers/clk/mediatek/clk-mt8135.c b/drivers/clk/mediatek/clk-mt8135.c index 09ad272d51f113a0cd768d561a90cbd6bed6af88..9ef524b448620d42231d859ed30f9d92ac639a8b 100644 --- a/drivers/clk/mediatek/clk-mt8135.c +++ b/drivers/clk/mediatek/clk-mt8135.c @@ -516,7 +516,7 @@ static const struct mtk_composite peri_clks[] __initconst = { static void __init mtk_topckgen_init(struct device_node *node) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; void __iomem *base; int r; @@ -533,9 +533,9 @@ static void __init mtk_topckgen_init(struct device_node *node) mtk_clk_register_composites(top_muxes, ARRAY_SIZE(top_muxes), base, &mt8135_clk_lock, clk_data); - clk_prepare_enable(clk_data->clks[CLK_TOP_CCI_SEL]); + clk_prepare_enable(clk_data->hws[CLK_TOP_CCI_SEL]->clk); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r) pr_err("%s(): could not register clock provider: %d\n", __func__, r); @@ -544,7 +544,7 @@ CLK_OF_DECLARE(mtk_topckgen, "mediatek,mt8135-topckgen", mtk_topckgen_init); static void __init mtk_infrasys_init(struct device_node *node) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; int r; clk_data = mtk_alloc_clk_data(CLK_INFRA_NR_CLK); @@ -552,9 +552,9 @@ static void __init mtk_infrasys_init(struct device_node *node) mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks), clk_data); - clk_prepare_enable(clk_data->clks[CLK_INFRA_M4U]); + clk_prepare_enable(clk_data->hws[CLK_INFRA_M4U]->clk); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r) pr_err("%s(): could not register clock provider: %d\n", __func__, r); @@ -565,7 +565,7 @@ CLK_OF_DECLARE(mtk_infrasys, "mediatek,mt8135-infracfg", mtk_infrasys_init); static void __init mtk_pericfg_init(struct device_node *node) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; int r; void __iomem *base; @@ -582,7 +582,7 @@ static void __init mtk_pericfg_init(struct device_node *node) mtk_clk_register_composites(peri_clks, ARRAY_SIZE(peri_clks), base, &mt8135_clk_lock, clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r) pr_err("%s(): could not register clock provider: %d\n", __func__, r); @@ -612,21 +612,21 @@ CLK_OF_DECLARE(mtk_pericfg, "mediatek,mt8135-pericfg", mtk_pericfg_init); } static const struct mtk_pll_data plls[] = { - PLL(CLK_APMIXED_ARMPLL1, "armpll1", 0x200, 0x218, 0x80000001, 0, 21, 0x204, 24, 0x0, 0x204, 0), - PLL(CLK_APMIXED_ARMPLL2, "armpll2", 0x2cc, 0x2e4, 0x80000001, 0, 21, 0x2d0, 24, 0x0, 0x2d0, 0), - PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x21c, 0x234, 0xf0000001, HAVE_RST_BAR, 21, 0x21c, 6, 0x0, 0x220, 0), - PLL(CLK_APMIXED_UNIVPLL, "univpll", 0x238, 0x250, 0xf3000001, HAVE_RST_BAR, 7, 0x238, 6, 0x0, 0x238, 9), - PLL(CLK_APMIXED_MMPLL, "mmpll", 0x254, 0x26c, 0xf0000001, HAVE_RST_BAR, 21, 0x254, 6, 0x0, 0x258, 0), - PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x278, 0x290, 0x80000001, 0, 21, 0x278, 6, 0x0, 0x27c, 0), - PLL(CLK_APMIXED_TVDPLL, "tvdpll", 0x294, 0x2ac, 0x80000001, 0, 31, 0x294, 6, 0x0, 0x298, 0), - PLL(CLK_APMIXED_LVDSPLL, "lvdspll", 0x2b0, 0x2c8, 0x80000001, 0, 21, 0x2b0, 6, 0x0, 0x2b4, 0), - PLL(CLK_APMIXED_AUDPLL, "audpll", 0x2e8, 0x300, 0x80000001, 0, 31, 0x2e8, 6, 0x2f8, 0x2ec, 0), - PLL(CLK_APMIXED_VDECPLL, "vdecpll", 0x304, 0x31c, 0x80000001, 0, 21, 0x2b0, 6, 0x0, 0x308, 0), + PLL(CLK_APMIXED_ARMPLL1, "armpll1", 0x200, 0x218, 0x80000000, 0, 21, 0x204, 24, 0x0, 0x204, 0), + PLL(CLK_APMIXED_ARMPLL2, "armpll2", 0x2cc, 0x2e4, 0x80000000, 0, 21, 0x2d0, 24, 0x0, 0x2d0, 0), + PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x21c, 0x234, 0xf0000000, HAVE_RST_BAR, 21, 0x21c, 6, 0x0, 0x220, 0), + PLL(CLK_APMIXED_UNIVPLL, "univpll", 0x238, 0x250, 0xf3000000, HAVE_RST_BAR, 7, 0x238, 6, 0x0, 0x238, 9), + PLL(CLK_APMIXED_MMPLL, "mmpll", 0x254, 0x26c, 0xf0000000, HAVE_RST_BAR, 21, 0x254, 6, 0x0, 0x258, 0), + PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x278, 0x290, 0x80000000, 0, 21, 0x278, 6, 0x0, 0x27c, 0), + PLL(CLK_APMIXED_TVDPLL, "tvdpll", 0x294, 0x2ac, 0x80000000, 0, 31, 0x294, 6, 0x0, 0x298, 0), + PLL(CLK_APMIXED_LVDSPLL, "lvdspll", 0x2b0, 0x2c8, 0x80000000, 0, 21, 0x2b0, 6, 0x0, 0x2b4, 0), + PLL(CLK_APMIXED_AUDPLL, "audpll", 0x2e8, 0x300, 0x80000000, 0, 31, 0x2e8, 6, 0x2f8, 0x2ec, 0), + PLL(CLK_APMIXED_VDECPLL, "vdecpll", 0x304, 0x31c, 0x80000000, 0, 21, 0x2b0, 6, 0x0, 0x308, 0), }; static void __init mtk_apmixedsys_init(struct device_node *node) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK); if (!clk_data) diff --git a/drivers/clk/mediatek/clk-mt8167-aud.c b/drivers/clk/mediatek/clk-mt8167-aud.c index 3f7bf6485792aabcaac214ed90074d126542304a..ce1ae8d243c33dd3c54364ac90f5555e301a507c 100644 --- a/drivers/clk/mediatek/clk-mt8167-aud.c +++ b/drivers/clk/mediatek/clk-mt8167-aud.c @@ -50,14 +50,14 @@ static const struct mtk_gate aud_clks[] __initconst = { static void __init mtk_audsys_init(struct device_node *node) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; int r; clk_data = mtk_alloc_clk_data(CLK_AUD_NR_CLK); mtk_clk_register_gates(node, aud_clks, ARRAY_SIZE(aud_clks), clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r) pr_err("%s(): could not register clock provider: %d\n", __func__, r); diff --git a/drivers/clk/mediatek/clk-mt8167-img.c b/drivers/clk/mediatek/clk-mt8167-img.c index 3b4ec9eae4321ef9f88f28865d4f9eae080a8d89..e359e563d2b79d80cb37b7ec4612b09b20aa51f6 100644 --- a/drivers/clk/mediatek/clk-mt8167-img.c +++ b/drivers/clk/mediatek/clk-mt8167-img.c @@ -43,14 +43,14 @@ static const struct mtk_gate img_clks[] __initconst = { static void __init mtk_imgsys_init(struct device_node *node) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; int r; clk_data = mtk_alloc_clk_data(CLK_IMG_NR_CLK); mtk_clk_register_gates(node, img_clks, ARRAY_SIZE(img_clks), clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r) pr_err("%s(): could not register clock provider: %d\n", diff --git a/drivers/clk/mediatek/clk-mt8167-mfgcfg.c b/drivers/clk/mediatek/clk-mt8167-mfgcfg.c index 90b871730f2df62c7be597c4426ef18bb6758ae7..4fd82fe87d6e51ed5bad6418247a0ecc60d85342 100644 --- a/drivers/clk/mediatek/clk-mt8167-mfgcfg.c +++ b/drivers/clk/mediatek/clk-mt8167-mfgcfg.c @@ -41,14 +41,14 @@ static const struct mtk_gate mfg_clks[] __initconst = { static void __init mtk_mfgcfg_init(struct device_node *node) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; int r; clk_data = mtk_alloc_clk_data(CLK_MFG_NR_CLK); mtk_clk_register_gates(node, mfg_clks, ARRAY_SIZE(mfg_clks), clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r) pr_err("%s(): could not register clock provider: %d\n", diff --git a/drivers/clk/mediatek/clk-mt8167-mm.c b/drivers/clk/mediatek/clk-mt8167-mm.c index 963b129aade1c0dacf0094e3b1881cc92f0dc86d..73910060577f6c55f9f803c950d970117ec9f2af 100644 --- a/drivers/clk/mediatek/clk-mt8167-mm.c +++ b/drivers/clk/mediatek/clk-mt8167-mm.c @@ -101,7 +101,7 @@ static int clk_mt8167_mm_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct device_node *node = dev->parent->of_node; const struct clk_mt8167_mm_driver_data *data; - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; int ret; clk_data = mtk_alloc_clk_data(CLK_MM_NR_CLK); @@ -115,7 +115,7 @@ static int clk_mt8167_mm_probe(struct platform_device *pdev) if (ret) return ret; - ret = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + ret = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (ret) return ret; diff --git a/drivers/clk/mediatek/clk-mt8167-vdec.c b/drivers/clk/mediatek/clk-mt8167-vdec.c index 910b28355ec0eb8e96af829ab02f684e2c48f6b1..ee4fffb6859dabd3d4146943e5d4f45d1fbefc43 100644 --- a/drivers/clk/mediatek/clk-mt8167-vdec.c +++ b/drivers/clk/mediatek/clk-mt8167-vdec.c @@ -56,14 +56,14 @@ static const struct mtk_gate vdec_clks[] __initconst = { static void __init mtk_vdecsys_init(struct device_node *node) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; int r; clk_data = mtk_alloc_clk_data(CLK_VDEC_NR_CLK); mtk_clk_register_gates(node, vdec_clks, ARRAY_SIZE(vdec_clks), clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r) pr_err("%s(): could not register clock provider: %d\n", diff --git a/drivers/clk/mediatek/clk-mt8167.c b/drivers/clk/mediatek/clk-mt8167.c index 812b33a57530c84e6dbc03eaeca726b20125df3e..f900ac4bf7b8d9f86eac5ddf7c397c4e20cade85 100644 --- a/drivers/clk/mediatek/clk-mt8167.c +++ b/drivers/clk/mediatek/clk-mt8167.c @@ -923,7 +923,7 @@ static const struct mtk_gate top_clks[] __initconst = { static void __init mtk_topckgen_init(struct device_node *node) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; int r; void __iomem *base; @@ -945,7 +945,7 @@ static void __init mtk_topckgen_init(struct device_node *node) mtk_clk_register_dividers(top_adj_divs, ARRAY_SIZE(top_adj_divs), base, &mt8167_clk_lock, clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r) pr_err("%s(): could not register clock provider: %d\n", __func__, r); @@ -954,7 +954,7 @@ CLK_OF_DECLARE(mtk_topckgen, "mediatek,mt8167-topckgen", mtk_topckgen_init); static void __init mtk_infracfg_init(struct device_node *node) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; int r; void __iomem *base; @@ -969,7 +969,7 @@ static void __init mtk_infracfg_init(struct device_node *node) mtk_clk_register_composites(ifr_muxes, ARRAY_SIZE(ifr_muxes), base, &mt8167_clk_lock, clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r) pr_err("%s(): could not register clock provider: %d\n", __func__, r); @@ -1017,27 +1017,27 @@ static const struct mtk_pll_div_table mmpll_div_table[] = { }; static const struct mtk_pll_data plls[] = { - PLL(CLK_APMIXED_ARMPLL, "armpll", 0x0100, 0x0110, 0x00000001, 0, + PLL(CLK_APMIXED_ARMPLL, "armpll", 0x0100, 0x0110, 0, 0, 21, 0x0104, 24, 0, 0x0104, 0), - PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x0120, 0x0130, 0x00000001, + PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x0120, 0x0130, 0, HAVE_RST_BAR, 21, 0x0124, 24, 0, 0x0124, 0), - PLL(CLK_APMIXED_UNIVPLL, "univpll", 0x0140, 0x0150, 0x30000001, + PLL(CLK_APMIXED_UNIVPLL, "univpll", 0x0140, 0x0150, 0x30000000, HAVE_RST_BAR, 7, 0x0144, 24, 0, 0x0144, 0), - PLL_B(CLK_APMIXED_MMPLL, "mmpll", 0x0160, 0x0170, 0x00000001, 0, + PLL_B(CLK_APMIXED_MMPLL, "mmpll", 0x0160, 0x0170, 0, 0, 21, 0x0164, 24, 0, 0x0164, 0, mmpll_div_table), - PLL(CLK_APMIXED_APLL1, "apll1", 0x0180, 0x0190, 0x00000001, 0, + PLL(CLK_APMIXED_APLL1, "apll1", 0x0180, 0x0190, 0, 0, 31, 0x0180, 1, 0x0194, 0x0184, 0), - PLL(CLK_APMIXED_APLL2, "apll2", 0x01A0, 0x01B0, 0x00000001, 0, + PLL(CLK_APMIXED_APLL2, "apll2", 0x01A0, 0x01B0, 0, 0, 31, 0x01A0, 1, 0x01B4, 0x01A4, 0), - PLL(CLK_APMIXED_TVDPLL, "tvdpll", 0x01C0, 0x01D0, 0x00000001, 0, + PLL(CLK_APMIXED_TVDPLL, "tvdpll", 0x01C0, 0x01D0, 0, 0, 21, 0x01C4, 24, 0, 0x01C4, 0), - PLL(CLK_APMIXED_LVDSPLL, "lvdspll", 0x01E0, 0x01F0, 0x00000001, 0, + PLL(CLK_APMIXED_LVDSPLL, "lvdspll", 0x01E0, 0x01F0, 0, 0, 21, 0x01E4, 24, 0, 0x01E4, 0), }; static void __init mtk_apmixedsys_init(struct device_node *node) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; void __iomem *base; int r; @@ -1053,7 +1053,7 @@ static void __init mtk_apmixedsys_init(struct device_node *node) mtk_clk_register_dividers(apmixed_adj_divs, ARRAY_SIZE(apmixed_adj_divs), base, &mt8167_clk_lock, clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r) pr_err("%s(): could not register clock provider: %d\n", __func__, r); diff --git a/drivers/clk/mediatek/clk-mt8173-mm.c b/drivers/clk/mediatek/clk-mt8173-mm.c index 36fa20be77b615bd46781691627581b55360a487..8abf42c2030c67b62b449cb5cb6ebd5dc40379f9 100644 --- a/drivers/clk/mediatek/clk-mt8173-mm.c +++ b/drivers/clk/mediatek/clk-mt8173-mm.c @@ -115,7 +115,7 @@ static int clk_mt8173_mm_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct device_node *node = dev->parent->of_node; const struct clk_mt8173_mm_driver_data *data; - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; int ret; clk_data = mtk_alloc_clk_data(CLK_MM_NR_CLK); @@ -129,7 +129,7 @@ static int clk_mt8173_mm_probe(struct platform_device *pdev) if (ret) return ret; - ret = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + ret = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (ret) return ret; diff --git a/drivers/clk/mediatek/clk-mt8173.c b/drivers/clk/mediatek/clk-mt8173.c index 46b7655feeaa169e4bdb43ff98ac6b801dbea07c..0929db330852e124de8550232ffd65e0064d0684 100644 --- a/drivers/clk/mediatek/clk-mt8173.c +++ b/drivers/clk/mediatek/clk-mt8173.c @@ -819,25 +819,25 @@ static const struct mtk_gate venclt_clks[] __initconst = { GATE_VENCLT(CLK_VENCLT_CKE1, "venclt_cke1", "venclt_sel", 4), }; -static struct clk_onecell_data *mt8173_top_clk_data __initdata; -static struct clk_onecell_data *mt8173_pll_clk_data __initdata; +static struct clk_hw_onecell_data *mt8173_top_clk_data __initdata; +static struct clk_hw_onecell_data *mt8173_pll_clk_data __initdata; static void __init mtk_clk_enable_critical(void) { if (!mt8173_top_clk_data || !mt8173_pll_clk_data) return; - clk_prepare_enable(mt8173_pll_clk_data->clks[CLK_APMIXED_ARMCA15PLL]); - clk_prepare_enable(mt8173_pll_clk_data->clks[CLK_APMIXED_ARMCA7PLL]); - clk_prepare_enable(mt8173_top_clk_data->clks[CLK_TOP_MEM_SEL]); - clk_prepare_enable(mt8173_top_clk_data->clks[CLK_TOP_DDRPHYCFG_SEL]); - clk_prepare_enable(mt8173_top_clk_data->clks[CLK_TOP_CCI400_SEL]); - clk_prepare_enable(mt8173_top_clk_data->clks[CLK_TOP_RTC_SEL]); + clk_prepare_enable(mt8173_pll_clk_data->hws[CLK_APMIXED_ARMCA15PLL]->clk); + clk_prepare_enable(mt8173_pll_clk_data->hws[CLK_APMIXED_ARMCA7PLL]->clk); + clk_prepare_enable(mt8173_top_clk_data->hws[CLK_TOP_MEM_SEL]->clk); + clk_prepare_enable(mt8173_top_clk_data->hws[CLK_TOP_DDRPHYCFG_SEL]->clk); + clk_prepare_enable(mt8173_top_clk_data->hws[CLK_TOP_CCI400_SEL]->clk); + clk_prepare_enable(mt8173_top_clk_data->hws[CLK_TOP_RTC_SEL]->clk); } static void __init mtk_topckgen_init(struct device_node *node) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; void __iomem *base; int r; @@ -854,7 +854,7 @@ static void __init mtk_topckgen_init(struct device_node *node) mtk_clk_register_composites(top_muxes, ARRAY_SIZE(top_muxes), base, &mt8173_clk_lock, clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r) pr_err("%s(): could not register clock provider: %d\n", __func__, r); @@ -865,7 +865,7 @@ CLK_OF_DECLARE(mtk_topckgen, "mediatek,mt8173-topckgen", mtk_topckgen_init); static void __init mtk_infrasys_init(struct device_node *node) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; int r; clk_data = mtk_alloc_clk_data(CLK_INFRA_NR_CLK); @@ -877,7 +877,7 @@ static void __init mtk_infrasys_init(struct device_node *node) mtk_clk_register_cpumuxes(node, cpu_muxes, ARRAY_SIZE(cpu_muxes), clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r) pr_err("%s(): could not register clock provider: %d\n", __func__, r); @@ -888,7 +888,7 @@ CLK_OF_DECLARE(mtk_infrasys, "mediatek,mt8173-infracfg", mtk_infrasys_init); static void __init mtk_pericfg_init(struct device_node *node) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; int r; void __iomem *base; @@ -905,7 +905,7 @@ static void __init mtk_pericfg_init(struct device_node *node) mtk_clk_register_composites(peri_clks, ARRAY_SIZE(peri_clks), base, &mt8173_clk_lock, clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r) pr_err("%s(): could not register clock provider: %d\n", __func__, r); @@ -973,27 +973,27 @@ static const struct mtk_pll_div_table mmpll_div_table[] = { }; static const struct mtk_pll_data plls[] = { - PLL(CLK_APMIXED_ARMCA15PLL, "armca15pll", 0x200, 0x20c, 0x00000001, 0, 21, 0x204, 24, 0x0, 0x204, 0), - PLL(CLK_APMIXED_ARMCA7PLL, "armca7pll", 0x210, 0x21c, 0x00000001, 0, 21, 0x214, 24, 0x0, 0x214, 0), - PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x220, 0x22c, 0xf0000101, HAVE_RST_BAR, 21, 0x220, 4, 0x0, 0x224, 0), - PLL(CLK_APMIXED_UNIVPLL, "univpll", 0x230, 0x23c, 0xfe000001, HAVE_RST_BAR, 7, 0x230, 4, 0x0, 0x234, 14), - PLL_B(CLK_APMIXED_MMPLL, "mmpll", 0x240, 0x24c, 0x00000001, 0, 21, 0x244, 24, 0x0, 0x244, 0, mmpll_div_table), - PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x250, 0x25c, 0x00000001, 0, 21, 0x250, 4, 0x0, 0x254, 0), - PLL(CLK_APMIXED_VENCPLL, "vencpll", 0x260, 0x26c, 0x00000001, 0, 21, 0x260, 4, 0x0, 0x264, 0), - PLL(CLK_APMIXED_TVDPLL, "tvdpll", 0x270, 0x27c, 0x00000001, 0, 21, 0x270, 4, 0x0, 0x274, 0), - PLL(CLK_APMIXED_MPLL, "mpll", 0x280, 0x28c, 0x00000001, 0, 21, 0x280, 4, 0x0, 0x284, 0), - PLL(CLK_APMIXED_VCODECPLL, "vcodecpll", 0x290, 0x29c, 0x00000001, 0, 21, 0x290, 4, 0x0, 0x294, 0), - PLL(CLK_APMIXED_APLL1, "apll1", 0x2a0, 0x2b0, 0x00000001, 0, 31, 0x2a0, 4, 0x2a4, 0x2a4, 0), - PLL(CLK_APMIXED_APLL2, "apll2", 0x2b4, 0x2c4, 0x00000001, 0, 31, 0x2b4, 4, 0x2b8, 0x2b8, 0), - PLL(CLK_APMIXED_LVDSPLL, "lvdspll", 0x2d0, 0x2dc, 0x00000001, 0, 21, 0x2d0, 4, 0x0, 0x2d4, 0), - PLL(CLK_APMIXED_MSDCPLL2, "msdcpll2", 0x2f0, 0x2fc, 0x00000001, 0, 21, 0x2f0, 4, 0x0, 0x2f4, 0), + PLL(CLK_APMIXED_ARMCA15PLL, "armca15pll", 0x200, 0x20c, 0, 0, 21, 0x204, 24, 0x0, 0x204, 0), + PLL(CLK_APMIXED_ARMCA7PLL, "armca7pll", 0x210, 0x21c, 0, 0, 21, 0x214, 24, 0x0, 0x214, 0), + PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x220, 0x22c, 0xf0000100, HAVE_RST_BAR, 21, 0x220, 4, 0x0, 0x224, 0), + PLL(CLK_APMIXED_UNIVPLL, "univpll", 0x230, 0x23c, 0xfe000000, HAVE_RST_BAR, 7, 0x230, 4, 0x0, 0x234, 14), + PLL_B(CLK_APMIXED_MMPLL, "mmpll", 0x240, 0x24c, 0, 0, 21, 0x244, 24, 0x0, 0x244, 0, mmpll_div_table), + PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x250, 0x25c, 0, 0, 21, 0x250, 4, 0x0, 0x254, 0), + PLL(CLK_APMIXED_VENCPLL, "vencpll", 0x260, 0x26c, 0, 0, 21, 0x260, 4, 0x0, 0x264, 0), + PLL(CLK_APMIXED_TVDPLL, "tvdpll", 0x270, 0x27c, 0, 0, 21, 0x270, 4, 0x0, 0x274, 0), + PLL(CLK_APMIXED_MPLL, "mpll", 0x280, 0x28c, 0, 0, 21, 0x280, 4, 0x0, 0x284, 0), + PLL(CLK_APMIXED_VCODECPLL, "vcodecpll", 0x290, 0x29c, 0, 0, 21, 0x290, 4, 0x0, 0x294, 0), + PLL(CLK_APMIXED_APLL1, "apll1", 0x2a0, 0x2b0, 0, 0, 31, 0x2a0, 4, 0x2a4, 0x2a4, 0), + PLL(CLK_APMIXED_APLL2, "apll2", 0x2b4, 0x2c4, 0, 0, 31, 0x2b4, 4, 0x2b8, 0x2b8, 0), + PLL(CLK_APMIXED_LVDSPLL, "lvdspll", 0x2d0, 0x2dc, 0, 0, 21, 0x2d0, 4, 0x0, 0x2d4, 0), + PLL(CLK_APMIXED_MSDCPLL2, "msdcpll2", 0x2f0, 0x2fc, 0, 0, 21, 0x2f0, 4, 0x0, 0x2f4, 0), }; static void __init mtk_apmixedsys_init(struct device_node *node) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; void __iomem *base; - struct clk *clk; + struct clk_hw *hw; int r, i; base = of_iomap(node, 0); @@ -1013,24 +1013,21 @@ static void __init mtk_apmixedsys_init(struct device_node *node) for (i = 0; i < ARRAY_SIZE(apmixed_usb); i++) { const struct mtk_clk_usb *cku = &apmixed_usb[i]; - clk = mtk_clk_register_ref2usb_tx(cku->name, cku->parent, - base + cku->reg_ofs); - - if (IS_ERR(clk)) { - pr_err("Failed to register clk %s: %ld\n", cku->name, - PTR_ERR(clk)); + hw = mtk_clk_register_ref2usb_tx(cku->name, cku->parent, base + cku->reg_ofs); + if (IS_ERR(hw)) { + pr_err("Failed to register clk %s: %ld\n", cku->name, PTR_ERR(hw)); continue; } - clk_data->clks[cku->id] = clk; + clk_data->hws[cku->id] = hw; } - clk = clk_register_divider(NULL, "hdmi_ref", "tvdpll_594m", 0, - base + 0x40, 16, 3, CLK_DIVIDER_POWER_OF_TWO, - NULL); - clk_data->clks[CLK_APMIXED_HDMI_REF] = clk; + hw = clk_hw_register_divider(NULL, "hdmi_ref", "tvdpll_594m", 0, + base + 0x40, 16, 3, CLK_DIVIDER_POWER_OF_TWO, + NULL); + clk_data->hws[CLK_APMIXED_HDMI_REF] = hw; - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r) pr_err("%s(): could not register clock provider: %d\n", __func__, r); @@ -1042,7 +1039,7 @@ CLK_OF_DECLARE(mtk_apmixedsys, "mediatek,mt8173-apmixedsys", static void __init mtk_imgsys_init(struct device_node *node) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; int r; clk_data = mtk_alloc_clk_data(CLK_IMG_NR_CLK); @@ -1050,7 +1047,7 @@ static void __init mtk_imgsys_init(struct device_node *node) mtk_clk_register_gates(node, img_clks, ARRAY_SIZE(img_clks), clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r) pr_err("%s(): could not register clock provider: %d\n", @@ -1060,7 +1057,7 @@ CLK_OF_DECLARE(mtk_imgsys, "mediatek,mt8173-imgsys", mtk_imgsys_init); static void __init mtk_vdecsys_init(struct device_node *node) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; int r; clk_data = mtk_alloc_clk_data(CLK_VDEC_NR_CLK); @@ -1068,7 +1065,7 @@ static void __init mtk_vdecsys_init(struct device_node *node) mtk_clk_register_gates(node, vdec_clks, ARRAY_SIZE(vdec_clks), clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r) pr_err("%s(): could not register clock provider: %d\n", __func__, r); @@ -1077,7 +1074,7 @@ CLK_OF_DECLARE(mtk_vdecsys, "mediatek,mt8173-vdecsys", mtk_vdecsys_init); static void __init mtk_vencsys_init(struct device_node *node) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; int r; clk_data = mtk_alloc_clk_data(CLK_VENC_NR_CLK); @@ -1085,7 +1082,7 @@ static void __init mtk_vencsys_init(struct device_node *node) mtk_clk_register_gates(node, venc_clks, ARRAY_SIZE(venc_clks), clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r) pr_err("%s(): could not register clock provider: %d\n", __func__, r); @@ -1094,7 +1091,7 @@ CLK_OF_DECLARE(mtk_vencsys, "mediatek,mt8173-vencsys", mtk_vencsys_init); static void __init mtk_vencltsys_init(struct device_node *node) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; int r; clk_data = mtk_alloc_clk_data(CLK_VENCLT_NR_CLK); @@ -1102,7 +1099,7 @@ static void __init mtk_vencltsys_init(struct device_node *node) mtk_clk_register_gates(node, venclt_clks, ARRAY_SIZE(venclt_clks), clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r) pr_err("%s(): could not register clock provider: %d\n", __func__, r); diff --git a/drivers/clk/mediatek/clk-mt8183-audio.c b/drivers/clk/mediatek/clk-mt8183-audio.c index c87450180b7b6f688dfb36d468ff5a85ce86f78d..b2d7746eddbed9d8e4e8442579d4097362caff85 100644 --- a/drivers/clk/mediatek/clk-mt8183-audio.c +++ b/drivers/clk/mediatek/clk-mt8183-audio.c @@ -69,7 +69,7 @@ static const struct mtk_gate audio_clks[] = { static int clk_mt8183_audio_probe(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; int r; struct device_node *node = pdev->dev.of_node; @@ -78,7 +78,7 @@ static int clk_mt8183_audio_probe(struct platform_device *pdev) mtk_clk_register_gates(node, audio_clks, ARRAY_SIZE(audio_clks), clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r) return r; diff --git a/drivers/clk/mediatek/clk-mt8183-cam.c b/drivers/clk/mediatek/clk-mt8183-cam.c index 8643802c44713954cb52e3f80cdc5cf9c4146b92..fcc598a45165c313a1c92a881a3419546e58d0b0 100644 --- a/drivers/clk/mediatek/clk-mt8183-cam.c +++ b/drivers/clk/mediatek/clk-mt8183-cam.c @@ -36,7 +36,7 @@ static const struct mtk_gate cam_clks[] = { static int clk_mt8183_cam_probe(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; struct device_node *node = pdev->dev.of_node; clk_data = mtk_alloc_clk_data(CLK_CAM_NR_CLK); @@ -44,7 +44,7 @@ static int clk_mt8183_cam_probe(struct platform_device *pdev) mtk_clk_register_gates(node, cam_clks, ARRAY_SIZE(cam_clks), clk_data); - return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); } static const struct of_device_id of_match_clk_mt8183_cam[] = { diff --git a/drivers/clk/mediatek/clk-mt8183-img.c b/drivers/clk/mediatek/clk-mt8183-img.c index 470d676a4a10638b3610439fcc70106c83c77476..eb2def2cf0ae54a394febdde08c65574610b4bd3 100644 --- a/drivers/clk/mediatek/clk-mt8183-img.c +++ b/drivers/clk/mediatek/clk-mt8183-img.c @@ -36,7 +36,7 @@ static const struct mtk_gate img_clks[] = { static int clk_mt8183_img_probe(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; struct device_node *node = pdev->dev.of_node; clk_data = mtk_alloc_clk_data(CLK_IMG_NR_CLK); @@ -44,7 +44,7 @@ static int clk_mt8183_img_probe(struct platform_device *pdev) mtk_clk_register_gates(node, img_clks, ARRAY_SIZE(img_clks), clk_data); - return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); } static const struct of_device_id of_match_clk_mt8183_img[] = { diff --git a/drivers/clk/mediatek/clk-mt8183-ipu0.c b/drivers/clk/mediatek/clk-mt8183-ipu0.c index c5cb76fc9e5e61beae32efbde213dd03d07b697c..b30fc9f47518e9ac3013cd76738f44e7bb761da7 100644 --- a/drivers/clk/mediatek/clk-mt8183-ipu0.c +++ b/drivers/clk/mediatek/clk-mt8183-ipu0.c @@ -29,7 +29,7 @@ static const struct mtk_gate ipu_core0_clks[] = { static int clk_mt8183_ipu_core0_probe(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; struct device_node *node = pdev->dev.of_node; clk_data = mtk_alloc_clk_data(CLK_IPU_CORE0_NR_CLK); @@ -37,7 +37,7 @@ static int clk_mt8183_ipu_core0_probe(struct platform_device *pdev) mtk_clk_register_gates(node, ipu_core0_clks, ARRAY_SIZE(ipu_core0_clks), clk_data); - return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); } static const struct of_device_id of_match_clk_mt8183_ipu_core0[] = { diff --git a/drivers/clk/mediatek/clk-mt8183-ipu1.c b/drivers/clk/mediatek/clk-mt8183-ipu1.c index 8fd5fe002890de9e9bd64b38b3eb635dd5a0619a..b378957e11d0f74032d3fc3e90f37fa4803db2d2 100644 --- a/drivers/clk/mediatek/clk-mt8183-ipu1.c +++ b/drivers/clk/mediatek/clk-mt8183-ipu1.c @@ -29,7 +29,7 @@ static const struct mtk_gate ipu_core1_clks[] = { static int clk_mt8183_ipu_core1_probe(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; struct device_node *node = pdev->dev.of_node; clk_data = mtk_alloc_clk_data(CLK_IPU_CORE1_NR_CLK); @@ -37,7 +37,7 @@ static int clk_mt8183_ipu_core1_probe(struct platform_device *pdev) mtk_clk_register_gates(node, ipu_core1_clks, ARRAY_SIZE(ipu_core1_clks), clk_data); - return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); } static const struct of_device_id of_match_clk_mt8183_ipu_core1[] = { diff --git a/drivers/clk/mediatek/clk-mt8183-ipu_adl.c b/drivers/clk/mediatek/clk-mt8183-ipu_adl.c index 3f37d0ef1df171e77fc1c588051403f339728066..941b43ac8bec6cb61d164128a28c5b93fcd3e6e9 100644 --- a/drivers/clk/mediatek/clk-mt8183-ipu_adl.c +++ b/drivers/clk/mediatek/clk-mt8183-ipu_adl.c @@ -27,7 +27,7 @@ static const struct mtk_gate ipu_adl_clks[] = { static int clk_mt8183_ipu_adl_probe(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; struct device_node *node = pdev->dev.of_node; clk_data = mtk_alloc_clk_data(CLK_IPU_ADL_NR_CLK); @@ -35,7 +35,7 @@ static int clk_mt8183_ipu_adl_probe(struct platform_device *pdev) mtk_clk_register_gates(node, ipu_adl_clks, ARRAY_SIZE(ipu_adl_clks), clk_data); - return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); } static const struct of_device_id of_match_clk_mt8183_ipu_adl[] = { diff --git a/drivers/clk/mediatek/clk-mt8183-ipu_conn.c b/drivers/clk/mediatek/clk-mt8183-ipu_conn.c index 7e0eef79c461e7bf9d9d8afe17ce704162f549b4..ae82c2e17110f3ed2f792974c640b0e58b6cdd35 100644 --- a/drivers/clk/mediatek/clk-mt8183-ipu_conn.c +++ b/drivers/clk/mediatek/clk-mt8183-ipu_conn.c @@ -96,7 +96,7 @@ static const struct mtk_gate ipu_conn_clks[] = { static int clk_mt8183_ipu_conn_probe(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; struct device_node *node = pdev->dev.of_node; clk_data = mtk_alloc_clk_data(CLK_IPU_CONN_NR_CLK); @@ -104,7 +104,7 @@ static int clk_mt8183_ipu_conn_probe(struct platform_device *pdev) mtk_clk_register_gates(node, ipu_conn_clks, ARRAY_SIZE(ipu_conn_clks), clk_data); - return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); } static const struct of_device_id of_match_clk_mt8183_ipu_conn[] = { diff --git a/drivers/clk/mediatek/clk-mt8183-mfgcfg.c b/drivers/clk/mediatek/clk-mt8183-mfgcfg.c index 37b4162c5882036da6e74afea176361f8a108258..d774edaf760be73b08e3a24b3155da1d465bed6e 100644 --- a/drivers/clk/mediatek/clk-mt8183-mfgcfg.c +++ b/drivers/clk/mediatek/clk-mt8183-mfgcfg.c @@ -28,7 +28,7 @@ static const struct mtk_gate mfg_clks[] = { static int clk_mt8183_mfg_probe(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; struct device_node *node = pdev->dev.of_node; pm_runtime_enable(&pdev->dev); @@ -38,7 +38,7 @@ static int clk_mt8183_mfg_probe(struct platform_device *pdev) mtk_clk_register_gates_with_dev(node, mfg_clks, ARRAY_SIZE(mfg_clks), clk_data, &pdev->dev); - return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); } static const struct of_device_id of_match_clk_mt8183_mfg[] = { diff --git a/drivers/clk/mediatek/clk-mt8183-mm.c b/drivers/clk/mediatek/clk-mt8183-mm.c index 9d60e09619c19f20d7d848bd55b564fbcabec584..11ecc6fb0065b5c2eacabc1aa413a2e3590ed984 100644 --- a/drivers/clk/mediatek/clk-mt8183-mm.c +++ b/drivers/clk/mediatek/clk-mt8183-mm.c @@ -86,14 +86,14 @@ static int clk_mt8183_mm_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct device_node *node = dev->parent->of_node; - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; clk_data = mtk_alloc_clk_data(CLK_MM_NR_CLK); mtk_clk_register_gates(node, mm_clks, ARRAY_SIZE(mm_clks), clk_data); - return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); } static struct platform_driver clk_mt8183_mm_drv = { diff --git a/drivers/clk/mediatek/clk-mt8183-vdec.c b/drivers/clk/mediatek/clk-mt8183-vdec.c index 6250fd1e0edc52b00847bbfbe5764a3309010761..0548cde159d09aba75e3bc0116d7807eb14769ad 100644 --- a/drivers/clk/mediatek/clk-mt8183-vdec.c +++ b/drivers/clk/mediatek/clk-mt8183-vdec.c @@ -40,7 +40,7 @@ static const struct mtk_gate vdec_clks[] = { static int clk_mt8183_vdec_probe(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; struct device_node *node = pdev->dev.of_node; clk_data = mtk_alloc_clk_data(CLK_VDEC_NR_CLK); @@ -48,7 +48,7 @@ static int clk_mt8183_vdec_probe(struct platform_device *pdev) mtk_clk_register_gates(node, vdec_clks, ARRAY_SIZE(vdec_clks), clk_data); - return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); } static const struct of_device_id of_match_clk_mt8183_vdec[] = { diff --git a/drivers/clk/mediatek/clk-mt8183-venc.c b/drivers/clk/mediatek/clk-mt8183-venc.c index 6678ef03fab22756a0b4f7f7edb68d460b9041e2..f86ec607d87a999213c7722edc2a2e7c67e82b9d 100644 --- a/drivers/clk/mediatek/clk-mt8183-venc.c +++ b/drivers/clk/mediatek/clk-mt8183-venc.c @@ -32,7 +32,7 @@ static const struct mtk_gate venc_clks[] = { static int clk_mt8183_venc_probe(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; struct device_node *node = pdev->dev.of_node; clk_data = mtk_alloc_clk_data(CLK_VENC_NR_CLK); @@ -40,7 +40,7 @@ static int clk_mt8183_venc_probe(struct platform_device *pdev) mtk_clk_register_gates(node, venc_clks, ARRAY_SIZE(venc_clks), clk_data); - return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); } static const struct of_device_id of_match_clk_mt8183_venc[] = { diff --git a/drivers/clk/mediatek/clk-mt8183.c b/drivers/clk/mediatek/clk-mt8183.c index 68496554dd3dbefdccbf3dfffb7e0edf42f44d64..b5c17988c337183f5c074546db76e499686838ab 100644 --- a/drivers/clk/mediatek/clk-mt8183.c +++ b/drivers/clk/mediatek/clk-mt8183.c @@ -1122,40 +1122,40 @@ static const struct mtk_pll_div_table mfgpll_div_table[] = { }; static const struct mtk_pll_data plls[] = { - PLL_B(CLK_APMIXED_ARMPLL_LL, "armpll_ll", 0x0200, 0x020C, 0x00000001, + PLL_B(CLK_APMIXED_ARMPLL_LL, "armpll_ll", 0x0200, 0x020C, 0, HAVE_RST_BAR | PLL_AO, BIT(24), 22, 8, 0x0204, 24, 0x0, 0x0, 0, 0x0204, 0, 0, armpll_div_table), - PLL_B(CLK_APMIXED_ARMPLL_L, "armpll_l", 0x0210, 0x021C, 0x00000001, + PLL_B(CLK_APMIXED_ARMPLL_L, "armpll_l", 0x0210, 0x021C, 0, HAVE_RST_BAR | PLL_AO, BIT(24), 22, 8, 0x0214, 24, 0x0, 0x0, 0, 0x0214, 0, 0, armpll_div_table), - PLL(CLK_APMIXED_CCIPLL, "ccipll", 0x0290, 0x029C, 0x00000001, + PLL(CLK_APMIXED_CCIPLL, "ccipll", 0x0290, 0x029C, 0, HAVE_RST_BAR | PLL_AO, BIT(24), 22, 8, 0x0294, 24, 0x0, 0x0, 0, 0x0294, 0, 0), - PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x0220, 0x022C, 0x00000001, + PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x0220, 0x022C, 0, HAVE_RST_BAR, BIT(24), 22, 8, 0x0224, 24, 0x0, 0x0, 0, 0x0224, 0, 0), - PLL(CLK_APMIXED_UNIV2PLL, "univ2pll", 0x0230, 0x023C, 0x00000001, + PLL(CLK_APMIXED_UNIV2PLL, "univ2pll", 0x0230, 0x023C, 0, HAVE_RST_BAR, BIT(24), 22, 8, 0x0234, 24, 0x0, 0x0, 0, 0x0234, 0, 0), - PLL_B(CLK_APMIXED_MFGPLL, "mfgpll", 0x0240, 0x024C, 0x00000001, + PLL_B(CLK_APMIXED_MFGPLL, "mfgpll", 0x0240, 0x024C, 0, 0, 0, 22, 8, 0x0244, 24, 0x0, 0x0, 0, 0x0244, 0, 0, mfgpll_div_table), - PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x0250, 0x025C, 0x00000001, + PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x0250, 0x025C, 0, 0, 0, 22, 8, 0x0254, 24, 0x0, 0x0, 0, 0x0254, 0, 0), - PLL(CLK_APMIXED_TVDPLL, "tvdpll", 0x0260, 0x026C, 0x00000001, + PLL(CLK_APMIXED_TVDPLL, "tvdpll", 0x0260, 0x026C, 0, 0, 0, 22, 8, 0x0264, 24, 0x0, 0x0, 0, 0x0264, 0, 0), - PLL(CLK_APMIXED_MMPLL, "mmpll", 0x0270, 0x027C, 0x00000001, + PLL(CLK_APMIXED_MMPLL, "mmpll", 0x0270, 0x027C, 0, HAVE_RST_BAR, BIT(23), 22, 8, 0x0274, 24, 0x0, 0x0, 0, 0x0274, 0, 0), - PLL(CLK_APMIXED_APLL1, "apll1", 0x02A0, 0x02B0, 0x00000001, + PLL(CLK_APMIXED_APLL1, "apll1", 0x02A0, 0x02B0, 0, 0, 0, 32, 8, 0x02A0, 1, 0x02A8, 0x0014, 0, 0x02A4, 0, 0x02A0), - PLL(CLK_APMIXED_APLL2, "apll2", 0x02b4, 0x02c4, 0x00000001, + PLL(CLK_APMIXED_APLL2, "apll2", 0x02b4, 0x02c4, 0, 0, 0, 32, 8, 0x02B4, 1, 0x02BC, 0x0014, 1, 0x02B8, 0, 0x02B4), }; static int clk_mt8183_apmixed_probe(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; struct device_node *node = pdev->dev.of_node; clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK); @@ -1165,10 +1165,10 @@ static int clk_mt8183_apmixed_probe(struct platform_device *pdev) mtk_clk_register_gates(node, apmixed_clks, ARRAY_SIZE(apmixed_clks), clk_data); - return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); } -static struct clk_onecell_data *top_clk_data; +static struct clk_hw_onecell_data *top_clk_data; static void clk_mt8183_top_init_early(struct device_node *node) { @@ -1177,12 +1177,12 @@ static void clk_mt8183_top_init_early(struct device_node *node) top_clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK); for (i = 0; i < CLK_TOP_NR_CLK; i++) - top_clk_data->clks[i] = ERR_PTR(-EPROBE_DEFER); + top_clk_data->hws[i] = ERR_PTR(-EPROBE_DEFER); mtk_clk_register_factors(top_early_divs, ARRAY_SIZE(top_early_divs), top_clk_data); - of_clk_add_provider(node, of_clk_src_onecell_get, top_clk_data); + of_clk_add_hw_provider(node, of_clk_hw_onecell_get, top_clk_data); } CLK_OF_DECLARE_DRIVER(mt8183_topckgen, "mediatek,mt8183-topckgen", @@ -1217,12 +1217,13 @@ static int clk_mt8183_top_probe(struct platform_device *pdev) mtk_clk_register_gates(node, top_clks, ARRAY_SIZE(top_clks), top_clk_data); - return of_clk_add_provider(node, of_clk_src_onecell_get, top_clk_data); + return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, + top_clk_data); } static int clk_mt8183_infra_probe(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; struct device_node *node = pdev->dev.of_node; int r; @@ -1231,7 +1232,7 @@ static int clk_mt8183_infra_probe(struct platform_device *pdev) mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks), clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r) { dev_err(&pdev->dev, "%s(): could not register clock provider: %d\n", @@ -1246,7 +1247,7 @@ static int clk_mt8183_infra_probe(struct platform_device *pdev) static int clk_mt8183_peri_probe(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; struct device_node *node = pdev->dev.of_node; clk_data = mtk_alloc_clk_data(CLK_PERI_NR_CLK); @@ -1254,12 +1255,12 @@ static int clk_mt8183_peri_probe(struct platform_device *pdev) mtk_clk_register_gates(node, peri_clks, ARRAY_SIZE(peri_clks), clk_data); - return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); } static int clk_mt8183_mcu_probe(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; struct device_node *node = pdev->dev.of_node; void __iomem *base; @@ -1272,7 +1273,7 @@ static int clk_mt8183_mcu_probe(struct platform_device *pdev) mtk_clk_register_composites(mcu_muxes, ARRAY_SIZE(mcu_muxes), base, &mt8183_clk_lock, clk_data); - return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); } static const struct of_device_id of_match_clk_mt8183[] = { diff --git a/drivers/clk/mediatek/clk-mt8186-apmixedsys.c b/drivers/clk/mediatek/clk-mt8186-apmixedsys.c new file mode 100644 index 0000000000000000000000000000000000000000..e692a2a67ce1cd6470e2d89a39701fc3aa98dac9 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8186-apmixedsys.c @@ -0,0 +1,133 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright (c) 2022 MediaTek Inc. +// Author: Chun-Jie Chen + +#include +#include +#include + +#include "clk-mtk.h" +#include "clk-pll.h" + +#define MT8186_PLL_FMAX (3800UL * MHZ) +#define MT8186_PLL_FMIN (1500UL * MHZ) +#define MT8186_INTEGER_BITS (8) + +#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, \ + _rst_bar_mask, _pcwbits, _pd_reg, _pd_shift, \ + _tuner_reg, _tuner_en_reg, _tuner_en_bit, \ + _pcw_reg) { \ + .id = _id, \ + .name = _name, \ + .reg = _reg, \ + .pwr_reg = _pwr_reg, \ + .en_mask = _en_mask, \ + .flags = _flags, \ + .rst_bar_mask = _rst_bar_mask, \ + .fmax = MT8186_PLL_FMAX, \ + .fmin = MT8186_PLL_FMIN, \ + .pcwbits = _pcwbits, \ + .pcwibits = MT8186_INTEGER_BITS, \ + .pd_reg = _pd_reg, \ + .pd_shift = _pd_shift, \ + .tuner_reg = _tuner_reg, \ + .tuner_en_reg = _tuner_en_reg, \ + .tuner_en_bit = _tuner_en_bit, \ + .pcw_reg = _pcw_reg, \ + .pcw_shift = 0, \ + .pcw_chg_reg = 0, \ + .en_reg = 0, \ + .pll_en_bit = 0, \ + } + +static const struct mtk_pll_data plls[] = { + /* + * armpll_ll/armpll_bl/ccipll are main clock source of AP MCU, + * should not be closed in Linux world. + */ + PLL(CLK_APMIXED_ARMPLL_LL, "armpll_ll", 0x0204, 0x0210, 0, + PLL_AO, 0, 22, 0x0208, 24, 0, 0, 0, 0x0208), + PLL(CLK_APMIXED_ARMPLL_BL, "armpll_bl", 0x0214, 0x0220, 0, + PLL_AO, 0, 22, 0x0218, 24, 0, 0, 0, 0x0218), + PLL(CLK_APMIXED_CCIPLL, "ccipll", 0x0224, 0x0230, 0, + PLL_AO, 0, 22, 0x0228, 24, 0, 0, 0, 0x0228), + PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x0244, 0x0250, 0xff000000, + HAVE_RST_BAR, BIT(23), 22, 0x0248, 24, 0, 0, 0, 0x0248), + PLL(CLK_APMIXED_UNIV2PLL, "univ2pll", 0x0324, 0x0330, 0xff000000, + HAVE_RST_BAR, BIT(23), 22, 0x0328, 24, 0, 0, 0, 0x0328), + PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x038C, 0x0398, 0, + 0, 0, 22, 0x0390, 24, 0, 0, 0, 0x0390), + PLL(CLK_APMIXED_MMPLL, "mmpll", 0x0254, 0x0260, 0, + 0, 0, 22, 0x0258, 24, 0, 0, 0, 0x0258), + PLL(CLK_APMIXED_NNAPLL, "nnapll", 0x035C, 0x0368, 0, + 0, 0, 22, 0x0360, 24, 0, 0, 0, 0x0360), + PLL(CLK_APMIXED_NNA2PLL, "nna2pll", 0x036C, 0x0378, 0, + 0, 0, 22, 0x0370, 24, 0, 0, 0, 0x0370), + PLL(CLK_APMIXED_ADSPPLL, "adsppll", 0x0304, 0x0310, 0, + 0, 0, 22, 0x0308, 24, 0, 0, 0, 0x0308), + PLL(CLK_APMIXED_MFGPLL, "mfgpll", 0x0314, 0x0320, 0, + 0, 0, 22, 0x0318, 24, 0, 0, 0, 0x0318), + PLL(CLK_APMIXED_TVDPLL, "tvdpll", 0x0264, 0x0270, 0, + 0, 0, 22, 0x0268, 24, 0, 0, 0, 0x0268), + PLL(CLK_APMIXED_APLL1, "apll1", 0x0334, 0x0344, 0, + 0, 0, 32, 0x0338, 24, 0x0040, 0x000C, 0, 0x033C), + PLL(CLK_APMIXED_APLL2, "apll2", 0x0348, 0x0358, 0, + 0, 0, 32, 0x034C, 24, 0x0044, 0x000C, 5, 0x0350), +}; + +static const struct of_device_id of_match_clk_mt8186_apmixed[] = { + { .compatible = "mediatek,mt8186-apmixedsys", }, + {} +}; + +static int clk_mt8186_apmixed_probe(struct platform_device *pdev) +{ + struct clk_hw_onecell_data *clk_data; + struct device_node *node = pdev->dev.of_node; + int r; + + clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK); + if (!clk_data) + return -ENOMEM; + + r = mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data); + if (r) + goto free_apmixed_data; + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) + goto unregister_plls; + + platform_set_drvdata(pdev, clk_data); + + return r; + +unregister_plls: + mtk_clk_unregister_plls(plls, ARRAY_SIZE(plls), clk_data); +free_apmixed_data: + mtk_free_clk_data(clk_data); + return r; +} + +static int clk_mt8186_apmixed_remove(struct platform_device *pdev) +{ + struct device_node *node = pdev->dev.of_node; + struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev); + + of_clk_del_provider(node); + mtk_clk_unregister_plls(plls, ARRAY_SIZE(plls), clk_data); + mtk_free_clk_data(clk_data); + + return 0; +} + +static struct platform_driver clk_mt8186_apmixed_drv = { + .probe = clk_mt8186_apmixed_probe, + .remove = clk_mt8186_apmixed_remove, + .driver = { + .name = "clk-mt8186-apmixed", + .of_match_table = of_match_clk_mt8186_apmixed, + }, +}; +builtin_platform_driver(clk_mt8186_apmixed_drv); diff --git a/drivers/clk/mediatek/clk-mt8186-cam.c b/drivers/clk/mediatek/clk-mt8186-cam.c new file mode 100644 index 0000000000000000000000000000000000000000..9ec345a2ce66f8abfcf6967249bbe12ebfa217cd --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8186-cam.c @@ -0,0 +1,90 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright (c) 2022 MediaTek Inc. +// Author: Chun-Jie Chen + +#include +#include +#include + +#include "clk-gate.h" +#include "clk-mtk.h" + +static const struct mtk_gate_regs cam_cg_regs = { + .set_ofs = 0x4, + .clr_ofs = 0x8, + .sta_ofs = 0x0, +}; + +#define GATE_CAM(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &cam_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +static const struct mtk_gate cam_clks[] = { + GATE_CAM(CLK_CAM_LARB13, "cam_larb13", "top_cam", 0), + GATE_CAM(CLK_CAM_DFP_VAD, "cam_dfp_vad", "top_cam", 1), + GATE_CAM(CLK_CAM_LARB14, "cam_larb14", "top_cam", 2), + GATE_CAM(CLK_CAM, "cam", "top_cam", 6), + GATE_CAM(CLK_CAMTG, "camtg", "top_cam", 7), + GATE_CAM(CLK_CAM_SENINF, "cam_seninf", "top_cam", 8), + GATE_CAM(CLK_CAMSV1, "camsv1", "top_cam", 10), + GATE_CAM(CLK_CAMSV2, "camsv2", "top_cam", 11), + GATE_CAM(CLK_CAMSV3, "camsv3", "top_cam", 12), + GATE_CAM(CLK_CAM_CCU0, "cam_ccu0", "top_cam", 13), + GATE_CAM(CLK_CAM_CCU1, "cam_ccu1", "top_cam", 14), + GATE_CAM(CLK_CAM_MRAW0, "cam_mraw0", "top_cam", 15), + GATE_CAM(CLK_CAM_FAKE_ENG, "cam_fake_eng", "top_cam", 17), + GATE_CAM(CLK_CAM_CCU_GALS, "cam_ccu_gals", "top_cam", 18), + GATE_CAM(CLK_CAM2MM_GALS, "cam2mm_gals", "top_cam", 19), +}; + +static const struct mtk_gate cam_rawa_clks[] = { + GATE_CAM(CLK_CAM_RAWA_LARBX_RAWA, "cam_rawa_larbx_rawa", "top_cam", 0), + GATE_CAM(CLK_CAM_RAWA, "cam_rawa", "top_cam", 1), + GATE_CAM(CLK_CAM_RAWA_CAMTG_RAWA, "cam_rawa_camtg_rawa", "top_cam", 2), +}; + +static const struct mtk_gate cam_rawb_clks[] = { + GATE_CAM(CLK_CAM_RAWB_LARBX_RAWB, "cam_rawb_larbx_rawb", "top_cam", 0), + GATE_CAM(CLK_CAM_RAWB, "cam_rawb", "top_cam", 1), + GATE_CAM(CLK_CAM_RAWB_CAMTG_RAWB, "cam_rawb_camtg_rawb", "top_cam", 2), +}; + +static const struct mtk_clk_desc cam_desc = { + .clks = cam_clks, + .num_clks = ARRAY_SIZE(cam_clks), +}; + +static const struct mtk_clk_desc cam_rawa_desc = { + .clks = cam_rawa_clks, + .num_clks = ARRAY_SIZE(cam_rawa_clks), +}; + +static const struct mtk_clk_desc cam_rawb_desc = { + .clks = cam_rawb_clks, + .num_clks = ARRAY_SIZE(cam_rawb_clks), +}; + +static const struct of_device_id of_match_clk_mt8186_cam[] = { + { + .compatible = "mediatek,mt8186-camsys", + .data = &cam_desc, + }, { + .compatible = "mediatek,mt8186-camsys_rawa", + .data = &cam_rawa_desc, + }, { + .compatible = "mediatek,mt8186-camsys_rawb", + .data = &cam_rawb_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt8186_cam_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt8186-cam", + .of_match_table = of_match_clk_mt8186_cam, + }, +}; +builtin_platform_driver(clk_mt8186_cam_drv); diff --git a/drivers/clk/mediatek/clk-mt8186-img.c b/drivers/clk/mediatek/clk-mt8186-img.c new file mode 100644 index 0000000000000000000000000000000000000000..08a625475aeee28d6943e841e8f328fa04289d78 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8186-img.c @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright (c) 2022 MediaTek Inc. +// Author: Chun-Jie Chen + +#include +#include +#include + +#include "clk-gate.h" +#include "clk-mtk.h" + +static const struct mtk_gate_regs img_cg_regs = { + .set_ofs = 0x4, + .clr_ofs = 0x8, + .sta_ofs = 0x0, +}; + +#define GATE_IMG(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &img_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +static const struct mtk_gate img1_clks[] = { + GATE_IMG(CLK_IMG1_LARB9_IMG1, "img1_larb9_img1", "top_img1", 0), + GATE_IMG(CLK_IMG1_LARB10_IMG1, "img1_larb10_img1", "top_img1", 1), + GATE_IMG(CLK_IMG1_DIP, "img1_dip", "top_img1", 2), + GATE_IMG(CLK_IMG1_GALS_IMG1, "img1_gals_img1", "top_img1", 12), +}; + +static const struct mtk_gate img2_clks[] = { + GATE_IMG(CLK_IMG2_LARB9_IMG2, "img2_larb9_img2", "top_img1", 0), + GATE_IMG(CLK_IMG2_LARB10_IMG2, "img2_larb10_img2", "top_img1", 1), + GATE_IMG(CLK_IMG2_MFB, "img2_mfb", "top_img1", 6), + GATE_IMG(CLK_IMG2_WPE, "img2_wpe", "top_img1", 7), + GATE_IMG(CLK_IMG2_MSS, "img2_mss", "top_img1", 8), + GATE_IMG(CLK_IMG2_GALS_IMG2, "img2_gals_img2", "top_img1", 12), +}; + +static const struct mtk_clk_desc img1_desc = { + .clks = img1_clks, + .num_clks = ARRAY_SIZE(img1_clks), +}; + +static const struct mtk_clk_desc img2_desc = { + .clks = img2_clks, + .num_clks = ARRAY_SIZE(img2_clks), +}; + +static const struct of_device_id of_match_clk_mt8186_img[] = { + { + .compatible = "mediatek,mt8186-imgsys1", + .data = &img1_desc, + }, { + .compatible = "mediatek,mt8186-imgsys2", + .data = &img2_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt8186_img_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt8186-img", + .of_match_table = of_match_clk_mt8186_img, + }, +}; +builtin_platform_driver(clk_mt8186_img_drv); diff --git a/drivers/clk/mediatek/clk-mt8186-imp_iic_wrap.c b/drivers/clk/mediatek/clk-mt8186-imp_iic_wrap.c new file mode 100644 index 0000000000000000000000000000000000000000..47f2e480a05ebf98a18d510e699cf7fef222843b --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8186-imp_iic_wrap.c @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright (c) 2022 MediaTek Inc. +// Author: Chun-Jie Chen + +#include +#include +#include + +#include "clk-gate.h" +#include "clk-mtk.h" + +static const struct mtk_gate_regs imp_iic_wrap_cg_regs = { + .set_ofs = 0xe08, + .clr_ofs = 0xe04, + .sta_ofs = 0xe00, +}; + +#define GATE_IMP_IIC_WRAP(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &imp_iic_wrap_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +static const struct mtk_gate imp_iic_wrap_clks[] = { + GATE_IMP_IIC_WRAP(CLK_IMP_IIC_WRAP_AP_CLOCK_I2C0, + "imp_iic_wrap_ap_clock_i2c0", "infra_ao_i2c_ap", 0), + GATE_IMP_IIC_WRAP(CLK_IMP_IIC_WRAP_AP_CLOCK_I2C1, + "imp_iic_wrap_ap_clock_i2c1", "infra_ao_i2c_ap", 1), + GATE_IMP_IIC_WRAP(CLK_IMP_IIC_WRAP_AP_CLOCK_I2C2, + "imp_iic_wrap_ap_clock_i2c2", "infra_ao_i2c_ap", 2), + GATE_IMP_IIC_WRAP(CLK_IMP_IIC_WRAP_AP_CLOCK_I2C3, + "imp_iic_wrap_ap_clock_i2c3", "infra_ao_i2c_ap", 3), + GATE_IMP_IIC_WRAP(CLK_IMP_IIC_WRAP_AP_CLOCK_I2C4, + "imp_iic_wrap_ap_clock_i2c4", "infra_ao_i2c_ap", 4), + GATE_IMP_IIC_WRAP(CLK_IMP_IIC_WRAP_AP_CLOCK_I2C5, + "imp_iic_wrap_ap_clock_i2c5", "infra_ao_i2c_ap", 5), + GATE_IMP_IIC_WRAP(CLK_IMP_IIC_WRAP_AP_CLOCK_I2C6, + "imp_iic_wrap_ap_clock_i2c6", "infra_ao_i2c_ap", 6), + GATE_IMP_IIC_WRAP(CLK_IMP_IIC_WRAP_AP_CLOCK_I2C7, + "imp_iic_wrap_ap_clock_i2c7", "infra_ao_i2c_ap", 7), + GATE_IMP_IIC_WRAP(CLK_IMP_IIC_WRAP_AP_CLOCK_I2C8, + "imp_iic_wrap_ap_clock_i2c8", "infra_ao_i2c_ap", 8), + GATE_IMP_IIC_WRAP(CLK_IMP_IIC_WRAP_AP_CLOCK_I2C9, + "imp_iic_wrap_ap_clock_i2c9", "infra_ao_i2c_ap", 9), +}; + +static const struct mtk_clk_desc imp_iic_wrap_desc = { + .clks = imp_iic_wrap_clks, + .num_clks = ARRAY_SIZE(imp_iic_wrap_clks), +}; + +static const struct of_device_id of_match_clk_mt8186_imp_iic_wrap[] = { + { + .compatible = "mediatek,mt8186-imp_iic_wrap", + .data = &imp_iic_wrap_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt8186_imp_iic_wrap_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt8186-imp_iic_wrap", + .of_match_table = of_match_clk_mt8186_imp_iic_wrap, + }, +}; +builtin_platform_driver(clk_mt8186_imp_iic_wrap_drv); diff --git a/drivers/clk/mediatek/clk-mt8186-infra_ao.c b/drivers/clk/mediatek/clk-mt8186-infra_ao.c new file mode 100644 index 0000000000000000000000000000000000000000..2a7adc25abaab9996e26dfb8756c5cce2008058c --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8186-infra_ao.c @@ -0,0 +1,216 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright (c) 2022 MediaTek Inc. +// Author: Chun-Jie Chen + +#include +#include +#include + +#include "clk-gate.h" +#include "clk-mtk.h" + +static const struct mtk_gate_regs infra_ao0_cg_regs = { + .set_ofs = 0x80, + .clr_ofs = 0x84, + .sta_ofs = 0x90, +}; + +static const struct mtk_gate_regs infra_ao1_cg_regs = { + .set_ofs = 0x88, + .clr_ofs = 0x8c, + .sta_ofs = 0x94, +}; + +static const struct mtk_gate_regs infra_ao2_cg_regs = { + .set_ofs = 0xa4, + .clr_ofs = 0xa8, + .sta_ofs = 0xac, +}; + +static const struct mtk_gate_regs infra_ao3_cg_regs = { + .set_ofs = 0xc0, + .clr_ofs = 0xc4, + .sta_ofs = 0xc8, +}; + +#define GATE_INFRA_AO0_FLAGS(_id, _name, _parent, _shift, _flag) \ + GATE_MTK_FLAGS(_id, _name, _parent, &infra_ao0_cg_regs, _shift, \ + &mtk_clk_gate_ops_setclr, _flag) + +#define GATE_INFRA_AO0(_id, _name, _parent, _shift) \ + GATE_INFRA_AO0_FLAGS(_id, _name, _parent, _shift, 0) + +#define GATE_INFRA_AO1_FLAGS(_id, _name, _parent, _shift, _flag) \ + GATE_MTK_FLAGS(_id, _name, _parent, &infra_ao1_cg_regs, _shift, \ + &mtk_clk_gate_ops_setclr, _flag) + +#define GATE_INFRA_AO1(_id, _name, _parent, _shift) \ + GATE_INFRA_AO1_FLAGS(_id, _name, _parent, _shift, 0) + +#define GATE_INFRA_AO2_FLAGS(_id, _name, _parent, _shift, _flag) \ + GATE_MTK_FLAGS(_id, _name, _parent, &infra_ao2_cg_regs, _shift, \ + &mtk_clk_gate_ops_setclr, _flag) + +#define GATE_INFRA_AO2(_id, _name, _parent, _shift) \ + GATE_INFRA_AO2_FLAGS(_id, _name, _parent, _shift, 0) + + #define GATE_INFRA_AO3_FLAGS(_id, _name, _parent, _shift, _flag) \ + GATE_MTK_FLAGS(_id, _name, _parent, &infra_ao3_cg_regs, _shift, \ + &mtk_clk_gate_ops_setclr, _flag) + +#define GATE_INFRA_AO3(_id, _name, _parent, _shift) \ + GATE_INFRA_AO3_FLAGS(_id, _name, _parent, _shift, 0) + +static const struct mtk_gate infra_ao_clks[] = { + /* INFRA_AO0 */ + GATE_INFRA_AO0(CLK_INFRA_AO_PMIC_TMR, "infra_ao_pmic_tmr", "top_pwrap_ulposc", 0), + GATE_INFRA_AO0(CLK_INFRA_AO_PMIC_AP, "infra_ao_pmic_ap", "top_pwrap_ulposc", 1), + GATE_INFRA_AO0(CLK_INFRA_AO_PMIC_MD, "infra_ao_pmic_md", "top_pwrap_ulposc", 2), + GATE_INFRA_AO0(CLK_INFRA_AO_PMIC_CONN, "infra_ao_pmic_conn", "top_pwrap_ulposc", 3), + /* infra_ao_scp_core are main clock in always-on co-processor. */ + GATE_INFRA_AO0_FLAGS(CLK_INFRA_AO_SCP_CORE, + "infra_ao_scp_core", "top_scp", 4, CLK_IS_CRITICAL), + /* infra_ao_sej is main clock for secure engine with JTAG support */ + GATE_INFRA_AO0_FLAGS(CLK_INFRA_AO_SEJ, + "infra_ao_sej", "top_axi", 5, CLK_IS_CRITICAL), + GATE_INFRA_AO0(CLK_INFRA_AO_APXGPT, "infra_ao_apxgpt", "top_axi", 6), + GATE_INFRA_AO0(CLK_INFRA_AO_ICUSB, "infra_ao_icusb", "top_axi", 8), + GATE_INFRA_AO0(CLK_INFRA_AO_GCE, "infra_ao_gce", "top_axi", 9), + GATE_INFRA_AO0(CLK_INFRA_AO_THERM, "infra_ao_therm", "top_axi", 10), + GATE_INFRA_AO0(CLK_INFRA_AO_I2C_AP, "infra_ao_i2c_ap", "top_i2c", 11), + GATE_INFRA_AO0(CLK_INFRA_AO_I2C_CCU, "infra_ao_i2c_ccu", "top_i2c", 12), + GATE_INFRA_AO0(CLK_INFRA_AO_I2C_SSPM, "infra_ao_i2c_sspm", "top_i2c", 13), + GATE_INFRA_AO0(CLK_INFRA_AO_I2C_RSV, "infra_ao_i2c_rsv", "top_i2c", 14), + GATE_INFRA_AO0(CLK_INFRA_AO_PWM_HCLK, "infra_ao_pwm_hclk", "top_axi", 15), + GATE_INFRA_AO0(CLK_INFRA_AO_PWM1, "infra_ao_pwm1", "top_pwm", 16), + GATE_INFRA_AO0(CLK_INFRA_AO_PWM2, "infra_ao_pwm2", "top_pwm", 17), + GATE_INFRA_AO0(CLK_INFRA_AO_PWM3, "infra_ao_pwm3", "top_pwm", 18), + GATE_INFRA_AO0(CLK_INFRA_AO_PWM4, "infra_ao_pwm4", "top_pwm", 19), + GATE_INFRA_AO0(CLK_INFRA_AO_PWM5, "infra_ao_pwm5", "top_pwm", 20), + GATE_INFRA_AO0(CLK_INFRA_AO_PWM, "infra_ao_pwm", "top_pwm", 21), + GATE_INFRA_AO0(CLK_INFRA_AO_UART0, "infra_ao_uart0", "top_uart", 22), + GATE_INFRA_AO0(CLK_INFRA_AO_UART1, "infra_ao_uart1", "top_uart", 23), + GATE_INFRA_AO0(CLK_INFRA_AO_UART2, "infra_ao_uart2", "top_uart", 24), + GATE_INFRA_AO0(CLK_INFRA_AO_GCE_26M, "infra_ao_gce_26m", "clk26m", 27), + GATE_INFRA_AO0(CLK_INFRA_AO_CQ_DMA_FPC, "infra_ao_dma", "top_axi", 28), + GATE_INFRA_AO0(CLK_INFRA_AO_BTIF, "infra_ao_btif", "top_axi", 31), + /* INFRA_AO1 */ + GATE_INFRA_AO1(CLK_INFRA_AO_SPI0, "infra_ao_spi0", "top_spi", 1), + GATE_INFRA_AO1(CLK_INFRA_AO_MSDC0, "infra_ao_msdc0", "top_msdc5hclk", 2), + GATE_INFRA_AO1(CLK_INFRA_AO_MSDCFDE, "infra_ao_msdcfde", "top_aes_msdcfde", 3), + GATE_INFRA_AO1(CLK_INFRA_AO_MSDC1, "infra_ao_msdc1", "top_axi", 4), + /* infra_ao_dvfsrc is for internal DVFS usage, should not be handled by Linux */ + GATE_INFRA_AO1_FLAGS(CLK_INFRA_AO_DVFSRC, + "infra_ao_dvfsrc", "top_dvfsrc", 7, CLK_IS_CRITICAL), + GATE_INFRA_AO1(CLK_INFRA_AO_GCPU, "infra_ao_gcpu", "top_axi", 8), + GATE_INFRA_AO1(CLK_INFRA_AO_TRNG, "infra_ao_trng", "top_axi", 9), + GATE_INFRA_AO1(CLK_INFRA_AO_AUXADC, "infra_ao_auxadc", "clk26m", 10), + GATE_INFRA_AO1(CLK_INFRA_AO_CPUM, "infra_ao_cpum", "top_axi", 11), + GATE_INFRA_AO1(CLK_INFRA_AO_CCIF1_AP, "infra_ao_ccif1_ap", "top_axi", 12), + GATE_INFRA_AO1(CLK_INFRA_AO_CCIF1_MD, "infra_ao_ccif1_md", "top_axi", 13), + GATE_INFRA_AO1(CLK_INFRA_AO_AUXADC_MD, "infra_ao_auxadc_md", "clk26m", 14), + GATE_INFRA_AO1(CLK_INFRA_AO_AP_DMA, "infra_ao_ap_dma", "top_axi", 18), + GATE_INFRA_AO1(CLK_INFRA_AO_XIU, "infra_ao_xiu", "top_axi", 19), + /* infra_ao_device_apc is for device access permission control module */ + GATE_INFRA_AO1_FLAGS(CLK_INFRA_AO_DEVICE_APC, + "infra_ao_dapc", "top_axi", 20, CLK_IS_CRITICAL), + GATE_INFRA_AO1(CLK_INFRA_AO_CCIF_AP, "infra_ao_ccif_ap", "top_axi", 23), + GATE_INFRA_AO1(CLK_INFRA_AO_DEBUGTOP, "infra_ao_debugtop", "top_axi", 24), + GATE_INFRA_AO1(CLK_INFRA_AO_AUDIO, "infra_ao_audio", "top_axi", 25), + GATE_INFRA_AO1(CLK_INFRA_AO_CCIF_MD, "infra_ao_ccif_md", "top_axi", 26), + GATE_INFRA_AO1(CLK_INFRA_AO_DXCC_SEC_CORE, "infra_ao_secore", "top_dxcc", 27), + GATE_INFRA_AO1(CLK_INFRA_AO_DXCC_AO, "infra_ao_dxcc_ao", "top_dxcc", 28), + GATE_INFRA_AO1(CLK_INFRA_AO_IMP_IIC, "infra_ao_imp_iic", "top_axi", 29), + GATE_INFRA_AO1(CLK_INFRA_AO_DRAMC_F26M, "infra_ao_dramc26", "clk26m", 31), + /* INFRA_AO2 */ + GATE_INFRA_AO2(CLK_INFRA_AO_RG_PWM_FBCLK6, "infra_ao_pwm_fbclk6", "clk26m", 0), + GATE_INFRA_AO2(CLK_INFRA_AO_SSUSB_TOP_HCLK, "infra_ao_ssusb_hclk", "top_axi", 1), + GATE_INFRA_AO2(CLK_INFRA_AO_DISP_PWM, "infra_ao_disp_pwm", "top_disp_pwm", 2), + GATE_INFRA_AO2(CLK_INFRA_AO_CLDMA_BCLK, "infra_ao_cldmabclk", "top_axi", 3), + GATE_INFRA_AO2(CLK_INFRA_AO_AUDIO_26M_BCLK, "infra_ao_audio26m", "clk26m", 4), + GATE_INFRA_AO2(CLK_INFRA_AO_SSUSB_TOP_P1_HCLK, "infra_ao_ssusb_p1_hclk", "top_axi", 5), + GATE_INFRA_AO2(CLK_INFRA_AO_SPI1, "infra_ao_spi1", "top_spi", 6), + GATE_INFRA_AO2(CLK_INFRA_AO_I2C4, "infra_ao_i2c4", "top_i2c", 7), + GATE_INFRA_AO2(CLK_INFRA_AO_MODEM_TEMP_SHARE, "infra_ao_mdtemp", "clk26m", 8), + GATE_INFRA_AO2(CLK_INFRA_AO_SPI2, "infra_ao_spi2", "top_spi", 9), + GATE_INFRA_AO2(CLK_INFRA_AO_SPI3, "infra_ao_spi3", "top_spi", 10), + GATE_INFRA_AO2(CLK_INFRA_AO_SSUSB_TOP_REF, "infra_ao_ssusb_ref", "clk26m", 11), + GATE_INFRA_AO2(CLK_INFRA_AO_SSUSB_TOP_XHCI, "infra_ao_ssusb_xhci", "top_ssusb_xhci", 12), + GATE_INFRA_AO2(CLK_INFRA_AO_SSUSB_TOP_P1_REF, "infra_ao_ssusb_p1_ref", "clk26m", 13), + GATE_INFRA_AO2(CLK_INFRA_AO_SSUSB_TOP_P1_XHCI, + "infra_ao_ssusb_p1_xhci", "top_ssusb_xhci_1p", 14), + /* infra_ao_sspm is main clock in co-processor, should not be closed in Linux. */ + GATE_INFRA_AO2_FLAGS(CLK_INFRA_AO_SSPM, "infra_ao_sspm", "top_sspm", 15, CLK_IS_CRITICAL), + GATE_INFRA_AO2(CLK_INFRA_AO_SSUSB_TOP_P1_SYS, + "infra_ao_ssusb_p1_sys", "top_ssusb_1p", 16), + GATE_INFRA_AO2(CLK_INFRA_AO_I2C5, "infra_ao_i2c5", "top_i2c", 18), + GATE_INFRA_AO2(CLK_INFRA_AO_I2C5_ARBITER, "infra_ao_i2c5a", "top_i2c", 19), + GATE_INFRA_AO2(CLK_INFRA_AO_I2C5_IMM, "infra_ao_i2c5_imm", "top_i2c", 20), + GATE_INFRA_AO2(CLK_INFRA_AO_I2C1_ARBITER, "infra_ao_i2c1a", "top_i2c", 21), + GATE_INFRA_AO2(CLK_INFRA_AO_I2C1_IMM, "infra_ao_i2c1_imm", "top_i2c", 22), + GATE_INFRA_AO2(CLK_INFRA_AO_I2C2_ARBITER, "infra_ao_i2c2a", "top_i2c", 23), + GATE_INFRA_AO2(CLK_INFRA_AO_I2C2_IMM, "infra_ao_i2c2_imm", "top_i2c", 24), + GATE_INFRA_AO2(CLK_INFRA_AO_SPI4, "infra_ao_spi4", "top_spi", 25), + GATE_INFRA_AO2(CLK_INFRA_AO_SPI5, "infra_ao_spi5", "top_spi", 26), + GATE_INFRA_AO2(CLK_INFRA_AO_CQ_DMA, "infra_ao_cq_dma", "top_axi", 27), + GATE_INFRA_AO2(CLK_INFRA_AO_BIST2FPC, "infra_ao_bist2fpc", "f_bist2fpc_ck", 28), + /* INFRA_AO3 */ + GATE_INFRA_AO3(CLK_INFRA_AO_MSDC0_SELF, "infra_ao_msdc0sf", "top_msdc50_0", 0), + GATE_INFRA_AO3(CLK_INFRA_AO_SPINOR, "infra_ao_spinor", "top_spinor", 1), + /* + * infra_ao_sspm_26m/infra_ao_sspm_32k are main clocks in co-processor, + * should not be closed in Linux. + */ + GATE_INFRA_AO3_FLAGS(CLK_INFRA_AO_SSPM_26M_SELF, "infra_ao_sspm_26m", "clk26m", 3, + CLK_IS_CRITICAL), + GATE_INFRA_AO3_FLAGS(CLK_INFRA_AO_SSPM_32K_SELF, "infra_ao_sspm_32k", "clk32k", 4, + CLK_IS_CRITICAL), + GATE_INFRA_AO3(CLK_INFRA_AO_I2C6, "infra_ao_i2c6", "top_i2c", 6), + GATE_INFRA_AO3(CLK_INFRA_AO_AP_MSDC0, "infra_ao_ap_msdc0", "top_axi", 7), + GATE_INFRA_AO3(CLK_INFRA_AO_MD_MSDC0, "infra_ao_md_msdc0", "top_axi", 8), + GATE_INFRA_AO3(CLK_INFRA_AO_MSDC0_SRC, "infra_ao_msdc0_clk", "top_msdc50_0", 9), + GATE_INFRA_AO3(CLK_INFRA_AO_MSDC1_SRC, "infra_ao_msdc1_clk", "top_msdc30_1", 10), + /* infra_ao_sej_f13m is main clock for secure engine with JTAG support */ + GATE_INFRA_AO3_FLAGS(CLK_INFRA_AO_SEJ_F13M, + "infra_ao_sej_f13m", "clk26m", 15, CLK_IS_CRITICAL), + /* infra_ao_aes_top0_bclk is for secure encryption */ + GATE_INFRA_AO3_FLAGS(CLK_INFRA_AO_AES_TOP0_BCLK, + "infra_ao_aes_top0_bclk", "top_axi", 16, CLK_IS_CRITICAL), + GATE_INFRA_AO3(CLK_INFRA_AO_MCU_PM_BCLK, "infra_ao_mcu_pm_bclk", "top_axi", 17), + GATE_INFRA_AO3(CLK_INFRA_AO_CCIF2_AP, "infra_ao_ccif2_ap", "top_axi", 18), + GATE_INFRA_AO3(CLK_INFRA_AO_CCIF2_MD, "infra_ao_ccif2_md", "top_axi", 19), + GATE_INFRA_AO3(CLK_INFRA_AO_CCIF3_AP, "infra_ao_ccif3_ap", "top_axi", 20), + GATE_INFRA_AO3(CLK_INFRA_AO_CCIF3_MD, "infra_ao_ccif3_md", "top_axi", 21), + GATE_INFRA_AO3(CLK_INFRA_AO_FADSP_26M, "infra_ao_fadsp_26m", "clk26m", 22), + GATE_INFRA_AO3(CLK_INFRA_AO_FADSP_32K, "infra_ao_fadsp_32k", "clk32k", 23), + GATE_INFRA_AO3(CLK_INFRA_AO_CCIF4_AP, "infra_ao_ccif4_ap", "top_axi", 24), + GATE_INFRA_AO3(CLK_INFRA_AO_CCIF4_MD, "infra_ao_ccif4_md", "top_axi", 25), + GATE_INFRA_AO3(CLK_INFRA_AO_FADSP, "infra_ao_fadsp", "top_audiodsp", 27), + GATE_INFRA_AO3(CLK_INFRA_AO_FLASHIF_133M, "infra_ao_flashif_133m", "top_axi", 28), + GATE_INFRA_AO3(CLK_INFRA_AO_FLASHIF_66M, "infra_ao_flashif_66m", "top_axi", 29), +}; + +static const struct mtk_clk_desc infra_ao_desc = { + .clks = infra_ao_clks, + .num_clks = ARRAY_SIZE(infra_ao_clks), +}; + +static const struct of_device_id of_match_clk_mt8186_infra_ao[] = { + { + .compatible = "mediatek,mt8186-infracfg_ao", + .data = &infra_ao_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt8186_infra_ao_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt8186-infra-ao", + .of_match_table = of_match_clk_mt8186_infra_ao, + }, +}; +builtin_platform_driver(clk_mt8186_infra_ao_drv); diff --git a/drivers/clk/mediatek/clk-mt8186-ipe.c b/drivers/clk/mediatek/clk-mt8186-ipe.c new file mode 100644 index 0000000000000000000000000000000000000000..8fca148effa6f52dbae454ea6328287922f9e4f0 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8186-ipe.c @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright (c) 2022 MediaTek Inc. +// Author: Chun-Jie Chen + +#include +#include +#include + +#include "clk-gate.h" +#include "clk-mtk.h" + +static const struct mtk_gate_regs ipe_cg_regs = { + .set_ofs = 0x4, + .clr_ofs = 0x8, + .sta_ofs = 0x0, +}; + +#define GATE_IPE(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &ipe_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +static const struct mtk_gate ipe_clks[] = { + GATE_IPE(CLK_IPE_LARB19, "ipe_larb19", "top_ipe", 0), + GATE_IPE(CLK_IPE_LARB20, "ipe_larb20", "top_ipe", 1), + GATE_IPE(CLK_IPE_SMI_SUBCOM, "ipe_smi_subcom", "top_ipe", 2), + GATE_IPE(CLK_IPE_FD, "ipe_fd", "top_ipe", 3), + GATE_IPE(CLK_IPE_FE, "ipe_fe", "top_ipe", 4), + GATE_IPE(CLK_IPE_RSC, "ipe_rsc", "top_ipe", 5), + GATE_IPE(CLK_IPE_DPE, "ipe_dpe", "top_ipe", 6), + GATE_IPE(CLK_IPE_GALS_IPE, "ipe_gals_ipe", "top_img1", 8), +}; + +static const struct mtk_clk_desc ipe_desc = { + .clks = ipe_clks, + .num_clks = ARRAY_SIZE(ipe_clks), +}; + +static const struct of_device_id of_match_clk_mt8186_ipe[] = { + { + .compatible = "mediatek,mt8186-ipesys", + .data = &ipe_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt8186_ipe_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt8186-ipe", + .of_match_table = of_match_clk_mt8186_ipe, + }, +}; +builtin_platform_driver(clk_mt8186_ipe_drv); diff --git a/drivers/clk/mediatek/clk-mt8186-mcu.c b/drivers/clk/mediatek/clk-mt8186-mcu.c new file mode 100644 index 0000000000000000000000000000000000000000..dfc305c1fc5d8ffd822573d889870abe02136f1e --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8186-mcu.c @@ -0,0 +1,108 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright (c) 2022 MediaTek Inc. +// Author: Chun-Jie Chen + +#include +#include +#include + +#include "clk-mtk.h" + +static const char * const mcu_armpll_ll_parents[] = { + "clk26m", + "armpll_ll", + "mainpll", + "univpll_d2" +}; + +static const char * const mcu_armpll_bl_parents[] = { + "clk26m", + "armpll_bl", + "mainpll", + "univpll_d2" +}; + +static const char * const mcu_armpll_bus_parents[] = { + "clk26m", + "ccipll", + "mainpll", + "univpll_d2" +}; + +/* + * We only configure the CPU muxes when adjust CPU frequency in MediaTek CPUFreq Driver. + * Other fields like divider always keep the same value. (set once in bootloader) + */ +static struct mtk_composite mcu_muxes[] = { + /* CPU_PLLDIV_CFG0 */ + MUX(CLK_MCU_ARMPLL_LL_SEL, "mcu_armpll_ll_sel", mcu_armpll_ll_parents, 0x2A0, 9, 2), + /* CPU_PLLDIV_CFG1 */ + MUX(CLK_MCU_ARMPLL_BL_SEL, "mcu_armpll_bl_sel", mcu_armpll_bl_parents, 0x2A4, 9, 2), + /* BUS_PLLDIV_CFG */ + MUX(CLK_MCU_ARMPLL_BUS_SEL, "mcu_armpll_bus_sel", mcu_armpll_bus_parents, 0x2E0, 9, 2), +}; + +static const struct of_device_id of_match_clk_mt8186_mcu[] = { + { .compatible = "mediatek,mt8186-mcusys", }, + {} +}; + +static int clk_mt8186_mcu_probe(struct platform_device *pdev) +{ + struct clk_hw_onecell_data *clk_data; + struct device_node *node = pdev->dev.of_node; + int r; + void __iomem *base; + + clk_data = mtk_alloc_clk_data(CLK_MCU_NR_CLK); + if (!clk_data) + return -ENOMEM; + + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) { + r = PTR_ERR(base); + goto free_mcu_data; + } + + r = mtk_clk_register_composites(mcu_muxes, ARRAY_SIZE(mcu_muxes), base, + NULL, clk_data); + if (r) + goto free_mcu_data; + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) + goto unregister_composite_muxes; + + platform_set_drvdata(pdev, clk_data); + + return r; + +unregister_composite_muxes: + mtk_clk_unregister_composites(mcu_muxes, ARRAY_SIZE(mcu_muxes), clk_data); +free_mcu_data: + mtk_free_clk_data(clk_data); + return r; +} + +static int clk_mt8186_mcu_remove(struct platform_device *pdev) +{ + struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev); + struct device_node *node = pdev->dev.of_node; + + of_clk_del_provider(node); + mtk_clk_unregister_composites(mcu_muxes, ARRAY_SIZE(mcu_muxes), clk_data); + mtk_free_clk_data(clk_data); + + return 0; +} + +static struct platform_driver clk_mt8186_mcu_drv = { + .probe = clk_mt8186_mcu_probe, + .remove = clk_mt8186_mcu_remove, + .driver = { + .name = "clk-mt8186-mcu", + .of_match_table = of_match_clk_mt8186_mcu, + }, +}; +builtin_platform_driver(clk_mt8186_mcu_drv); diff --git a/drivers/clk/mediatek/clk-mt8186-mdp.c b/drivers/clk/mediatek/clk-mt8186-mdp.c new file mode 100644 index 0000000000000000000000000000000000000000..05174088ef20ad40d8a0c406876a0a19075d5162 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8186-mdp.c @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright (c) 2022 MediaTek Inc. +// Author: Chun-Jie Chen + +#include +#include +#include + +#include "clk-gate.h" +#include "clk-mtk.h" + +static const struct mtk_gate_regs mdp0_cg_regs = { + .set_ofs = 0x104, + .clr_ofs = 0x108, + .sta_ofs = 0x100, +}; + +static const struct mtk_gate_regs mdp2_cg_regs = { + .set_ofs = 0x124, + .clr_ofs = 0x128, + .sta_ofs = 0x120, +}; + +#define GATE_MDP0(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &mdp0_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +#define GATE_MDP2(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &mdp2_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +static const struct mtk_gate mdp_clks[] = { + /* MDP0 */ + GATE_MDP0(CLK_MDP_RDMA0, "mdp_rdma0", "top_mdp", 0), + GATE_MDP0(CLK_MDP_TDSHP0, "mdp_tdshp0", "top_mdp", 1), + GATE_MDP0(CLK_MDP_IMG_DL_ASYNC0, "mdp_img_dl_async0", "top_mdp", 2), + GATE_MDP0(CLK_MDP_IMG_DL_ASYNC1, "mdp_img_dl_async1", "top_mdp", 3), + GATE_MDP0(CLK_MDP_DISP_RDMA, "mdp_disp_rdma", "top_mdp", 4), + GATE_MDP0(CLK_MDP_HMS, "mdp_hms", "top_mdp", 5), + GATE_MDP0(CLK_MDP_SMI0, "mdp_smi0", "top_mdp", 6), + GATE_MDP0(CLK_MDP_APB_BUS, "mdp_apb_bus", "top_mdp", 7), + GATE_MDP0(CLK_MDP_WROT0, "mdp_wrot0", "top_mdp", 8), + GATE_MDP0(CLK_MDP_RSZ0, "mdp_rsz0", "top_mdp", 9), + GATE_MDP0(CLK_MDP_HDR0, "mdp_hdr0", "top_mdp", 10), + GATE_MDP0(CLK_MDP_MUTEX0, "mdp_mutex0", "top_mdp", 11), + GATE_MDP0(CLK_MDP_WROT1, "mdp_wrot1", "top_mdp", 12), + GATE_MDP0(CLK_MDP_RSZ1, "mdp_rsz1", "top_mdp", 13), + GATE_MDP0(CLK_MDP_FAKE_ENG0, "mdp_fake_eng0", "top_mdp", 14), + GATE_MDP0(CLK_MDP_AAL0, "mdp_aal0", "top_mdp", 15), + GATE_MDP0(CLK_MDP_DISP_WDMA, "mdp_disp_wdma", "top_mdp", 16), + GATE_MDP0(CLK_MDP_COLOR, "mdp_color", "top_mdp", 17), + GATE_MDP0(CLK_MDP_IMG_DL_ASYNC2, "mdp_img_dl_async2", "top_mdp", 18), + /* MDP2 */ + GATE_MDP2(CLK_MDP_IMG_DL_RELAY0_ASYNC0, "mdp_img_dl_rel0_as0", "top_mdp", 0), + GATE_MDP2(CLK_MDP_IMG_DL_RELAY1_ASYNC1, "mdp_img_dl_rel1_as1", "top_mdp", 8), + GATE_MDP2(CLK_MDP_IMG_DL_RELAY2_ASYNC2, "mdp_img_dl_rel2_as2", "top_mdp", 24), +}; + +static const struct mtk_clk_desc mdp_desc = { + .clks = mdp_clks, + .num_clks = ARRAY_SIZE(mdp_clks), +}; + +static const struct of_device_id of_match_clk_mt8186_mdp[] = { + { + .compatible = "mediatek,mt8186-mdpsys", + .data = &mdp_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt8186_mdp_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt8186-mdp", + .of_match_table = of_match_clk_mt8186_mdp, + }, +}; +builtin_platform_driver(clk_mt8186_mdp_drv); diff --git a/drivers/clk/mediatek/clk-mt8186-mfg.c b/drivers/clk/mediatek/clk-mt8186-mfg.c new file mode 100644 index 0000000000000000000000000000000000000000..f1f92216f8944ffb0496565f813f36f6bfde4f4a --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8186-mfg.c @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright (c) 2022 MediaTek Inc. +// Author: Chun-Jie Chen + +#include +#include +#include + +#include "clk-gate.h" +#include "clk-mtk.h" + +static const struct mtk_gate_regs mfg_cg_regs = { + .set_ofs = 0x4, + .clr_ofs = 0x8, + .sta_ofs = 0x0, +}; + +#define GATE_MFG(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &mfg_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +static const struct mtk_gate mfg_clks[] = { + GATE_MFG(CLK_MFG_BG3D, "mfg_bg3d", "top_mfg", 0), +}; + +static const struct mtk_clk_desc mfg_desc = { + .clks = mfg_clks, + .num_clks = ARRAY_SIZE(mfg_clks), +}; + +static const struct of_device_id of_match_clk_mt8186_mfg[] = { + { + .compatible = "mediatek,mt8186-mfgsys", + .data = &mfg_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt8186_mfg_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt8186-mfg", + .of_match_table = of_match_clk_mt8186_mfg, + }, +}; +builtin_platform_driver(clk_mt8186_mfg_drv); diff --git a/drivers/clk/mediatek/clk-mt8186-mm.c b/drivers/clk/mediatek/clk-mt8186-mm.c new file mode 100644 index 0000000000000000000000000000000000000000..1d33be4079470e814334128ff9f5b661d425692d --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8186-mm.c @@ -0,0 +1,111 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright (c) 2022 MediaTek Inc. +// Author: Chun-Jie Chen + +#include +#include +#include + +#include "clk-gate.h" +#include "clk-mtk.h" + +static const struct mtk_gate_regs mm0_cg_regs = { + .set_ofs = 0x104, + .clr_ofs = 0x108, + .sta_ofs = 0x100, +}; + +static const struct mtk_gate_regs mm1_cg_regs = { + .set_ofs = 0x1a4, + .clr_ofs = 0x1a8, + .sta_ofs = 0x1a0, +}; + +#define GATE_MM0(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &mm0_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +#define GATE_MM1(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &mm1_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +static const struct mtk_gate mm_clks[] = { + /* MM0 */ + GATE_MM0(CLK_MM_DISP_MUTEX0, "mm_disp_mutex0", "top_disp", 0), + GATE_MM0(CLK_MM_APB_MM_BUS, "mm_apb_mm_bus", "top_disp", 1), + GATE_MM0(CLK_MM_DISP_OVL0, "mm_disp_ovl0", "top_disp", 2), + GATE_MM0(CLK_MM_DISP_RDMA0, "mm_disp_rdma0", "top_disp", 3), + GATE_MM0(CLK_MM_DISP_OVL0_2L, "mm_disp_ovl0_2l", "top_disp", 4), + GATE_MM0(CLK_MM_DISP_WDMA0, "mm_disp_wdma0", "top_disp", 5), + GATE_MM0(CLK_MM_DISP_RSZ0, "mm_disp_rsz0", "top_disp", 7), + GATE_MM0(CLK_MM_DISP_AAL0, "mm_disp_aal0", "top_disp", 8), + GATE_MM0(CLK_MM_DISP_CCORR0, "mm_disp_ccorr0", "top_disp", 9), + GATE_MM0(CLK_MM_DISP_COLOR0, "mm_disp_color0", "top_disp", 10), + GATE_MM0(CLK_MM_SMI_INFRA, "mm_smi_infra", "top_disp", 11), + GATE_MM0(CLK_MM_DISP_DSC_WRAP0, "mm_disp_dsc_wrap0", "top_disp", 12), + GATE_MM0(CLK_MM_DISP_GAMMA0, "mm_disp_gamma0", "top_disp", 13), + GATE_MM0(CLK_MM_DISP_POSTMASK0, "mm_disp_postmask0", "top_disp", 14), + GATE_MM0(CLK_MM_DISP_DITHER0, "mm_disp_dither0", "top_disp", 16), + GATE_MM0(CLK_MM_SMI_COMMON, "mm_smi_common", "top_disp", 17), + GATE_MM0(CLK_MM_DSI0, "mm_dsi0", "top_disp", 19), + GATE_MM0(CLK_MM_DISP_FAKE_ENG0, "mm_disp_fake_eng0", "top_disp", 20), + GATE_MM0(CLK_MM_DISP_FAKE_ENG1, "mm_disp_fake_eng1", "top_disp", 21), + GATE_MM0(CLK_MM_SMI_GALS, "mm_smi_gals", "top_disp", 22), + GATE_MM0(CLK_MM_SMI_IOMMU, "mm_smi_iommu", "top_disp", 24), + GATE_MM0(CLK_MM_DISP_RDMA1, "mm_disp_rdma1", "top_disp", 25), + GATE_MM0(CLK_MM_DISP_DPI, "mm_disp_dpi", "top_disp", 26), + /* MM1 */ + GATE_MM1(CLK_MM_DSI0_DSI_CK_DOMAIN, "mm_dsi0_dsi_domain", "top_disp", 0), + GATE_MM1(CLK_MM_DISP_26M, "mm_disp_26m_ck", "top_disp", 10), +}; + +static int clk_mt8186_mm_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *node = dev->parent->of_node; + struct clk_hw_onecell_data *clk_data; + int r; + + clk_data = mtk_alloc_clk_data(CLK_MM_NR_CLK); + if (!clk_data) + return -ENOMEM; + + r = mtk_clk_register_gates(node, mm_clks, ARRAY_SIZE(mm_clks), clk_data); + if (r) + goto free_mm_data; + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) + goto unregister_gates; + + platform_set_drvdata(pdev, clk_data); + + return r; + +unregister_gates: + mtk_clk_unregister_gates(mm_clks, ARRAY_SIZE(mm_clks), clk_data); +free_mm_data: + mtk_free_clk_data(clk_data); + return r; +} + +static int clk_mt8186_mm_remove(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *node = dev->parent->of_node; + struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev); + + of_clk_del_provider(node); + mtk_clk_unregister_gates(mm_clks, ARRAY_SIZE(mm_clks), clk_data); + mtk_free_clk_data(clk_data); + + return 0; +} + +static struct platform_driver clk_mt8186_mm_drv = { + .probe = clk_mt8186_mm_probe, + .remove = clk_mt8186_mm_remove, + .driver = { + .name = "clk-mt8186-mm", + }, +}; +builtin_platform_driver(clk_mt8186_mm_drv); diff --git a/drivers/clk/mediatek/clk-mt8186-topckgen.c b/drivers/clk/mediatek/clk-mt8186-topckgen.c new file mode 100644 index 0000000000000000000000000000000000000000..d7f2c4663c853a46bd8beb7a9394b7fc929e9c69 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8186-topckgen.c @@ -0,0 +1,780 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright (c) 2022 MediaTek Inc. +// Author: Chun-Jie Chen + +#include +#include +#include + +#include "clk-mtk.h" +#include "clk-mux.h" + +static DEFINE_SPINLOCK(mt8186_clk_lock); + +static const struct mtk_fixed_clk top_fixed_clks[] = { + FIXED_CLK(CLK_TOP_ULPOSC1, "ulposc1", NULL, 250000000), + FIXED_CLK(CLK_TOP_466M_FMEM, "hd_466m_fmem_ck", NULL, 466000000), + FIXED_CLK(CLK_TOP_MPLL, "mpll", NULL, 208000000), +}; + +static const struct mtk_fixed_factor top_divs[] = { + FACTOR(CLK_TOP_MAINPLL_D2, "mainpll_d2", "mainpll", 1, 2), + FACTOR(CLK_TOP_MAINPLL_D2_D2, "mainpll_d2_d2", "mainpll_d2", 1, 2), + FACTOR(CLK_TOP_MAINPLL_D2_D4, "mainpll_d2_d4", "mainpll_d2", 1, 4), + FACTOR(CLK_TOP_MAINPLL_D2_D16, "mainpll_d2_d16", "mainpll_d2", 1, 16), + FACTOR(CLK_TOP_MAINPLL_D3, "mainpll_d3", "mainpll", 1, 3), + FACTOR(CLK_TOP_MAINPLL_D3_D2, "mainpll_d3_d2", "mainpll_d3", 1, 2), + FACTOR(CLK_TOP_MAINPLL_D3_D4, "mainpll_d3_d4", "mainpll_d3", 1, 4), + FACTOR(CLK_TOP_MAINPLL_D5, "mainpll_d5", "mainpll", 1, 5), + FACTOR(CLK_TOP_MAINPLL_D5_D2, "mainpll_d5_d2", "mainpll_d5", 1, 2), + FACTOR(CLK_TOP_MAINPLL_D5_D4, "mainpll_d5_d4", "mainpll_d5", 1, 4), + FACTOR(CLK_TOP_MAINPLL_D7, "mainpll_d7", "mainpll", 1, 7), + FACTOR(CLK_TOP_MAINPLL_D7_D2, "mainpll_d7_d2", "mainpll_d7", 1, 2), + FACTOR(CLK_TOP_MAINPLL_D7_D4, "mainpll_d7_d4", "mainpll_d7", 1, 4), + FACTOR(CLK_TOP_UNIVPLL, "univpll", "univ2pll", 1, 2), + FACTOR(CLK_TOP_UNIVPLL_D2, "univpll_d2", "univpll", 1, 2), + FACTOR(CLK_TOP_UNIVPLL_D2_D2, "univpll_d2_d2", "univpll_d2", 1, 2), + FACTOR(CLK_TOP_UNIVPLL_D2_D4, "univpll_d2_d4", "univpll_d2", 1, 4), + FACTOR(CLK_TOP_UNIVPLL_D3, "univpll_d3", "univpll", 1, 3), + FACTOR(CLK_TOP_UNIVPLL_D3_D2, "univpll_d3_d2", "univpll_d3", 1, 2), + FACTOR(CLK_TOP_UNIVPLL_D3_D4, "univpll_d3_d4", "univpll_d3", 1, 4), + FACTOR(CLK_TOP_UNIVPLL_D3_D8, "univpll_d3_d8", "univpll_d3", 1, 8), + FACTOR(CLK_TOP_UNIVPLL_D3_D32, "univpll_d3_d32", "univpll_d3", 1, 32), + FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univpll", 1, 5), + FACTOR(CLK_TOP_UNIVPLL_D5_D2, "univpll_d5_d2", "univpll_d5", 1, 2), + FACTOR(CLK_TOP_UNIVPLL_D5_D4, "univpll_d5_d4", "univpll_d5", 1, 4), + FACTOR(CLK_TOP_UNIVPLL_D7, "univpll_d7", "univpll", 1, 7), + FACTOR(CLK_TOP_UNIVPLL_192M, "univpll_192m", "univ2pll", 1, 13), + FACTOR(CLK_TOP_UNIVPLL_192M_D4, "univpll_192m_d4", "univpll_192m", 1, 4), + FACTOR(CLK_TOP_UNIVPLL_192M_D8, "univpll_192m_d8", "univpll_192m", 1, 8), + FACTOR(CLK_TOP_UNIVPLL_192M_D16, "univpll_192m_d16", "univpll_192m", 1, 16), + FACTOR(CLK_TOP_UNIVPLL_192M_D32, "univpll_192m_d32", "univpll_192m", 1, 32), + FACTOR(CLK_TOP_APLL1_D2, "apll1_d2", "apll1", 1, 2), + FACTOR(CLK_TOP_APLL1_D4, "apll1_d4", "apll1", 1, 4), + FACTOR(CLK_TOP_APLL1_D8, "apll1_d8", "apll1", 1, 8), + FACTOR(CLK_TOP_APLL2_D2, "apll2_d2", "apll2", 1, 2), + FACTOR(CLK_TOP_APLL2_D4, "apll2_d4", "apll2", 1, 4), + FACTOR(CLK_TOP_APLL2_D8, "apll2_d8", "apll2", 1, 8), + FACTOR(CLK_TOP_MMPLL_D2, "mmpll_d2", "mmpll", 1, 2), + FACTOR(CLK_TOP_TVDPLL_D2, "tvdpll_d2", "tvdpll", 1, 2), + FACTOR(CLK_TOP_TVDPLL_D4, "tvdpll_d4", "tvdpll", 1, 4), + FACTOR(CLK_TOP_TVDPLL_D8, "tvdpll_d8", "tvdpll", 1, 8), + FACTOR(CLK_TOP_TVDPLL_D16, "tvdpll_d16", "tvdpll", 1, 16), + FACTOR(CLK_TOP_TVDPLL_D32, "tvdpll_d32", "tvdpll", 1, 32), + FACTOR(CLK_TOP_MSDCPLL_D2, "msdcpll_d2", "msdcpll", 1, 2), + FACTOR(CLK_TOP_ULPOSC1_D2, "ulposc1_d2", "ulposc1", 1, 2), + FACTOR(CLK_TOP_ULPOSC1_D4, "ulposc1_d4", "ulposc1", 1, 4), + FACTOR(CLK_TOP_ULPOSC1_D8, "ulposc1_d8", "ulposc1", 1, 8), + FACTOR(CLK_TOP_ULPOSC1_D10, "ulposc1_d10", "ulposc1", 1, 10), + FACTOR(CLK_TOP_ULPOSC1_D16, "ulposc1_d16", "ulposc1", 1, 16), + FACTOR(CLK_TOP_ULPOSC1_D32, "ulposc1_d32", "ulposc1", 1, 32), + FACTOR(CLK_TOP_ADSPPLL_D2, "adsppll_d2", "adsppll", 1, 2), + FACTOR(CLK_TOP_ADSPPLL_D4, "adsppll_d4", "adsppll", 1, 4), + FACTOR(CLK_TOP_ADSPPLL_D8, "adsppll_d8", "adsppll", 1, 8), + FACTOR(CLK_TOP_NNAPLL_D2, "nnapll_d2", "nnapll", 1, 2), + FACTOR(CLK_TOP_NNAPLL_D4, "nnapll_d4", "nnapll", 1, 4), + FACTOR(CLK_TOP_NNAPLL_D8, "nnapll_d8", "nnapll", 1, 8), + FACTOR(CLK_TOP_NNA2PLL_D2, "nna2pll_d2", "nna2pll", 1, 2), + FACTOR(CLK_TOP_NNA2PLL_D4, "nna2pll_d4", "nna2pll", 1, 4), + FACTOR(CLK_TOP_NNA2PLL_D8, "nna2pll_d8", "nna2pll", 1, 8), + FACTOR(CLK_TOP_F_BIST2FPC, "f_bist2fpc_ck", "univpll_d3_d2", 1, 1), +}; + +static const char * const axi_parents[] = { + "clk26m", + "mainpll_d7", + "mainpll_d2_d4", + "univpll_d7" +}; + +static const char * const scp_parents[] = { + "clk26m", + "mainpll_d2_d4", + "mainpll_d5", + "mainpll_d2_d2", + "mainpll_d3", + "univpll_d3" +}; + +static const char * const mfg_parents[] = { + "clk26m", + "mfgpll", + "mainpll_d3", + "mainpll_d5" +}; + +static const char * const camtg_parents[] = { + "clk26m", + "univpll_192m_d8", + "univpll_d3_d8", + "univpll_192m_d4", + "univpll_d3_d32", + "univpll_192m_d16", + "univpll_192m_d32" +}; + +static const char * const uart_parents[] = { + "clk26m", + "univpll_d3_d8" +}; + +static const char * const spi_parents[] = { + "clk26m", + "mainpll_d5_d4", + "mainpll_d3_d4", + "mainpll_d5_d2", + "mainpll_d2_d4", + "mainpll_d7", + "mainpll_d3_d2", + "mainpll_d5" +}; + +static const char * const msdc5hclk_parents[] = { + "clk26m", + "mainpll_d2_d2", + "mainpll_d7", + "mainpll_d3_d2" +}; + +static const char * const msdc50_0_parents[] = { + "clk26m", + "msdcpll", + "univpll_d3", + "msdcpll_d2", + "mainpll_d7", + "mainpll_d3_d2", + "univpll_d2_d2" +}; + +static const char * const msdc30_1_parents[] = { + "clk26m", + "msdcpll_d2", + "univpll_d3_d2", + "mainpll_d3_d2", + "mainpll_d7" +}; + +static const char * const audio_parents[] = { + "clk26m", + "mainpll_d5_d4", + "mainpll_d7_d4", + "mainpll_d2_d16" +}; + +static const char * const aud_intbus_parents[] = { + "clk26m", + "mainpll_d2_d4", + "mainpll_d7_d2" +}; + +static const char * const aud_1_parents[] = { + "clk26m", + "apll1" +}; + +static const char * const aud_2_parents[] = { + "clk26m", + "apll2" +}; + +static const char * const aud_engen1_parents[] = { + "clk26m", + "apll1_d2", + "apll1_d4", + "apll1_d8" +}; + +static const char * const aud_engen2_parents[] = { + "clk26m", + "apll2_d2", + "apll2_d4", + "apll2_d8" +}; + +static const char * const disp_pwm_parents[] = { + "clk26m", + "univpll_d5_d2", + "univpll_d3_d4", + "ulposc1_d2", + "ulposc1_d8" +}; + +static const char * const sspm_parents[] = { + "clk26m", + "mainpll_d2_d2", + "mainpll_d3_d2", + "mainpll_d5", + "mainpll_d3" +}; + +static const char * const dxcc_parents[] = { + "clk26m", + "mainpll_d2_d2", + "mainpll_d2_d4" +}; + +static const char * const usb_parents[] = { + "clk26m", + "univpll_d5_d4", + "univpll_d5_d2" +}; + +static const char * const srck_parents[] = { + "clk32k", + "clk26m", + "ulposc1_d10" +}; + +static const char * const spm_parents[] = { + "clk32k", + "ulposc1_d10", + "clk26m", + "mainpll_d7_d2" +}; + +static const char * const i2c_parents[] = { + "clk26m", + "univpll_d5_d4", + "univpll_d3_d4", + "univpll_d5_d2" +}; + +static const char * const pwm_parents[] = { + "clk26m", + "univpll_d3_d8", + "univpll_d3_d4", + "univpll_d2_d4" +}; + +static const char * const seninf_parents[] = { + "clk26m", + "univpll_d2_d4", + "univpll_d2_d2", + "univpll_d3_d2" +}; + +static const char * const aes_msdcfde_parents[] = { + "clk26m", + "univpll_d3", + "mainpll_d3", + "univpll_d2_d2", + "mainpll_d2_d2", + "mainpll_d2_d4" +}; + +static const char * const pwrap_ulposc_parents[] = { + "clk26m", + "univpll_d5_d4", + "ulposc1_d4", + "ulposc1_d8", + "ulposc1_d10", + "ulposc1_d16", + "ulposc1_d32" +}; + +static const char * const camtm_parents[] = { + "clk26m", + "univpll_d2_d4", + "univpll_d3_d2" +}; + +static const char * const venc_parents[] = { + "clk26m", + "mmpll", + "mainpll_d2_d2", + "mainpll_d2", + "univpll_d3", + "univpll_d2_d2", + "mainpll_d3", + "mmpll" +}; + +static const char * const isp_parents[] = { + "clk26m", + "mainpll_d2", + "mainpll_d2_d2", + "univpll_d3", + "mainpll_d3", + "mmpll", + "univpll_d5", + "univpll_d2_d2", + "mmpll_d2" +}; + +static const char * const dpmaif_parents[] = { + "clk26m", + "univpll_d2_d2", + "mainpll_d3", + "mainpll_d2_d2", + "univpll_d3_d2" +}; + +static const char * const vdec_parents[] = { + "clk26m", + "mainpll_d3", + "mainpll_d2_d2", + "univpll_d5", + "mainpll_d2", + "univpll_d3", + "univpll_d2_d2" +}; + +static const char * const disp_parents[] = { + "clk26m", + "univpll_d3_d2", + "mainpll_d5", + "univpll_d5", + "univpll_d2_d2", + "mainpll_d3", + "univpll_d3", + "mainpll_d2", + "mmpll" +}; + +static const char * const mdp_parents[] = { + "clk26m", + "mainpll_d5", + "univpll_d5", + "mainpll_d2_d2", + "univpll_d2_d2", + "mainpll_d3", + "univpll_d3", + "mainpll_d2", + "mmpll" +}; + +static const char * const audio_h_parents[] = { + "clk26m", + "univpll_d7", + "apll1", + "apll2" +}; + +static const char * const ufs_parents[] = { + "clk26m", + "mainpll_d7", + "univpll_d2_d4", + "mainpll_d2_d4" +}; + +static const char * const aes_fde_parents[] = { + "clk26m", + "univpll_d3", + "mainpll_d2_d2", + "univpll_d5" +}; + +static const char * const audiodsp_parents[] = { + "clk26m", + "ulposc1_d10", + "adsppll", + "adsppll_d2", + "adsppll_d4", + "adsppll_d8" +}; + +static const char * const dvfsrc_parents[] = { + "clk26m", + "ulposc1_d10", +}; + +static const char * const dsi_occ_parents[] = { + "clk26m", + "univpll_d3_d2", + "mpll", + "mainpll_d5" +}; + +static const char * const spmi_mst_parents[] = { + "clk26m", + "univpll_d5_d4", + "ulposc1_d4", + "ulposc1_d8", + "ulposc1_d10", + "ulposc1_d16", + "ulposc1_d32" +}; + +static const char * const spinor_parents[] = { + "clk26m", + "clk13m", + "mainpll_d7_d4", + "univpll_d3_d8", + "univpll_d5_d4", + "mainpll_d7_d2" +}; + +static const char * const nna_parents[] = { + "clk26m", + "univpll_d3_d8", + "mainpll_d2_d4", + "univpll_d3_d2", + "mainpll_d2_d2", + "univpll_d2_d2", + "mainpll_d3", + "univpll_d3", + "mmpll", + "mainpll_d2", + "univpll_d2", + "nnapll_d2", + "nnapll_d4", + "nnapll_d8", + "nnapll", + "nna2pll" +}; + +static const char * const nna2_parents[] = { + "clk26m", + "univpll_d3_d8", + "mainpll_d2_d4", + "univpll_d3_d2", + "mainpll_d2_d2", + "univpll_d2_d2", + "mainpll_d3", + "univpll_d3", + "mmpll", + "mainpll_d2", + "univpll_d2", + "nna2pll_d2", + "nna2pll_d4", + "nna2pll_d8", + "nnapll", + "nna2pll" +}; + +static const char * const ssusb_parents[] = { + "clk26m", + "univpll_d5_d4", + "univpll_d5_d2" +}; + +static const char * const wpe_parents[] = { + "clk26m", + "univpll_d3_d2", + "mainpll_d5", + "univpll_d5", + "univpll_d2_d2", + "mainpll_d3", + "univpll_d3", + "mainpll_d2", + "mmpll" +}; + +static const char * const dpi_parents[] = { + "clk26m", + "tvdpll", + "tvdpll_d2", + "tvdpll_d4", + "tvdpll_d8", + "tvdpll_d16", + "tvdpll_d32" +}; + +static const char * const u3_occ_250m_parents[] = { + "clk26m", + "univpll_d5" +}; + +static const char * const u3_occ_500m_parents[] = { + "clk26m", + "nna2pll_d2" +}; + +static const char * const adsp_bus_parents[] = { + "clk26m", + "ulposc1_d2", + "mainpll_d5", + "mainpll_d2_d2", + "mainpll_d3", + "mainpll_d2", + "univpll_d3" +}; + +static const char * const apll_mck_parents[] = { + "top_aud_1", + "top_aud_2" +}; + +static const struct mtk_mux top_mtk_muxes[] = { + /* + * CLK_CFG_0 + * top_axi is bus clock, should not be closed by Linux. + * top_scp is main clock in always-on co-processor. + */ + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_AXI, "top_axi", axi_parents, + 0x0040, 0x0044, 0x0048, 0, 2, 7, 0x0004, 0, + CLK_IS_CRITICAL), + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SCP, "top_scp", scp_parents, + 0x0040, 0x0044, 0x0048, 8, 3, 15, 0x0004, 1, + CLK_IS_CRITICAL), + MUX_GATE_CLR_SET_UPD(CLK_TOP_MFG, "top_mfg", + mfg_parents, 0x0040, 0x0044, 0x0048, 16, 2, 23, 0x0004, 2), + MUX_GATE_CLR_SET_UPD(CLK_TOP_CAMTG, "top_camtg", + camtg_parents, 0x0040, 0x0044, 0x0048, 24, 3, 31, 0x0004, 3), + /* CLK_CFG_1 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_CAMTG1, "top_camtg1", + camtg_parents, 0x0050, 0x0054, 0x0058, 0, 3, 7, 0x0004, 4), + MUX_GATE_CLR_SET_UPD(CLK_TOP_CAMTG2, "top_camtg2", + camtg_parents, 0x0050, 0x0054, 0x0058, 8, 3, 15, 0x0004, 5), + MUX_GATE_CLR_SET_UPD(CLK_TOP_CAMTG3, "top_camtg3", + camtg_parents, 0x0050, 0x0054, 0x0058, 16, 3, 23, 0x0004, 6), + MUX_GATE_CLR_SET_UPD(CLK_TOP_CAMTG4, "top_camtg4", + camtg_parents, 0x0050, 0x0054, 0x0058, 24, 3, 31, 0x0004, 7), + /* CLK_CFG_2 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_CAMTG5, "top_camtg5", + camtg_parents, 0x0060, 0x0064, 0x0068, 0, 3, 7, 0x0004, 8), + MUX_GATE_CLR_SET_UPD(CLK_TOP_CAMTG6, "top_camtg6", + camtg_parents, 0x0060, 0x0064, 0x0068, 8, 3, 15, 0x0004, 9), + MUX_GATE_CLR_SET_UPD(CLK_TOP_UART, "top_uart", + uart_parents, 0x0060, 0x0064, 0x0068, 16, 1, 23, 0x0004, 10), + MUX_GATE_CLR_SET_UPD(CLK_TOP_SPI, "top_spi", + spi_parents, 0x0060, 0x0064, 0x0068, 24, 3, 31, 0x0004, 11), + /* CLK_CFG_3 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC50_0_HCLK, "top_msdc5hclk", + msdc5hclk_parents, 0x0070, 0x0074, 0x0078, 0, 2, 7, 0x0004, 12), + MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC50_0, "top_msdc50_0", + msdc50_0_parents, 0x0070, 0x0074, 0x0078, 8, 3, 15, 0x0004, 13), + MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC30_1, "top_msdc30_1", + msdc30_1_parents, 0x0070, 0x0074, 0x0078, 16, 3, 23, 0x0004, 14), + MUX_GATE_CLR_SET_UPD(CLK_TOP_AUDIO, "top_audio", + audio_parents, 0x0070, 0x0074, 0x0078, 24, 2, 31, 0x0004, 15), + /* CLK_CFG_4 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_INTBUS, "top_aud_intbus", + aud_intbus_parents, 0x0080, 0x0084, 0x0088, 0, 2, 7, 0x0004, 16), + MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_1, "top_aud_1", + aud_1_parents, 0x0080, 0x0084, 0x0088, 8, 1, 15, 0x0004, 17), + MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_2, "top_aud_2", + aud_2_parents, 0x0080, 0x0084, 0x0088, 16, 1, 23, 0x0004, 18), + MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_ENGEN1, "top_aud_engen1", + aud_engen1_parents, 0x0080, 0x0084, 0x0088, 24, 2, 31, 0x0004, 19), + /* + * CLK_CFG_5 + * top_sspm is main clock in always-on co-processor, should not be closed + * in Linux. + */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_ENGEN2, "top_aud_engen2", + aud_engen2_parents, 0x0090, 0x0094, 0x0098, 0, 2, 7, 0x0004, 20), + MUX_GATE_CLR_SET_UPD(CLK_TOP_DISP_PWM, "top_disp_pwm", + disp_pwm_parents, 0x0090, 0x0094, 0x0098, 8, 3, 15, 0x0004, 21), + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SSPM, "top_sspm", sspm_parents, + 0x0090, 0x0094, 0x0098, 16, 3, 23, 0x0004, 22, + CLK_IS_CRITICAL), + MUX_GATE_CLR_SET_UPD(CLK_TOP_DXCC, "top_dxcc", + dxcc_parents, 0x0090, 0x0094, 0x0098, 24, 2, 31, 0x0004, 23), + /* + * CLK_CFG_6 + * top_spm and top_srck are main clocks in always-on co-processor. + */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_USB_TOP, "top_usb", + usb_parents, 0x00a0, 0x00a4, 0x00a8, 0, 2, 7, 0x0004, 24), + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SRCK, "top_srck", srck_parents, + 0x00a0, 0x00a4, 0x00a8, 8, 2, 15, 0x0004, 25, + CLK_IS_CRITICAL), + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SPM, "top_spm", spm_parents, + 0x00a0, 0x00a4, 0x00a8, 16, 2, 23, 0x0004, 26, + CLK_IS_CRITICAL), + MUX_GATE_CLR_SET_UPD(CLK_TOP_I2C, "top_i2c", + i2c_parents, 0x00a0, 0x00a4, 0x00a8, 24, 2, 31, 0x0004, 27), + /* CLK_CFG_7 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_PWM, "top_pwm", + pwm_parents, 0x00b0, 0x00b4, 0x00b8, 0, 2, 7, 0x0004, 28), + MUX_GATE_CLR_SET_UPD(CLK_TOP_SENINF, "top_seninf", + seninf_parents, 0x00b0, 0x00b4, 0x00b8, 8, 2, 15, 0x0004, 29), + MUX_GATE_CLR_SET_UPD(CLK_TOP_SENINF1, "top_seninf1", + seninf_parents, 0x00b0, 0x00b4, 0x00b8, 16, 2, 23, 0x0004, 30), + MUX_GATE_CLR_SET_UPD(CLK_TOP_SENINF2, "top_seninf2", + seninf_parents, 0x00b0, 0x00b4, 0x00b8, 24, 2, 31, 0x0008, 0), + /* CLK_CFG_8 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_SENINF3, "top_seninf3", + seninf_parents, 0x00c0, 0x00c4, 0x00c8, 0, 2, 7, 0x0008, 1), + MUX_GATE_CLR_SET_UPD(CLK_TOP_AES_MSDCFDE, "top_aes_msdcfde", + aes_msdcfde_parents, 0x00c0, 0x00c4, 0x00c8, 8, 3, 15, 0x0008, 2), + MUX_GATE_CLR_SET_UPD(CLK_TOP_PWRAP_ULPOSC, "top_pwrap_ulposc", + pwrap_ulposc_parents, 0x00c0, 0x00c4, 0x00c8, 16, 3, 23, 0x0008, 3), + MUX_GATE_CLR_SET_UPD(CLK_TOP_CAMTM, "top_camtm", + camtm_parents, 0x00c0, 0x00c4, 0x00c8, 24, 2, 31, 0x0008, 4), + /* CLK_CFG_9 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_VENC, "top_venc", + venc_parents, 0x00d0, 0x00d4, 0x00d8, 0, 3, 7, 0x0008, 5), + MUX_GATE_CLR_SET_UPD(CLK_TOP_CAM, "top_cam", + isp_parents, 0x00d0, 0x00d4, 0x00d8, 8, 4, 15, 0x0008, 6), + MUX_GATE_CLR_SET_UPD(CLK_TOP_IMG1, "top_img1", + isp_parents, 0x00d0, 0x00d4, 0x00d8, 16, 4, 23, 0x0008, 7), + MUX_GATE_CLR_SET_UPD(CLK_TOP_IPE, "top_ipe", + isp_parents, 0x00d0, 0x00d4, 0x00d8, 24, 4, 31, 0x0008, 8), + /* CLK_CFG_10 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_DPMAIF, "top_dpmaif", + dpmaif_parents, 0x00e0, 0x00e4, 0x00e8, 0, 3, 7, 0x0008, 9), + MUX_GATE_CLR_SET_UPD(CLK_TOP_VDEC, "top_vdec", + vdec_parents, 0x00e0, 0x00e4, 0x00e8, 8, 3, 15, 0x0008, 10), + MUX_GATE_CLR_SET_UPD(CLK_TOP_DISP, "top_disp", + disp_parents, 0x00e0, 0x00e4, 0x00e8, 16, 4, 23, 0x0008, 11), + MUX_GATE_CLR_SET_UPD(CLK_TOP_MDP, "top_mdp", + mdp_parents, 0x00e0, 0x00e4, 0x00e8, 24, 4, 31, 0x0008, 12), + /* CLK_CFG_11 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_AUDIO_H, "top_audio_h", + audio_h_parents, 0x00ec, 0x00f0, 0x00f4, 0, 2, 7, 0x0008, 13), + MUX_GATE_CLR_SET_UPD(CLK_TOP_UFS, "top_ufs", + ufs_parents, 0x00ec, 0x00f0, 0x00f4, 8, 2, 15, 0x0008, 14), + MUX_GATE_CLR_SET_UPD(CLK_TOP_AES_FDE, "top_aes_fde", + aes_fde_parents, 0x00ec, 0x00f0, 0x00f4, 16, 2, 23, 0x0008, 15), + MUX_GATE_CLR_SET_UPD(CLK_TOP_AUDIODSP, "top_audiodsp", + audiodsp_parents, 0x00ec, 0x00f0, 0x00f4, 24, 3, 31, 0x0008, 16), + /* + * CLK_CFG_12 + * dvfsrc is for internal DVFS usage, should not be closed in Linux. + */ + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_DVFSRC, "top_dvfsrc", dvfsrc_parents, + 0x0100, 0x0104, 0x0108, 0, 1, 7, 0x0008, 17, + CLK_IS_CRITICAL), + MUX_GATE_CLR_SET_UPD(CLK_TOP_DSI_OCC, "top_dsi_occ", + dsi_occ_parents, 0x0100, 0x0104, 0x0108, 8, 2, 15, 0x0008, 18), + MUX_GATE_CLR_SET_UPD(CLK_TOP_SPMI_MST, "top_spmi_mst", + spmi_mst_parents, 0x0100, 0x0104, 0x0108, 16, 3, 23, 0x0008, 19), + /* CLK_CFG_13 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_SPINOR, "top_spinor", + spinor_parents, 0x0110, 0x0114, 0x0118, 0, 3, 6, 0x0008, 20), + MUX_GATE_CLR_SET_UPD(CLK_TOP_NNA, "top_nna", + nna_parents, 0x0110, 0x0114, 0x0118, 7, 4, 14, 0x0008, 21), + MUX_GATE_CLR_SET_UPD(CLK_TOP_NNA1, "top_nna1", + nna_parents, 0x0110, 0x0114, 0x0118, 15, 4, 22, 0x0008, 22), + MUX_GATE_CLR_SET_UPD(CLK_TOP_NNA2, "top_nna2", + nna2_parents, 0x0110, 0x0114, 0x0118, 23, 4, 30, 0x0008, 23), + /* CLK_CFG_14 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_SSUSB_XHCI, "top_ssusb_xhci", + ssusb_parents, 0x0120, 0x0124, 0x0128, 0, 2, 5, 0x0008, 24), + MUX_GATE_CLR_SET_UPD(CLK_TOP_SSUSB_TOP_1P, "top_ssusb_1p", + ssusb_parents, 0x0120, 0x0124, 0x0128, 6, 2, 11, 0x0008, 25), + MUX_GATE_CLR_SET_UPD(CLK_TOP_SSUSB_XHCI_1P, "top_ssusb_xhci_1p", + ssusb_parents, 0x0120, 0x0124, 0x0128, 12, 2, 17, 0x0008, 26), + MUX_GATE_CLR_SET_UPD(CLK_TOP_WPE, "top_wpe", + wpe_parents, 0x0120, 0x0124, 0x0128, 18, 4, 25, 0x0008, 27), + /* CLK_CFG_15 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_DPI, "top_dpi", + dpi_parents, 0x0180, 0x0184, 0x0188, 0, 3, 6, 0x0008, 28), + MUX_GATE_CLR_SET_UPD(CLK_TOP_U3_OCC_250M, "top_u3_occ_250m", + u3_occ_250m_parents, 0x0180, 0x0184, 0x0188, 7, 1, 11, 0x0008, 29), + MUX_GATE_CLR_SET_UPD(CLK_TOP_U3_OCC_500M, "top_u3_occ_500m", + u3_occ_500m_parents, 0x0180, 0x0184, 0x0188, 12, 1, 16, 0x0008, 30), + MUX_GATE_CLR_SET_UPD(CLK_TOP_ADSP_BUS, "top_adsp_bus", + adsp_bus_parents, 0x0180, 0x0184, 0x0188, 17, 3, 23, 0x0008, 31), +}; + +static struct mtk_composite top_muxes[] = { + /* CLK_AUDDIV_0 */ + MUX(CLK_TOP_APLL_I2S0_MCK_SEL, "apll_i2s0_mck_sel", apll_mck_parents, 0x0320, 16, 1), + MUX(CLK_TOP_APLL_I2S1_MCK_SEL, "apll_i2s1_mck_sel", apll_mck_parents, 0x0320, 17, 1), + MUX(CLK_TOP_APLL_I2S2_MCK_SEL, "apll_i2s2_mck_sel", apll_mck_parents, 0x0320, 18, 1), + MUX(CLK_TOP_APLL_I2S4_MCK_SEL, "apll_i2s4_mck_sel", apll_mck_parents, 0x0320, 19, 1), + MUX(CLK_TOP_APLL_TDMOUT_MCK_SEL, "apll_tdmout_mck_sel", apll_mck_parents, + 0x0320, 20, 1), +}; + +static const struct mtk_composite top_adj_divs[] = { + DIV_GATE(CLK_TOP_APLL12_CK_DIV0, "apll12_div0", "apll_i2s0_mck_sel", + 0x0320, 0, 0x0328, 8, 0), + DIV_GATE(CLK_TOP_APLL12_CK_DIV1, "apll12_div1", "apll_i2s1_mck_sel", + 0x0320, 1, 0x0328, 8, 8), + DIV_GATE(CLK_TOP_APLL12_CK_DIV2, "apll12_div2", "apll_i2s2_mck_sel", + 0x0320, 2, 0x0328, 8, 16), + DIV_GATE(CLK_TOP_APLL12_CK_DIV4, "apll12_div4", "apll_i2s4_mck_sel", + 0x0320, 3, 0x0328, 8, 24), + DIV_GATE(CLK_TOP_APLL12_CK_DIV_TDMOUT_M, "apll12_div_tdmout_m", "apll_tdmout_mck_sel", + 0x0320, 4, 0x0334, 8, 0), +}; + +static const struct of_device_id of_match_clk_mt8186_topck[] = { + { .compatible = "mediatek,mt8186-topckgen", }, + {} +}; + +static int clk_mt8186_topck_probe(struct platform_device *pdev) +{ + struct clk_hw_onecell_data *clk_data; + struct device_node *node = pdev->dev.of_node; + int r; + void __iomem *base; + + clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK); + if (!clk_data) + return -ENOMEM; + + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) { + r = PTR_ERR(base); + goto free_top_data; + } + + r = mtk_clk_register_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks), + clk_data); + if (r) + goto free_top_data; + + r = mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), clk_data); + if (r) + goto unregister_fixed_clks; + + r = mtk_clk_register_muxes(top_mtk_muxes, ARRAY_SIZE(top_mtk_muxes), node, + &mt8186_clk_lock, clk_data); + if (r) + goto unregister_factors; + + r = mtk_clk_register_composites(top_muxes, ARRAY_SIZE(top_muxes), base, + &mt8186_clk_lock, clk_data); + if (r) + goto unregister_muxes; + + r = mtk_clk_register_composites(top_adj_divs, ARRAY_SIZE(top_adj_divs), base, + &mt8186_clk_lock, clk_data); + if (r) + goto unregister_composite_muxes; + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) + goto unregister_composite_divs; + + platform_set_drvdata(pdev, clk_data); + + return r; + +unregister_composite_divs: + mtk_clk_unregister_composites(top_adj_divs, ARRAY_SIZE(top_adj_divs), clk_data); +unregister_composite_muxes: + mtk_clk_unregister_composites(top_muxes, ARRAY_SIZE(top_muxes), clk_data); +unregister_muxes: + mtk_clk_unregister_muxes(top_mtk_muxes, ARRAY_SIZE(top_mtk_muxes), clk_data); +unregister_factors: + mtk_clk_unregister_factors(top_divs, ARRAY_SIZE(top_divs), clk_data); +unregister_fixed_clks: + mtk_clk_unregister_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks), clk_data); +free_top_data: + mtk_free_clk_data(clk_data); + return r; +} + +static int clk_mt8186_topck_remove(struct platform_device *pdev) +{ + struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev); + struct device_node *node = pdev->dev.of_node; + + of_clk_del_provider(node); + mtk_clk_unregister_composites(top_adj_divs, ARRAY_SIZE(top_adj_divs), clk_data); + mtk_clk_unregister_composites(top_muxes, ARRAY_SIZE(top_muxes), clk_data); + mtk_clk_unregister_muxes(top_mtk_muxes, ARRAY_SIZE(top_mtk_muxes), clk_data); + mtk_clk_unregister_factors(top_divs, ARRAY_SIZE(top_divs), clk_data); + mtk_clk_unregister_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks), clk_data); + mtk_free_clk_data(clk_data); + + return 0; +} + +static struct platform_driver clk_mt8186_topck_drv = { + .probe = clk_mt8186_topck_probe, + .remove = clk_mt8186_topck_remove, + .driver = { + .name = "clk-mt8186-topck", + .of_match_table = of_match_clk_mt8186_topck, + }, +}; +builtin_platform_driver(clk_mt8186_topck_drv); diff --git a/drivers/clk/mediatek/clk-mt8186-vdec.c b/drivers/clk/mediatek/clk-mt8186-vdec.c new file mode 100644 index 0000000000000000000000000000000000000000..5ad7e1ae0bacd5df120313503b2426fba5b98f37 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8186-vdec.c @@ -0,0 +1,88 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright (c) 2022 MediaTek Inc. +// Author: Chun-Jie Chen + +#include +#include +#include + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include + +static const struct mtk_gate_regs vdec0_cg_regs = { + .set_ofs = 0x0, + .clr_ofs = 0x4, + .sta_ofs = 0x0, +}; + +static const struct mtk_gate_regs vdec1_cg_regs = { + .set_ofs = 0x190, + .clr_ofs = 0x190, + .sta_ofs = 0x190, +}; + +static const struct mtk_gate_regs vdec2_cg_regs = { + .set_ofs = 0x200, + .clr_ofs = 0x204, + .sta_ofs = 0x200, +}; + +static const struct mtk_gate_regs vdec3_cg_regs = { + .set_ofs = 0x8, + .clr_ofs = 0xc, + .sta_ofs = 0x8, +}; + +#define GATE_VDEC0(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &vdec0_cg_regs, _shift, &mtk_clk_gate_ops_setclr_inv) + +#define GATE_VDEC1(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &vdec1_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr_inv) + +#define GATE_VDEC2(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &vdec2_cg_regs, _shift, &mtk_clk_gate_ops_setclr_inv) + +#define GATE_VDEC3(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &vdec3_cg_regs, _shift, &mtk_clk_gate_ops_setclr_inv) + +static const struct mtk_gate vdec_clks[] = { + /* VDEC0 */ + GATE_VDEC0(CLK_VDEC_CKEN, "vdec_cken", "top_vdec", 0), + GATE_VDEC0(CLK_VDEC_ACTIVE, "vdec_active", "top_vdec", 4), + GATE_VDEC0(CLK_VDEC_CKEN_ENG, "vdec_cken_eng", "top_vdec", 8), + /* VDEC1 */ + GATE_VDEC1(CLK_VDEC_MINI_MDP_CKEN_CFG_RG, "vdec_mini_mdp_cken_cfg_rg", "top_vdec", 0), + /* VDEC2 */ + GATE_VDEC2(CLK_VDEC_LAT_CKEN, "vdec_lat_cken", "top_vdec", 0), + GATE_VDEC2(CLK_VDEC_LAT_ACTIVE, "vdec_lat_active", "top_vdec", 4), + GATE_VDEC2(CLK_VDEC_LAT_CKEN_ENG, "vdec_lat_cken_eng", "top_vdec", 8), + /* VDEC3 */ + GATE_VDEC3(CLK_VDEC_LARB1_CKEN, "vdec_larb1_cken", "top_vdec", 0), +}; + +static const struct mtk_clk_desc vdec_desc = { + .clks = vdec_clks, + .num_clks = ARRAY_SIZE(vdec_clks), +}; + +static const struct of_device_id of_match_clk_mt8186_vdec[] = { + { + .compatible = "mediatek,mt8186-vdecsys", + .data = &vdec_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt8186_vdec_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt8186-vdec", + .of_match_table = of_match_clk_mt8186_vdec, + }, +}; +builtin_platform_driver(clk_mt8186_vdec_drv); diff --git a/drivers/clk/mediatek/clk-mt8186-venc.c b/drivers/clk/mediatek/clk-mt8186-venc.c new file mode 100644 index 0000000000000000000000000000000000000000..f5519f794c4569d8005ff3c28250ac4ff1f76879 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8186-venc.c @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright (c) 2022 MediaTek Inc. +// Author: Chun-Jie Chen + +#include +#include +#include + +#include "clk-gate.h" +#include "clk-mtk.h" + +static const struct mtk_gate_regs venc_cg_regs = { + .set_ofs = 0x4, + .clr_ofs = 0x8, + .sta_ofs = 0x0, +}; + +#define GATE_VENC(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &venc_cg_regs, _shift, &mtk_clk_gate_ops_setclr_inv) + +static const struct mtk_gate venc_clks[] = { + GATE_VENC(CLK_VENC_CKE0_LARB, "venc_cke0_larb", "top_venc", 0), + GATE_VENC(CLK_VENC_CKE1_VENC, "venc_cke1_venc", "top_venc", 4), + GATE_VENC(CLK_VENC_CKE2_JPGENC, "venc_cke2_jpgenc", "top_venc", 8), + GATE_VENC(CLK_VENC_CKE5_GALS, "venc_cke5_gals", "top_venc", 28), +}; + +static const struct mtk_clk_desc venc_desc = { + .clks = venc_clks, + .num_clks = ARRAY_SIZE(venc_clks), +}; + +static const struct of_device_id of_match_clk_mt8186_venc[] = { + { + .compatible = "mediatek,mt8186-vencsys", + .data = &venc_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt8186_venc_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt8186-venc", + .of_match_table = of_match_clk_mt8186_venc, + }, +}; +builtin_platform_driver(clk_mt8186_venc_drv); diff --git a/drivers/clk/mediatek/clk-mt8186-wpe.c b/drivers/clk/mediatek/clk-mt8186-wpe.c new file mode 100644 index 0000000000000000000000000000000000000000..8db3e9178a1ec43d1580429378c2da722ca57dca --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8186-wpe.c @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright (c) 2022 MediaTek Inc. +// Author: Chun-Jie Chen + +#include +#include +#include + +#include "clk-gate.h" +#include "clk-mtk.h" + +static const struct mtk_gate_regs wpe_cg_regs = { + .set_ofs = 0x0, + .clr_ofs = 0x0, + .sta_ofs = 0x0, +}; + +#define GATE_WPE(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &wpe_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr_inv) + +static const struct mtk_gate wpe_clks[] = { + GATE_WPE(CLK_WPE_CK_EN, "wpe", "top_wpe", 17), + GATE_WPE(CLK_WPE_SMI_LARB8_CK_EN, "wpe_smi_larb8", "top_wpe", 19), + GATE_WPE(CLK_WPE_SYS_EVENT_TX_CK_EN, "wpe_sys_event_tx", "top_wpe", 20), + GATE_WPE(CLK_WPE_SMI_LARB8_PCLK_EN, "wpe_smi_larb8_p_en", "top_wpe", 25), +}; + +static const struct mtk_clk_desc wpe_desc = { + .clks = wpe_clks, + .num_clks = ARRAY_SIZE(wpe_clks), +}; + +static const struct of_device_id of_match_clk_mt8186_wpe[] = { + { + .compatible = "mediatek,mt8186-wpesys", + .data = &wpe_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt8186_wpe_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt8186-wpe", + .of_match_table = of_match_clk_mt8186_wpe, + }, +}; +builtin_platform_driver(clk_mt8186_wpe_drv); diff --git a/drivers/clk/mediatek/clk-mt8192-aud.c b/drivers/clk/mediatek/clk-mt8192-aud.c index f28d56628045ec65d9bd4e62b2c9717594d8ffaf..8c989bffd8c726a8816366f38812df280e18331b 100644 --- a/drivers/clk/mediatek/clk-mt8192-aud.c +++ b/drivers/clk/mediatek/clk-mt8192-aud.c @@ -79,7 +79,7 @@ static const struct mtk_gate aud_clks[] = { static int clk_mt8192_aud_probe(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; struct device_node *node = pdev->dev.of_node; int r; @@ -91,7 +91,7 @@ static int clk_mt8192_aud_probe(struct platform_device *pdev) if (r) return r; - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r) return r; diff --git a/drivers/clk/mediatek/clk-mt8192-mm.c b/drivers/clk/mediatek/clk-mt8192-mm.c index 4a0b4c4bc06a6ce90eb641ebb4ec06281c0cd637..1be3ff4d407db0e4035955f2326f6b46d82a09ae 100644 --- a/drivers/clk/mediatek/clk-mt8192-mm.c +++ b/drivers/clk/mediatek/clk-mt8192-mm.c @@ -84,7 +84,7 @@ static int clk_mt8192_mm_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct device_node *node = dev->parent->of_node; - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; int r; clk_data = mtk_alloc_clk_data(CLK_MM_NR_CLK); @@ -95,7 +95,7 @@ static int clk_mt8192_mm_probe(struct platform_device *pdev) if (r) return r; - return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); } static struct platform_driver clk_mt8192_mm_drv = { diff --git a/drivers/clk/mediatek/clk-mt8192.c b/drivers/clk/mediatek/clk-mt8192.c index ab27cd66b866919e319ca0d97c27895b25877620..dda211b7a745dee918df738dc5af024ce1d18f86 100644 --- a/drivers/clk/mediatek/clk-mt8192.c +++ b/drivers/clk/mediatek/clk-mt8192.c @@ -1178,7 +1178,7 @@ static const struct mtk_pll_data plls[] = { 0, 0, 32, 0x0330, 24, 0, 0, 0, 0x0334, 0), }; -static struct clk_onecell_data *top_clk_data; +static struct clk_hw_onecell_data *top_clk_data; static void clk_mt8192_top_init_early(struct device_node *node) { @@ -1189,11 +1189,11 @@ static void clk_mt8192_top_init_early(struct device_node *node) return; for (i = 0; i < CLK_TOP_NR_CLK; i++) - top_clk_data->clks[i] = ERR_PTR(-EPROBE_DEFER); + top_clk_data->hws[i] = ERR_PTR(-EPROBE_DEFER); mtk_clk_register_factors(top_early_divs, ARRAY_SIZE(top_early_divs), top_clk_data); - of_clk_add_provider(node, of_clk_src_onecell_get, top_clk_data); + of_clk_add_hw_provider(node, of_clk_hw_onecell_get, top_clk_data); } CLK_OF_DECLARE_DRIVER(mt8192_topckgen, "mediatek,mt8192-topckgen", @@ -1222,12 +1222,13 @@ static int clk_mt8192_top_probe(struct platform_device *pdev) if (r) return r; - return of_clk_add_provider(node, of_clk_src_onecell_get, top_clk_data); + return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, + top_clk_data); } static int clk_mt8192_infra_probe(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; struct device_node *node = pdev->dev.of_node; int r; @@ -1239,7 +1240,7 @@ static int clk_mt8192_infra_probe(struct platform_device *pdev) if (r) goto free_clk_data; - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r) goto free_clk_data; @@ -1252,7 +1253,7 @@ free_clk_data: static int clk_mt8192_peri_probe(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; struct device_node *node = pdev->dev.of_node; int r; @@ -1264,7 +1265,7 @@ static int clk_mt8192_peri_probe(struct platform_device *pdev) if (r) goto free_clk_data; - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r) goto free_clk_data; @@ -1277,7 +1278,7 @@ free_clk_data: static int clk_mt8192_apmixed_probe(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; struct device_node *node = pdev->dev.of_node; int r; @@ -1290,7 +1291,7 @@ static int clk_mt8192_apmixed_probe(struct platform_device *pdev) if (r) goto free_clk_data; - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r) goto free_clk_data; diff --git a/drivers/clk/mediatek/clk-mt8195-apmixedsys.c b/drivers/clk/mediatek/clk-mt8195-apmixedsys.c index eecc7035a56a7f51572204497ae516122bc765f7..0dfed6ec4d15516830526be86fc44e2a3894e9c5 100644 --- a/drivers/clk/mediatek/clk-mt8195-apmixedsys.c +++ b/drivers/clk/mediatek/clk-mt8195-apmixedsys.c @@ -112,7 +112,7 @@ static const struct of_device_id of_match_clk_mt8195_apmixed[] = { static int clk_mt8195_apmixed_probe(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; struct device_node *node = pdev->dev.of_node; int r; @@ -128,7 +128,7 @@ static int clk_mt8195_apmixed_probe(struct platform_device *pdev) if (r) goto unregister_plls; - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r) goto unregister_gates; @@ -148,7 +148,7 @@ free_apmixed_data: static int clk_mt8195_apmixed_remove(struct platform_device *pdev) { struct device_node *node = pdev->dev.of_node; - struct clk_onecell_data *clk_data = platform_get_drvdata(pdev); + struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev); of_clk_del_provider(node); mtk_clk_unregister_gates(apmixed_clks, ARRAY_SIZE(apmixed_clks), clk_data); diff --git a/drivers/clk/mediatek/clk-mt8195-apusys_pll.c b/drivers/clk/mediatek/clk-mt8195-apusys_pll.c index 8cd88dfc3283f125bb9a101784a37250fdf9f38f..0b52f6a009c4bbb735df8d6a776488463fb7fafe 100644 --- a/drivers/clk/mediatek/clk-mt8195-apusys_pll.c +++ b/drivers/clk/mediatek/clk-mt8195-apusys_pll.c @@ -58,7 +58,7 @@ static const struct mtk_pll_data apusys_plls[] = { static int clk_mt8195_apusys_pll_probe(struct platform_device *pdev) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; struct device_node *node = pdev->dev.of_node; int r; @@ -70,7 +70,7 @@ static int clk_mt8195_apusys_pll_probe(struct platform_device *pdev) if (r) goto free_apusys_pll_data; - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r) goto unregister_plls; @@ -87,7 +87,7 @@ free_apusys_pll_data: static int clk_mt8195_apusys_pll_remove(struct platform_device *pdev) { - struct clk_onecell_data *clk_data = platform_get_drvdata(pdev); + struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev); struct device_node *node = pdev->dev.of_node; of_clk_del_provider(node); diff --git a/drivers/clk/mediatek/clk-mt8195-topckgen.c b/drivers/clk/mediatek/clk-mt8195-topckgen.c index b602fcd7f1d1edb882b9978607d6483b093af21a..ec70e1f65eafb43c19fcb6c2b9cc962557f23d86 100644 --- a/drivers/clk/mediatek/clk-mt8195-topckgen.c +++ b/drivers/clk/mediatek/clk-mt8195-topckgen.c @@ -1224,7 +1224,7 @@ static const struct of_device_id of_match_clk_mt8195_topck[] = { static int clk_mt8195_topck_probe(struct platform_device *pdev) { - struct clk_onecell_data *top_clk_data; + struct clk_hw_onecell_data *top_clk_data; struct device_node *node = pdev->dev.of_node; int r; void __iomem *base; @@ -1267,7 +1267,7 @@ static int clk_mt8195_topck_probe(struct platform_device *pdev) if (r) goto unregister_composite_divs; - r = of_clk_add_provider(node, of_clk_src_onecell_get, top_clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, top_clk_data); if (r) goto unregister_gates; @@ -1294,7 +1294,7 @@ free_top_data: static int clk_mt8195_topck_remove(struct platform_device *pdev) { - struct clk_onecell_data *top_clk_data = platform_get_drvdata(pdev); + struct clk_hw_onecell_data *top_clk_data = platform_get_drvdata(pdev); struct device_node *node = pdev->dev.of_node; of_clk_del_provider(node); diff --git a/drivers/clk/mediatek/clk-mt8195-vdo0.c b/drivers/clk/mediatek/clk-mt8195-vdo0.c index 3bc7ed19d5508f2638227a98c8e87e50d7b01df1..261a7f76dd3cc12954e4ca166b41505a0dd0fb74 100644 --- a/drivers/clk/mediatek/clk-mt8195-vdo0.c +++ b/drivers/clk/mediatek/clk-mt8195-vdo0.c @@ -92,7 +92,7 @@ static int clk_mt8195_vdo0_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct device_node *node = dev->parent->of_node; - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; int r; clk_data = mtk_alloc_clk_data(CLK_VDO0_NR_CLK); @@ -103,7 +103,7 @@ static int clk_mt8195_vdo0_probe(struct platform_device *pdev) if (r) goto free_vdo0_data; - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r) goto unregister_gates; @@ -122,7 +122,7 @@ static int clk_mt8195_vdo0_remove(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct device_node *node = dev->parent->of_node; - struct clk_onecell_data *clk_data = platform_get_drvdata(pdev); + struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev); of_clk_del_provider(node); mtk_clk_unregister_gates(vdo0_clks, ARRAY_SIZE(vdo0_clks), clk_data); diff --git a/drivers/clk/mediatek/clk-mt8195-vdo1.c b/drivers/clk/mediatek/clk-mt8195-vdo1.c index 90c738a85ff1f5c472d3e7660fa36f6488dc413e..3378487d2c904c3454fa670aed46bab6a14dd1ae 100644 --- a/drivers/clk/mediatek/clk-mt8195-vdo1.c +++ b/drivers/clk/mediatek/clk-mt8195-vdo1.c @@ -109,7 +109,7 @@ static int clk_mt8195_vdo1_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct device_node *node = dev->parent->of_node; - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; int r; clk_data = mtk_alloc_clk_data(CLK_VDO1_NR_CLK); @@ -120,7 +120,7 @@ static int clk_mt8195_vdo1_probe(struct platform_device *pdev) if (r) goto free_vdo1_data; - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r) goto unregister_gates; @@ -139,7 +139,7 @@ static int clk_mt8195_vdo1_remove(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct device_node *node = dev->parent->of_node; - struct clk_onecell_data *clk_data = platform_get_drvdata(pdev); + struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev); of_clk_del_provider(node); mtk_clk_unregister_gates(vdo1_clks, ARRAY_SIZE(vdo1_clks), clk_data); diff --git a/drivers/clk/mediatek/clk-mt8516-aud.c b/drivers/clk/mediatek/clk-mt8516-aud.c index 6ab3a06dc9d598062972a8c8c37a2bae727382e9..90f48068a8de7007367d033d41ca1ee1ff6b2bbc 100644 --- a/drivers/clk/mediatek/clk-mt8516-aud.c +++ b/drivers/clk/mediatek/clk-mt8516-aud.c @@ -49,14 +49,14 @@ static const struct mtk_gate aud_clks[] __initconst = { static void __init mtk_audsys_init(struct device_node *node) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; int r; clk_data = mtk_alloc_clk_data(CLK_AUD_NR_CLK); mtk_clk_register_gates(node, aud_clks, ARRAY_SIZE(aud_clks), clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r) pr_err("%s(): could not register clock provider: %d\n", __func__, r); diff --git a/drivers/clk/mediatek/clk-mt8516.c b/drivers/clk/mediatek/clk-mt8516.c index a37143f920cebf89e93634e7ee4d596e6190a94a..b96db88893e23cc844473758d0d928085bf017b6 100644 --- a/drivers/clk/mediatek/clk-mt8516.c +++ b/drivers/clk/mediatek/clk-mt8516.c @@ -677,7 +677,7 @@ static const struct mtk_gate top_clks[] __initconst = { static void __init mtk_topckgen_init(struct device_node *node) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; int r; void __iomem *base; @@ -699,7 +699,7 @@ static void __init mtk_topckgen_init(struct device_node *node) mtk_clk_register_dividers(top_adj_divs, ARRAY_SIZE(top_adj_divs), base, &mt8516_clk_lock, clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r) pr_err("%s(): could not register clock provider: %d\n", __func__, r); @@ -708,7 +708,7 @@ CLK_OF_DECLARE(mtk_topckgen, "mediatek,mt8516-topckgen", mtk_topckgen_init); static void __init mtk_infracfg_init(struct device_node *node) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; int r; void __iomem *base; @@ -723,7 +723,7 @@ static void __init mtk_infracfg_init(struct device_node *node) mtk_clk_register_composites(ifr_muxes, ARRAY_SIZE(ifr_muxes), base, &mt8516_clk_lock, clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r) pr_err("%s(): could not register clock provider: %d\n", __func__, r); @@ -771,23 +771,23 @@ static const struct mtk_pll_div_table mmpll_div_table[] = { }; static const struct mtk_pll_data plls[] = { - PLL(CLK_APMIXED_ARMPLL, "armpll", 0x0100, 0x0110, 0x00000001, 0, + PLL(CLK_APMIXED_ARMPLL, "armpll", 0x0100, 0x0110, 0, 0, 21, 0x0104, 24, 0, 0x0104, 0), - PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x0120, 0x0130, 0x00000001, + PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x0120, 0x0130, 0, HAVE_RST_BAR, 21, 0x0124, 24, 0, 0x0124, 0), - PLL(CLK_APMIXED_UNIVPLL, "univpll", 0x0140, 0x0150, 0x30000001, + PLL(CLK_APMIXED_UNIVPLL, "univpll", 0x0140, 0x0150, 0x30000000, HAVE_RST_BAR, 7, 0x0144, 24, 0, 0x0144, 0), - PLL_B(CLK_APMIXED_MMPLL, "mmpll", 0x0160, 0x0170, 0x00000001, 0, + PLL_B(CLK_APMIXED_MMPLL, "mmpll", 0x0160, 0x0170, 0, 0, 21, 0x0164, 24, 0, 0x0164, 0, mmpll_div_table), - PLL(CLK_APMIXED_APLL1, "apll1", 0x0180, 0x0190, 0x00000001, 0, + PLL(CLK_APMIXED_APLL1, "apll1", 0x0180, 0x0190, 0, 0, 31, 0x0180, 1, 0x0194, 0x0184, 0), - PLL(CLK_APMIXED_APLL2, "apll2", 0x01A0, 0x01B0, 0x00000001, 0, + PLL(CLK_APMIXED_APLL2, "apll2", 0x01A0, 0x01B0, 0, 0, 31, 0x01A0, 1, 0x01B4, 0x01A4, 0), }; static void __init mtk_apmixedsys_init(struct device_node *node) { - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; void __iomem *base; int r; @@ -801,7 +801,7 @@ static void __init mtk_apmixedsys_init(struct device_node *node) mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r) pr_err("%s(): could not register clock provider: %d\n", __func__, r); diff --git a/drivers/clk/mediatek/clk-mtk.c b/drivers/clk/mediatek/clk-mtk.c index b4063261cf56104f8ab504dca431112a02ba6985..b9188000ab3c683d47e60ed156a49646a3c61650 100644 --- a/drivers/clk/mediatek/clk-mtk.c +++ b/drivers/clk/mediatek/clk-mtk.c @@ -18,46 +18,35 @@ #include "clk-mtk.h" #include "clk-gate.h" -struct clk_onecell_data *mtk_alloc_clk_data(unsigned int clk_num) +struct clk_hw_onecell_data *mtk_alloc_clk_data(unsigned int clk_num) { int i; - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; - clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL); + clk_data = kzalloc(struct_size(clk_data, hws, clk_num), GFP_KERNEL); if (!clk_data) return NULL; - clk_data->clks = kcalloc(clk_num, sizeof(*clk_data->clks), GFP_KERNEL); - if (!clk_data->clks) - goto err_out; - - clk_data->clk_num = clk_num; + clk_data->num = clk_num; for (i = 0; i < clk_num; i++) - clk_data->clks[i] = ERR_PTR(-ENOENT); + clk_data->hws[i] = ERR_PTR(-ENOENT); return clk_data; -err_out: - kfree(clk_data); - - return NULL; } EXPORT_SYMBOL_GPL(mtk_alloc_clk_data); -void mtk_free_clk_data(struct clk_onecell_data *clk_data) +void mtk_free_clk_data(struct clk_hw_onecell_data *clk_data) { - if (!clk_data) - return; - - kfree(clk_data->clks); kfree(clk_data); } +EXPORT_SYMBOL_GPL(mtk_free_clk_data); int mtk_clk_register_fixed_clks(const struct mtk_fixed_clk *clks, int num, - struct clk_onecell_data *clk_data) + struct clk_hw_onecell_data *clk_data) { int i; - struct clk *clk; + struct clk_hw *hw; if (!clk_data) return -ENOMEM; @@ -65,20 +54,21 @@ int mtk_clk_register_fixed_clks(const struct mtk_fixed_clk *clks, int num, for (i = 0; i < num; i++) { const struct mtk_fixed_clk *rc = &clks[i]; - if (!IS_ERR_OR_NULL(clk_data->clks[rc->id])) { + if (!IS_ERR_OR_NULL(clk_data->hws[rc->id])) { pr_warn("Trying to register duplicate clock ID: %d\n", rc->id); continue; } - clk = clk_register_fixed_rate(NULL, rc->name, rc->parent, 0, + hw = clk_hw_register_fixed_rate(NULL, rc->name, rc->parent, 0, rc->rate); - if (IS_ERR(clk)) { - pr_err("Failed to register clk %s: %pe\n", rc->name, clk); + if (IS_ERR(hw)) { + pr_err("Failed to register clk %s: %pe\n", rc->name, + hw); goto err; } - clk_data->clks[rc->id] = clk; + clk_data->hws[rc->id] = hw; } return 0; @@ -87,19 +77,19 @@ err: while (--i >= 0) { const struct mtk_fixed_clk *rc = &clks[i]; - if (IS_ERR_OR_NULL(clk_data->clks[rc->id])) + if (IS_ERR_OR_NULL(clk_data->hws[rc->id])) continue; - clk_unregister_fixed_rate(clk_data->clks[rc->id]); - clk_data->clks[rc->id] = ERR_PTR(-ENOENT); + clk_unregister_fixed_rate(clk_data->hws[rc->id]->clk); + clk_data->hws[rc->id] = ERR_PTR(-ENOENT); } - return PTR_ERR(clk); + return PTR_ERR(hw); } EXPORT_SYMBOL_GPL(mtk_clk_register_fixed_clks); void mtk_clk_unregister_fixed_clks(const struct mtk_fixed_clk *clks, int num, - struct clk_onecell_data *clk_data) + struct clk_hw_onecell_data *clk_data) { int i; @@ -109,20 +99,20 @@ void mtk_clk_unregister_fixed_clks(const struct mtk_fixed_clk *clks, int num, for (i = num; i > 0; i--) { const struct mtk_fixed_clk *rc = &clks[i - 1]; - if (IS_ERR_OR_NULL(clk_data->clks[rc->id])) + if (IS_ERR_OR_NULL(clk_data->hws[rc->id])) continue; - clk_unregister_fixed_rate(clk_data->clks[rc->id]); - clk_data->clks[rc->id] = ERR_PTR(-ENOENT); + clk_unregister_fixed_rate(clk_data->hws[rc->id]->clk); + clk_data->hws[rc->id] = ERR_PTR(-ENOENT); } } EXPORT_SYMBOL_GPL(mtk_clk_unregister_fixed_clks); int mtk_clk_register_factors(const struct mtk_fixed_factor *clks, int num, - struct clk_onecell_data *clk_data) + struct clk_hw_onecell_data *clk_data) { int i; - struct clk *clk; + struct clk_hw *hw; if (!clk_data) return -ENOMEM; @@ -130,20 +120,21 @@ int mtk_clk_register_factors(const struct mtk_fixed_factor *clks, int num, for (i = 0; i < num; i++) { const struct mtk_fixed_factor *ff = &clks[i]; - if (!IS_ERR_OR_NULL(clk_data->clks[ff->id])) { + if (!IS_ERR_OR_NULL(clk_data->hws[ff->id])) { pr_warn("Trying to register duplicate clock ID: %d\n", ff->id); continue; } - clk = clk_register_fixed_factor(NULL, ff->name, ff->parent_name, + hw = clk_hw_register_fixed_factor(NULL, ff->name, ff->parent_name, CLK_SET_RATE_PARENT, ff->mult, ff->div); - if (IS_ERR(clk)) { - pr_err("Failed to register clk %s: %pe\n", ff->name, clk); + if (IS_ERR(hw)) { + pr_err("Failed to register clk %s: %pe\n", ff->name, + hw); goto err; } - clk_data->clks[ff->id] = clk; + clk_data->hws[ff->id] = hw; } return 0; @@ -152,19 +143,19 @@ err: while (--i >= 0) { const struct mtk_fixed_factor *ff = &clks[i]; - if (IS_ERR_OR_NULL(clk_data->clks[ff->id])) + if (IS_ERR_OR_NULL(clk_data->hws[ff->id])) continue; - clk_unregister_fixed_factor(clk_data->clks[ff->id]); - clk_data->clks[ff->id] = ERR_PTR(-ENOENT); + clk_unregister_fixed_factor(clk_data->hws[ff->id]->clk); + clk_data->hws[ff->id] = ERR_PTR(-ENOENT); } - return PTR_ERR(clk); + return PTR_ERR(hw); } EXPORT_SYMBOL_GPL(mtk_clk_register_factors); void mtk_clk_unregister_factors(const struct mtk_fixed_factor *clks, int num, - struct clk_onecell_data *clk_data) + struct clk_hw_onecell_data *clk_data) { int i; @@ -174,19 +165,19 @@ void mtk_clk_unregister_factors(const struct mtk_fixed_factor *clks, int num, for (i = num; i > 0; i--) { const struct mtk_fixed_factor *ff = &clks[i - 1]; - if (IS_ERR_OR_NULL(clk_data->clks[ff->id])) + if (IS_ERR_OR_NULL(clk_data->hws[ff->id])) continue; - clk_unregister_fixed_factor(clk_data->clks[ff->id]); - clk_data->clks[ff->id] = ERR_PTR(-ENOENT); + clk_unregister_fixed_factor(clk_data->hws[ff->id]->clk); + clk_data->hws[ff->id] = ERR_PTR(-ENOENT); } } EXPORT_SYMBOL_GPL(mtk_clk_unregister_factors); -struct clk *mtk_clk_register_composite(const struct mtk_composite *mc, +static struct clk_hw *mtk_clk_register_composite(const struct mtk_composite *mc, void __iomem *base, spinlock_t *lock) { - struct clk *clk; + struct clk_hw *hw; struct clk_mux *mux = NULL; struct clk_gate *gate = NULL; struct clk_divider *div = NULL; @@ -250,18 +241,18 @@ struct clk *mtk_clk_register_composite(const struct mtk_composite *mc, div_ops = &clk_divider_ops; } - clk = clk_register_composite(NULL, mc->name, parent_names, num_parents, + hw = clk_hw_register_composite(NULL, mc->name, parent_names, num_parents, mux_hw, mux_ops, div_hw, div_ops, gate_hw, gate_ops, mc->flags); - if (IS_ERR(clk)) { - ret = PTR_ERR(clk); + if (IS_ERR(hw)) { + ret = PTR_ERR(hw); goto err_out; } - return clk; + return hw; err_out: kfree(div); kfree(gate); @@ -270,15 +261,13 @@ err_out: return ERR_PTR(ret); } -static void mtk_clk_unregister_composite(struct clk *clk) +static void mtk_clk_unregister_composite(struct clk_hw *hw) { - struct clk_hw *hw; struct clk_composite *composite; struct clk_mux *mux = NULL; struct clk_gate *gate = NULL; struct clk_divider *div = NULL; - hw = __clk_get_hw(clk); if (!hw) return; @@ -290,7 +279,7 @@ static void mtk_clk_unregister_composite(struct clk *clk) if (composite->rate_hw) div = to_clk_divider(composite->rate_hw); - clk_unregister_composite(clk); + clk_hw_unregister_composite(hw); kfree(div); kfree(gate); kfree(mux); @@ -298,9 +287,9 @@ static void mtk_clk_unregister_composite(struct clk *clk) int mtk_clk_register_composites(const struct mtk_composite *mcs, int num, void __iomem *base, spinlock_t *lock, - struct clk_onecell_data *clk_data) + struct clk_hw_onecell_data *clk_data) { - struct clk *clk; + struct clk_hw *hw; int i; if (!clk_data) @@ -309,20 +298,21 @@ int mtk_clk_register_composites(const struct mtk_composite *mcs, int num, for (i = 0; i < num; i++) { const struct mtk_composite *mc = &mcs[i]; - if (!IS_ERR_OR_NULL(clk_data->clks[mc->id])) { + if (!IS_ERR_OR_NULL(clk_data->hws[mc->id])) { pr_warn("Trying to register duplicate clock ID: %d\n", mc->id); continue; } - clk = mtk_clk_register_composite(mc, base, lock); + hw = mtk_clk_register_composite(mc, base, lock); - if (IS_ERR(clk)) { - pr_err("Failed to register clk %s: %pe\n", mc->name, clk); + if (IS_ERR(hw)) { + pr_err("Failed to register clk %s: %pe\n", mc->name, + hw); goto err; } - clk_data->clks[mc->id] = clk; + clk_data->hws[mc->id] = hw; } return 0; @@ -331,19 +321,19 @@ err: while (--i >= 0) { const struct mtk_composite *mc = &mcs[i]; - if (IS_ERR_OR_NULL(clk_data->clks[mcs->id])) + if (IS_ERR_OR_NULL(clk_data->hws[mcs->id])) continue; - mtk_clk_unregister_composite(clk_data->clks[mc->id]); - clk_data->clks[mc->id] = ERR_PTR(-ENOENT); + mtk_clk_unregister_composite(clk_data->hws[mc->id]); + clk_data->hws[mc->id] = ERR_PTR(-ENOENT); } - return PTR_ERR(clk); + return PTR_ERR(hw); } EXPORT_SYMBOL_GPL(mtk_clk_register_composites); void mtk_clk_unregister_composites(const struct mtk_composite *mcs, int num, - struct clk_onecell_data *clk_data) + struct clk_hw_onecell_data *clk_data) { int i; @@ -353,20 +343,20 @@ void mtk_clk_unregister_composites(const struct mtk_composite *mcs, int num, for (i = num; i > 0; i--) { const struct mtk_composite *mc = &mcs[i - 1]; - if (IS_ERR_OR_NULL(clk_data->clks[mc->id])) + if (IS_ERR_OR_NULL(clk_data->hws[mc->id])) continue; - mtk_clk_unregister_composite(clk_data->clks[mc->id]); - clk_data->clks[mc->id] = ERR_PTR(-ENOENT); + mtk_clk_unregister_composite(clk_data->hws[mc->id]); + clk_data->hws[mc->id] = ERR_PTR(-ENOENT); } } EXPORT_SYMBOL_GPL(mtk_clk_unregister_composites); int mtk_clk_register_dividers(const struct mtk_clk_divider *mcds, int num, void __iomem *base, spinlock_t *lock, - struct clk_onecell_data *clk_data) + struct clk_hw_onecell_data *clk_data) { - struct clk *clk; + struct clk_hw *hw; int i; if (!clk_data) @@ -375,22 +365,23 @@ int mtk_clk_register_dividers(const struct mtk_clk_divider *mcds, int num, for (i = 0; i < num; i++) { const struct mtk_clk_divider *mcd = &mcds[i]; - if (!IS_ERR_OR_NULL(clk_data->clks[mcd->id])) { + if (!IS_ERR_OR_NULL(clk_data->hws[mcd->id])) { pr_warn("Trying to register duplicate clock ID: %d\n", mcd->id); continue; } - clk = clk_register_divider(NULL, mcd->name, mcd->parent_name, + hw = clk_hw_register_divider(NULL, mcd->name, mcd->parent_name, mcd->flags, base + mcd->div_reg, mcd->div_shift, mcd->div_width, mcd->clk_divider_flags, lock); - if (IS_ERR(clk)) { - pr_err("Failed to register clk %s: %pe\n", mcd->name, clk); + if (IS_ERR(hw)) { + pr_err("Failed to register clk %s: %pe\n", mcd->name, + hw); goto err; } - clk_data->clks[mcd->id] = clk; + clk_data->hws[mcd->id] = hw; } return 0; @@ -399,18 +390,18 @@ err: while (--i >= 0) { const struct mtk_clk_divider *mcd = &mcds[i]; - if (IS_ERR_OR_NULL(clk_data->clks[mcd->id])) + if (IS_ERR_OR_NULL(clk_data->hws[mcd->id])) continue; - mtk_clk_unregister_composite(clk_data->clks[mcd->id]); - clk_data->clks[mcd->id] = ERR_PTR(-ENOENT); + mtk_clk_unregister_composite(clk_data->hws[mcd->id]); + clk_data->hws[mcd->id] = ERR_PTR(-ENOENT); } - return PTR_ERR(clk); + return PTR_ERR(hw); } void mtk_clk_unregister_dividers(const struct mtk_clk_divider *mcds, int num, - struct clk_onecell_data *clk_data) + struct clk_hw_onecell_data *clk_data) { int i; @@ -420,18 +411,18 @@ void mtk_clk_unregister_dividers(const struct mtk_clk_divider *mcds, int num, for (i = num; i > 0; i--) { const struct mtk_clk_divider *mcd = &mcds[i - 1]; - if (IS_ERR_OR_NULL(clk_data->clks[mcd->id])) + if (IS_ERR_OR_NULL(clk_data->hws[mcd->id])) continue; - clk_unregister_divider(clk_data->clks[mcd->id]); - clk_data->clks[mcd->id] = ERR_PTR(-ENOENT); + clk_unregister_divider(clk_data->hws[mcd->id]->clk); + clk_data->hws[mcd->id] = ERR_PTR(-ENOENT); } } int mtk_clk_simple_probe(struct platform_device *pdev) { const struct mtk_clk_desc *mcd; - struct clk_onecell_data *clk_data; + struct clk_hw_onecell_data *clk_data; struct device_node *node = pdev->dev.of_node; int r; @@ -447,7 +438,7 @@ int mtk_clk_simple_probe(struct platform_device *pdev) if (r) goto free_data; - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); if (r) goto unregister_clks; @@ -465,7 +456,7 @@ free_data: int mtk_clk_simple_remove(struct platform_device *pdev) { const struct mtk_clk_desc *mcd = of_device_get_match_data(&pdev->dev); - struct clk_onecell_data *clk_data = platform_get_drvdata(pdev); + struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev); struct device_node *node = pdev->dev.of_node; of_clk_del_provider(node); diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h index bf6565aa731961897e69af4e910f71b133d3ce22..adb1304d35d4842fcf021460f75bff5e969271ce 100644 --- a/drivers/clk/mediatek/clk-mtk.h +++ b/drivers/clk/mediatek/clk-mtk.h @@ -35,9 +35,9 @@ struct mtk_fixed_clk { } int mtk_clk_register_fixed_clks(const struct mtk_fixed_clk *clks, int num, - struct clk_onecell_data *clk_data); + struct clk_hw_onecell_data *clk_data); void mtk_clk_unregister_fixed_clks(const struct mtk_fixed_clk *clks, int num, - struct clk_onecell_data *clk_data); + struct clk_hw_onecell_data *clk_data); struct mtk_fixed_factor { int id; @@ -56,9 +56,9 @@ struct mtk_fixed_factor { } int mtk_clk_register_factors(const struct mtk_fixed_factor *clks, int num, - struct clk_onecell_data *clk_data); + struct clk_hw_onecell_data *clk_data); void mtk_clk_unregister_factors(const struct mtk_fixed_factor *clks, int num, - struct clk_onecell_data *clk_data); + struct clk_hw_onecell_data *clk_data); struct mtk_composite { int id; @@ -147,14 +147,11 @@ struct mtk_composite { .flags = 0, \ } -struct clk *mtk_clk_register_composite(const struct mtk_composite *mc, - void __iomem *base, spinlock_t *lock); - int mtk_clk_register_composites(const struct mtk_composite *mcs, int num, void __iomem *base, spinlock_t *lock, - struct clk_onecell_data *clk_data); + struct clk_hw_onecell_data *clk_data); void mtk_clk_unregister_composites(const struct mtk_composite *mcs, int num, - struct clk_onecell_data *clk_data); + struct clk_hw_onecell_data *clk_data); struct mtk_clk_divider { int id; @@ -180,14 +177,14 @@ struct mtk_clk_divider { int mtk_clk_register_dividers(const struct mtk_clk_divider *mcds, int num, void __iomem *base, spinlock_t *lock, - struct clk_onecell_data *clk_data); + struct clk_hw_onecell_data *clk_data); void mtk_clk_unregister_dividers(const struct mtk_clk_divider *mcds, int num, - struct clk_onecell_data *clk_data); + struct clk_hw_onecell_data *clk_data); -struct clk_onecell_data *mtk_alloc_clk_data(unsigned int clk_num); -void mtk_free_clk_data(struct clk_onecell_data *clk_data); +struct clk_hw_onecell_data *mtk_alloc_clk_data(unsigned int clk_num); +void mtk_free_clk_data(struct clk_hw_onecell_data *clk_data); -struct clk *mtk_clk_register_ref2usb_tx(const char *name, +struct clk_hw *mtk_clk_register_ref2usb_tx(const char *name, const char *parent_name, void __iomem *reg); void mtk_register_reset_controller(struct device_node *np, diff --git a/drivers/clk/mediatek/clk-mux.c b/drivers/clk/mediatek/clk-mux.c index 21ad5a4afd65c537453101ee671271bbd4ff0339..cd5f9fd8cb98e14a38b4eb6e2f98886a9ead9b9c 100644 --- a/drivers/clk/mediatek/clk-mux.c +++ b/drivers/clk/mediatek/clk-mux.c @@ -143,13 +143,13 @@ const struct clk_ops mtk_mux_gate_clr_set_upd_ops = { }; EXPORT_SYMBOL_GPL(mtk_mux_gate_clr_set_upd_ops); -static struct clk *mtk_clk_register_mux(const struct mtk_mux *mux, +static struct clk_hw *mtk_clk_register_mux(const struct mtk_mux *mux, struct regmap *regmap, spinlock_t *lock) { struct mtk_clk_mux *clk_mux; struct clk_init_data init = {}; - struct clk *clk; + int ret; clk_mux = kzalloc(sizeof(*clk_mux), GFP_KERNEL); if (!clk_mux) @@ -166,37 +166,34 @@ static struct clk *mtk_clk_register_mux(const struct mtk_mux *mux, clk_mux->lock = lock; clk_mux->hw.init = &init; - clk = clk_register(NULL, &clk_mux->hw); - if (IS_ERR(clk)) { + ret = clk_hw_register(NULL, &clk_mux->hw); + if (ret) { kfree(clk_mux); - return clk; + return ERR_PTR(ret); } - return clk; + return &clk_mux->hw; } -static void mtk_clk_unregister_mux(struct clk *clk) +static void mtk_clk_unregister_mux(struct clk_hw *hw) { struct mtk_clk_mux *mux; - struct clk_hw *hw; - - hw = __clk_get_hw(clk); if (!hw) return; mux = to_mtk_clk_mux(hw); - clk_unregister(clk); + clk_hw_unregister(hw); kfree(mux); } int mtk_clk_register_muxes(const struct mtk_mux *muxes, int num, struct device_node *node, spinlock_t *lock, - struct clk_onecell_data *clk_data) + struct clk_hw_onecell_data *clk_data) { struct regmap *regmap; - struct clk *clk; + struct clk_hw *hw; int i; regmap = device_node_to_regmap(node); @@ -208,20 +205,21 @@ int mtk_clk_register_muxes(const struct mtk_mux *muxes, for (i = 0; i < num; i++) { const struct mtk_mux *mux = &muxes[i]; - if (!IS_ERR_OR_NULL(clk_data->clks[mux->id])) { + if (!IS_ERR_OR_NULL(clk_data->hws[mux->id])) { pr_warn("%pOF: Trying to register duplicate clock ID: %d\n", node, mux->id); continue; } - clk = mtk_clk_register_mux(mux, regmap, lock); + hw = mtk_clk_register_mux(mux, regmap, lock); - if (IS_ERR(clk)) { - pr_err("Failed to register clk %s: %pe\n", mux->name, clk); + if (IS_ERR(hw)) { + pr_err("Failed to register clk %s: %pe\n", mux->name, + hw); goto err; } - clk_data->clks[mux->id] = clk; + clk_data->hws[mux->id] = hw; } return 0; @@ -230,19 +228,19 @@ err: while (--i >= 0) { const struct mtk_mux *mux = &muxes[i]; - if (IS_ERR_OR_NULL(clk_data->clks[mux->id])) + if (IS_ERR_OR_NULL(clk_data->hws[mux->id])) continue; - mtk_clk_unregister_mux(clk_data->clks[mux->id]); - clk_data->clks[mux->id] = ERR_PTR(-ENOENT); + mtk_clk_unregister_mux(clk_data->hws[mux->id]); + clk_data->hws[mux->id] = ERR_PTR(-ENOENT); } - return PTR_ERR(clk); + return PTR_ERR(hw); } EXPORT_SYMBOL_GPL(mtk_clk_register_muxes); void mtk_clk_unregister_muxes(const struct mtk_mux *muxes, int num, - struct clk_onecell_data *clk_data) + struct clk_hw_onecell_data *clk_data) { int i; @@ -252,11 +250,11 @@ void mtk_clk_unregister_muxes(const struct mtk_mux *muxes, int num, for (i = num; i > 0; i--) { const struct mtk_mux *mux = &muxes[i - 1]; - if (IS_ERR_OR_NULL(clk_data->clks[mux->id])) + if (IS_ERR_OR_NULL(clk_data->hws[mux->id])) continue; - mtk_clk_unregister_mux(clk_data->clks[mux->id]); - clk_data->clks[mux->id] = ERR_PTR(-ENOENT); + mtk_clk_unregister_mux(clk_data->hws[mux->id]); + clk_data->hws[mux->id] = ERR_PTR(-ENOENT); } } EXPORT_SYMBOL_GPL(mtk_clk_unregister_muxes); diff --git a/drivers/clk/mediatek/clk-mux.h b/drivers/clk/mediatek/clk-mux.h index 903a3c937959bfdf159f30670c3baebc15489cc4..6539c58f5d7df1f4d200ba3c911f507c613d260e 100644 --- a/drivers/clk/mediatek/clk-mux.h +++ b/drivers/clk/mediatek/clk-mux.h @@ -11,7 +11,7 @@ #include struct clk; -struct clk_onecell_data; +struct clk_hw_onecell_data; struct clk_ops; struct device_node; @@ -84,9 +84,9 @@ extern const struct clk_ops mtk_mux_gate_clr_set_upd_ops; int mtk_clk_register_muxes(const struct mtk_mux *muxes, int num, struct device_node *node, spinlock_t *lock, - struct clk_onecell_data *clk_data); + struct clk_hw_onecell_data *clk_data); void mtk_clk_unregister_muxes(const struct mtk_mux *muxes, int num, - struct clk_onecell_data *clk_data); + struct clk_hw_onecell_data *clk_data); #endif /* __DRV_CLK_MTK_MUX_H */ diff --git a/drivers/clk/mediatek/clk-pll.c b/drivers/clk/mediatek/clk-pll.c index ccaa2085ab4db1f069660c702ca89a245cad7633..54e6cfd29dfc3ffcdea390b5b8ea2a8f49c14885 100644 --- a/drivers/clk/mediatek/clk-pll.c +++ b/drivers/clk/mediatek/clk-pll.c @@ -243,7 +243,6 @@ static int mtk_pll_prepare(struct clk_hw *hw) { struct mtk_clk_pll *pll = to_mtk_clk_pll(hw); u32 r; - u32 div_en_mask; r = readl(pll->pwr_addr) | CON0_PWR_ON; writel(r, pll->pwr_addr); @@ -256,9 +255,8 @@ static int mtk_pll_prepare(struct clk_hw *hw) r = readl(pll->en_addr) | BIT(pll->data->pll_en_bit); writel(r, pll->en_addr); - div_en_mask = pll->data->en_mask & ~CON0_BASE_EN; - if (div_en_mask) { - r = readl(pll->base_addr + REG_CON0) | div_en_mask; + if (pll->data->en_mask) { + r = readl(pll->base_addr + REG_CON0) | pll->data->en_mask; writel(r, pll->base_addr + REG_CON0); } @@ -279,7 +277,6 @@ static void mtk_pll_unprepare(struct clk_hw *hw) { struct mtk_clk_pll *pll = to_mtk_clk_pll(hw); u32 r; - u32 div_en_mask; if (pll->data->flags & HAVE_RST_BAR) { r = readl(pll->base_addr + REG_CON0); @@ -289,9 +286,8 @@ static void mtk_pll_unprepare(struct clk_hw *hw) __mtk_pll_tuner_disable(pll); - div_en_mask = pll->data->en_mask & ~CON0_BASE_EN; - if (div_en_mask) { - r = readl(pll->base_addr + REG_CON0) & ~div_en_mask; + if (pll->data->en_mask) { + r = readl(pll->base_addr + REG_CON0) & ~pll->data->en_mask; writel(r, pll->base_addr + REG_CON0); } @@ -314,12 +310,12 @@ static const struct clk_ops mtk_pll_ops = { .set_rate = mtk_pll_set_rate, }; -static struct clk *mtk_clk_register_pll(const struct mtk_pll_data *data, +static struct clk_hw *mtk_clk_register_pll(const struct mtk_pll_data *data, void __iomem *base) { struct mtk_clk_pll *pll; struct clk_init_data init = {}; - struct clk *clk; + int ret; const char *parent_name = "clk26m"; pll = kzalloc(sizeof(*pll), GFP_KERNEL); @@ -354,36 +350,36 @@ static struct clk *mtk_clk_register_pll(const struct mtk_pll_data *data, init.parent_names = &parent_name; init.num_parents = 1; - clk = clk_register(NULL, &pll->hw); + ret = clk_hw_register(NULL, &pll->hw); - if (IS_ERR(clk)) + if (ret) { kfree(pll); + return ERR_PTR(ret); + } - return clk; + return &pll->hw; } -static void mtk_clk_unregister_pll(struct clk *clk) +static void mtk_clk_unregister_pll(struct clk_hw *hw) { - struct clk_hw *hw; struct mtk_clk_pll *pll; - hw = __clk_get_hw(clk); if (!hw) return; pll = to_mtk_clk_pll(hw); - clk_unregister(clk); + clk_hw_unregister(hw); kfree(pll); } int mtk_clk_register_plls(struct device_node *node, const struct mtk_pll_data *plls, int num_plls, - struct clk_onecell_data *clk_data) + struct clk_hw_onecell_data *clk_data) { void __iomem *base; int i; - struct clk *clk; + struct clk_hw *hw; base = of_iomap(node, 0); if (!base) { @@ -394,20 +390,21 @@ int mtk_clk_register_plls(struct device_node *node, for (i = 0; i < num_plls; i++) { const struct mtk_pll_data *pll = &plls[i]; - if (!IS_ERR_OR_NULL(clk_data->clks[pll->id])) { + if (!IS_ERR_OR_NULL(clk_data->hws[pll->id])) { pr_warn("%pOF: Trying to register duplicate clock ID: %d\n", node, pll->id); continue; } - clk = mtk_clk_register_pll(pll, base); + hw = mtk_clk_register_pll(pll, base); - if (IS_ERR(clk)) { - pr_err("Failed to register clk %s: %pe\n", pll->name, clk); + if (IS_ERR(hw)) { + pr_err("Failed to register clk %s: %pe\n", pll->name, + hw); goto err; } - clk_data->clks[pll->id] = clk; + clk_data->hws[pll->id] = hw; } return 0; @@ -416,27 +413,26 @@ err: while (--i >= 0) { const struct mtk_pll_data *pll = &plls[i]; - mtk_clk_unregister_pll(clk_data->clks[pll->id]); - clk_data->clks[pll->id] = ERR_PTR(-ENOENT); + mtk_clk_unregister_pll(clk_data->hws[pll->id]); + clk_data->hws[pll->id] = ERR_PTR(-ENOENT); } iounmap(base); - return PTR_ERR(clk); + return PTR_ERR(hw); } EXPORT_SYMBOL_GPL(mtk_clk_register_plls); -static __iomem void *mtk_clk_pll_get_base(struct clk *clk, +static __iomem void *mtk_clk_pll_get_base(struct clk_hw *hw, const struct mtk_pll_data *data) { - struct clk_hw *hw = __clk_get_hw(clk); struct mtk_clk_pll *pll = to_mtk_clk_pll(hw); return pll->base_addr - data->reg; } void mtk_clk_unregister_plls(const struct mtk_pll_data *plls, int num_plls, - struct clk_onecell_data *clk_data) + struct clk_hw_onecell_data *clk_data) { __iomem void *base = NULL; int i; @@ -447,7 +443,7 @@ void mtk_clk_unregister_plls(const struct mtk_pll_data *plls, int num_plls, for (i = num_plls; i > 0; i--) { const struct mtk_pll_data *pll = &plls[i - 1]; - if (IS_ERR_OR_NULL(clk_data->clks[pll->id])) + if (IS_ERR_OR_NULL(clk_data->hws[pll->id])) continue; /* @@ -456,10 +452,10 @@ void mtk_clk_unregister_plls(const struct mtk_pll_data *plls, int num_plls, * pointer to the I/O region base address. We have to fetch * it from one of the registered clks. */ - base = mtk_clk_pll_get_base(clk_data->clks[pll->id], pll); + base = mtk_clk_pll_get_base(clk_data->hws[pll->id], pll); - mtk_clk_unregister_pll(clk_data->clks[pll->id]); - clk_data->clks[pll->id] = ERR_PTR(-ENOENT); + mtk_clk_unregister_pll(clk_data->hws[pll->id]); + clk_data->hws[pll->id] = ERR_PTR(-ENOENT); } iounmap(base); diff --git a/drivers/clk/mediatek/clk-pll.h b/drivers/clk/mediatek/clk-pll.h index bf06e44caef93cec1eff406027aa1cdf60eaa0e0..fe319971568864764b6ac4a77d69a3407de1c872 100644 --- a/drivers/clk/mediatek/clk-pll.h +++ b/drivers/clk/mediatek/clk-pll.h @@ -10,7 +10,7 @@ #include struct clk_ops; -struct clk_onecell_data; +struct clk_hw_onecell_data; struct device_node; struct mtk_pll_div_table { @@ -50,8 +50,8 @@ struct mtk_pll_data { int mtk_clk_register_plls(struct device_node *node, const struct mtk_pll_data *plls, int num_plls, - struct clk_onecell_data *clk_data); + struct clk_hw_onecell_data *clk_data); void mtk_clk_unregister_plls(const struct mtk_pll_data *plls, int num_plls, - struct clk_onecell_data *clk_data); + struct clk_hw_onecell_data *clk_data); #endif /* __DRV_CLK_MTK_PLL_H */ diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index d01436be6d7a55958074418808d145b20903f30e..bc4dcf356d8285d9005853aeede82a7c33d9b48e 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -419,6 +419,15 @@ config SC_GCC_8180X Say Y if you want to use peripheral devices such as UART, SPI, I2C, USB, UFS, SDCC, etc. +config SC_GCC_8280XP + tristate "SC8280XP Global Clock Controller" + select QCOM_GDSC + depends on COMMON_CLK_QCOM + help + Support for the global clock controller on SC8280XP devices. + Say Y if you want to use peripheral devices such as UART, SPI, + I2C, USB, UFS, SDCC, etc. + config SC_GPUCC_7180 tristate "SC7180 Graphics Clock Controller" select SC_GCC_7180 @@ -452,6 +461,16 @@ config SC_LPASS_CORECC_7180 Say Y if you want to use LPASS clocks and power domains of the LPASS core clock controller. +config SC_LPASS_CORECC_7280 + tristate "SC7280 LPASS Core & Audio Clock Controller" + select SC_GCC_7280 + select QCOM_GDSC + help + Support for the LPASS(Low Power Audio Subsystem) core and audio clock + controller on SC7280 devices. + Say Y if you want to use LPASS clocks and power domains of the LPASS + core clock controller. + config SC_MSS_7180 tristate "SC7180 Modem Clock Controller" select SC_GCC_7180 diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile index 671cf5821af1cbbf2938fa90278cec95a7a4d584..36789f5233ef088dcfdb9f67a93d6d8d548dcf5e 100644 --- a/drivers/clk/qcom/Makefile +++ b/drivers/clk/qcom/Makefile @@ -67,10 +67,12 @@ obj-$(CONFIG_SC_DISPCC_7280) += dispcc-sc7280.o obj-$(CONFIG_SC_GCC_7180) += gcc-sc7180.o obj-$(CONFIG_SC_GCC_7280) += gcc-sc7280.o obj-$(CONFIG_SC_GCC_8180X) += gcc-sc8180x.o +obj-$(CONFIG_SC_GCC_8280XP) += gcc-sc8280xp.o obj-$(CONFIG_SC_GPUCC_7180) += gpucc-sc7180.o obj-$(CONFIG_SC_GPUCC_7280) += gpucc-sc7280.o obj-$(CONFIG_SC_LPASSCC_7280) += lpasscc-sc7280.o obj-$(CONFIG_SC_LPASS_CORECC_7180) += lpasscorecc-sc7180.o +obj-$(CONFIG_SC_LPASS_CORECC_7280) += lpasscorecc-sc7280.o lpassaudiocc-sc7280.o obj-$(CONFIG_SC_MSS_7180) += mss-sc7180.o obj-$(CONFIG_SC_VIDEOCC_7180) += videocc-sc7180.o obj-$(CONFIG_SC_VIDEOCC_7280) += videocc-sc7280.o diff --git a/drivers/clk/qcom/clk-rcg.h b/drivers/clk/qcom/clk-rcg.h index 00cea508d49ee238cd473e1b6f762a54fd156861..012e745794fde2ee97eaa50c0022b038b4e2b570 100644 --- a/drivers/clk/qcom/clk-rcg.h +++ b/drivers/clk/qcom/clk-rcg.h @@ -140,6 +140,7 @@ extern const struct clk_ops clk_dyn_rcg_ops; * @freq_tbl: frequency table * @clkr: regmap clock handle * @cfg_off: defines the cfg register offset from the CMD_RCGR + CFG_REG + * @parked_cfg: cached value of the CFG register for parked RCGs */ struct clk_rcg2 { u32 cmd_rcgr; @@ -150,6 +151,7 @@ struct clk_rcg2 { const struct freq_tbl *freq_tbl; struct clk_regmap clkr; u8 cfg_off; + u32 parked_cfg; }; #define to_clk_rcg2(_hw) container_of(to_clk_regmap(_hw), struct clk_rcg2, clkr) diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c index e9c357309fd9f75321403d95f11f4e4b58f1a40e..8e5dce09d162e30df2c3cd7c42cb8fac6d5f69de 100644 --- a/drivers/clk/qcom/clk-rcg2.c +++ b/drivers/clk/qcom/clk-rcg2.c @@ -73,16 +73,11 @@ static int clk_rcg2_is_enabled(struct clk_hw *hw) return (cmd & CMD_ROOT_OFF) == 0; } -static u8 clk_rcg2_get_parent(struct clk_hw *hw) +static u8 __clk_rcg2_get_parent(struct clk_hw *hw, u32 cfg) { struct clk_rcg2 *rcg = to_clk_rcg2(hw); int num_parents = clk_hw_get_num_parents(hw); - u32 cfg; - int i, ret; - - ret = regmap_read(rcg->clkr.regmap, RCG_CFG_OFFSET(rcg), &cfg); - if (ret) - goto err; + int i; cfg &= CFG_SRC_SEL_MASK; cfg >>= CFG_SRC_SEL_SHIFT; @@ -91,12 +86,27 @@ static u8 clk_rcg2_get_parent(struct clk_hw *hw) if (cfg == rcg->parent_map[i].cfg) return i; -err: pr_debug("%s: Clock %s has invalid parent, using default.\n", __func__, clk_hw_get_name(hw)); return 0; } +static u8 clk_rcg2_get_parent(struct clk_hw *hw) +{ + struct clk_rcg2 *rcg = to_clk_rcg2(hw); + u32 cfg; + int ret; + + ret = regmap_read(rcg->clkr.regmap, RCG_CFG_OFFSET(rcg), &cfg); + if (ret) { + pr_debug("%s: Unable to read CFG register for %s\n", + __func__, clk_hw_get_name(hw)); + return 0; + } + + return __clk_rcg2_get_parent(hw, cfg); +} + static int update_config(struct clk_rcg2 *rcg) { int count, ret; @@ -163,12 +173,10 @@ calc_rate(unsigned long rate, u32 m, u32 n, u32 mode, u32 hid_div) } static unsigned long -clk_rcg2_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) +__clk_rcg2_recalc_rate(struct clk_hw *hw, unsigned long parent_rate, u32 cfg) { struct clk_rcg2 *rcg = to_clk_rcg2(hw); - u32 cfg, hid_div, m = 0, n = 0, mode = 0, mask; - - regmap_read(rcg->clkr.regmap, RCG_CFG_OFFSET(rcg), &cfg); + u32 hid_div, m = 0, n = 0, mode = 0, mask; if (rcg->mnd_width) { mask = BIT(rcg->mnd_width) - 1; @@ -189,6 +197,17 @@ clk_rcg2_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) return calc_rate(parent_rate, m, n, mode, hid_div); } +static unsigned long +clk_rcg2_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) +{ + struct clk_rcg2 *rcg = to_clk_rcg2(hw); + u32 cfg; + + regmap_read(rcg->clkr.regmap, RCG_CFG_OFFSET(rcg), &cfg); + + return __clk_rcg2_recalc_rate(hw, parent_rate, cfg); +} + static int _freq_tbl_determine_rate(struct clk_hw *hw, const struct freq_tbl *f, struct clk_rate_request *req, enum freq_policy policy) @@ -262,7 +281,8 @@ static int clk_rcg2_determine_floor_rate(struct clk_hw *hw, return _freq_tbl_determine_rate(hw, rcg->freq_tbl, req, FLOOR); } -static int __clk_rcg2_configure(struct clk_rcg2 *rcg, const struct freq_tbl *f) +static int __clk_rcg2_configure(struct clk_rcg2 *rcg, const struct freq_tbl *f, + u32 *_cfg) { u32 cfg, mask, d_val, not2d_val, n_minus_m; struct clk_hw *hw = &rcg->clkr.hw; @@ -304,15 +324,27 @@ static int __clk_rcg2_configure(struct clk_rcg2 *rcg, const struct freq_tbl *f) cfg |= rcg->parent_map[index].cfg << CFG_SRC_SEL_SHIFT; if (rcg->mnd_width && f->n && (f->m != f->n)) cfg |= CFG_MODE_DUAL_EDGE; - return regmap_update_bits(rcg->clkr.regmap, RCG_CFG_OFFSET(rcg), - mask, cfg); + + *_cfg &= ~mask; + *_cfg |= cfg; + + return 0; } static int clk_rcg2_configure(struct clk_rcg2 *rcg, const struct freq_tbl *f) { + u32 cfg; int ret; - ret = __clk_rcg2_configure(rcg, f); + ret = regmap_read(rcg->clkr.regmap, RCG_CFG_OFFSET(rcg), &cfg); + if (ret) + return ret; + + ret = __clk_rcg2_configure(rcg, f, &cfg); + if (ret) + return ret; + + ret = regmap_write(rcg->clkr.regmap, RCG_CFG_OFFSET(rcg), cfg); if (ret) return ret; @@ -979,11 +1011,12 @@ static int clk_rcg2_shared_set_rate(struct clk_hw *hw, unsigned long rate, return -EINVAL; /* - * In case clock is disabled, update the CFG, M, N and D registers - * and don't hit the update bit of CMD register. + * In case clock is disabled, update the M, N and D registers, cache + * the CFG value in parked_cfg and don't hit the update bit of CMD + * register. */ - if (!__clk_is_enabled(hw->clk)) - return __clk_rcg2_configure(rcg, f); + if (!clk_hw_is_enabled(hw)) + return __clk_rcg2_configure(rcg, f, &rcg->parked_cfg); return clk_rcg2_shared_force_enable_clear(hw, f); } @@ -1007,6 +1040,11 @@ static int clk_rcg2_shared_enable(struct clk_hw *hw) if (ret) return ret; + /* Write back the stored configuration corresponding to current rate */ + ret = regmap_write(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG, rcg->parked_cfg); + if (ret) + return ret; + ret = update_config(rcg); if (ret) return ret; @@ -1017,13 +1055,12 @@ static int clk_rcg2_shared_enable(struct clk_hw *hw) static void clk_rcg2_shared_disable(struct clk_hw *hw) { struct clk_rcg2 *rcg = to_clk_rcg2(hw); - u32 cfg; /* * Store current configuration as switching to safe source would clear * the SRC and DIV of CFG register */ - regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG, &cfg); + regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG, &rcg->parked_cfg); /* * Park the RCG at a safe configuration - sourced off of safe source. @@ -1041,17 +1078,52 @@ static void clk_rcg2_shared_disable(struct clk_hw *hw) update_config(rcg); clk_rcg2_clear_force_enable(hw); +} - /* Write back the stored configuration corresponding to current rate */ - regmap_write(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG, cfg); +static u8 clk_rcg2_shared_get_parent(struct clk_hw *hw) +{ + struct clk_rcg2 *rcg = to_clk_rcg2(hw); + + /* If the shared rcg is parked use the cached cfg instead */ + if (!clk_hw_is_enabled(hw)) + return __clk_rcg2_get_parent(hw, rcg->parked_cfg); + + return clk_rcg2_get_parent(hw); +} + +static int clk_rcg2_shared_set_parent(struct clk_hw *hw, u8 index) +{ + struct clk_rcg2 *rcg = to_clk_rcg2(hw); + + /* If the shared rcg is parked only update the cached cfg */ + if (!clk_hw_is_enabled(hw)) { + rcg->parked_cfg &= ~CFG_SRC_SEL_MASK; + rcg->parked_cfg |= rcg->parent_map[index].cfg << CFG_SRC_SEL_SHIFT; + + return 0; + } + + return clk_rcg2_set_parent(hw, index); +} + +static unsigned long +clk_rcg2_shared_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) +{ + struct clk_rcg2 *rcg = to_clk_rcg2(hw); + + /* If the shared rcg is parked use the cached cfg instead */ + if (!clk_hw_is_enabled(hw)) + return __clk_rcg2_recalc_rate(hw, parent_rate, rcg->parked_cfg); + + return clk_rcg2_recalc_rate(hw, parent_rate); } const struct clk_ops clk_rcg2_shared_ops = { .enable = clk_rcg2_shared_enable, .disable = clk_rcg2_shared_disable, - .get_parent = clk_rcg2_get_parent, - .set_parent = clk_rcg2_set_parent, - .recalc_rate = clk_rcg2_recalc_rate, + .get_parent = clk_rcg2_shared_get_parent, + .set_parent = clk_rcg2_shared_set_parent, + .recalc_rate = clk_rcg2_shared_recalc_rate, .determine_rate = clk_rcg2_determine_rate, .set_rate = clk_rcg2_shared_set_rate, .set_rate_and_parent = clk_rcg2_shared_set_rate_and_parent, diff --git a/drivers/clk/qcom/clk-smd-rpm.c b/drivers/clk/qcom/clk-smd-rpm.c index afc6dc9300111326257a94e15826f4a09715ecef..10b4e6d8d10f30e06b01db7328bd4d925c05f5b2 100644 --- a/drivers/clk/qcom/clk-smd-rpm.c +++ b/drivers/clk/qcom/clk-smd-rpm.c @@ -563,17 +563,19 @@ static const struct rpm_smd_clk_desc rpm_clk_msm8974 = { .num_clks = ARRAY_SIZE(msm8974_clks), }; -DEFINE_CLK_SMD_RPM(msm8976, mmssnoc_ahb_clk, mmssnoc_ahb_a_clk, - QCOM_SMD_RPM_BUS_CLK, 2); DEFINE_CLK_SMD_RPM(msm8976, ipa_clk, ipa_a_clk, QCOM_SMD_RPM_IPA_CLK, 0); static struct clk_smd_rpm *msm8976_clks[] = { + [RPM_SMD_XO_CLK_SRC] = &sdm660_bi_tcxo, + [RPM_SMD_XO_A_CLK_SRC] = &sdm660_bi_tcxo_a, [RPM_SMD_PCNOC_CLK] = &msm8916_pcnoc_clk, [RPM_SMD_PCNOC_A_CLK] = &msm8916_pcnoc_a_clk, [RPM_SMD_SNOC_CLK] = &msm8916_snoc_clk, [RPM_SMD_SNOC_A_CLK] = &msm8916_snoc_a_clk, [RPM_SMD_BIMC_CLK] = &msm8916_bimc_clk, [RPM_SMD_BIMC_A_CLK] = &msm8916_bimc_a_clk, + [RPM_SMD_SYSMMNOC_CLK] = &msm8936_sysmmnoc_clk, + [RPM_SMD_SYSMMNOC_A_CLK] = &msm8936_sysmmnoc_a_clk, [RPM_SMD_QDSS_CLK] = &msm8916_qdss_clk, [RPM_SMD_QDSS_A_CLK] = &msm8916_qdss_a_clk, [RPM_SMD_BB_CLK1] = &msm8916_bb_clk1, @@ -586,8 +588,6 @@ static struct clk_smd_rpm *msm8976_clks[] = { [RPM_SMD_BB_CLK1_A_PIN] = &msm8916_bb_clk1_a_pin, [RPM_SMD_BB_CLK2_PIN] = &msm8916_bb_clk2_pin, [RPM_SMD_BB_CLK2_A_PIN] = &msm8916_bb_clk2_a_pin, - [RPM_SMD_MMSSNOC_AHB_CLK] = &msm8976_mmssnoc_ahb_clk, - [RPM_SMD_MMSSNOC_AHB_A_CLK] = &msm8976_mmssnoc_ahb_a_clk, [RPM_SMD_DIV_CLK2] = &msm8974_div_clk2, [RPM_SMD_DIV_A_CLK2] = &msm8974_div_a_clk2, [RPM_SMD_IPA_CLK] = &msm8976_ipa_clk, diff --git a/drivers/clk/qcom/gcc-msm8976.c b/drivers/clk/qcom/gcc-msm8976.c index a8b15814933ec95461a7385047ae63f60f53f330..6b112984694c752b9bc00825e9d859db100c8760 100644 --- a/drivers/clk/qcom/gcc-msm8976.c +++ b/drivers/clk/qcom/gcc-msm8976.c @@ -1486,7 +1486,7 @@ static const struct clk_init_data sdcc1_apps_clk_src_8976v1_1_init = { .name = "sdcc1_apps_clk_src", .parent_data = gcc_parent_data_v1_1, .num_parents = ARRAY_SIZE(gcc_parent_data_v1_1), - .ops = &clk_rcg2_ops, + .ops = &clk_rcg2_floor_ops, }; static struct clk_rcg2 sdcc1_apps_clk_src = { @@ -1499,7 +1499,7 @@ static struct clk_rcg2 sdcc1_apps_clk_src = { .name = "sdcc1_apps_clk_src", .parent_data = gcc_parent_data_1, .num_parents = ARRAY_SIZE(gcc_parent_data_1), - .ops = &clk_rcg2_ops, + .ops = &clk_rcg2_floor_ops, }, }; @@ -1547,7 +1547,7 @@ static struct clk_rcg2 sdcc2_apps_clk_src = { .name = "sdcc2_apps_clk_src", .parent_data = gcc_parent_data_4_8, .num_parents = ARRAY_SIZE(gcc_parent_data_4_8), - .ops = &clk_rcg2_ops, + .ops = &clk_rcg2_floor_ops, }, }; @@ -4056,6 +4056,7 @@ static const struct qcom_reset_map gcc_msm8976_resets[] = { [RST_CAMSS_CSI_VFE1_BCR] = { 0x58070 }, [RST_CAMSS_VFE1_BCR] = { 0x5807c }, [RST_CAMSS_CPP_BCR] = { 0x58080 }, + [RST_MSS_BCR] = { 0x71000 }, }; static struct gdsc *gcc_msm8976_gdscs[] = { diff --git a/drivers/clk/qcom/gcc-msm8998.c b/drivers/clk/qcom/gcc-msm8998.c index 1310c23c5008398a57defea8de72ba1a200d5c1c..8b4e4a31d0e1ec2f1d5840e2a3d9caa00b50c638 100644 --- a/drivers/clk/qcom/gcc-msm8998.c +++ b/drivers/clk/qcom/gcc-msm8998.c @@ -2833,6 +2833,58 @@ static struct clk_branch gcc_rx1_usb2_clkref_clk = { }, }; +static struct clk_branch gcc_im_sleep_clk = { + .halt_reg = 0x4300c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x4300c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data){ + .name = "gcc_im_sleep_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch aggre2_snoc_north_axi_clk = { + .halt_reg = 0x83010, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x83010, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data){ + .name = "aggre2_snoc_north_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch ssc_xo_clk = { + .halt_reg = 0x63018, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x63018, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data){ + .name = "ssc_xo_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch ssc_cnoc_ahbs_clk = { + .halt_reg = 0x6300c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x6300c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data){ + .name = "ssc_cnoc_ahbs_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + static struct gdsc pcie_0_gdsc = { .gdscr = 0x6b004, .gds_hw_ctrl = 0x0, @@ -3036,6 +3088,10 @@ static struct clk_regmap *gcc_msm8998_clocks[] = { [GCC_MSS_MNOC_BIMC_AXI_CLK] = &gcc_mss_mnoc_bimc_axi_clk.clkr, [GCC_MMSS_GPLL0_CLK] = &gcc_mmss_gpll0_clk.clkr, [HMSS_GPLL0_CLK_SRC] = &hmss_gpll0_clk_src.clkr, + [GCC_IM_SLEEP] = &gcc_im_sleep_clk.clkr, + [AGGRE2_SNOC_NORTH_AXI] = &aggre2_snoc_north_axi_clk.clkr, + [SSC_XO] = &ssc_xo_clk.clkr, + [SSC_CNOC_AHBS_CLK] = &ssc_cnoc_ahbs_clk.clkr, }; static struct gdsc *gcc_msm8998_gdscs[] = { diff --git a/drivers/clk/qcom/gcc-sc8280xp.c b/drivers/clk/qcom/gcc-sc8280xp.c new file mode 100644 index 0000000000000000000000000000000000000000..4b894442fdf5c39f15d19841d9927ae51f81a2fa --- /dev/null +++ b/drivers/clk/qcom/gcc-sc8280xp.c @@ -0,0 +1,7488 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2022, Linaro Ltd. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "clk-alpha-pll.h" +#include "clk-branch.h" +#include "clk-rcg.h" +#include "clk-regmap.h" +#include "clk-regmap-divider.h" +#include "clk-regmap-mux.h" +#include "common.h" +#include "gdsc.h" +#include "reset.h" + +/* Need to match the order of clocks in DT binding */ +enum { + DT_BI_TCXO, + DT_SLEEP_CLK, + DT_UFS_PHY_RX_SYMBOL_0_CLK, + DT_UFS_PHY_RX_SYMBOL_1_CLK, + DT_UFS_PHY_TX_SYMBOL_0_CLK, + DT_UFS_CARD_RX_SYMBOL_0_CLK, + DT_UFS_CARD_RX_SYMBOL_1_CLK, + DT_UFS_CARD_TX_SYMBOL_0_CLK, + DT_USB3_PHY_WRAPPER_GCC_USB30_PIPE_CLK, + DT_GCC_USB4_PHY_PIPEGMUX_CLK_SRC, + DT_GCC_USB4_PHY_DP_GMUX_CLK_SRC, + DT_GCC_USB4_PHY_SYS_PIPEGMUX_CLK_SRC, + DT_USB4_PHY_GCC_USB4_PCIE_PIPE_CLK, + DT_USB4_PHY_GCC_USB4RTR_MAX_PIPE_CLK, + DT_QUSB4PHY_GCC_USB4_RX0_CLK, + DT_QUSB4PHY_GCC_USB4_RX1_CLK, + DT_USB3_UNI_PHY_SEC_GCC_USB30_PIPE_CLK, + DT_GCC_USB4_1_PHY_PIPEGMUX_CLK_SRC, + DT_GCC_USB4_1_PHY_DP_GMUX_CLK_SRC, + DT_GCC_USB4_1_PHY_SYS_PIPEGMUX_CLK_SRC, + DT_USB4_1_PHY_GCC_USB4_PCIE_PIPE_CLK, + DT_USB4_1_PHY_GCC_USB4RTR_MAX_PIPE_CLK, + DT_QUSB4PHY_1_GCC_USB4_RX0_CLK, + DT_QUSB4PHY_1_GCC_USB4_RX1_CLK, + DT_USB3_UNI_PHY_MP_GCC_USB30_PIPE_0_CLK, + DT_USB3_UNI_PHY_MP_GCC_USB30_PIPE_1_CLK, + DT_PCIE_2A_PIPE_CLK, + DT_PCIE_2B_PIPE_CLK, + DT_PCIE_3A_PIPE_CLK, + DT_PCIE_3B_PIPE_CLK, + DT_PCIE_4_PIPE_CLK, + DT_RXC0_REF_CLK, + DT_RXC1_REF_CLK, +}; + +enum { + P_BI_TCXO, + P_GCC_GPLL0_OUT_EVEN, + P_GCC_GPLL0_OUT_MAIN, + P_GCC_GPLL2_OUT_MAIN, + P_GCC_GPLL4_OUT_MAIN, + P_GCC_GPLL7_OUT_MAIN, + P_GCC_GPLL8_OUT_MAIN, + P_GCC_GPLL9_OUT_MAIN, + P_GCC_USB3_PRIM_PHY_PIPE_CLK_SRC, + P_GCC_USB3_SEC_PHY_PIPE_CLK_SRC, + P_GCC_USB4_1_PHY_DP_GMUX_CLK_SRC, + P_GCC_USB4_1_PHY_PCIE_PIPE_CLK_SRC, + P_GCC_USB4_1_PHY_PCIE_PIPEGMUX_CLK_SRC, + P_GCC_USB4_1_PHY_PIPEGMUX_CLK_SRC, + P_GCC_USB4_1_PHY_SYS_PIPEGMUX_CLK_SRC, + P_GCC_USB4_PHY_DP_GMUX_CLK_SRC, + P_GCC_USB4_PHY_PCIE_PIPE_CLK_SRC, + P_GCC_USB4_PHY_PCIE_PIPEGMUX_CLK_SRC, + P_GCC_USB4_PHY_PIPEGMUX_CLK_SRC, + P_GCC_USB4_PHY_SYS_PIPEGMUX_CLK_SRC, + P_PCIE_2A_PIPE_CLK, + P_PCIE_2B_PIPE_CLK, + P_PCIE_3A_PIPE_CLK, + P_PCIE_3B_PIPE_CLK, + P_PCIE_4_PIPE_CLK, + P_QUSB4PHY_1_GCC_USB4_RX0_CLK, + P_QUSB4PHY_1_GCC_USB4_RX1_CLK, + P_QUSB4PHY_GCC_USB4_RX0_CLK, + P_QUSB4PHY_GCC_USB4_RX1_CLK, + P_RXC0_REF_CLK, + P_RXC1_REF_CLK, + P_SLEEP_CLK, + P_UFS_CARD_RX_SYMBOL_0_CLK, + P_UFS_CARD_RX_SYMBOL_1_CLK, + P_UFS_CARD_TX_SYMBOL_0_CLK, + P_UFS_PHY_RX_SYMBOL_0_CLK, + P_UFS_PHY_RX_SYMBOL_1_CLK, + P_UFS_PHY_TX_SYMBOL_0_CLK, + P_USB3_PHY_WRAPPER_GCC_USB30_PIPE_CLK, + P_USB3_UNI_PHY_MP_GCC_USB30_PIPE_0_CLK, + P_USB3_UNI_PHY_MP_GCC_USB30_PIPE_1_CLK, + P_USB3_UNI_PHY_SEC_GCC_USB30_PIPE_CLK, + P_USB4_1_PHY_GCC_USB4_PCIE_PIPE_CLK, + P_USB4_1_PHY_GCC_USB4RTR_MAX_PIPE_CLK, + P_USB4_PHY_GCC_USB4_PCIE_PIPE_CLK, + P_USB4_PHY_GCC_USB4RTR_MAX_PIPE_CLK, +}; + +static const struct clk_parent_data gcc_parent_data_tcxo = { .index = DT_BI_TCXO }; + +static struct clk_alpha_pll gcc_gpll0 = { + .offset = 0x0, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID], + .clkr = { + .enable_reg = 0x52028, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_gpll0", + .parent_data = &gcc_parent_data_tcxo, + .num_parents = 1, + .ops = &clk_alpha_pll_fixed_lucid_5lpe_ops, + }, + }, +}; + +static const struct clk_div_table post_div_table_gcc_gpll0_out_even[] = { + { 0x1, 2 }, + { } +}; + +static struct clk_alpha_pll_postdiv gcc_gpll0_out_even = { + .offset = 0x0, + .post_div_shift = 8, + .post_div_table = post_div_table_gcc_gpll0_out_even, + .num_post_div = ARRAY_SIZE(post_div_table_gcc_gpll0_out_even), + .width = 4, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID], + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_gpll0_out_even", + .parent_hws = (const struct clk_hw*[]){ + &gcc_gpll0.clkr.hw, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_postdiv_lucid_5lpe_ops, + }, +}; + +static struct clk_alpha_pll gcc_gpll2 = { + .offset = 0x2000, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID], + .clkr = { + .enable_reg = 0x52028, + .enable_mask = BIT(2), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_gpll2", + .parent_data = &gcc_parent_data_tcxo, + .num_parents = 1, + .ops = &clk_alpha_pll_fixed_lucid_5lpe_ops, + }, + }, +}; + +static struct clk_alpha_pll gcc_gpll4 = { + .offset = 0x76000, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID], + .clkr = { + .enable_reg = 0x52028, + .enable_mask = BIT(4), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_gpll4", + .parent_data = &gcc_parent_data_tcxo, + .num_parents = 1, + .ops = &clk_alpha_pll_fixed_lucid_5lpe_ops, + }, + }, +}; + +static struct clk_alpha_pll gcc_gpll7 = { + .offset = 0x1a000, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID], + .clkr = { + .enable_reg = 0x52028, + .enable_mask = BIT(7), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_gpll7", + .parent_data = &gcc_parent_data_tcxo, + .num_parents = 1, + .ops = &clk_alpha_pll_fixed_lucid_5lpe_ops, + }, + }, +}; + +static struct clk_alpha_pll gcc_gpll8 = { + .offset = 0x1b000, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID], + .clkr = { + .enable_reg = 0x52028, + .enable_mask = BIT(8), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_gpll8", + .parent_data = &gcc_parent_data_tcxo, + .num_parents = 1, + .ops = &clk_alpha_pll_fixed_lucid_5lpe_ops, + }, + }, +}; + +static struct clk_alpha_pll gcc_gpll9 = { + .offset = 0x1c000, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID], + .clkr = { + .enable_reg = 0x52028, + .enable_mask = BIT(9), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_gpll9", + .parent_data = &gcc_parent_data_tcxo, + .num_parents = 1, + .ops = &clk_alpha_pll_fixed_lucid_5lpe_ops, + }, + }, +}; + +static struct clk_rcg2 gcc_usb4_1_phy_pcie_pipe_clk_src; +static struct clk_rcg2 gcc_usb4_phy_pcie_pipe_clk_src; + +static const struct parent_map gcc_parent_map_0[] = { + { P_BI_TCXO, 0 }, + { P_GCC_GPLL0_OUT_MAIN, 1 }, + { P_GCC_GPLL0_OUT_EVEN, 6 }, +}; + +static const struct clk_parent_data gcc_parent_data_0[] = { + { .index = DT_BI_TCXO }, + { .hw = &gcc_gpll0.clkr.hw }, + { .hw = &gcc_gpll0_out_even.clkr.hw }, +}; + +static const struct parent_map gcc_parent_map_1[] = { + { P_BI_TCXO, 0 }, + { P_SLEEP_CLK, 5 }, +}; + +static const struct clk_parent_data gcc_parent_data_1[] = { + { .index = DT_BI_TCXO }, + { .index = DT_SLEEP_CLK }, +}; + +static const struct parent_map gcc_parent_map_2[] = { + { P_BI_TCXO, 0 }, + { P_GCC_GPLL0_OUT_MAIN, 1 }, + { P_SLEEP_CLK, 5 }, + { P_GCC_GPLL0_OUT_EVEN, 6 }, +}; + +static const struct clk_parent_data gcc_parent_data_2[] = { + { .index = DT_BI_TCXO }, + { .hw = &gcc_gpll0.clkr.hw }, + { .index = DT_SLEEP_CLK }, + { .hw = &gcc_gpll0_out_even.clkr.hw }, +}; + +static const struct parent_map gcc_parent_map_3[] = { + { P_BI_TCXO, 0 }, +}; + +static const struct clk_parent_data gcc_parent_data_3[] = { + { .index = DT_BI_TCXO }, +}; + +static const struct parent_map gcc_parent_map_4[] = { + { P_BI_TCXO, 0 }, + { P_GCC_GPLL7_OUT_MAIN, 2 }, + { P_GCC_GPLL4_OUT_MAIN, 5 }, + { P_GCC_GPLL0_OUT_EVEN, 6 }, +}; + +static const struct clk_parent_data gcc_parent_data_4[] = { + { .index = DT_BI_TCXO }, + { .hw = &gcc_gpll7.clkr.hw }, + { .hw = &gcc_gpll4.clkr.hw }, + { .hw = &gcc_gpll0_out_even.clkr.hw }, +}; + +static const struct parent_map gcc_parent_map_5[] = { + { P_BI_TCXO, 0 }, + { P_GCC_GPLL0_OUT_MAIN, 1 }, + { P_GCC_GPLL8_OUT_MAIN, 2 }, + { P_GCC_GPLL0_OUT_EVEN, 6 }, +}; + +static const struct clk_parent_data gcc_parent_data_5[] = { + { .index = DT_BI_TCXO }, + { .hw = &gcc_gpll0.clkr.hw }, + { .hw = &gcc_gpll8.clkr.hw }, + { .hw = &gcc_gpll0_out_even.clkr.hw }, +}; + +static const struct parent_map gcc_parent_map_6[] = { + { P_BI_TCXO, 0 }, + { P_GCC_GPLL0_OUT_MAIN, 1 }, + { P_GCC_GPLL7_OUT_MAIN, 2 }, +}; + +static const struct clk_parent_data gcc_parent_data_6[] = { + { .index = DT_BI_TCXO }, + { .hw = &gcc_gpll0.clkr.hw }, + { .hw = &gcc_gpll7.clkr.hw }, +}; + +static const struct parent_map gcc_parent_map_7[] = { + { P_BI_TCXO, 0 }, + { P_GCC_GPLL0_OUT_MAIN, 1 }, + { P_GCC_GPLL2_OUT_MAIN, 2 }, +}; + +static const struct clk_parent_data gcc_parent_data_7[] = { + { .index = DT_BI_TCXO }, + { .hw = &gcc_gpll0.clkr.hw }, + { .hw = &gcc_gpll2.clkr.hw }, +}; + +static const struct parent_map gcc_parent_map_8[] = { + { P_BI_TCXO, 0 }, + { P_GCC_GPLL7_OUT_MAIN, 2 }, + { P_RXC0_REF_CLK, 3 }, + { P_GCC_GPLL0_OUT_EVEN, 6 }, +}; + +static const struct clk_parent_data gcc_parent_data_8[] = { + { .index = DT_BI_TCXO }, + { .hw = &gcc_gpll7.clkr.hw }, + { .index = DT_RXC0_REF_CLK }, + { .hw = &gcc_gpll0_out_even.clkr.hw }, +}; + +static const struct parent_map gcc_parent_map_9[] = { + { P_BI_TCXO, 0 }, + { P_GCC_GPLL7_OUT_MAIN, 2 }, + { P_RXC1_REF_CLK, 3 }, + { P_GCC_GPLL0_OUT_EVEN, 6 }, +}; + +static const struct clk_parent_data gcc_parent_data_9[] = { + { .index = DT_BI_TCXO }, + { .hw = &gcc_gpll7.clkr.hw }, + { .index = DT_RXC1_REF_CLK }, + { .hw = &gcc_gpll0_out_even.clkr.hw }, +}; + +static const struct parent_map gcc_parent_map_10[] = { + { P_PCIE_2A_PIPE_CLK, 0 }, + { P_BI_TCXO, 2 }, +}; + +static const struct clk_parent_data gcc_parent_data_10[] = { + { .index = DT_PCIE_2A_PIPE_CLK }, + { .index = DT_BI_TCXO }, +}; + +static const struct parent_map gcc_parent_map_11[] = { + { P_PCIE_2B_PIPE_CLK, 0 }, + { P_BI_TCXO, 2 }, +}; + +static const struct clk_parent_data gcc_parent_data_11[] = { + { .index = DT_PCIE_2B_PIPE_CLK }, + { .index = DT_BI_TCXO }, +}; + +static const struct parent_map gcc_parent_map_12[] = { + { P_PCIE_3A_PIPE_CLK, 0 }, + { P_BI_TCXO, 2 }, +}; + +static const struct clk_parent_data gcc_parent_data_12[] = { + { .index = DT_PCIE_3A_PIPE_CLK }, + { .index = DT_BI_TCXO }, +}; + +static const struct parent_map gcc_parent_map_13[] = { + { P_PCIE_3B_PIPE_CLK, 0 }, + { P_BI_TCXO, 2 }, +}; + +static const struct clk_parent_data gcc_parent_data_13[] = { + { .index = DT_PCIE_3B_PIPE_CLK }, + { .index = DT_BI_TCXO }, +}; + +static const struct parent_map gcc_parent_map_14[] = { + { P_PCIE_4_PIPE_CLK, 0 }, + { P_BI_TCXO, 2 }, +}; + +static const struct clk_parent_data gcc_parent_data_14[] = { + { .index = DT_PCIE_4_PIPE_CLK }, + { .index = DT_BI_TCXO }, +}; + +static const struct parent_map gcc_parent_map_15[] = { + { P_BI_TCXO, 0 }, + { P_GCC_GPLL0_OUT_MAIN, 1 }, + { P_GCC_GPLL9_OUT_MAIN, 2 }, + { P_GCC_GPLL4_OUT_MAIN, 5 }, + { P_GCC_GPLL0_OUT_EVEN, 6 }, +}; + +static const struct clk_parent_data gcc_parent_data_15[] = { + { .index = DT_BI_TCXO }, + { .hw = &gcc_gpll0.clkr.hw }, + { .hw = &gcc_gpll9.clkr.hw }, + { .hw = &gcc_gpll4.clkr.hw }, + { .hw = &gcc_gpll0_out_even.clkr.hw }, +}; + +static const struct parent_map gcc_parent_map_16[] = { + { P_UFS_CARD_RX_SYMBOL_0_CLK, 0 }, + { P_BI_TCXO, 2 }, +}; + +static const struct clk_parent_data gcc_parent_data_16[] = { + { .index = DT_UFS_CARD_RX_SYMBOL_0_CLK }, + { .index = DT_BI_TCXO }, +}; + +static const struct parent_map gcc_parent_map_17[] = { + { P_UFS_CARD_RX_SYMBOL_1_CLK, 0 }, + { P_BI_TCXO, 2 }, +}; + +static const struct clk_parent_data gcc_parent_data_17[] = { + { .index = DT_UFS_CARD_RX_SYMBOL_1_CLK }, + { .index = DT_BI_TCXO }, +}; + +static const struct parent_map gcc_parent_map_18[] = { + { P_UFS_CARD_TX_SYMBOL_0_CLK, 0 }, + { P_BI_TCXO, 2 }, +}; + +static const struct clk_parent_data gcc_parent_data_18[] = { + { .index = DT_UFS_CARD_TX_SYMBOL_0_CLK }, + { .index = DT_BI_TCXO }, +}; + +static const struct parent_map gcc_parent_map_19[] = { + { P_UFS_PHY_RX_SYMBOL_0_CLK, 0 }, + { P_BI_TCXO, 2 }, +}; + +static const struct clk_parent_data gcc_parent_data_19[] = { + { .index = DT_UFS_PHY_RX_SYMBOL_0_CLK }, + { .index = DT_BI_TCXO }, +}; + +static const struct parent_map gcc_parent_map_20[] = { + { P_UFS_PHY_RX_SYMBOL_1_CLK, 0 }, + { P_BI_TCXO, 2 }, +}; + +static const struct clk_parent_data gcc_parent_data_20[] = { + { .index = DT_UFS_PHY_RX_SYMBOL_1_CLK }, + { .index = DT_BI_TCXO }, +}; + +static const struct parent_map gcc_parent_map_21[] = { + { P_UFS_PHY_TX_SYMBOL_0_CLK, 0 }, + { P_BI_TCXO, 2 }, +}; + +static const struct clk_parent_data gcc_parent_data_21[] = { + { .index = DT_UFS_PHY_TX_SYMBOL_0_CLK }, + { .index = DT_BI_TCXO }, +}; + +static const struct parent_map gcc_parent_map_22[] = { + { P_USB3_PHY_WRAPPER_GCC_USB30_PIPE_CLK, 0 }, + { P_BI_TCXO, 2 }, +}; + +static const struct clk_parent_data gcc_parent_data_22[] = { + { .index = DT_USB3_PHY_WRAPPER_GCC_USB30_PIPE_CLK }, + { .index = DT_BI_TCXO }, +}; + +static const struct parent_map gcc_parent_map_23[] = { + { P_USB3_UNI_PHY_SEC_GCC_USB30_PIPE_CLK, 0 }, + { P_BI_TCXO, 2 }, +}; + +static const struct clk_parent_data gcc_parent_data_23[] = { + { .index = DT_USB3_UNI_PHY_SEC_GCC_USB30_PIPE_CLK }, + { .index = DT_BI_TCXO }, +}; + +static struct clk_regmap_mux gcc_usb3_prim_phy_pipe_clk_src = { + .reg = 0xf060, + .shift = 0, + .width = 2, + .parent_map = gcc_parent_map_22, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb3_prim_phy_pipe_clk_src", + .parent_data = gcc_parent_data_22, + .num_parents = ARRAY_SIZE(gcc_parent_data_22), + .ops = &clk_regmap_mux_closest_ops, + }, + }, +}; + +static struct clk_regmap_mux gcc_usb3_sec_phy_pipe_clk_src = { + .reg = 0x10060, + .shift = 0, + .width = 2, + .parent_map = gcc_parent_map_23, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb3_sec_phy_pipe_clk_src", + .parent_data = gcc_parent_data_23, + .num_parents = ARRAY_SIZE(gcc_parent_data_23), + .ops = &clk_regmap_mux_closest_ops, + }, + }, +}; + +static const struct parent_map gcc_parent_map_24[] = { + { P_USB3_UNI_PHY_MP_GCC_USB30_PIPE_0_CLK, 0 }, + { P_BI_TCXO, 2 }, +}; + +static const struct clk_parent_data gcc_parent_data_24[] = { + { .index = DT_USB3_UNI_PHY_MP_GCC_USB30_PIPE_0_CLK }, + { .index = DT_BI_TCXO }, +}; + +static const struct parent_map gcc_parent_map_25[] = { + { P_USB3_UNI_PHY_MP_GCC_USB30_PIPE_1_CLK, 0 }, + { P_BI_TCXO, 2 }, +}; + +static const struct clk_parent_data gcc_parent_data_25[] = { + { .index = DT_USB3_UNI_PHY_MP_GCC_USB30_PIPE_1_CLK }, + { .index = DT_BI_TCXO }, +}; + +static const struct parent_map gcc_parent_map_26[] = { + { P_GCC_USB3_PRIM_PHY_PIPE_CLK_SRC, 0 }, + { P_USB4_PHY_GCC_USB4RTR_MAX_PIPE_CLK, 1 }, + { P_GCC_USB4_PHY_PIPEGMUX_CLK_SRC, 3 }, +}; + +static const struct clk_parent_data gcc_parent_data_26[] = { + { .hw = &gcc_usb3_prim_phy_pipe_clk_src.clkr.hw }, + { .index = DT_USB4_PHY_GCC_USB4RTR_MAX_PIPE_CLK }, + { .index = DT_GCC_USB4_PHY_PIPEGMUX_CLK_SRC }, +}; + +static const struct parent_map gcc_parent_map_27[] = { + { P_GCC_USB3_SEC_PHY_PIPE_CLK_SRC, 0 }, + { P_USB4_1_PHY_GCC_USB4RTR_MAX_PIPE_CLK, 1 }, + { P_GCC_USB4_1_PHY_PIPEGMUX_CLK_SRC, 3 }, +}; + +static const struct clk_parent_data gcc_parent_data_27[] = { + { .hw = &gcc_usb3_sec_phy_pipe_clk_src.clkr.hw }, + { .index = DT_USB4_1_PHY_GCC_USB4RTR_MAX_PIPE_CLK }, + { .index = DT_GCC_USB4_1_PHY_PIPEGMUX_CLK_SRC }, +}; + +static const struct parent_map gcc_parent_map_28[] = { + { P_GCC_USB4_1_PHY_DP_GMUX_CLK_SRC, 0 }, + { P_USB4_1_PHY_GCC_USB4RTR_MAX_PIPE_CLK, 2 }, +}; + +static const struct clk_parent_data gcc_parent_data_28[] = { + { .index = DT_GCC_USB4_1_PHY_DP_GMUX_CLK_SRC }, + { .index = DT_USB4_1_PHY_GCC_USB4RTR_MAX_PIPE_CLK }, +}; + +static const struct parent_map gcc_parent_map_29[] = { + { P_USB4_1_PHY_GCC_USB4_PCIE_PIPE_CLK, 0 }, + { P_BI_TCXO, 2 }, +}; + +static const struct clk_parent_data gcc_parent_data_29[] = { + { .index = DT_USB4_1_PHY_GCC_USB4_PCIE_PIPE_CLK }, + { .index = DT_BI_TCXO }, +}; + +static const struct parent_map gcc_parent_map_30[] = { + { P_GCC_USB4_1_PHY_SYS_PIPEGMUX_CLK_SRC, 0 }, + { P_GCC_USB4_1_PHY_PCIE_PIPE_CLK_SRC, 1 }, +}; + +static const struct clk_parent_data gcc_parent_data_30[] = { + { .index = DT_GCC_USB4_1_PHY_SYS_PIPEGMUX_CLK_SRC }, + { .hw = &gcc_usb4_1_phy_pcie_pipe_clk_src.clkr.hw }, +}; + +static struct clk_regmap_mux gcc_usb4_1_phy_pcie_pipegmux_clk_src = { + .reg = 0xb80dc, + .shift = 0, + .width = 1, + .parent_map = gcc_parent_map_30, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb4_1_phy_pcie_pipegmux_clk_src", + .parent_data = gcc_parent_data_30, + .num_parents = ARRAY_SIZE(gcc_parent_data_30), + .ops = &clk_regmap_mux_closest_ops, + }, + }, +}; + +static const struct parent_map gcc_parent_map_31[] = { + { P_GCC_USB4_1_PHY_PCIE_PIPEGMUX_CLK_SRC, 0 }, + { P_USB4_1_PHY_GCC_USB4_PCIE_PIPE_CLK, 2 }, +}; + +static const struct clk_parent_data gcc_parent_data_31[] = { + { .hw = &gcc_usb4_1_phy_pcie_pipegmux_clk_src.clkr.hw }, + { .index = DT_USB4_1_PHY_GCC_USB4_PCIE_PIPE_CLK }, +}; + +static const struct parent_map gcc_parent_map_32[] = { + { P_QUSB4PHY_1_GCC_USB4_RX0_CLK, 0 }, + { P_BI_TCXO, 2 }, +}; + +static const struct clk_parent_data gcc_parent_data_32[] = { + { .index = DT_QUSB4PHY_1_GCC_USB4_RX0_CLK }, + { .index = DT_BI_TCXO }, +}; + +static const struct parent_map gcc_parent_map_33[] = { + { P_QUSB4PHY_1_GCC_USB4_RX1_CLK, 0 }, + { P_BI_TCXO, 2 }, +}; + +static const struct clk_parent_data gcc_parent_data_33[] = { + { .index = DT_QUSB4PHY_1_GCC_USB4_RX1_CLK }, + { .index = DT_BI_TCXO }, +}; + +static const struct parent_map gcc_parent_map_34[] = { + { P_GCC_USB4_1_PHY_SYS_PIPEGMUX_CLK_SRC, 0 }, + { P_USB4_1_PHY_GCC_USB4_PCIE_PIPE_CLK, 2 }, +}; + +static const struct clk_parent_data gcc_parent_data_34[] = { + { .index = DT_GCC_USB4_1_PHY_SYS_PIPEGMUX_CLK_SRC }, + { .index = DT_USB4_1_PHY_GCC_USB4_PCIE_PIPE_CLK }, +}; + +static const struct parent_map gcc_parent_map_35[] = { + { P_GCC_USB4_PHY_DP_GMUX_CLK_SRC, 0 }, + { P_USB4_PHY_GCC_USB4RTR_MAX_PIPE_CLK, 2 }, +}; + +static const struct clk_parent_data gcc_parent_data_35[] = { + { .index = DT_GCC_USB4_PHY_DP_GMUX_CLK_SRC }, + { .index = DT_USB4_PHY_GCC_USB4RTR_MAX_PIPE_CLK }, +}; + +static const struct parent_map gcc_parent_map_36[] = { + { P_USB4_PHY_GCC_USB4_PCIE_PIPE_CLK, 0 }, + { P_BI_TCXO, 2 }, +}; + +static const struct clk_parent_data gcc_parent_data_36[] = { + { .index = DT_USB4_PHY_GCC_USB4_PCIE_PIPE_CLK }, + { .index = DT_BI_TCXO }, +}; + +static const struct parent_map gcc_parent_map_37[] = { + { P_GCC_USB4_PHY_SYS_PIPEGMUX_CLK_SRC, 0 }, + { P_GCC_USB4_PHY_PCIE_PIPE_CLK_SRC, 1 }, +}; + +static const struct clk_parent_data gcc_parent_data_37[] = { + { .index = DT_GCC_USB4_PHY_SYS_PIPEGMUX_CLK_SRC }, + { .hw = &gcc_usb4_phy_pcie_pipe_clk_src.clkr.hw }, +}; + +static struct clk_regmap_mux gcc_usb4_phy_pcie_pipegmux_clk_src = { + .reg = 0x2a0dc, + .shift = 0, + .width = 1, + .parent_map = gcc_parent_map_37, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb4_phy_pcie_pipegmux_clk_src", + .parent_data = gcc_parent_data_37, + .num_parents = ARRAY_SIZE(gcc_parent_data_37), + .ops = &clk_regmap_mux_closest_ops, + }, + }, +}; + +static const struct parent_map gcc_parent_map_38[] = { + { P_GCC_USB4_PHY_PCIE_PIPEGMUX_CLK_SRC, 0 }, + { P_USB4_PHY_GCC_USB4_PCIE_PIPE_CLK, 2 }, +}; + +static const struct clk_parent_data gcc_parent_data_38[] = { + { .hw = &gcc_usb4_phy_pcie_pipegmux_clk_src.clkr.hw }, + { .index = DT_USB4_PHY_GCC_USB4_PCIE_PIPE_CLK }, +}; + +static const struct parent_map gcc_parent_map_39[] = { + { P_QUSB4PHY_GCC_USB4_RX0_CLK, 0 }, + { P_BI_TCXO, 2 }, +}; + +static const struct clk_parent_data gcc_parent_data_39[] = { + { .index = DT_QUSB4PHY_GCC_USB4_RX0_CLK }, + { .index = DT_BI_TCXO }, +}; + +static const struct parent_map gcc_parent_map_40[] = { + { P_QUSB4PHY_GCC_USB4_RX1_CLK, 0 }, + { P_BI_TCXO, 2 }, +}; + +static const struct clk_parent_data gcc_parent_data_40[] = { + { .index = DT_QUSB4PHY_GCC_USB4_RX1_CLK }, + { .index = DT_BI_TCXO }, +}; + +static const struct parent_map gcc_parent_map_41[] = { + { P_GCC_USB4_PHY_SYS_PIPEGMUX_CLK_SRC, 0 }, + { P_USB4_PHY_GCC_USB4_PCIE_PIPE_CLK, 2 }, +}; + +static const struct clk_parent_data gcc_parent_data_41[] = { + { .index = DT_GCC_USB4_PHY_SYS_PIPEGMUX_CLK_SRC }, + { .index = DT_USB4_PHY_GCC_USB4_PCIE_PIPE_CLK }, +}; + +static struct clk_regmap_mux gcc_pcie_2a_pipe_clk_src = { + .reg = 0x9d05c, + .shift = 0, + .width = 2, + .parent_map = gcc_parent_map_10, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_2a_pipe_clk_src", + .parent_data = gcc_parent_data_10, + .num_parents = ARRAY_SIZE(gcc_parent_data_10), + .ops = &clk_regmap_mux_closest_ops, + }, + }, +}; + +static struct clk_regmap_mux gcc_pcie_2b_pipe_clk_src = { + .reg = 0x9e05c, + .shift = 0, + .width = 2, + .parent_map = gcc_parent_map_11, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_2b_pipe_clk_src", + .parent_data = gcc_parent_data_11, + .num_parents = ARRAY_SIZE(gcc_parent_data_11), + .ops = &clk_regmap_mux_closest_ops, + }, + }, +}; + +static struct clk_regmap_mux gcc_pcie_3a_pipe_clk_src = { + .reg = 0xa005c, + .shift = 0, + .width = 2, + .parent_map = gcc_parent_map_12, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_3a_pipe_clk_src", + .parent_data = gcc_parent_data_12, + .num_parents = ARRAY_SIZE(gcc_parent_data_12), + .ops = &clk_regmap_mux_closest_ops, + }, + }, +}; + +static struct clk_regmap_mux gcc_pcie_3b_pipe_clk_src = { + .reg = 0xa205c, + .shift = 0, + .width = 2, + .parent_map = gcc_parent_map_13, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_3b_pipe_clk_src", + .parent_data = gcc_parent_data_13, + .num_parents = ARRAY_SIZE(gcc_parent_data_13), + .ops = &clk_regmap_mux_closest_ops, + }, + }, +}; + +static struct clk_regmap_mux gcc_pcie_4_pipe_clk_src = { + .reg = 0x6b05c, + .shift = 0, + .width = 2, + .parent_map = gcc_parent_map_14, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_4_pipe_clk_src", + .parent_data = gcc_parent_data_14, + .num_parents = ARRAY_SIZE(gcc_parent_data_14), + .ops = &clk_regmap_mux_closest_ops, + }, + }, +}; + +static struct clk_regmap_mux gcc_ufs_card_rx_symbol_0_clk_src = { + .reg = 0x75058, + .shift = 0, + .width = 2, + .parent_map = gcc_parent_map_16, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_ufs_card_rx_symbol_0_clk_src", + .parent_data = gcc_parent_data_16, + .num_parents = ARRAY_SIZE(gcc_parent_data_16), + .ops = &clk_regmap_mux_closest_ops, + }, + }, +}; + +static struct clk_regmap_mux gcc_ufs_card_rx_symbol_1_clk_src = { + .reg = 0x750c8, + .shift = 0, + .width = 2, + .parent_map = gcc_parent_map_17, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_ufs_card_rx_symbol_1_clk_src", + .parent_data = gcc_parent_data_17, + .num_parents = ARRAY_SIZE(gcc_parent_data_17), + .ops = &clk_regmap_mux_closest_ops, + }, + }, +}; + +static struct clk_regmap_mux gcc_ufs_card_tx_symbol_0_clk_src = { + .reg = 0x75048, + .shift = 0, + .width = 2, + .parent_map = gcc_parent_map_18, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_ufs_card_tx_symbol_0_clk_src", + .parent_data = gcc_parent_data_18, + .num_parents = ARRAY_SIZE(gcc_parent_data_18), + .ops = &clk_regmap_mux_closest_ops, + }, + }, +}; + +static struct clk_regmap_mux gcc_ufs_phy_rx_symbol_0_clk_src = { + .reg = 0x77058, + .shift = 0, + .width = 2, + .parent_map = gcc_parent_map_19, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_ufs_phy_rx_symbol_0_clk_src", + .parent_data = gcc_parent_data_19, + .num_parents = ARRAY_SIZE(gcc_parent_data_19), + .ops = &clk_regmap_mux_closest_ops, + }, + }, +}; + +static struct clk_regmap_mux gcc_ufs_phy_rx_symbol_1_clk_src = { + .reg = 0x770c8, + .shift = 0, + .width = 2, + .parent_map = gcc_parent_map_20, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_ufs_phy_rx_symbol_1_clk_src", + .parent_data = gcc_parent_data_20, + .num_parents = ARRAY_SIZE(gcc_parent_data_20), + .ops = &clk_regmap_mux_closest_ops, + }, + }, +}; + +static struct clk_regmap_mux gcc_ufs_phy_tx_symbol_0_clk_src = { + .reg = 0x77048, + .shift = 0, + .width = 2, + .parent_map = gcc_parent_map_21, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_ufs_phy_tx_symbol_0_clk_src", + .parent_data = gcc_parent_data_21, + .num_parents = ARRAY_SIZE(gcc_parent_data_21), + .ops = &clk_regmap_mux_closest_ops, + }, + }, +}; + +static struct clk_regmap_mux gcc_usb34_prim_phy_pipe_clk_src = { + .reg = 0xf064, + .shift = 0, + .width = 2, + .parent_map = gcc_parent_map_26, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb34_prim_phy_pipe_clk_src", + .parent_data = gcc_parent_data_26, + .num_parents = ARRAY_SIZE(gcc_parent_data_26), + .ops = &clk_regmap_mux_closest_ops, + }, + }, +}; + +static struct clk_regmap_mux gcc_usb34_sec_phy_pipe_clk_src = { + .reg = 0x10064, + .shift = 0, + .width = 2, + .parent_map = gcc_parent_map_27, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb34_sec_phy_pipe_clk_src", + .parent_data = gcc_parent_data_27, + .num_parents = ARRAY_SIZE(gcc_parent_data_27), + .ops = &clk_regmap_mux_closest_ops, + }, + }, +}; + +static struct clk_regmap_mux gcc_usb3_mp_phy_pipe_0_clk_src = { + .reg = 0xab060, + .shift = 0, + .width = 2, + .parent_map = gcc_parent_map_24, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb3_mp_phy_pipe_0_clk_src", + .parent_data = gcc_parent_data_24, + .num_parents = ARRAY_SIZE(gcc_parent_data_24), + .ops = &clk_regmap_mux_closest_ops, + }, + }, +}; + +static struct clk_regmap_mux gcc_usb3_mp_phy_pipe_1_clk_src = { + .reg = 0xab068, + .shift = 0, + .width = 2, + .parent_map = gcc_parent_map_25, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb3_mp_phy_pipe_1_clk_src", + .parent_data = gcc_parent_data_25, + .num_parents = ARRAY_SIZE(gcc_parent_data_25), + .ops = &clk_regmap_mux_closest_ops, + }, + }, +}; + +static struct clk_regmap_mux gcc_usb4_1_phy_dp_clk_src = { + .reg = 0xb8050, + .shift = 0, + .width = 2, + .parent_map = gcc_parent_map_28, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb4_1_phy_dp_clk_src", + .parent_data = gcc_parent_data_28, + .num_parents = ARRAY_SIZE(gcc_parent_data_28), + .ops = &clk_regmap_mux_closest_ops, + }, + }, +}; + +static struct clk_regmap_mux gcc_usb4_1_phy_p2rr2p_pipe_clk_src = { + .reg = 0xb80b0, + .shift = 0, + .width = 2, + .parent_map = gcc_parent_map_29, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb4_1_phy_p2rr2p_pipe_clk_src", + .parent_data = gcc_parent_data_29, + .num_parents = ARRAY_SIZE(gcc_parent_data_29), + .ops = &clk_regmap_mux_closest_ops, + }, + }, +}; + +static struct clk_regmap_mux gcc_usb4_1_phy_pcie_pipe_mux_clk_src = { + .reg = 0xb80e0, + .shift = 0, + .width = 2, + .parent_map = gcc_parent_map_31, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb4_1_phy_pcie_pipe_mux_clk_src", + .parent_data = gcc_parent_data_31, + .num_parents = ARRAY_SIZE(gcc_parent_data_31), + .ops = &clk_regmap_mux_closest_ops, + }, + }, +}; + +static struct clk_regmap_mux gcc_usb4_1_phy_rx0_clk_src = { + .reg = 0xb8090, + .shift = 0, + .width = 2, + .parent_map = gcc_parent_map_32, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb4_1_phy_rx0_clk_src", + .parent_data = gcc_parent_data_32, + .num_parents = ARRAY_SIZE(gcc_parent_data_32), + .ops = &clk_regmap_mux_closest_ops, + }, + }, +}; + +static struct clk_regmap_mux gcc_usb4_1_phy_rx1_clk_src = { + .reg = 0xb809c, + .shift = 0, + .width = 2, + .parent_map = gcc_parent_map_33, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb4_1_phy_rx1_clk_src", + .parent_data = gcc_parent_data_33, + .num_parents = ARRAY_SIZE(gcc_parent_data_33), + .ops = &clk_regmap_mux_closest_ops, + }, + }, +}; + +static struct clk_regmap_mux gcc_usb4_1_phy_sys_clk_src = { + .reg = 0xb80c0, + .shift = 0, + .width = 2, + .parent_map = gcc_parent_map_34, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb4_1_phy_sys_clk_src", + .parent_data = gcc_parent_data_34, + .num_parents = ARRAY_SIZE(gcc_parent_data_34), + .ops = &clk_regmap_mux_closest_ops, + }, + }, +}; + +static struct clk_regmap_mux gcc_usb4_phy_dp_clk_src = { + .reg = 0x2a050, + .shift = 0, + .width = 2, + .parent_map = gcc_parent_map_35, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb4_phy_dp_clk_src", + .parent_data = gcc_parent_data_35, + .num_parents = ARRAY_SIZE(gcc_parent_data_35), + .ops = &clk_regmap_mux_closest_ops, + }, + }, +}; + +static struct clk_regmap_mux gcc_usb4_phy_p2rr2p_pipe_clk_src = { + .reg = 0x2a0b0, + .shift = 0, + .width = 2, + .parent_map = gcc_parent_map_36, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb4_phy_p2rr2p_pipe_clk_src", + .parent_data = gcc_parent_data_36, + .num_parents = ARRAY_SIZE(gcc_parent_data_36), + .ops = &clk_regmap_mux_closest_ops, + }, + }, +}; + +static struct clk_regmap_mux gcc_usb4_phy_pcie_pipe_mux_clk_src = { + .reg = 0x2a0e0, + .shift = 0, + .width = 2, + .parent_map = gcc_parent_map_38, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb4_phy_pcie_pipe_mux_clk_src", + .parent_data = gcc_parent_data_38, + .num_parents = ARRAY_SIZE(gcc_parent_data_38), + .ops = &clk_regmap_mux_closest_ops, + }, + }, +}; + +static struct clk_regmap_mux gcc_usb4_phy_rx0_clk_src = { + .reg = 0x2a090, + .shift = 0, + .width = 2, + .parent_map = gcc_parent_map_39, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb4_phy_rx0_clk_src", + .parent_data = gcc_parent_data_39, + .num_parents = ARRAY_SIZE(gcc_parent_data_39), + .ops = &clk_regmap_mux_closest_ops, + }, + }, +}; + +static struct clk_regmap_mux gcc_usb4_phy_rx1_clk_src = { + .reg = 0x2a09c, + .shift = 0, + .width = 2, + .parent_map = gcc_parent_map_40, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb4_phy_rx1_clk_src", + .parent_data = gcc_parent_data_40, + .num_parents = ARRAY_SIZE(gcc_parent_data_40), + .ops = &clk_regmap_mux_closest_ops, + }, + }, +}; + +static struct clk_regmap_mux gcc_usb4_phy_sys_clk_src = { + .reg = 0x2a0c0, + .shift = 0, + .width = 2, + .parent_map = gcc_parent_map_41, + .clkr = { + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb4_phy_sys_clk_src", + .parent_data = gcc_parent_data_41, + .num_parents = ARRAY_SIZE(gcc_parent_data_41), + .ops = &clk_regmap_mux_closest_ops, + }, + }, +}; + +static const struct freq_tbl ftbl_gcc_emac0_ptp_clk_src[] = { + F(75000000, P_GCC_GPLL0_OUT_EVEN, 4, 0, 0), + F(125000000, P_GCC_GPLL7_OUT_MAIN, 4, 0, 0), + F(230400000, P_GCC_GPLL4_OUT_MAIN, 3.5, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_emac0_ptp_clk_src = { + .cmd_rcgr = 0xaa020, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_4, + .freq_tbl = ftbl_gcc_emac0_ptp_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_emac0_ptp_clk_src", + .parent_data = gcc_parent_data_4, + .num_parents = ARRAY_SIZE(gcc_parent_data_4), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_emac0_rgmii_clk_src[] = { + F(50000000, P_GCC_GPLL0_OUT_EVEN, 6, 0, 0), + F(125000000, P_GCC_GPLL7_OUT_MAIN, 4, 0, 0), + F(250000000, P_GCC_GPLL7_OUT_MAIN, 2, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_emac0_rgmii_clk_src = { + .cmd_rcgr = 0xaa040, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_8, + .freq_tbl = ftbl_gcc_emac0_rgmii_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_emac0_rgmii_clk_src", + .parent_data = gcc_parent_data_8, + .num_parents = ARRAY_SIZE(gcc_parent_data_8), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_emac1_ptp_clk_src = { + .cmd_rcgr = 0xba020, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_4, + .freq_tbl = ftbl_gcc_emac0_ptp_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_emac1_ptp_clk_src", + .parent_data = gcc_parent_data_4, + .num_parents = ARRAY_SIZE(gcc_parent_data_4), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_emac1_rgmii_clk_src = { + .cmd_rcgr = 0xba040, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_9, + .freq_tbl = ftbl_gcc_emac0_rgmii_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_emac1_rgmii_clk_src", + .parent_data = gcc_parent_data_9, + .num_parents = ARRAY_SIZE(gcc_parent_data_9), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_gp1_clk_src[] = { + F(50000000, P_GCC_GPLL0_OUT_EVEN, 6, 0, 0), + F(100000000, P_GCC_GPLL0_OUT_MAIN, 6, 0, 0), + F(200000000, P_GCC_GPLL0_OUT_MAIN, 3, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_gp1_clk_src = { + .cmd_rcgr = 0x64004, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_2, + .freq_tbl = ftbl_gcc_gp1_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_gp1_clk_src", + .parent_data = gcc_parent_data_2, + .num_parents = ARRAY_SIZE(gcc_parent_data_2), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_gp2_clk_src = { + .cmd_rcgr = 0x65004, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_2, + .freq_tbl = ftbl_gcc_gp1_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_gp2_clk_src", + .parent_data = gcc_parent_data_2, + .num_parents = ARRAY_SIZE(gcc_parent_data_2), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_gp3_clk_src = { + .cmd_rcgr = 0x66004, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_2, + .freq_tbl = ftbl_gcc_gp1_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_gp3_clk_src", + .parent_data = gcc_parent_data_2, + .num_parents = ARRAY_SIZE(gcc_parent_data_2), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_gp4_clk_src = { + .cmd_rcgr = 0xc2004, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_2, + .freq_tbl = ftbl_gcc_gp1_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_gp4_clk_src", + .parent_data = gcc_parent_data_2, + .num_parents = ARRAY_SIZE(gcc_parent_data_2), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_gp5_clk_src = { + .cmd_rcgr = 0xc3004, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_2, + .freq_tbl = ftbl_gcc_gp1_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_gp5_clk_src", + .parent_data = gcc_parent_data_2, + .num_parents = ARRAY_SIZE(gcc_parent_data_2), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_pcie_0_aux_clk_src[] = { + F(9600000, P_BI_TCXO, 2, 0, 0), + F(19200000, P_BI_TCXO, 1, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_pcie_0_aux_clk_src = { + .cmd_rcgr = 0xa4054, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_pcie_0_aux_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_0_aux_clk_src", + .parent_data = gcc_parent_data_1, + .num_parents = ARRAY_SIZE(gcc_parent_data_1), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_pcie_0_phy_rchng_clk_src[] = { + F(100000000, P_GCC_GPLL0_OUT_EVEN, 3, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_pcie_0_phy_rchng_clk_src = { + .cmd_rcgr = 0xa403c, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_pcie_0_phy_rchng_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_0_phy_rchng_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_pcie_1_aux_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_pcie_1_aux_clk_src = { + .cmd_rcgr = 0x8d054, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_pcie_1_aux_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_1_aux_clk_src", + .parent_data = gcc_parent_data_1, + .num_parents = ARRAY_SIZE(gcc_parent_data_1), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_pcie_1_phy_rchng_clk_src = { + .cmd_rcgr = 0x8d03c, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_pcie_0_phy_rchng_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_1_phy_rchng_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_pcie_2a_aux_clk_src = { + .cmd_rcgr = 0x9d064, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_pcie_1_aux_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_2a_aux_clk_src", + .parent_data = gcc_parent_data_1, + .num_parents = ARRAY_SIZE(gcc_parent_data_1), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_pcie_2a_phy_rchng_clk_src = { + .cmd_rcgr = 0x9d044, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_pcie_0_phy_rchng_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_2a_phy_rchng_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_pcie_2b_aux_clk_src = { + .cmd_rcgr = 0x9e064, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_pcie_1_aux_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_2b_aux_clk_src", + .parent_data = gcc_parent_data_1, + .num_parents = ARRAY_SIZE(gcc_parent_data_1), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_pcie_2b_phy_rchng_clk_src = { + .cmd_rcgr = 0x9e044, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_pcie_0_phy_rchng_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_2b_phy_rchng_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_pcie_3a_aux_clk_src = { + .cmd_rcgr = 0xa0064, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_pcie_1_aux_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_3a_aux_clk_src", + .parent_data = gcc_parent_data_1, + .num_parents = ARRAY_SIZE(gcc_parent_data_1), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_pcie_3a_phy_rchng_clk_src = { + .cmd_rcgr = 0xa0044, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_pcie_0_phy_rchng_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_3a_phy_rchng_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_pcie_3b_aux_clk_src = { + .cmd_rcgr = 0xa2064, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_pcie_1_aux_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_3b_aux_clk_src", + .parent_data = gcc_parent_data_1, + .num_parents = ARRAY_SIZE(gcc_parent_data_1), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_pcie_3b_phy_rchng_clk_src = { + .cmd_rcgr = 0xa2044, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_pcie_0_phy_rchng_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_3b_phy_rchng_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_pcie_4_aux_clk_src = { + .cmd_rcgr = 0x6b064, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_pcie_0_aux_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_4_aux_clk_src", + .parent_data = gcc_parent_data_1, + .num_parents = ARRAY_SIZE(gcc_parent_data_1), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_pcie_4_phy_rchng_clk_src = { + .cmd_rcgr = 0x6b044, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_pcie_0_phy_rchng_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_4_phy_rchng_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_pcie_rscc_xo_clk_src = { + .cmd_rcgr = 0xae00c, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_3, + .freq_tbl = ftbl_gcc_pcie_1_aux_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_rscc_xo_clk_src", + .parent_data = gcc_parent_data_3, + .num_parents = ARRAY_SIZE(gcc_parent_data_3), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_pdm2_clk_src[] = { + F(60000000, P_GCC_GPLL0_OUT_EVEN, 5, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_pdm2_clk_src = { + .cmd_rcgr = 0x33010, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_pdm2_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_pdm2_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_qupv3_wrap0_s0_clk_src[] = { + F(7372800, P_GCC_GPLL0_OUT_EVEN, 1, 384, 15625), + F(14745600, P_GCC_GPLL0_OUT_EVEN, 1, 768, 15625), + F(19200000, P_BI_TCXO, 1, 0, 0), + F(29491200, P_GCC_GPLL0_OUT_EVEN, 1, 1536, 15625), + F(32000000, P_GCC_GPLL0_OUT_EVEN, 1, 8, 75), + F(48000000, P_GCC_GPLL0_OUT_EVEN, 1, 4, 25), + F(64000000, P_GCC_GPLL0_OUT_EVEN, 1, 16, 75), + F(75000000, P_GCC_GPLL0_OUT_EVEN, 4, 0, 0), + F(80000000, P_GCC_GPLL0_OUT_EVEN, 1, 4, 15), + F(96000000, P_GCC_GPLL0_OUT_EVEN, 1, 8, 25), + F(100000000, P_GCC_GPLL0_OUT_MAIN, 6, 0, 0), + { } +}; + +static struct clk_init_data gcc_qupv3_wrap0_s0_clk_src_init = { + .name = "gcc_qupv3_wrap0_s0_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s0_clk_src = { + .cmd_rcgr = 0x17148, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap0_s0_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap0_s1_clk_src_init = { + .name = "gcc_qupv3_wrap0_s1_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s1_clk_src = { + .cmd_rcgr = 0x17278, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap0_s1_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap0_s2_clk_src_init = { + .name = "gcc_qupv3_wrap0_s2_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s2_clk_src = { + .cmd_rcgr = 0x173a8, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap0_s2_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap0_s3_clk_src_init = { + .name = "gcc_qupv3_wrap0_s3_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s3_clk_src = { + .cmd_rcgr = 0x174d8, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap0_s3_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap0_s4_clk_src_init = { + .name = "gcc_qupv3_wrap0_s4_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s4_clk_src = { + .cmd_rcgr = 0x17608, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap0_s4_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap0_s5_clk_src_init = { + .name = "gcc_qupv3_wrap0_s5_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s5_clk_src = { + .cmd_rcgr = 0x17738, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap0_s5_clk_src_init, +}; + +static const struct freq_tbl ftbl_gcc_qupv3_wrap0_s6_clk_src[] = { + F(7372800, P_GCC_GPLL0_OUT_EVEN, 1, 384, 15625), + F(14745600, P_GCC_GPLL0_OUT_EVEN, 1, 768, 15625), + F(19200000, P_BI_TCXO, 1, 0, 0), + F(29491200, P_GCC_GPLL0_OUT_EVEN, 1, 1536, 15625), + F(32000000, P_GCC_GPLL0_OUT_EVEN, 1, 8, 75), + F(48000000, P_GCC_GPLL0_OUT_EVEN, 1, 4, 25), + F(64000000, P_GCC_GPLL0_OUT_EVEN, 1, 16, 75), + F(75000000, P_GCC_GPLL0_OUT_EVEN, 4, 0, 0), + F(80000000, P_GCC_GPLL0_OUT_EVEN, 1, 4, 15), + F(96000000, P_GCC_GPLL0_OUT_EVEN, 1, 8, 25), + F(120000000, P_GCC_GPLL0_OUT_MAIN, 5, 0, 0), + { } +}; + +static struct clk_init_data gcc_qupv3_wrap0_s6_clk_src_init = { + .name = "gcc_qupv3_wrap0_s6_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s6_clk_src = { + .cmd_rcgr = 0x17868, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s6_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap0_s6_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap0_s7_clk_src_init = { + .name = "gcc_qupv3_wrap0_s7_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s7_clk_src = { + .cmd_rcgr = 0x17998, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s6_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap0_s7_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap1_s0_clk_src_init = { + .name = "gcc_qupv3_wrap1_s0_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap1_s0_clk_src = { + .cmd_rcgr = 0x18148, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap1_s0_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap1_s1_clk_src_init = { + .name = "gcc_qupv3_wrap1_s1_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap1_s1_clk_src = { + .cmd_rcgr = 0x18278, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap1_s1_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap1_s2_clk_src_init = { + .name = "gcc_qupv3_wrap1_s2_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap1_s2_clk_src = { + .cmd_rcgr = 0x183a8, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap1_s2_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap1_s3_clk_src_init = { + .name = "gcc_qupv3_wrap1_s3_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap1_s3_clk_src = { + .cmd_rcgr = 0x184d8, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap1_s3_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap1_s4_clk_src_init = { + .name = "gcc_qupv3_wrap1_s4_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap1_s4_clk_src = { + .cmd_rcgr = 0x18608, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap1_s4_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap1_s5_clk_src_init = { + .name = "gcc_qupv3_wrap1_s5_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap1_s5_clk_src = { + .cmd_rcgr = 0x18738, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap1_s5_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap1_s6_clk_src_init = { + .name = "gcc_qupv3_wrap1_s6_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap1_s6_clk_src = { + .cmd_rcgr = 0x18868, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s6_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap1_s6_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap1_s7_clk_src_init = { + .name = "gcc_qupv3_wrap1_s7_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap1_s7_clk_src = { + .cmd_rcgr = 0x18998, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s6_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap1_s7_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap2_s0_clk_src_init = { + .name = "gcc_qupv3_wrap2_s0_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap2_s0_clk_src = { + .cmd_rcgr = 0x1e148, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap2_s0_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap2_s1_clk_src_init = { + .name = "gcc_qupv3_wrap2_s1_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap2_s1_clk_src = { + .cmd_rcgr = 0x1e278, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap2_s1_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap2_s2_clk_src_init = { + .name = "gcc_qupv3_wrap2_s2_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap2_s2_clk_src = { + .cmd_rcgr = 0x1e3a8, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap2_s2_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap2_s3_clk_src_init = { + .name = "gcc_qupv3_wrap2_s3_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap2_s3_clk_src = { + .cmd_rcgr = 0x1e4d8, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap2_s3_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap2_s4_clk_src_init = { + .name = "gcc_qupv3_wrap2_s4_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap2_s4_clk_src = { + .cmd_rcgr = 0x1e608, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap2_s4_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap2_s5_clk_src_init = { + .name = "gcc_qupv3_wrap2_s5_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap2_s5_clk_src = { + .cmd_rcgr = 0x1e738, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap2_s5_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap2_s6_clk_src_init = { + .name = "gcc_qupv3_wrap2_s6_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap2_s6_clk_src = { + .cmd_rcgr = 0x1e868, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s6_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap2_s6_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap2_s7_clk_src_init = { + .name = "gcc_qupv3_wrap2_s7_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap2_s7_clk_src = { + .cmd_rcgr = 0x1e998, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s6_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap2_s7_clk_src_init, +}; + +static const struct freq_tbl ftbl_gcc_sdcc2_apps_clk_src[] = { + F(400000, P_BI_TCXO, 12, 1, 4), + F(25000000, P_GCC_GPLL0_OUT_EVEN, 12, 0, 0), + F(50000000, P_GCC_GPLL0_OUT_EVEN, 6, 0, 0), + F(100000000, P_GCC_GPLL0_OUT_EVEN, 3, 0, 0), + F(202000000, P_GCC_GPLL9_OUT_MAIN, 4, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_sdcc2_apps_clk_src = { + .cmd_rcgr = 0x1400c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_15, + .freq_tbl = ftbl_gcc_sdcc2_apps_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_sdcc2_apps_clk_src", + .parent_data = gcc_parent_data_15, + .num_parents = ARRAY_SIZE(gcc_parent_data_15), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_sdcc4_apps_clk_src[] = { + F(400000, P_BI_TCXO, 12, 1, 4), + F(25000000, P_GCC_GPLL0_OUT_EVEN, 12, 0, 0), + F(100000000, P_GCC_GPLL0_OUT_EVEN, 3, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_sdcc4_apps_clk_src = { + .cmd_rcgr = 0x1600c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_sdcc4_apps_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_sdcc4_apps_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_ufs_card_axi_clk_src[] = { + F(25000000, P_GCC_GPLL0_OUT_EVEN, 12, 0, 0), + F(75000000, P_GCC_GPLL0_OUT_EVEN, 4, 0, 0), + F(150000000, P_GCC_GPLL0_OUT_MAIN, 4, 0, 0), + F(300000000, P_GCC_GPLL0_OUT_MAIN, 2, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_ufs_card_axi_clk_src = { + .cmd_rcgr = 0x75024, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_ufs_card_axi_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_ufs_card_axi_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_ufs_card_ice_core_clk_src[] = { + F(75000000, P_GCC_GPLL0_OUT_EVEN, 4, 0, 0), + F(150000000, P_GCC_GPLL0_OUT_MAIN, 4, 0, 0), + F(300000000, P_GCC_GPLL0_OUT_MAIN, 2, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_ufs_card_ice_core_clk_src = { + .cmd_rcgr = 0x7506c, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_ufs_card_ice_core_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_ufs_card_ice_core_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_ufs_card_phy_aux_clk_src = { + .cmd_rcgr = 0x750a0, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_3, + .freq_tbl = ftbl_gcc_pcie_1_aux_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_ufs_card_phy_aux_clk_src", + .parent_data = gcc_parent_data_3, + .num_parents = ARRAY_SIZE(gcc_parent_data_3), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_ufs_card_unipro_core_clk_src = { + .cmd_rcgr = 0x75084, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_ufs_card_ice_core_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_ufs_card_unipro_core_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_ufs_phy_axi_clk_src = { + .cmd_rcgr = 0x77024, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_ufs_card_axi_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_ufs_phy_axi_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_ufs_phy_ice_core_clk_src = { + .cmd_rcgr = 0x7706c, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_ufs_card_ice_core_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_ufs_phy_ice_core_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_ufs_phy_phy_aux_clk_src = { + .cmd_rcgr = 0x770a0, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_3, + .freq_tbl = ftbl_gcc_pcie_0_aux_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_ufs_phy_phy_aux_clk_src", + .parent_data = gcc_parent_data_3, + .num_parents = ARRAY_SIZE(gcc_parent_data_3), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_ufs_phy_unipro_core_clk_src = { + .cmd_rcgr = 0x77084, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_ufs_card_ice_core_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_ufs_phy_unipro_core_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_usb30_mp_master_clk_src[] = { + F(66666667, P_GCC_GPLL0_OUT_EVEN, 4.5, 0, 0), + F(133333333, P_GCC_GPLL0_OUT_MAIN, 4.5, 0, 0), + F(200000000, P_GCC_GPLL0_OUT_MAIN, 3, 0, 0), + F(240000000, P_GCC_GPLL0_OUT_MAIN, 2.5, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_usb30_mp_master_clk_src = { + .cmd_rcgr = 0xab020, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_usb30_mp_master_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_usb30_mp_master_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_usb30_mp_mock_utmi_clk_src = { + .cmd_rcgr = 0xab038, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_pcie_1_aux_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_usb30_mp_mock_utmi_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_usb30_prim_master_clk_src = { + .cmd_rcgr = 0xf020, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_usb30_mp_master_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_usb30_prim_master_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_usb30_prim_mock_utmi_clk_src = { + .cmd_rcgr = 0xf038, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_pcie_1_aux_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_usb30_prim_mock_utmi_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_usb30_sec_master_clk_src = { + .cmd_rcgr = 0x10020, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_usb30_mp_master_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_usb30_sec_master_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_usb30_sec_mock_utmi_clk_src = { + .cmd_rcgr = 0x10038, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_pcie_1_aux_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_usb30_sec_mock_utmi_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_usb3_mp_phy_aux_clk_src = { + .cmd_rcgr = 0xab06c, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_pcie_1_aux_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_usb3_mp_phy_aux_clk_src", + .parent_data = gcc_parent_data_1, + .num_parents = ARRAY_SIZE(gcc_parent_data_1), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_usb3_prim_phy_aux_clk_src = { + .cmd_rcgr = 0xf068, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_pcie_1_aux_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_usb3_prim_phy_aux_clk_src", + .parent_data = gcc_parent_data_1, + .num_parents = ARRAY_SIZE(gcc_parent_data_1), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_usb3_sec_phy_aux_clk_src = { + .cmd_rcgr = 0x10068, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_pcie_1_aux_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_usb3_sec_phy_aux_clk_src", + .parent_data = gcc_parent_data_1, + .num_parents = ARRAY_SIZE(gcc_parent_data_1), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_usb4_1_master_clk_src[] = { + F(85714286, P_GCC_GPLL0_OUT_EVEN, 3.5, 0, 0), + F(175000000, P_GCC_GPLL8_OUT_MAIN, 4, 0, 0), + F(350000000, P_GCC_GPLL8_OUT_MAIN, 2, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_usb4_1_master_clk_src = { + .cmd_rcgr = 0xb8018, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_5, + .freq_tbl = ftbl_gcc_usb4_1_master_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_usb4_1_master_clk_src", + .parent_data = gcc_parent_data_5, + .num_parents = ARRAY_SIZE(gcc_parent_data_5), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_usb4_1_phy_pcie_pipe_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(125000000, P_GCC_GPLL7_OUT_MAIN, 4, 0, 0), + F(250000000, P_GCC_GPLL7_OUT_MAIN, 2, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_usb4_1_phy_pcie_pipe_clk_src = { + .cmd_rcgr = 0xb80c4, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_6, + .freq_tbl = ftbl_gcc_usb4_1_phy_pcie_pipe_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_usb4_1_phy_pcie_pipe_clk_src", + .parent_data = gcc_parent_data_6, + .num_parents = ARRAY_SIZE(gcc_parent_data_6), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_usb4_1_sb_if_clk_src = { + .cmd_rcgr = 0xb8070, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_pcie_1_aux_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_usb4_1_sb_if_clk_src", + .parent_data = gcc_parent_data_1, + .num_parents = ARRAY_SIZE(gcc_parent_data_1), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_usb4_1_tmu_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(250000000, P_GCC_GPLL2_OUT_MAIN, 4, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_usb4_1_tmu_clk_src = { + .cmd_rcgr = 0xb8054, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_7, + .freq_tbl = ftbl_gcc_usb4_1_tmu_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_usb4_1_tmu_clk_src", + .parent_data = gcc_parent_data_7, + .num_parents = ARRAY_SIZE(gcc_parent_data_7), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_usb4_master_clk_src = { + .cmd_rcgr = 0x2a018, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_5, + .freq_tbl = ftbl_gcc_usb4_1_master_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_usb4_master_clk_src", + .parent_data = gcc_parent_data_5, + .num_parents = ARRAY_SIZE(gcc_parent_data_5), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_usb4_phy_pcie_pipe_clk_src = { + .cmd_rcgr = 0x2a0c4, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_6, + .freq_tbl = ftbl_gcc_usb4_1_phy_pcie_pipe_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_usb4_phy_pcie_pipe_clk_src", + .parent_data = gcc_parent_data_6, + .num_parents = ARRAY_SIZE(gcc_parent_data_6), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_usb4_sb_if_clk_src = { + .cmd_rcgr = 0x2a070, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_pcie_1_aux_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_usb4_sb_if_clk_src", + .parent_data = gcc_parent_data_1, + .num_parents = ARRAY_SIZE(gcc_parent_data_1), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 gcc_usb4_tmu_clk_src = { + .cmd_rcgr = 0x2a054, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_7, + .freq_tbl = ftbl_gcc_usb4_1_tmu_clk_src, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_usb4_tmu_clk_src", + .parent_data = gcc_parent_data_7, + .num_parents = ARRAY_SIZE(gcc_parent_data_7), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_regmap_div gcc_pcie_2a_pipe_div_clk_src = { + .reg = 0x9d060, + .shift = 0, + .width = 4, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_2a_pipe_div_clk_src", + .parent_hws = (const struct clk_hw*[]){ + &gcc_pcie_2a_pipe_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ro_ops, + }, +}; + +static struct clk_regmap_div gcc_pcie_2b_pipe_div_clk_src = { + .reg = 0x9e060, + .shift = 0, + .width = 4, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_2b_pipe_div_clk_src", + .parent_hws = (const struct clk_hw*[]){ + &gcc_pcie_2b_pipe_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ro_ops, + }, +}; + +static struct clk_regmap_div gcc_pcie_3a_pipe_div_clk_src = { + .reg = 0xa0060, + .shift = 0, + .width = 4, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_3a_pipe_div_clk_src", + .parent_hws = (const struct clk_hw*[]){ + &gcc_pcie_3a_pipe_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ro_ops, + }, +}; + +static struct clk_regmap_div gcc_pcie_3b_pipe_div_clk_src = { + .reg = 0xa2060, + .shift = 0, + .width = 4, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_3b_pipe_div_clk_src", + .parent_hws = (const struct clk_hw*[]){ + &gcc_pcie_3b_pipe_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ro_ops, + }, +}; + +static struct clk_regmap_div gcc_pcie_4_pipe_div_clk_src = { + .reg = 0x6b060, + .shift = 0, + .width = 4, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_4_pipe_div_clk_src", + .parent_hws = (const struct clk_hw*[]){ + &gcc_pcie_4_pipe_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ro_ops, + }, +}; + +static struct clk_regmap_div gcc_qupv3_wrap0_s4_div_clk_src = { + .reg = 0x17ac8, + .shift = 0, + .width = 4, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap0_s4_div_clk_src", + .parent_hws = (const struct clk_hw*[]){ + &gcc_qupv3_wrap0_s4_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ro_ops, + }, +}; + +static struct clk_regmap_div gcc_qupv3_wrap1_s4_div_clk_src = { + .reg = 0x18ac8, + .shift = 0, + .width = 4, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap1_s4_div_clk_src", + .parent_hws = (const struct clk_hw*[]){ + &gcc_qupv3_wrap1_s4_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ro_ops, + }, +}; + +static struct clk_regmap_div gcc_qupv3_wrap2_s4_div_clk_src = { + .reg = 0x1eac8, + .shift = 0, + .width = 4, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap2_s4_div_clk_src", + .parent_hws = (const struct clk_hw*[]){ + &gcc_qupv3_wrap2_s4_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ro_ops, + }, +}; + +static struct clk_regmap_div gcc_usb30_mp_mock_utmi_postdiv_clk_src = { + .reg = 0xab050, + .shift = 0, + .width = 4, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_usb30_mp_mock_utmi_postdiv_clk_src", + .parent_hws = (const struct clk_hw*[]){ + &gcc_usb30_mp_mock_utmi_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ro_ops, + }, +}; + +static struct clk_regmap_div gcc_usb30_prim_mock_utmi_postdiv_clk_src = { + .reg = 0xf050, + .shift = 0, + .width = 4, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_usb30_prim_mock_utmi_postdiv_clk_src", + .parent_hws = (const struct clk_hw*[]){ + &gcc_usb30_prim_mock_utmi_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ro_ops, + }, +}; + +static struct clk_regmap_div gcc_usb30_sec_mock_utmi_postdiv_clk_src = { + .reg = 0x10050, + .shift = 0, + .width = 4, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "gcc_usb30_sec_mock_utmi_postdiv_clk_src", + .parent_hws = (const struct clk_hw*[]){ + &gcc_usb30_sec_mock_utmi_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ro_ops, + }, +}; + +static struct clk_branch gcc_aggre_noc_pcie0_tunnel_axi_clk = { + .halt_reg = 0xa41a8, + .halt_check = BRANCH_HALT_SKIP, + .hwcg_reg = 0xa41a8, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x52018, + .enable_mask = BIT(14), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_aggre_noc_pcie0_tunnel_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_aggre_noc_pcie1_tunnel_axi_clk = { + .halt_reg = 0x8d07c, + .halt_check = BRANCH_HALT_SKIP, + .hwcg_reg = 0x8d07c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x52018, + .enable_mask = BIT(21), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_aggre_noc_pcie1_tunnel_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_aggre_noc_pcie_4_axi_clk = { + .halt_reg = 0x6b1b8, + .halt_check = BRANCH_HALT_SKIP, + .hwcg_reg = 0x6b1b8, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x52000, + .enable_mask = BIT(12), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_aggre_noc_pcie_4_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_aggre_noc_pcie_south_sf_axi_clk = { + .halt_reg = 0xbf13c, + .halt_check = BRANCH_HALT_SKIP, + .hwcg_reg = 0xbf13c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x52018, + .enable_mask = BIT(13), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_aggre_noc_pcie_south_sf_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_aggre_ufs_card_axi_clk = { + .halt_reg = 0x750cc, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x750cc, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x750cc, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_aggre_ufs_card_axi_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_ufs_card_axi_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_aggre_ufs_card_axi_hw_ctl_clk = { + .halt_reg = 0x750cc, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x750cc, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x750cc, + .enable_mask = BIT(1), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_aggre_ufs_card_axi_hw_ctl_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_ufs_card_axi_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_aggre_ufs_phy_axi_clk = { + .halt_reg = 0x770cc, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x770cc, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x770cc, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_aggre_ufs_phy_axi_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_ufs_phy_axi_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_aggre_ufs_phy_axi_hw_ctl_clk = { + .halt_reg = 0x770cc, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x770cc, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x770cc, + .enable_mask = BIT(1), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_aggre_ufs_phy_axi_hw_ctl_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_ufs_phy_axi_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_aggre_usb3_mp_axi_clk = { + .halt_reg = 0xab084, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0xab084, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0xab084, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_aggre_usb3_mp_axi_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_usb30_mp_master_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_aggre_usb3_prim_axi_clk = { + .halt_reg = 0xf080, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0xf080, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0xf080, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_aggre_usb3_prim_axi_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_usb30_prim_master_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_aggre_usb3_sec_axi_clk = { + .halt_reg = 0x10080, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x10080, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x10080, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_aggre_usb3_sec_axi_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_usb30_sec_master_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_aggre_usb4_1_axi_clk = { + .halt_reg = 0xb80e4, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0xb80e4, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0xb80e4, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_aggre_usb4_1_axi_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_usb4_1_master_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_aggre_usb4_axi_clk = { + .halt_reg = 0x2a0e4, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x2a0e4, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x2a0e4, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_aggre_usb4_axi_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_usb4_master_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_aggre_usb_noc_axi_clk = { + .halt_reg = 0x5d024, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x5d024, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x5d024, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_aggre_usb_noc_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_aggre_usb_noc_north_axi_clk = { + .halt_reg = 0x5d020, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x5d020, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x5d020, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_aggre_usb_noc_north_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_aggre_usb_noc_south_axi_clk = { + .halt_reg = 0x5d01c, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x5d01c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x5d01c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_aggre_usb_noc_south_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ahb2phy0_clk = { + .halt_reg = 0x6a004, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x6a004, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x6a004, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_ahb2phy0_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ahb2phy2_clk = { + .halt_reg = 0x6a008, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x6a008, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x6a008, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_ahb2phy2_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_boot_rom_ahb_clk = { + .halt_reg = 0x38004, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x38004, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x52000, + .enable_mask = BIT(10), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_boot_rom_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camera_hf_axi_clk = { + .halt_reg = 0x26010, + .halt_check = BRANCH_HALT_SKIP, + .hwcg_reg = 0x26010, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x26010, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_camera_hf_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camera_sf_axi_clk = { + .halt_reg = 0x26014, + .halt_check = BRANCH_HALT_SKIP, + .hwcg_reg = 0x26014, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x26014, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_camera_sf_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camera_throttle_nrt_axi_clk = { + .halt_reg = 0x2601c, + .halt_check = BRANCH_HALT_SKIP, + .hwcg_reg = 0x2601c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x2601c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_camera_throttle_nrt_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camera_throttle_rt_axi_clk = { + .halt_reg = 0x26018, + .halt_check = BRANCH_HALT_SKIP, + .hwcg_reg = 0x26018, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x26018, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_camera_throttle_rt_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camera_throttle_xo_clk = { + .halt_reg = 0x26024, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x26024, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_camera_throttle_xo_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_cfg_noc_usb3_mp_axi_clk = { + .halt_reg = 0xab088, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0xab088, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0xab088, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_cfg_noc_usb3_mp_axi_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_usb30_mp_master_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_cfg_noc_usb3_prim_axi_clk = { + .halt_reg = 0xf084, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0xf084, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0xf084, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_cfg_noc_usb3_prim_axi_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_usb30_prim_master_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_cfg_noc_usb3_sec_axi_clk = { + .halt_reg = 0x10084, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x10084, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x10084, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_cfg_noc_usb3_sec_axi_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_usb30_sec_master_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_cnoc_pcie0_tunnel_clk = { + .halt_reg = 0xa4074, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52020, + .enable_mask = BIT(8), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_cnoc_pcie0_tunnel_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_cnoc_pcie1_tunnel_clk = { + .halt_reg = 0x8d074, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52020, + .enable_mask = BIT(9), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_cnoc_pcie1_tunnel_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_cnoc_pcie4_qx_clk = { + .halt_reg = 0x6b084, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x6b084, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x52020, + .enable_mask = BIT(10), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_cnoc_pcie4_qx_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ddrss_gpu_axi_clk = { + .halt_reg = 0x7115c, + .halt_check = BRANCH_HALT_SKIP, + .hwcg_reg = 0x7115c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x7115c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_ddrss_gpu_axi_clk", + .ops = &clk_branch2_aon_ops, + }, + }, +}; + +static struct clk_branch gcc_ddrss_pcie_sf_tbu_clk = { + .halt_reg = 0xa602c, + .halt_check = BRANCH_HALT_SKIP, + .hwcg_reg = 0xa602c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x52000, + .enable_mask = BIT(19), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_ddrss_pcie_sf_tbu_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_disp1_hf_axi_clk = { + .halt_reg = 0xbb010, + .halt_check = BRANCH_HALT_SKIP, + .hwcg_reg = 0xbb010, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0xbb010, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_disp1_hf_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_disp1_sf_axi_clk = { + .halt_reg = 0xbb018, + .halt_check = BRANCH_HALT_SKIP, + .hwcg_reg = 0xbb018, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0xbb018, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_disp1_sf_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_disp1_throttle_nrt_axi_clk = { + .halt_reg = 0xbb024, + .halt_check = BRANCH_HALT_SKIP, + .hwcg_reg = 0xbb024, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0xbb024, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_disp1_throttle_nrt_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_disp1_throttle_rt_axi_clk = { + .halt_reg = 0xbb020, + .halt_check = BRANCH_HALT_SKIP, + .hwcg_reg = 0xbb020, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0xbb020, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_disp1_throttle_rt_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_disp_hf_axi_clk = { + .halt_reg = 0x27010, + .halt_check = BRANCH_HALT_SKIP, + .hwcg_reg = 0x27010, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x27010, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_disp_hf_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_disp_sf_axi_clk = { + .halt_reg = 0x27018, + .halt_check = BRANCH_HALT_SKIP, + .hwcg_reg = 0x27018, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x27018, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_disp_sf_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_disp_throttle_nrt_axi_clk = { + .halt_reg = 0x27024, + .halt_check = BRANCH_HALT_SKIP, + .hwcg_reg = 0x27024, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x27024, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_disp_throttle_nrt_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_disp_throttle_rt_axi_clk = { + .halt_reg = 0x27020, + .halt_check = BRANCH_HALT_SKIP, + .hwcg_reg = 0x27020, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x27020, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_disp_throttle_rt_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_emac0_axi_clk = { + .halt_reg = 0xaa010, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0xaa010, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0xaa010, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac0_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_emac0_ptp_clk = { + .halt_reg = 0xaa01c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xaa01c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac0_ptp_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_emac0_ptp_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_emac0_rgmii_clk = { + .halt_reg = 0xaa038, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xaa038, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac0_rgmii_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_emac0_rgmii_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_emac0_slv_ahb_clk = { + .halt_reg = 0xaa018, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0xaa018, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0xaa018, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac0_slv_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_emac1_axi_clk = { + .halt_reg = 0xba010, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0xba010, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0xba010, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac1_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_emac1_ptp_clk = { + .halt_reg = 0xba01c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xba01c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac1_ptp_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_emac1_ptp_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_emac1_rgmii_clk = { + .halt_reg = 0xba038, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xba038, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac1_rgmii_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_emac1_rgmii_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_emac1_slv_ahb_clk = { + .halt_reg = 0xba018, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0xba018, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0xba018, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_emac1_slv_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gp1_clk = { + .halt_reg = 0x64000, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x64000, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_gp1_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_gp1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gp2_clk = { + .halt_reg = 0x65000, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x65000, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_gp2_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_gp2_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gp3_clk = { + .halt_reg = 0x66000, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x66000, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_gp3_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_gp3_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gp4_clk = { + .halt_reg = 0xc2000, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xc2000, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_gp4_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_gp4_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gp5_clk = { + .halt_reg = 0xc3000, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xc3000, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_gp5_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_gp5_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gpu_gpll0_clk_src = { + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x52000, + .enable_mask = BIT(15), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_gpu_gpll0_clk_src", + .parent_hws = (const struct clk_hw*[]){ + &gcc_gpll0.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gpu_gpll0_div_clk_src = { + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x52000, + .enable_mask = BIT(16), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_gpu_gpll0_div_clk_src", + .parent_hws = (const struct clk_hw*[]){ + &gcc_gpll0_out_even.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gpu_iref_en = { + .halt_reg = 0x8c014, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x8c014, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_gpu_iref_en", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gpu_memnoc_gfx_clk = { + .halt_reg = 0x71010, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x71010, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x71010, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_gpu_memnoc_gfx_clk", + .ops = &clk_branch2_aon_ops, + }, + }, +}; + +static struct clk_branch gcc_gpu_snoc_dvm_gfx_clk = { + .halt_reg = 0x71020, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x71020, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_gpu_snoc_dvm_gfx_clk", + .ops = &clk_branch2_aon_ops, + }, + }, +}; + +static struct clk_branch gcc_gpu_tcu_throttle_ahb_clk = { + .halt_reg = 0x71008, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x71008, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x71008, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_gpu_tcu_throttle_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gpu_tcu_throttle_clk = { + .halt_reg = 0x71018, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x71018, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x71018, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_gpu_tcu_throttle_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie0_phy_rchng_clk = { + .halt_reg = 0xa4038, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52018, + .enable_mask = BIT(11), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie0_phy_rchng_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_pcie_0_phy_rchng_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie1_phy_rchng_clk = { + .halt_reg = 0x8d038, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52000, + .enable_mask = BIT(23), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie1_phy_rchng_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_pcie_1_phy_rchng_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie2a_phy_rchng_clk = { + .halt_reg = 0x9d040, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52010, + .enable_mask = BIT(15), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie2a_phy_rchng_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_pcie_2a_phy_rchng_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie2b_phy_rchng_clk = { + .halt_reg = 0x9e040, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52010, + .enable_mask = BIT(22), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie2b_phy_rchng_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_pcie_2b_phy_rchng_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie3a_phy_rchng_clk = { + .halt_reg = 0xa0040, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52010, + .enable_mask = BIT(29), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie3a_phy_rchng_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_pcie_3a_phy_rchng_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie3b_phy_rchng_clk = { + .halt_reg = 0xa2040, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52018, + .enable_mask = BIT(4), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie3b_phy_rchng_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_pcie_3b_phy_rchng_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie4_phy_rchng_clk = { + .halt_reg = 0x6b040, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52000, + .enable_mask = BIT(22), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie4_phy_rchng_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_pcie_4_phy_rchng_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_0_aux_clk = { + .halt_reg = 0xa4028, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52018, + .enable_mask = BIT(9), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_0_aux_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_pcie_0_aux_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_0_cfg_ahb_clk = { + .halt_reg = 0xa4024, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0xa4024, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x52018, + .enable_mask = BIT(8), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_0_cfg_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_0_mstr_axi_clk = { + .halt_reg = 0xa401c, + .halt_check = BRANCH_HALT_SKIP, + .hwcg_reg = 0xa401c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x52018, + .enable_mask = BIT(7), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_0_mstr_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_0_pipe_clk = { + .halt_reg = 0xa4030, + .halt_check = BRANCH_HALT_SKIP, + .clkr = { + .enable_reg = 0x52018, + .enable_mask = BIT(10), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_0_pipe_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_usb4_phy_pcie_pipe_mux_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_0_slv_axi_clk = { + .halt_reg = 0xa4014, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0xa4014, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x52018, + .enable_mask = BIT(6), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_0_slv_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_0_slv_q2a_axi_clk = { + .halt_reg = 0xa4010, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52018, + .enable_mask = BIT(5), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_0_slv_q2a_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_1_aux_clk = { + .halt_reg = 0x8d028, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52000, + .enable_mask = BIT(29), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_1_aux_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_pcie_1_aux_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_1_cfg_ahb_clk = { + .halt_reg = 0x8d024, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x8d024, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x52000, + .enable_mask = BIT(28), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_1_cfg_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_1_mstr_axi_clk = { + .halt_reg = 0x8d01c, + .halt_check = BRANCH_HALT_SKIP, + .hwcg_reg = 0x8d01c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x52000, + .enable_mask = BIT(27), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_1_mstr_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_1_pipe_clk = { + .halt_reg = 0x8d030, + .halt_check = BRANCH_HALT_SKIP, + .clkr = { + .enable_reg = 0x52000, + .enable_mask = BIT(30), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_1_pipe_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_usb4_1_phy_pcie_pipe_mux_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_1_slv_axi_clk = { + .halt_reg = 0x8d014, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x8d014, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x52000, + .enable_mask = BIT(26), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_1_slv_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_1_slv_q2a_axi_clk = { + .halt_reg = 0x8d010, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52000, + .enable_mask = BIT(25), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_1_slv_q2a_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_2a2b_clkref_clk = { + .halt_reg = 0x8c034, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x8c034, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_2a2b_clkref_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_2a_aux_clk = { + .halt_reg = 0x9d028, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52010, + .enable_mask = BIT(13), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_2a_aux_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_pcie_2a_aux_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_2a_cfg_ahb_clk = { + .halt_reg = 0x9d024, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x9d024, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x52010, + .enable_mask = BIT(12), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_2a_cfg_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_2a_mstr_axi_clk = { + .halt_reg = 0x9d01c, + .halt_check = BRANCH_HALT_SKIP, + .hwcg_reg = 0x9d01c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x52010, + .enable_mask = BIT(11), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_2a_mstr_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_2a_pipe_clk = { + .halt_reg = 0x9d030, + .halt_check = BRANCH_HALT_SKIP, + .clkr = { + .enable_reg = 0x52010, + .enable_mask = BIT(14), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_2a_pipe_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_pcie_2a_pipe_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_2a_pipediv2_clk = { + .halt_reg = 0x9d038, + .halt_check = BRANCH_HALT_SKIP, + .clkr = { + .enable_reg = 0x52018, + .enable_mask = BIT(22), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_2a_pipediv2_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_pcie_2a_pipe_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_2a_slv_axi_clk = { + .halt_reg = 0x9d014, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x9d014, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x52010, + .enable_mask = BIT(10), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_2a_slv_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_2a_slv_q2a_axi_clk = { + .halt_reg = 0x9d010, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52018, + .enable_mask = BIT(12), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_2a_slv_q2a_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_2b_aux_clk = { + .halt_reg = 0x9e028, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52010, + .enable_mask = BIT(20), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_2b_aux_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_pcie_2b_aux_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_2b_cfg_ahb_clk = { + .halt_reg = 0x9e024, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x9e024, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x52010, + .enable_mask = BIT(19), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_2b_cfg_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_2b_mstr_axi_clk = { + .halt_reg = 0x9e01c, + .halt_check = BRANCH_HALT_SKIP, + .hwcg_reg = 0x9e01c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x52010, + .enable_mask = BIT(18), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_2b_mstr_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_2b_pipe_clk = { + .halt_reg = 0x9e030, + .halt_check = BRANCH_HALT_SKIP, + .clkr = { + .enable_reg = 0x52010, + .enable_mask = BIT(21), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_2b_pipe_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_pcie_2b_pipe_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_2b_pipediv2_clk = { + .halt_reg = 0x9e038, + .halt_check = BRANCH_HALT_SKIP, + .clkr = { + .enable_reg = 0x52018, + .enable_mask = BIT(23), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_2b_pipediv2_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_pcie_2b_pipe_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_2b_slv_axi_clk = { + .halt_reg = 0x9e014, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x9e014, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x52010, + .enable_mask = BIT(17), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_2b_slv_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_2b_slv_q2a_axi_clk = { + .halt_reg = 0x9e010, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52010, + .enable_mask = BIT(16), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_2b_slv_q2a_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_3a3b_clkref_clk = { + .halt_reg = 0x8c038, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x8c038, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_3a3b_clkref_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_3a_aux_clk = { + .halt_reg = 0xa0028, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52010, + .enable_mask = BIT(27), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_3a_aux_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_pcie_3a_aux_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_3a_cfg_ahb_clk = { + .halt_reg = 0xa0024, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0xa0024, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x52010, + .enable_mask = BIT(26), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_3a_cfg_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_3a_mstr_axi_clk = { + .halt_reg = 0xa001c, + .halt_check = BRANCH_HALT_SKIP, + .hwcg_reg = 0xa001c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x52010, + .enable_mask = BIT(25), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_3a_mstr_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_3a_pipe_clk = { + .halt_reg = 0xa0030, + .halt_check = BRANCH_HALT_SKIP, + .clkr = { + .enable_reg = 0x52010, + .enable_mask = BIT(28), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_3a_pipe_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_pcie_3a_pipe_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_3a_pipediv2_clk = { + .halt_reg = 0xa0038, + .halt_check = BRANCH_HALT_SKIP, + .clkr = { + .enable_reg = 0x52018, + .enable_mask = BIT(24), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_3a_pipediv2_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_pcie_3a_pipe_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_3a_slv_axi_clk = { + .halt_reg = 0xa0014, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0xa0014, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x52010, + .enable_mask = BIT(24), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_3a_slv_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_3a_slv_q2a_axi_clk = { + .halt_reg = 0xa0010, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52010, + .enable_mask = BIT(23), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_3a_slv_q2a_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_3b_aux_clk = { + .halt_reg = 0xa2028, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52018, + .enable_mask = BIT(2), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_3b_aux_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_pcie_3b_aux_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_3b_cfg_ahb_clk = { + .halt_reg = 0xa2024, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0xa2024, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x52018, + .enable_mask = BIT(1), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_3b_cfg_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_3b_mstr_axi_clk = { + .halt_reg = 0xa201c, + .halt_check = BRANCH_HALT_SKIP, + .hwcg_reg = 0xa201c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x52018, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_3b_mstr_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_3b_pipe_clk = { + .halt_reg = 0xa2030, + .halt_check = BRANCH_HALT_SKIP, + .clkr = { + .enable_reg = 0x52018, + .enable_mask = BIT(3), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_3b_pipe_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_pcie_3b_pipe_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_3b_pipediv2_clk = { + .halt_reg = 0xa2038, + .halt_check = BRANCH_HALT_SKIP, + .clkr = { + .enable_reg = 0x52018, + .enable_mask = BIT(25), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_3b_pipediv2_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_pcie_3b_pipe_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_3b_slv_axi_clk = { + .halt_reg = 0xa2014, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0xa2014, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x52010, + .enable_mask = BIT(31), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_3b_slv_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_3b_slv_q2a_axi_clk = { + .halt_reg = 0xa2010, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52010, + .enable_mask = BIT(30), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_3b_slv_q2a_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_4_aux_clk = { + .halt_reg = 0x6b028, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(3), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_4_aux_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_pcie_4_aux_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_4_cfg_ahb_clk = { + .halt_reg = 0x6b024, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x6b024, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(2), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_4_cfg_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_4_clkref_clk = { + .halt_reg = 0x8c030, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x8c030, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_4_clkref_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_4_mstr_axi_clk = { + .halt_reg = 0x6b01c, + .halt_check = BRANCH_HALT_SKIP, + .hwcg_reg = 0x6b01c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(1), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_4_mstr_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_4_pipe_clk = { + .halt_reg = 0x6b030, + .halt_check = BRANCH_HALT_SKIP, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(4), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_4_pipe_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_pcie_4_pipe_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_4_pipediv2_clk = { + .halt_reg = 0x6b038, + .halt_check = BRANCH_HALT_SKIP, + .clkr = { + .enable_reg = 0x52018, + .enable_mask = BIT(16), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_4_pipediv2_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_pcie_4_pipe_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_4_slv_axi_clk = { + .halt_reg = 0x6b014, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x6b014, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_4_slv_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_4_slv_q2a_axi_clk = { + .halt_reg = 0x6b010, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(5), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_4_slv_q2a_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_rscc_ahb_clk = { + .halt_reg = 0xae008, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0xae008, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x52020, + .enable_mask = BIT(17), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_rscc_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_rscc_xo_clk = { + .halt_reg = 0xae004, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52020, + .enable_mask = BIT(16), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_rscc_xo_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_pcie_rscc_xo_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_throttle_cfg_clk = { + .halt_reg = 0xa6028, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52020, + .enable_mask = BIT(15), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pcie_throttle_cfg_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pdm2_clk = { + .halt_reg = 0x3300c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x3300c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pdm2_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_pdm2_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pdm_ahb_clk = { + .halt_reg = 0x33004, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x33004, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x33004, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pdm_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pdm_xo4_clk = { + .halt_reg = 0x33008, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x33008, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_pdm_xo4_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qmip_camera_nrt_ahb_clk = { + .halt_reg = 0x26008, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x26008, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x26008, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qmip_camera_nrt_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qmip_camera_rt_ahb_clk = { + .halt_reg = 0x2600c, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x2600c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x2600c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qmip_camera_rt_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qmip_disp1_ahb_clk = { + .halt_reg = 0xbb008, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0xbb008, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0xbb008, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qmip_disp1_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qmip_disp1_rot_ahb_clk = { + .halt_reg = 0xbb00c, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0xbb00c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0xbb00c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qmip_disp1_rot_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qmip_disp_ahb_clk = { + .halt_reg = 0x27008, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x27008, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x27008, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qmip_disp_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qmip_disp_rot_ahb_clk = { + .halt_reg = 0x2700c, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x2700c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x2700c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qmip_disp_rot_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qmip_video_cvp_ahb_clk = { + .halt_reg = 0x28008, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x28008, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x28008, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qmip_video_cvp_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qmip_video_vcodec_ahb_clk = { + .halt_reg = 0x2800c, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x2800c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x2800c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qmip_video_vcodec_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_core_2x_clk = { + .halt_reg = 0x17014, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(9), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap0_core_2x_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_core_clk = { + .halt_reg = 0x1700c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(8), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap0_core_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_qspi0_clk = { + .halt_reg = 0x17ac4, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52020, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap0_qspi0_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_qupv3_wrap0_s4_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_s0_clk = { + .halt_reg = 0x17144, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(10), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap0_s0_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_qupv3_wrap0_s0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_s1_clk = { + .halt_reg = 0x17274, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(11), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap0_s1_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_qupv3_wrap0_s1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_s2_clk = { + .halt_reg = 0x173a4, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(12), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap0_s2_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_qupv3_wrap0_s2_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_s3_clk = { + .halt_reg = 0x174d4, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(13), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap0_s3_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_qupv3_wrap0_s3_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_s4_clk = { + .halt_reg = 0x17604, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(14), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap0_s4_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_qupv3_wrap0_s4_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_s5_clk = { + .halt_reg = 0x17734, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(15), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap0_s5_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_qupv3_wrap0_s5_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_s6_clk = { + .halt_reg = 0x17864, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(16), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap0_s6_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_qupv3_wrap0_s6_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_s7_clk = { + .halt_reg = 0x17994, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(17), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap0_s7_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_qupv3_wrap0_s7_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap1_core_2x_clk = { + .halt_reg = 0x18014, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(18), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap1_core_2x_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap1_core_clk = { + .halt_reg = 0x1800c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(19), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap1_core_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap1_qspi0_clk = { + .halt_reg = 0x18ac4, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52020, + .enable_mask = BIT(2), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap1_qspi0_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_qupv3_wrap1_s4_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap1_s0_clk = { + .halt_reg = 0x18144, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(22), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap1_s0_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_qupv3_wrap1_s0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap1_s1_clk = { + .halt_reg = 0x18274, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(23), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap1_s1_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_qupv3_wrap1_s1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap1_s2_clk = { + .halt_reg = 0x183a4, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(24), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap1_s2_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_qupv3_wrap1_s2_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap1_s3_clk = { + .halt_reg = 0x184d4, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(25), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap1_s3_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_qupv3_wrap1_s3_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap1_s4_clk = { + .halt_reg = 0x18604, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(26), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap1_s4_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_qupv3_wrap1_s4_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap1_s5_clk = { + .halt_reg = 0x18734, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(27), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap1_s5_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_qupv3_wrap1_s5_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap1_s6_clk = { + .halt_reg = 0x18864, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52018, + .enable_mask = BIT(27), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap1_s6_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_qupv3_wrap1_s6_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap1_s7_clk = { + .halt_reg = 0x18994, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52018, + .enable_mask = BIT(28), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap1_s7_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_qupv3_wrap1_s7_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap2_core_2x_clk = { + .halt_reg = 0x1e014, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52010, + .enable_mask = BIT(3), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap2_core_2x_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap2_core_clk = { + .halt_reg = 0x1e00c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52010, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap2_core_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap2_qspi0_clk = { + .halt_reg = 0x1eac4, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52020, + .enable_mask = BIT(4), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap2_qspi0_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_qupv3_wrap2_s4_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap2_s0_clk = { + .halt_reg = 0x1e144, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52010, + .enable_mask = BIT(4), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap2_s0_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_qupv3_wrap2_s0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap2_s1_clk = { + .halt_reg = 0x1e274, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52010, + .enable_mask = BIT(5), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap2_s1_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_qupv3_wrap2_s1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap2_s2_clk = { + .halt_reg = 0x1e3a4, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52010, + .enable_mask = BIT(6), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap2_s2_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_qupv3_wrap2_s2_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap2_s3_clk = { + .halt_reg = 0x1e4d4, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52010, + .enable_mask = BIT(7), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap2_s3_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_qupv3_wrap2_s3_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap2_s4_clk = { + .halt_reg = 0x1e604, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52010, + .enable_mask = BIT(8), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap2_s4_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_qupv3_wrap2_s4_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap2_s5_clk = { + .halt_reg = 0x1e734, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52010, + .enable_mask = BIT(9), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap2_s5_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_qupv3_wrap2_s5_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap2_s6_clk = { + .halt_reg = 0x1e864, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52018, + .enable_mask = BIT(29), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap2_s6_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_qupv3_wrap2_s6_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap2_s7_clk = { + .halt_reg = 0x1e994, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52018, + .enable_mask = BIT(30), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap2_s7_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_qupv3_wrap2_s7_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap_0_m_ahb_clk = { + .halt_reg = 0x17004, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x17004, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(6), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap_0_m_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap_0_s_ahb_clk = { + .halt_reg = 0x17008, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x17008, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(7), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap_0_s_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap_1_m_ahb_clk = { + .halt_reg = 0x18004, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x18004, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(20), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap_1_m_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap_1_s_ahb_clk = { + .halt_reg = 0x18008, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x18008, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(21), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap_1_s_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap_2_m_ahb_clk = { + .halt_reg = 0x1e004, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x1e004, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x52010, + .enable_mask = BIT(2), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap_2_m_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap_2_s_ahb_clk = { + .halt_reg = 0x1e008, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x1e008, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x52010, + .enable_mask = BIT(1), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_qupv3_wrap_2_s_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sdcc2_ahb_clk = { + .halt_reg = 0x14008, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x14008, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_sdcc2_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sdcc2_apps_clk = { + .halt_reg = 0x14004, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x14004, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_sdcc2_apps_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_sdcc2_apps_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sdcc4_ahb_clk = { + .halt_reg = 0x16008, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x16008, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_sdcc4_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sdcc4_apps_clk = { + .halt_reg = 0x16004, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x16004, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_sdcc4_apps_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_sdcc4_apps_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sys_noc_usb_axi_clk = { + .halt_reg = 0x5d000, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x5d000, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x5d000, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_sys_noc_usb_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_1_card_clkref_clk = { + .halt_reg = 0x8c000, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x8c000, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_ufs_1_card_clkref_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_card_ahb_clk = { + .halt_reg = 0x75018, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x75018, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x75018, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_ufs_card_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_card_axi_clk = { + .halt_reg = 0x75010, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x75010, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x75010, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_ufs_card_axi_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_ufs_card_axi_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_card_axi_hw_ctl_clk = { + .halt_reg = 0x75010, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x75010, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x75010, + .enable_mask = BIT(1), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_ufs_card_axi_hw_ctl_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_ufs_card_axi_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_card_clkref_clk = { + .halt_reg = 0x8c054, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x8c054, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_ufs_card_clkref_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_card_ice_core_clk = { + .halt_reg = 0x75064, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x75064, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x75064, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_ufs_card_ice_core_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_ufs_card_ice_core_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_card_ice_core_hw_ctl_clk = { + .halt_reg = 0x75064, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x75064, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x75064, + .enable_mask = BIT(1), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_ufs_card_ice_core_hw_ctl_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_ufs_card_ice_core_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_card_phy_aux_clk = { + .halt_reg = 0x7509c, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x7509c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x7509c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_ufs_card_phy_aux_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_ufs_card_phy_aux_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_card_phy_aux_hw_ctl_clk = { + .halt_reg = 0x7509c, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x7509c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x7509c, + .enable_mask = BIT(1), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_ufs_card_phy_aux_hw_ctl_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_ufs_card_phy_aux_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_card_rx_symbol_0_clk = { + .halt_reg = 0x75020, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x75020, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_ufs_card_rx_symbol_0_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_ufs_card_rx_symbol_0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_card_rx_symbol_1_clk = { + .halt_reg = 0x750b8, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x750b8, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_ufs_card_rx_symbol_1_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_ufs_card_rx_symbol_1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_card_tx_symbol_0_clk = { + .halt_reg = 0x7501c, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x7501c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_ufs_card_tx_symbol_0_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_ufs_card_tx_symbol_0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_card_unipro_core_clk = { + .halt_reg = 0x7505c, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x7505c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x7505c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_ufs_card_unipro_core_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_ufs_card_unipro_core_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_card_unipro_core_hw_ctl_clk = { + .halt_reg = 0x7505c, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x7505c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x7505c, + .enable_mask = BIT(1), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_ufs_card_unipro_core_hw_ctl_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_ufs_card_unipro_core_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_phy_ahb_clk = { + .halt_reg = 0x77018, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x77018, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x77018, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_ufs_phy_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_phy_axi_clk = { + .halt_reg = 0x77010, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x77010, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x77010, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_ufs_phy_axi_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_ufs_phy_axi_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_phy_axi_hw_ctl_clk = { + .halt_reg = 0x77010, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x77010, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x77010, + .enable_mask = BIT(1), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_ufs_phy_axi_hw_ctl_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_ufs_phy_axi_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_phy_ice_core_clk = { + .halt_reg = 0x77064, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x77064, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x77064, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_ufs_phy_ice_core_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_ufs_phy_ice_core_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_phy_ice_core_hw_ctl_clk = { + .halt_reg = 0x77064, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x77064, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x77064, + .enable_mask = BIT(1), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_ufs_phy_ice_core_hw_ctl_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_ufs_phy_ice_core_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_phy_phy_aux_clk = { + .halt_reg = 0x7709c, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x7709c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x7709c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_ufs_phy_phy_aux_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_ufs_phy_phy_aux_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_phy_phy_aux_hw_ctl_clk = { + .halt_reg = 0x7709c, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x7709c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x7709c, + .enable_mask = BIT(1), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_ufs_phy_phy_aux_hw_ctl_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_ufs_phy_phy_aux_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_phy_rx_symbol_0_clk = { + .halt_reg = 0x77020, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x77020, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_ufs_phy_rx_symbol_0_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_ufs_phy_rx_symbol_0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_phy_rx_symbol_1_clk = { + .halt_reg = 0x770b8, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x770b8, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_ufs_phy_rx_symbol_1_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_ufs_phy_rx_symbol_1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_phy_tx_symbol_0_clk = { + .halt_reg = 0x7701c, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x7701c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_ufs_phy_tx_symbol_0_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_ufs_phy_tx_symbol_0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_phy_unipro_core_clk = { + .halt_reg = 0x7705c, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x7705c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x7705c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_ufs_phy_unipro_core_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_ufs_phy_unipro_core_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_phy_unipro_core_hw_ctl_clk = { + .halt_reg = 0x7705c, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x7705c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x7705c, + .enable_mask = BIT(1), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_ufs_phy_unipro_core_hw_ctl_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_ufs_phy_unipro_core_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_ref_clkref_clk = { + .halt_reg = 0x8c058, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x8c058, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_ufs_ref_clkref_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb2_hs0_clkref_clk = { + .halt_reg = 0x8c044, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x8c044, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb2_hs0_clkref_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb2_hs1_clkref_clk = { + .halt_reg = 0x8c048, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x8c048, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb2_hs1_clkref_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb2_hs2_clkref_clk = { + .halt_reg = 0x8c04c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x8c04c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb2_hs2_clkref_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb2_hs3_clkref_clk = { + .halt_reg = 0x8c050, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x8c050, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb2_hs3_clkref_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb30_mp_master_clk = { + .halt_reg = 0xab010, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xab010, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb30_mp_master_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_usb30_mp_master_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb30_mp_mock_utmi_clk = { + .halt_reg = 0xab01c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xab01c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb30_mp_mock_utmi_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_usb30_mp_mock_utmi_postdiv_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb30_mp_sleep_clk = { + .halt_reg = 0xab018, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xab018, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb30_mp_sleep_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb30_prim_master_clk = { + .halt_reg = 0xf010, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xf010, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb30_prim_master_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_usb30_prim_master_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb30_prim_mock_utmi_clk = { + .halt_reg = 0xf01c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xf01c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb30_prim_mock_utmi_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_usb30_prim_mock_utmi_postdiv_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb30_prim_sleep_clk = { + .halt_reg = 0xf018, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xf018, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb30_prim_sleep_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb30_sec_master_clk = { + .halt_reg = 0x10010, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x10010, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb30_sec_master_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_usb30_sec_master_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb30_sec_mock_utmi_clk = { + .halt_reg = 0x1001c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1001c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb30_sec_mock_utmi_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_usb30_sec_mock_utmi_postdiv_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb30_sec_sleep_clk = { + .halt_reg = 0x10018, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x10018, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb30_sec_sleep_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb3_mp0_clkref_clk = { + .halt_reg = 0x8c03c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x8c03c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb3_mp0_clkref_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb3_mp1_clkref_clk = { + .halt_reg = 0x8c040, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x8c040, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb3_mp1_clkref_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb3_mp_phy_aux_clk = { + .halt_reg = 0xab054, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xab054, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb3_mp_phy_aux_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_usb3_mp_phy_aux_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb3_mp_phy_com_aux_clk = { + .halt_reg = 0xab058, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xab058, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb3_mp_phy_com_aux_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_usb3_mp_phy_aux_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb3_mp_phy_pipe_0_clk = { + .halt_reg = 0xab05c, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0xab05c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb3_mp_phy_pipe_0_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_usb3_mp_phy_pipe_0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb3_mp_phy_pipe_1_clk = { + .halt_reg = 0xab064, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0xab064, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb3_mp_phy_pipe_1_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_usb3_mp_phy_pipe_1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb3_prim_phy_aux_clk = { + .halt_reg = 0xf054, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xf054, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb3_prim_phy_aux_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_usb3_prim_phy_aux_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb3_prim_phy_com_aux_clk = { + .halt_reg = 0xf058, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xf058, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb3_prim_phy_com_aux_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_usb3_prim_phy_aux_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb3_prim_phy_pipe_clk = { + .halt_reg = 0xf05c, + .halt_check = BRANCH_HALT_DELAY, + .hwcg_reg = 0xf05c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0xf05c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb3_prim_phy_pipe_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_usb34_prim_phy_pipe_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb3_sec_phy_aux_clk = { + .halt_reg = 0x10054, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x10054, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb3_sec_phy_aux_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_usb3_sec_phy_aux_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb3_sec_phy_com_aux_clk = { + .halt_reg = 0x10058, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x10058, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb3_sec_phy_com_aux_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_usb3_sec_phy_aux_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb3_sec_phy_pipe_clk = { + .halt_reg = 0x1005c, + .halt_check = BRANCH_HALT_DELAY, + .hwcg_reg = 0x1005c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x1005c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb3_sec_phy_pipe_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_usb34_sec_phy_pipe_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb4_1_cfg_ahb_clk = { + .halt_reg = 0xb808c, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0xb808c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0xb808c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb4_1_cfg_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb4_1_dp_clk = { + .halt_reg = 0xb8048, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xb8048, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb4_1_dp_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_usb4_1_phy_dp_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb4_1_master_clk = { + .halt_reg = 0xb8010, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xb8010, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb4_1_master_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_usb4_1_master_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb4_1_phy_p2rr2p_pipe_clk = { + .halt_reg = 0xb80b4, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0xb80b4, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb4_1_phy_p2rr2p_pipe_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_usb4_1_phy_p2rr2p_pipe_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb4_1_phy_pcie_pipe_clk = { + .halt_reg = 0xb8038, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x52020, + .enable_mask = BIT(19), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb4_1_phy_pcie_pipe_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_usb4_1_phy_pcie_pipe_mux_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb4_1_phy_rx0_clk = { + .halt_reg = 0xb8094, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xb8094, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb4_1_phy_rx0_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_usb4_1_phy_rx0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb4_1_phy_rx1_clk = { + .halt_reg = 0xb80a0, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xb80a0, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb4_1_phy_rx1_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_usb4_1_phy_rx1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb4_1_phy_usb_pipe_clk = { + .halt_reg = 0xb8088, + .halt_check = BRANCH_HALT_DELAY, + .hwcg_reg = 0xb8088, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0xb8088, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb4_1_phy_usb_pipe_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_usb34_sec_phy_pipe_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb4_1_sb_if_clk = { + .halt_reg = 0xb8034, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xb8034, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb4_1_sb_if_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_usb4_1_sb_if_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb4_1_sys_clk = { + .halt_reg = 0xb8040, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xb8040, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb4_1_sys_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_usb4_1_phy_sys_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb4_1_tmu_clk = { + .halt_reg = 0xb806c, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0xb806c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0xb806c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb4_1_tmu_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_usb4_1_tmu_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb4_cfg_ahb_clk = { + .halt_reg = 0x2a08c, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x2a08c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x2a08c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb4_cfg_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb4_clkref_clk = { + .halt_reg = 0x8c010, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x8c010, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb4_clkref_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb4_dp_clk = { + .halt_reg = 0x2a048, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x2a048, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb4_dp_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_usb4_phy_dp_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb4_eud_clkref_clk = { + .halt_reg = 0x8c02c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x8c02c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb4_eud_clkref_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb4_master_clk = { + .halt_reg = 0x2a010, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x2a010, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb4_master_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_usb4_master_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb4_phy_p2rr2p_pipe_clk = { + .halt_reg = 0x2a0b4, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x2a0b4, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb4_phy_p2rr2p_pipe_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_usb4_phy_p2rr2p_pipe_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb4_phy_pcie_pipe_clk = { + .halt_reg = 0x2a038, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x52020, + .enable_mask = BIT(18), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb4_phy_pcie_pipe_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_usb4_phy_pcie_pipe_mux_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb4_phy_rx0_clk = { + .halt_reg = 0x2a094, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x2a094, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb4_phy_rx0_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_usb4_phy_rx0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb4_phy_rx1_clk = { + .halt_reg = 0x2a0a0, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x2a0a0, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb4_phy_rx1_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_usb4_phy_rx1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb4_phy_usb_pipe_clk = { + .halt_reg = 0x2a088, + .halt_check = BRANCH_HALT_DELAY, + .hwcg_reg = 0x2a088, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x2a088, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb4_phy_usb_pipe_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_usb34_prim_phy_pipe_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb4_sb_if_clk = { + .halt_reg = 0x2a034, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x2a034, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb4_sb_if_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_usb4_sb_if_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb4_sys_clk = { + .halt_reg = 0x2a040, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x2a040, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb4_sys_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_usb4_phy_sys_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb4_tmu_clk = { + .halt_reg = 0x2a06c, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x2a06c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x2a06c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_usb4_tmu_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_usb4_tmu_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_video_axi0_clk = { + .halt_reg = 0x28010, + .halt_check = BRANCH_HALT_SKIP, + .hwcg_reg = 0x28010, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x28010, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_video_axi0_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_video_axi1_clk = { + .halt_reg = 0x28018, + .halt_check = BRANCH_HALT_SKIP, + .hwcg_reg = 0x28018, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x28018, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_video_axi1_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_video_cvp_throttle_clk = { + .halt_reg = 0x28024, + .halt_check = BRANCH_HALT_SKIP, + .hwcg_reg = 0x28024, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x28024, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_video_cvp_throttle_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_video_vcodec_throttle_clk = { + .halt_reg = 0x28020, + .halt_check = BRANCH_HALT_SKIP, + .hwcg_reg = 0x28020, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x28020, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "gcc_video_vcodec_throttle_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct gdsc pcie_0_tunnel_gdsc = { + .gdscr = 0xa4004, + .pd = { + .name = "pcie_0_tunnel_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc pcie_1_tunnel_gdsc = { + .gdscr = 0x8d004, + .pd = { + .name = "pcie_1_tunnel_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc pcie_2a_gdsc = { + .gdscr = 0x9d004, + .pd = { + .name = "pcie_2a_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc pcie_2b_gdsc = { + .gdscr = 0x9e004, + .pd = { + .name = "pcie_2b_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc pcie_3a_gdsc = { + .gdscr = 0xa0004, + .pd = { + .name = "pcie_3a_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc pcie_3b_gdsc = { + .gdscr = 0xa2004, + .pd = { + .name = "pcie_3b_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc pcie_4_gdsc = { + .gdscr = 0x6b004, + .pd = { + .name = "pcie_4_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc ufs_card_gdsc = { + .gdscr = 0x75004, + .pd = { + .name = "ufs_card_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc ufs_phy_gdsc = { + .gdscr = 0x77004, + .pd = { + .name = "ufs_phy_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc usb30_mp_gdsc = { + .gdscr = 0xab004, + .pd = { + .name = "usb30_mp_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc usb30_prim_gdsc = { + .gdscr = 0xf004, + .pd = { + .name = "usb30_prim_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc usb30_sec_gdsc = { + .gdscr = 0x10004, + .pd = { + .name = "usb30_sec_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct clk_regmap *gcc_sc8280xp_clocks[] = { + [GCC_AGGRE_NOC_PCIE0_TUNNEL_AXI_CLK] = &gcc_aggre_noc_pcie0_tunnel_axi_clk.clkr, + [GCC_AGGRE_NOC_PCIE1_TUNNEL_AXI_CLK] = &gcc_aggre_noc_pcie1_tunnel_axi_clk.clkr, + [GCC_AGGRE_NOC_PCIE_4_AXI_CLK] = &gcc_aggre_noc_pcie_4_axi_clk.clkr, + [GCC_AGGRE_NOC_PCIE_SOUTH_SF_AXI_CLK] = &gcc_aggre_noc_pcie_south_sf_axi_clk.clkr, + [GCC_AGGRE_UFS_CARD_AXI_CLK] = &gcc_aggre_ufs_card_axi_clk.clkr, + [GCC_AGGRE_UFS_CARD_AXI_HW_CTL_CLK] = &gcc_aggre_ufs_card_axi_hw_ctl_clk.clkr, + [GCC_AGGRE_UFS_PHY_AXI_CLK] = &gcc_aggre_ufs_phy_axi_clk.clkr, + [GCC_AGGRE_UFS_PHY_AXI_HW_CTL_CLK] = &gcc_aggre_ufs_phy_axi_hw_ctl_clk.clkr, + [GCC_AGGRE_USB3_MP_AXI_CLK] = &gcc_aggre_usb3_mp_axi_clk.clkr, + [GCC_AGGRE_USB3_PRIM_AXI_CLK] = &gcc_aggre_usb3_prim_axi_clk.clkr, + [GCC_AGGRE_USB3_SEC_AXI_CLK] = &gcc_aggre_usb3_sec_axi_clk.clkr, + [GCC_AGGRE_USB4_1_AXI_CLK] = &gcc_aggre_usb4_1_axi_clk.clkr, + [GCC_AGGRE_USB4_AXI_CLK] = &gcc_aggre_usb4_axi_clk.clkr, + [GCC_AGGRE_USB_NOC_AXI_CLK] = &gcc_aggre_usb_noc_axi_clk.clkr, + [GCC_AGGRE_USB_NOC_NORTH_AXI_CLK] = &gcc_aggre_usb_noc_north_axi_clk.clkr, + [GCC_AGGRE_USB_NOC_SOUTH_AXI_CLK] = &gcc_aggre_usb_noc_south_axi_clk.clkr, + [GCC_AHB2PHY0_CLK] = &gcc_ahb2phy0_clk.clkr, + [GCC_AHB2PHY2_CLK] = &gcc_ahb2phy2_clk.clkr, + [GCC_BOOT_ROM_AHB_CLK] = &gcc_boot_rom_ahb_clk.clkr, + [GCC_CAMERA_HF_AXI_CLK] = &gcc_camera_hf_axi_clk.clkr, + [GCC_CAMERA_SF_AXI_CLK] = &gcc_camera_sf_axi_clk.clkr, + [GCC_CAMERA_THROTTLE_NRT_AXI_CLK] = &gcc_camera_throttle_nrt_axi_clk.clkr, + [GCC_CAMERA_THROTTLE_RT_AXI_CLK] = &gcc_camera_throttle_rt_axi_clk.clkr, + [GCC_CAMERA_THROTTLE_XO_CLK] = &gcc_camera_throttle_xo_clk.clkr, + [GCC_CFG_NOC_USB3_MP_AXI_CLK] = &gcc_cfg_noc_usb3_mp_axi_clk.clkr, + [GCC_CFG_NOC_USB3_PRIM_AXI_CLK] = &gcc_cfg_noc_usb3_prim_axi_clk.clkr, + [GCC_CFG_NOC_USB3_SEC_AXI_CLK] = &gcc_cfg_noc_usb3_sec_axi_clk.clkr, + [GCC_CNOC_PCIE0_TUNNEL_CLK] = &gcc_cnoc_pcie0_tunnel_clk.clkr, + [GCC_CNOC_PCIE1_TUNNEL_CLK] = &gcc_cnoc_pcie1_tunnel_clk.clkr, + [GCC_CNOC_PCIE4_QX_CLK] = &gcc_cnoc_pcie4_qx_clk.clkr, + [GCC_DDRSS_GPU_AXI_CLK] = &gcc_ddrss_gpu_axi_clk.clkr, + [GCC_DDRSS_PCIE_SF_TBU_CLK] = &gcc_ddrss_pcie_sf_tbu_clk.clkr, + [GCC_DISP1_HF_AXI_CLK] = &gcc_disp1_hf_axi_clk.clkr, + [GCC_DISP1_SF_AXI_CLK] = &gcc_disp1_sf_axi_clk.clkr, + [GCC_DISP1_THROTTLE_NRT_AXI_CLK] = &gcc_disp1_throttle_nrt_axi_clk.clkr, + [GCC_DISP1_THROTTLE_RT_AXI_CLK] = &gcc_disp1_throttle_rt_axi_clk.clkr, + [GCC_DISP_HF_AXI_CLK] = &gcc_disp_hf_axi_clk.clkr, + [GCC_DISP_SF_AXI_CLK] = &gcc_disp_sf_axi_clk.clkr, + [GCC_DISP_THROTTLE_NRT_AXI_CLK] = &gcc_disp_throttle_nrt_axi_clk.clkr, + [GCC_DISP_THROTTLE_RT_AXI_CLK] = &gcc_disp_throttle_rt_axi_clk.clkr, + [GCC_EMAC0_AXI_CLK] = &gcc_emac0_axi_clk.clkr, + [GCC_EMAC0_PTP_CLK] = &gcc_emac0_ptp_clk.clkr, + [GCC_EMAC0_PTP_CLK_SRC] = &gcc_emac0_ptp_clk_src.clkr, + [GCC_EMAC0_RGMII_CLK] = &gcc_emac0_rgmii_clk.clkr, + [GCC_EMAC0_RGMII_CLK_SRC] = &gcc_emac0_rgmii_clk_src.clkr, + [GCC_EMAC0_SLV_AHB_CLK] = &gcc_emac0_slv_ahb_clk.clkr, + [GCC_EMAC1_AXI_CLK] = &gcc_emac1_axi_clk.clkr, + [GCC_EMAC1_PTP_CLK] = &gcc_emac1_ptp_clk.clkr, + [GCC_EMAC1_PTP_CLK_SRC] = &gcc_emac1_ptp_clk_src.clkr, + [GCC_EMAC1_RGMII_CLK] = &gcc_emac1_rgmii_clk.clkr, + [GCC_EMAC1_RGMII_CLK_SRC] = &gcc_emac1_rgmii_clk_src.clkr, + [GCC_EMAC1_SLV_AHB_CLK] = &gcc_emac1_slv_ahb_clk.clkr, + [GCC_GP1_CLK] = &gcc_gp1_clk.clkr, + [GCC_GP1_CLK_SRC] = &gcc_gp1_clk_src.clkr, + [GCC_GP2_CLK] = &gcc_gp2_clk.clkr, + [GCC_GP2_CLK_SRC] = &gcc_gp2_clk_src.clkr, + [GCC_GP3_CLK] = &gcc_gp3_clk.clkr, + [GCC_GP3_CLK_SRC] = &gcc_gp3_clk_src.clkr, + [GCC_GP4_CLK] = &gcc_gp4_clk.clkr, + [GCC_GP4_CLK_SRC] = &gcc_gp4_clk_src.clkr, + [GCC_GP5_CLK] = &gcc_gp5_clk.clkr, + [GCC_GP5_CLK_SRC] = &gcc_gp5_clk_src.clkr, + [GCC_GPLL0] = &gcc_gpll0.clkr, + [GCC_GPLL0_OUT_EVEN] = &gcc_gpll0_out_even.clkr, + [GCC_GPLL2] = &gcc_gpll2.clkr, + [GCC_GPLL4] = &gcc_gpll4.clkr, + [GCC_GPLL7] = &gcc_gpll7.clkr, + [GCC_GPLL8] = &gcc_gpll8.clkr, + [GCC_GPLL9] = &gcc_gpll9.clkr, + [GCC_GPU_GPLL0_CLK_SRC] = &gcc_gpu_gpll0_clk_src.clkr, + [GCC_GPU_GPLL0_DIV_CLK_SRC] = &gcc_gpu_gpll0_div_clk_src.clkr, + [GCC_GPU_IREF_EN] = &gcc_gpu_iref_en.clkr, + [GCC_GPU_MEMNOC_GFX_CLK] = &gcc_gpu_memnoc_gfx_clk.clkr, + [GCC_GPU_SNOC_DVM_GFX_CLK] = &gcc_gpu_snoc_dvm_gfx_clk.clkr, + [GCC_GPU_TCU_THROTTLE_AHB_CLK] = &gcc_gpu_tcu_throttle_ahb_clk.clkr, + [GCC_GPU_TCU_THROTTLE_CLK] = &gcc_gpu_tcu_throttle_clk.clkr, + [GCC_PCIE0_PHY_RCHNG_CLK] = &gcc_pcie0_phy_rchng_clk.clkr, + [GCC_PCIE1_PHY_RCHNG_CLK] = &gcc_pcie1_phy_rchng_clk.clkr, + [GCC_PCIE2A_PHY_RCHNG_CLK] = &gcc_pcie2a_phy_rchng_clk.clkr, + [GCC_PCIE2B_PHY_RCHNG_CLK] = &gcc_pcie2b_phy_rchng_clk.clkr, + [GCC_PCIE3A_PHY_RCHNG_CLK] = &gcc_pcie3a_phy_rchng_clk.clkr, + [GCC_PCIE3B_PHY_RCHNG_CLK] = &gcc_pcie3b_phy_rchng_clk.clkr, + [GCC_PCIE4_PHY_RCHNG_CLK] = &gcc_pcie4_phy_rchng_clk.clkr, + [GCC_PCIE_0_AUX_CLK] = &gcc_pcie_0_aux_clk.clkr, + [GCC_PCIE_0_AUX_CLK_SRC] = &gcc_pcie_0_aux_clk_src.clkr, + [GCC_PCIE_0_CFG_AHB_CLK] = &gcc_pcie_0_cfg_ahb_clk.clkr, + [GCC_PCIE_0_MSTR_AXI_CLK] = &gcc_pcie_0_mstr_axi_clk.clkr, + [GCC_PCIE_0_PHY_RCHNG_CLK_SRC] = &gcc_pcie_0_phy_rchng_clk_src.clkr, + [GCC_PCIE_0_PIPE_CLK] = &gcc_pcie_0_pipe_clk.clkr, + [GCC_PCIE_0_SLV_AXI_CLK] = &gcc_pcie_0_slv_axi_clk.clkr, + [GCC_PCIE_0_SLV_Q2A_AXI_CLK] = &gcc_pcie_0_slv_q2a_axi_clk.clkr, + [GCC_PCIE_1_AUX_CLK] = &gcc_pcie_1_aux_clk.clkr, + [GCC_PCIE_1_AUX_CLK_SRC] = &gcc_pcie_1_aux_clk_src.clkr, + [GCC_PCIE_1_CFG_AHB_CLK] = &gcc_pcie_1_cfg_ahb_clk.clkr, + [GCC_PCIE_1_MSTR_AXI_CLK] = &gcc_pcie_1_mstr_axi_clk.clkr, + [GCC_PCIE_1_PHY_RCHNG_CLK_SRC] = &gcc_pcie_1_phy_rchng_clk_src.clkr, + [GCC_PCIE_1_PIPE_CLK] = &gcc_pcie_1_pipe_clk.clkr, + [GCC_PCIE_1_SLV_AXI_CLK] = &gcc_pcie_1_slv_axi_clk.clkr, + [GCC_PCIE_1_SLV_Q2A_AXI_CLK] = &gcc_pcie_1_slv_q2a_axi_clk.clkr, + [GCC_PCIE_2A2B_CLKREF_CLK] = &gcc_pcie_2a2b_clkref_clk.clkr, + [GCC_PCIE_2A_AUX_CLK] = &gcc_pcie_2a_aux_clk.clkr, + [GCC_PCIE_2A_AUX_CLK_SRC] = &gcc_pcie_2a_aux_clk_src.clkr, + [GCC_PCIE_2A_CFG_AHB_CLK] = &gcc_pcie_2a_cfg_ahb_clk.clkr, + [GCC_PCIE_2A_MSTR_AXI_CLK] = &gcc_pcie_2a_mstr_axi_clk.clkr, + [GCC_PCIE_2A_PHY_RCHNG_CLK_SRC] = &gcc_pcie_2a_phy_rchng_clk_src.clkr, + [GCC_PCIE_2A_PIPE_CLK] = &gcc_pcie_2a_pipe_clk.clkr, + [GCC_PCIE_2A_PIPE_CLK_SRC] = &gcc_pcie_2a_pipe_clk_src.clkr, + [GCC_PCIE_2A_PIPE_DIV_CLK_SRC] = &gcc_pcie_2a_pipe_div_clk_src.clkr, + [GCC_PCIE_2A_PIPEDIV2_CLK] = &gcc_pcie_2a_pipediv2_clk.clkr, + [GCC_PCIE_2A_SLV_AXI_CLK] = &gcc_pcie_2a_slv_axi_clk.clkr, + [GCC_PCIE_2A_SLV_Q2A_AXI_CLK] = &gcc_pcie_2a_slv_q2a_axi_clk.clkr, + [GCC_PCIE_2B_AUX_CLK] = &gcc_pcie_2b_aux_clk.clkr, + [GCC_PCIE_2B_AUX_CLK_SRC] = &gcc_pcie_2b_aux_clk_src.clkr, + [GCC_PCIE_2B_CFG_AHB_CLK] = &gcc_pcie_2b_cfg_ahb_clk.clkr, + [GCC_PCIE_2B_MSTR_AXI_CLK] = &gcc_pcie_2b_mstr_axi_clk.clkr, + [GCC_PCIE_2B_PHY_RCHNG_CLK_SRC] = &gcc_pcie_2b_phy_rchng_clk_src.clkr, + [GCC_PCIE_2B_PIPE_CLK] = &gcc_pcie_2b_pipe_clk.clkr, + [GCC_PCIE_2B_PIPE_CLK_SRC] = &gcc_pcie_2b_pipe_clk_src.clkr, + [GCC_PCIE_2B_PIPE_DIV_CLK_SRC] = &gcc_pcie_2b_pipe_div_clk_src.clkr, + [GCC_PCIE_2B_PIPEDIV2_CLK] = &gcc_pcie_2b_pipediv2_clk.clkr, + [GCC_PCIE_2B_SLV_AXI_CLK] = &gcc_pcie_2b_slv_axi_clk.clkr, + [GCC_PCIE_2B_SLV_Q2A_AXI_CLK] = &gcc_pcie_2b_slv_q2a_axi_clk.clkr, + [GCC_PCIE_3A3B_CLKREF_CLK] = &gcc_pcie_3a3b_clkref_clk.clkr, + [GCC_PCIE_3A_AUX_CLK] = &gcc_pcie_3a_aux_clk.clkr, + [GCC_PCIE_3A_AUX_CLK_SRC] = &gcc_pcie_3a_aux_clk_src.clkr, + [GCC_PCIE_3A_CFG_AHB_CLK] = &gcc_pcie_3a_cfg_ahb_clk.clkr, + [GCC_PCIE_3A_MSTR_AXI_CLK] = &gcc_pcie_3a_mstr_axi_clk.clkr, + [GCC_PCIE_3A_PHY_RCHNG_CLK_SRC] = &gcc_pcie_3a_phy_rchng_clk_src.clkr, + [GCC_PCIE_3A_PIPE_CLK] = &gcc_pcie_3a_pipe_clk.clkr, + [GCC_PCIE_3A_PIPE_CLK_SRC] = &gcc_pcie_3a_pipe_clk_src.clkr, + [GCC_PCIE_3A_PIPE_DIV_CLK_SRC] = &gcc_pcie_3a_pipe_div_clk_src.clkr, + [GCC_PCIE_3A_PIPEDIV2_CLK] = &gcc_pcie_3a_pipediv2_clk.clkr, + [GCC_PCIE_3A_SLV_AXI_CLK] = &gcc_pcie_3a_slv_axi_clk.clkr, + [GCC_PCIE_3A_SLV_Q2A_AXI_CLK] = &gcc_pcie_3a_slv_q2a_axi_clk.clkr, + [GCC_PCIE_3B_AUX_CLK] = &gcc_pcie_3b_aux_clk.clkr, + [GCC_PCIE_3B_AUX_CLK_SRC] = &gcc_pcie_3b_aux_clk_src.clkr, + [GCC_PCIE_3B_CFG_AHB_CLK] = &gcc_pcie_3b_cfg_ahb_clk.clkr, + [GCC_PCIE_3B_MSTR_AXI_CLK] = &gcc_pcie_3b_mstr_axi_clk.clkr, + [GCC_PCIE_3B_PHY_RCHNG_CLK_SRC] = &gcc_pcie_3b_phy_rchng_clk_src.clkr, + [GCC_PCIE_3B_PIPE_CLK] = &gcc_pcie_3b_pipe_clk.clkr, + [GCC_PCIE_3B_PIPE_CLK_SRC] = &gcc_pcie_3b_pipe_clk_src.clkr, + [GCC_PCIE_3B_PIPE_DIV_CLK_SRC] = &gcc_pcie_3b_pipe_div_clk_src.clkr, + [GCC_PCIE_3B_PIPEDIV2_CLK] = &gcc_pcie_3b_pipediv2_clk.clkr, + [GCC_PCIE_3B_SLV_AXI_CLK] = &gcc_pcie_3b_slv_axi_clk.clkr, + [GCC_PCIE_3B_SLV_Q2A_AXI_CLK] = &gcc_pcie_3b_slv_q2a_axi_clk.clkr, + [GCC_PCIE_4_AUX_CLK] = &gcc_pcie_4_aux_clk.clkr, + [GCC_PCIE_4_AUX_CLK_SRC] = &gcc_pcie_4_aux_clk_src.clkr, + [GCC_PCIE_4_CFG_AHB_CLK] = &gcc_pcie_4_cfg_ahb_clk.clkr, + [GCC_PCIE_4_CLKREF_CLK] = &gcc_pcie_4_clkref_clk.clkr, + [GCC_PCIE_4_MSTR_AXI_CLK] = &gcc_pcie_4_mstr_axi_clk.clkr, + [GCC_PCIE_4_PHY_RCHNG_CLK_SRC] = &gcc_pcie_4_phy_rchng_clk_src.clkr, + [GCC_PCIE_4_PIPE_CLK] = &gcc_pcie_4_pipe_clk.clkr, + [GCC_PCIE_4_PIPE_CLK_SRC] = &gcc_pcie_4_pipe_clk_src.clkr, + [GCC_PCIE_4_PIPE_DIV_CLK_SRC] = &gcc_pcie_4_pipe_div_clk_src.clkr, + [GCC_PCIE_4_PIPEDIV2_CLK] = &gcc_pcie_4_pipediv2_clk.clkr, + [GCC_PCIE_4_SLV_AXI_CLK] = &gcc_pcie_4_slv_axi_clk.clkr, + [GCC_PCIE_4_SLV_Q2A_AXI_CLK] = &gcc_pcie_4_slv_q2a_axi_clk.clkr, + [GCC_PCIE_RSCC_AHB_CLK] = &gcc_pcie_rscc_ahb_clk.clkr, + [GCC_PCIE_RSCC_XO_CLK] = &gcc_pcie_rscc_xo_clk.clkr, + [GCC_PCIE_RSCC_XO_CLK_SRC] = &gcc_pcie_rscc_xo_clk_src.clkr, + [GCC_PCIE_THROTTLE_CFG_CLK] = &gcc_pcie_throttle_cfg_clk.clkr, + [GCC_PDM2_CLK] = &gcc_pdm2_clk.clkr, + [GCC_PDM2_CLK_SRC] = &gcc_pdm2_clk_src.clkr, + [GCC_PDM_AHB_CLK] = &gcc_pdm_ahb_clk.clkr, + [GCC_PDM_XO4_CLK] = &gcc_pdm_xo4_clk.clkr, + [GCC_QMIP_CAMERA_NRT_AHB_CLK] = &gcc_qmip_camera_nrt_ahb_clk.clkr, + [GCC_QMIP_CAMERA_RT_AHB_CLK] = &gcc_qmip_camera_rt_ahb_clk.clkr, + [GCC_QMIP_DISP1_AHB_CLK] = &gcc_qmip_disp1_ahb_clk.clkr, + [GCC_QMIP_DISP1_ROT_AHB_CLK] = &gcc_qmip_disp1_rot_ahb_clk.clkr, + [GCC_QMIP_DISP_AHB_CLK] = &gcc_qmip_disp_ahb_clk.clkr, + [GCC_QMIP_DISP_ROT_AHB_CLK] = &gcc_qmip_disp_rot_ahb_clk.clkr, + [GCC_QMIP_VIDEO_CVP_AHB_CLK] = &gcc_qmip_video_cvp_ahb_clk.clkr, + [GCC_QMIP_VIDEO_VCODEC_AHB_CLK] = &gcc_qmip_video_vcodec_ahb_clk.clkr, + [GCC_QUPV3_WRAP0_CORE_2X_CLK] = &gcc_qupv3_wrap0_core_2x_clk.clkr, + [GCC_QUPV3_WRAP0_CORE_CLK] = &gcc_qupv3_wrap0_core_clk.clkr, + [GCC_QUPV3_WRAP0_QSPI0_CLK] = &gcc_qupv3_wrap0_qspi0_clk.clkr, + [GCC_QUPV3_WRAP0_S0_CLK] = &gcc_qupv3_wrap0_s0_clk.clkr, + [GCC_QUPV3_WRAP0_S0_CLK_SRC] = &gcc_qupv3_wrap0_s0_clk_src.clkr, + [GCC_QUPV3_WRAP0_S1_CLK] = &gcc_qupv3_wrap0_s1_clk.clkr, + [GCC_QUPV3_WRAP0_S1_CLK_SRC] = &gcc_qupv3_wrap0_s1_clk_src.clkr, + [GCC_QUPV3_WRAP0_S2_CLK] = &gcc_qupv3_wrap0_s2_clk.clkr, + [GCC_QUPV3_WRAP0_S2_CLK_SRC] = &gcc_qupv3_wrap0_s2_clk_src.clkr, + [GCC_QUPV3_WRAP0_S3_CLK] = &gcc_qupv3_wrap0_s3_clk.clkr, + [GCC_QUPV3_WRAP0_S3_CLK_SRC] = &gcc_qupv3_wrap0_s3_clk_src.clkr, + [GCC_QUPV3_WRAP0_S4_CLK] = &gcc_qupv3_wrap0_s4_clk.clkr, + [GCC_QUPV3_WRAP0_S4_CLK_SRC] = &gcc_qupv3_wrap0_s4_clk_src.clkr, + [GCC_QUPV3_WRAP0_S4_DIV_CLK_SRC] = &gcc_qupv3_wrap0_s4_div_clk_src.clkr, + [GCC_QUPV3_WRAP0_S5_CLK] = &gcc_qupv3_wrap0_s5_clk.clkr, + [GCC_QUPV3_WRAP0_S5_CLK_SRC] = &gcc_qupv3_wrap0_s5_clk_src.clkr, + [GCC_QUPV3_WRAP0_S6_CLK] = &gcc_qupv3_wrap0_s6_clk.clkr, + [GCC_QUPV3_WRAP0_S6_CLK_SRC] = &gcc_qupv3_wrap0_s6_clk_src.clkr, + [GCC_QUPV3_WRAP0_S7_CLK] = &gcc_qupv3_wrap0_s7_clk.clkr, + [GCC_QUPV3_WRAP0_S7_CLK_SRC] = &gcc_qupv3_wrap0_s7_clk_src.clkr, + [GCC_QUPV3_WRAP1_CORE_2X_CLK] = &gcc_qupv3_wrap1_core_2x_clk.clkr, + [GCC_QUPV3_WRAP1_CORE_CLK] = &gcc_qupv3_wrap1_core_clk.clkr, + [GCC_QUPV3_WRAP1_QSPI0_CLK] = &gcc_qupv3_wrap1_qspi0_clk.clkr, + [GCC_QUPV3_WRAP1_S0_CLK] = &gcc_qupv3_wrap1_s0_clk.clkr, + [GCC_QUPV3_WRAP1_S0_CLK_SRC] = &gcc_qupv3_wrap1_s0_clk_src.clkr, + [GCC_QUPV3_WRAP1_S1_CLK] = &gcc_qupv3_wrap1_s1_clk.clkr, + [GCC_QUPV3_WRAP1_S1_CLK_SRC] = &gcc_qupv3_wrap1_s1_clk_src.clkr, + [GCC_QUPV3_WRAP1_S2_CLK] = &gcc_qupv3_wrap1_s2_clk.clkr, + [GCC_QUPV3_WRAP1_S2_CLK_SRC] = &gcc_qupv3_wrap1_s2_clk_src.clkr, + [GCC_QUPV3_WRAP1_S3_CLK] = &gcc_qupv3_wrap1_s3_clk.clkr, + [GCC_QUPV3_WRAP1_S3_CLK_SRC] = &gcc_qupv3_wrap1_s3_clk_src.clkr, + [GCC_QUPV3_WRAP1_S4_CLK] = &gcc_qupv3_wrap1_s4_clk.clkr, + [GCC_QUPV3_WRAP1_S4_CLK_SRC] = &gcc_qupv3_wrap1_s4_clk_src.clkr, + [GCC_QUPV3_WRAP1_S4_DIV_CLK_SRC] = &gcc_qupv3_wrap1_s4_div_clk_src.clkr, + [GCC_QUPV3_WRAP1_S5_CLK] = &gcc_qupv3_wrap1_s5_clk.clkr, + [GCC_QUPV3_WRAP1_S5_CLK_SRC] = &gcc_qupv3_wrap1_s5_clk_src.clkr, + [GCC_QUPV3_WRAP1_S6_CLK] = &gcc_qupv3_wrap1_s6_clk.clkr, + [GCC_QUPV3_WRAP1_S6_CLK_SRC] = &gcc_qupv3_wrap1_s6_clk_src.clkr, + [GCC_QUPV3_WRAP1_S7_CLK] = &gcc_qupv3_wrap1_s7_clk.clkr, + [GCC_QUPV3_WRAP1_S7_CLK_SRC] = &gcc_qupv3_wrap1_s7_clk_src.clkr, + [GCC_QUPV3_WRAP2_CORE_2X_CLK] = &gcc_qupv3_wrap2_core_2x_clk.clkr, + [GCC_QUPV3_WRAP2_CORE_CLK] = &gcc_qupv3_wrap2_core_clk.clkr, + [GCC_QUPV3_WRAP2_QSPI0_CLK] = &gcc_qupv3_wrap2_qspi0_clk.clkr, + [GCC_QUPV3_WRAP2_S0_CLK] = &gcc_qupv3_wrap2_s0_clk.clkr, + [GCC_QUPV3_WRAP2_S0_CLK_SRC] = &gcc_qupv3_wrap2_s0_clk_src.clkr, + [GCC_QUPV3_WRAP2_S1_CLK] = &gcc_qupv3_wrap2_s1_clk.clkr, + [GCC_QUPV3_WRAP2_S1_CLK_SRC] = &gcc_qupv3_wrap2_s1_clk_src.clkr, + [GCC_QUPV3_WRAP2_S2_CLK] = &gcc_qupv3_wrap2_s2_clk.clkr, + [GCC_QUPV3_WRAP2_S2_CLK_SRC] = &gcc_qupv3_wrap2_s2_clk_src.clkr, + [GCC_QUPV3_WRAP2_S3_CLK] = &gcc_qupv3_wrap2_s3_clk.clkr, + [GCC_QUPV3_WRAP2_S3_CLK_SRC] = &gcc_qupv3_wrap2_s3_clk_src.clkr, + [GCC_QUPV3_WRAP2_S4_CLK] = &gcc_qupv3_wrap2_s4_clk.clkr, + [GCC_QUPV3_WRAP2_S4_CLK_SRC] = &gcc_qupv3_wrap2_s4_clk_src.clkr, + [GCC_QUPV3_WRAP2_S4_DIV_CLK_SRC] = &gcc_qupv3_wrap2_s4_div_clk_src.clkr, + [GCC_QUPV3_WRAP2_S5_CLK] = &gcc_qupv3_wrap2_s5_clk.clkr, + [GCC_QUPV3_WRAP2_S5_CLK_SRC] = &gcc_qupv3_wrap2_s5_clk_src.clkr, + [GCC_QUPV3_WRAP2_S6_CLK] = &gcc_qupv3_wrap2_s6_clk.clkr, + [GCC_QUPV3_WRAP2_S6_CLK_SRC] = &gcc_qupv3_wrap2_s6_clk_src.clkr, + [GCC_QUPV3_WRAP2_S7_CLK] = &gcc_qupv3_wrap2_s7_clk.clkr, + [GCC_QUPV3_WRAP2_S7_CLK_SRC] = &gcc_qupv3_wrap2_s7_clk_src.clkr, + [GCC_QUPV3_WRAP_0_M_AHB_CLK] = &gcc_qupv3_wrap_0_m_ahb_clk.clkr, + [GCC_QUPV3_WRAP_0_S_AHB_CLK] = &gcc_qupv3_wrap_0_s_ahb_clk.clkr, + [GCC_QUPV3_WRAP_1_M_AHB_CLK] = &gcc_qupv3_wrap_1_m_ahb_clk.clkr, + [GCC_QUPV3_WRAP_1_S_AHB_CLK] = &gcc_qupv3_wrap_1_s_ahb_clk.clkr, + [GCC_QUPV3_WRAP_2_M_AHB_CLK] = &gcc_qupv3_wrap_2_m_ahb_clk.clkr, + [GCC_QUPV3_WRAP_2_S_AHB_CLK] = &gcc_qupv3_wrap_2_s_ahb_clk.clkr, + [GCC_SDCC2_AHB_CLK] = &gcc_sdcc2_ahb_clk.clkr, + [GCC_SDCC2_APPS_CLK] = &gcc_sdcc2_apps_clk.clkr, + [GCC_SDCC2_APPS_CLK_SRC] = &gcc_sdcc2_apps_clk_src.clkr, + [GCC_SDCC4_AHB_CLK] = &gcc_sdcc4_ahb_clk.clkr, + [GCC_SDCC4_APPS_CLK] = &gcc_sdcc4_apps_clk.clkr, + [GCC_SDCC4_APPS_CLK_SRC] = &gcc_sdcc4_apps_clk_src.clkr, + [GCC_SYS_NOC_USB_AXI_CLK] = &gcc_sys_noc_usb_axi_clk.clkr, + [GCC_UFS_1_CARD_CLKREF_CLK] = &gcc_ufs_1_card_clkref_clk.clkr, + [GCC_UFS_CARD_AHB_CLK] = &gcc_ufs_card_ahb_clk.clkr, + [GCC_UFS_CARD_AXI_CLK] = &gcc_ufs_card_axi_clk.clkr, + [GCC_UFS_CARD_AXI_CLK_SRC] = &gcc_ufs_card_axi_clk_src.clkr, + [GCC_UFS_CARD_AXI_HW_CTL_CLK] = &gcc_ufs_card_axi_hw_ctl_clk.clkr, + [GCC_UFS_CARD_CLKREF_CLK] = &gcc_ufs_card_clkref_clk.clkr, + [GCC_UFS_CARD_ICE_CORE_CLK] = &gcc_ufs_card_ice_core_clk.clkr, + [GCC_UFS_CARD_ICE_CORE_CLK_SRC] = &gcc_ufs_card_ice_core_clk_src.clkr, + [GCC_UFS_CARD_ICE_CORE_HW_CTL_CLK] = &gcc_ufs_card_ice_core_hw_ctl_clk.clkr, + [GCC_UFS_CARD_PHY_AUX_CLK] = &gcc_ufs_card_phy_aux_clk.clkr, + [GCC_UFS_CARD_PHY_AUX_CLK_SRC] = &gcc_ufs_card_phy_aux_clk_src.clkr, + [GCC_UFS_CARD_PHY_AUX_HW_CTL_CLK] = &gcc_ufs_card_phy_aux_hw_ctl_clk.clkr, + [GCC_UFS_CARD_RX_SYMBOL_0_CLK] = &gcc_ufs_card_rx_symbol_0_clk.clkr, + [GCC_UFS_CARD_RX_SYMBOL_0_CLK_SRC] = &gcc_ufs_card_rx_symbol_0_clk_src.clkr, + [GCC_UFS_CARD_RX_SYMBOL_1_CLK] = &gcc_ufs_card_rx_symbol_1_clk.clkr, + [GCC_UFS_CARD_RX_SYMBOL_1_CLK_SRC] = &gcc_ufs_card_rx_symbol_1_clk_src.clkr, + [GCC_UFS_CARD_TX_SYMBOL_0_CLK] = &gcc_ufs_card_tx_symbol_0_clk.clkr, + [GCC_UFS_CARD_TX_SYMBOL_0_CLK_SRC] = &gcc_ufs_card_tx_symbol_0_clk_src.clkr, + [GCC_UFS_CARD_UNIPRO_CORE_CLK] = &gcc_ufs_card_unipro_core_clk.clkr, + [GCC_UFS_CARD_UNIPRO_CORE_CLK_SRC] = &gcc_ufs_card_unipro_core_clk_src.clkr, + [GCC_UFS_CARD_UNIPRO_CORE_HW_CTL_CLK] = &gcc_ufs_card_unipro_core_hw_ctl_clk.clkr, + [GCC_UFS_PHY_AHB_CLK] = &gcc_ufs_phy_ahb_clk.clkr, + [GCC_UFS_PHY_AXI_CLK] = &gcc_ufs_phy_axi_clk.clkr, + [GCC_UFS_PHY_AXI_CLK_SRC] = &gcc_ufs_phy_axi_clk_src.clkr, + [GCC_UFS_PHY_AXI_HW_CTL_CLK] = &gcc_ufs_phy_axi_hw_ctl_clk.clkr, + [GCC_UFS_PHY_ICE_CORE_CLK] = &gcc_ufs_phy_ice_core_clk.clkr, + [GCC_UFS_PHY_ICE_CORE_CLK_SRC] = &gcc_ufs_phy_ice_core_clk_src.clkr, + [GCC_UFS_PHY_ICE_CORE_HW_CTL_CLK] = &gcc_ufs_phy_ice_core_hw_ctl_clk.clkr, + [GCC_UFS_PHY_PHY_AUX_CLK] = &gcc_ufs_phy_phy_aux_clk.clkr, + [GCC_UFS_PHY_PHY_AUX_CLK_SRC] = &gcc_ufs_phy_phy_aux_clk_src.clkr, + [GCC_UFS_PHY_PHY_AUX_HW_CTL_CLK] = &gcc_ufs_phy_phy_aux_hw_ctl_clk.clkr, + [GCC_UFS_PHY_RX_SYMBOL_0_CLK] = &gcc_ufs_phy_rx_symbol_0_clk.clkr, + [GCC_UFS_PHY_RX_SYMBOL_0_CLK_SRC] = &gcc_ufs_phy_rx_symbol_0_clk_src.clkr, + [GCC_UFS_PHY_RX_SYMBOL_1_CLK] = &gcc_ufs_phy_rx_symbol_1_clk.clkr, + [GCC_UFS_PHY_RX_SYMBOL_1_CLK_SRC] = &gcc_ufs_phy_rx_symbol_1_clk_src.clkr, + [GCC_UFS_PHY_TX_SYMBOL_0_CLK] = &gcc_ufs_phy_tx_symbol_0_clk.clkr, + [GCC_UFS_PHY_TX_SYMBOL_0_CLK_SRC] = &gcc_ufs_phy_tx_symbol_0_clk_src.clkr, + [GCC_UFS_PHY_UNIPRO_CORE_CLK] = &gcc_ufs_phy_unipro_core_clk.clkr, + [GCC_UFS_PHY_UNIPRO_CORE_CLK_SRC] = &gcc_ufs_phy_unipro_core_clk_src.clkr, + [GCC_UFS_PHY_UNIPRO_CORE_HW_CTL_CLK] = &gcc_ufs_phy_unipro_core_hw_ctl_clk.clkr, + [GCC_UFS_REF_CLKREF_CLK] = &gcc_ufs_ref_clkref_clk.clkr, + [GCC_USB2_HS0_CLKREF_CLK] = &gcc_usb2_hs0_clkref_clk.clkr, + [GCC_USB2_HS1_CLKREF_CLK] = &gcc_usb2_hs1_clkref_clk.clkr, + [GCC_USB2_HS2_CLKREF_CLK] = &gcc_usb2_hs2_clkref_clk.clkr, + [GCC_USB2_HS3_CLKREF_CLK] = &gcc_usb2_hs3_clkref_clk.clkr, + [GCC_USB30_MP_MASTER_CLK] = &gcc_usb30_mp_master_clk.clkr, + [GCC_USB30_MP_MASTER_CLK_SRC] = &gcc_usb30_mp_master_clk_src.clkr, + [GCC_USB30_MP_MOCK_UTMI_CLK] = &gcc_usb30_mp_mock_utmi_clk.clkr, + [GCC_USB30_MP_MOCK_UTMI_CLK_SRC] = &gcc_usb30_mp_mock_utmi_clk_src.clkr, + [GCC_USB30_MP_MOCK_UTMI_POSTDIV_CLK_SRC] = &gcc_usb30_mp_mock_utmi_postdiv_clk_src.clkr, + [GCC_USB30_MP_SLEEP_CLK] = &gcc_usb30_mp_sleep_clk.clkr, + [GCC_USB30_PRIM_MASTER_CLK] = &gcc_usb30_prim_master_clk.clkr, + [GCC_USB30_PRIM_MASTER_CLK_SRC] = &gcc_usb30_prim_master_clk_src.clkr, + [GCC_USB30_PRIM_MOCK_UTMI_CLK] = &gcc_usb30_prim_mock_utmi_clk.clkr, + [GCC_USB30_PRIM_MOCK_UTMI_CLK_SRC] = &gcc_usb30_prim_mock_utmi_clk_src.clkr, + [GCC_USB30_PRIM_MOCK_UTMI_POSTDIV_CLK_SRC] = &gcc_usb30_prim_mock_utmi_postdiv_clk_src.clkr, + [GCC_USB30_PRIM_SLEEP_CLK] = &gcc_usb30_prim_sleep_clk.clkr, + [GCC_USB30_SEC_MASTER_CLK] = &gcc_usb30_sec_master_clk.clkr, + [GCC_USB30_SEC_MASTER_CLK_SRC] = &gcc_usb30_sec_master_clk_src.clkr, + [GCC_USB30_SEC_MOCK_UTMI_CLK] = &gcc_usb30_sec_mock_utmi_clk.clkr, + [GCC_USB30_SEC_MOCK_UTMI_CLK_SRC] = &gcc_usb30_sec_mock_utmi_clk_src.clkr, + [GCC_USB30_SEC_MOCK_UTMI_POSTDIV_CLK_SRC] = &gcc_usb30_sec_mock_utmi_postdiv_clk_src.clkr, + [GCC_USB30_SEC_SLEEP_CLK] = &gcc_usb30_sec_sleep_clk.clkr, + [GCC_USB34_PRIM_PHY_PIPE_CLK_SRC] = &gcc_usb34_prim_phy_pipe_clk_src.clkr, + [GCC_USB34_SEC_PHY_PIPE_CLK_SRC] = &gcc_usb34_sec_phy_pipe_clk_src.clkr, + [GCC_USB3_MP0_CLKREF_CLK] = &gcc_usb3_mp0_clkref_clk.clkr, + [GCC_USB3_MP1_CLKREF_CLK] = &gcc_usb3_mp1_clkref_clk.clkr, + [GCC_USB3_MP_PHY_AUX_CLK] = &gcc_usb3_mp_phy_aux_clk.clkr, + [GCC_USB3_MP_PHY_AUX_CLK_SRC] = &gcc_usb3_mp_phy_aux_clk_src.clkr, + [GCC_USB3_MP_PHY_COM_AUX_CLK] = &gcc_usb3_mp_phy_com_aux_clk.clkr, + [GCC_USB3_MP_PHY_PIPE_0_CLK] = &gcc_usb3_mp_phy_pipe_0_clk.clkr, + [GCC_USB3_MP_PHY_PIPE_0_CLK_SRC] = &gcc_usb3_mp_phy_pipe_0_clk_src.clkr, + [GCC_USB3_MP_PHY_PIPE_1_CLK] = &gcc_usb3_mp_phy_pipe_1_clk.clkr, + [GCC_USB3_MP_PHY_PIPE_1_CLK_SRC] = &gcc_usb3_mp_phy_pipe_1_clk_src.clkr, + [GCC_USB3_PRIM_PHY_AUX_CLK] = &gcc_usb3_prim_phy_aux_clk.clkr, + [GCC_USB3_PRIM_PHY_AUX_CLK_SRC] = &gcc_usb3_prim_phy_aux_clk_src.clkr, + [GCC_USB3_PRIM_PHY_COM_AUX_CLK] = &gcc_usb3_prim_phy_com_aux_clk.clkr, + [GCC_USB3_PRIM_PHY_PIPE_CLK] = &gcc_usb3_prim_phy_pipe_clk.clkr, + [GCC_USB3_PRIM_PHY_PIPE_CLK_SRC] = &gcc_usb3_prim_phy_pipe_clk_src.clkr, + [GCC_USB3_SEC_PHY_AUX_CLK] = &gcc_usb3_sec_phy_aux_clk.clkr, + [GCC_USB3_SEC_PHY_AUX_CLK_SRC] = &gcc_usb3_sec_phy_aux_clk_src.clkr, + [GCC_USB3_SEC_PHY_COM_AUX_CLK] = &gcc_usb3_sec_phy_com_aux_clk.clkr, + [GCC_USB3_SEC_PHY_PIPE_CLK] = &gcc_usb3_sec_phy_pipe_clk.clkr, + [GCC_USB3_SEC_PHY_PIPE_CLK_SRC] = &gcc_usb3_sec_phy_pipe_clk_src.clkr, + [GCC_USB4_1_CFG_AHB_CLK] = &gcc_usb4_1_cfg_ahb_clk.clkr, + [GCC_USB4_1_DP_CLK] = &gcc_usb4_1_dp_clk.clkr, + [GCC_USB4_1_MASTER_CLK] = &gcc_usb4_1_master_clk.clkr, + [GCC_USB4_1_MASTER_CLK_SRC] = &gcc_usb4_1_master_clk_src.clkr, + [GCC_USB4_1_PHY_DP_CLK_SRC] = &gcc_usb4_1_phy_dp_clk_src.clkr, + [GCC_USB4_1_PHY_P2RR2P_PIPE_CLK] = &gcc_usb4_1_phy_p2rr2p_pipe_clk.clkr, + [GCC_USB4_1_PHY_P2RR2P_PIPE_CLK_SRC] = &gcc_usb4_1_phy_p2rr2p_pipe_clk_src.clkr, + [GCC_USB4_1_PHY_PCIE_PIPE_CLK] = &gcc_usb4_1_phy_pcie_pipe_clk.clkr, + [GCC_USB4_1_PHY_PCIE_PIPE_CLK_SRC] = &gcc_usb4_1_phy_pcie_pipe_clk_src.clkr, + [GCC_USB4_1_PHY_PCIE_PIPE_MUX_CLK_SRC] = &gcc_usb4_1_phy_pcie_pipe_mux_clk_src.clkr, + [GCC_USB4_1_PHY_PCIE_PIPEGMUX_CLK_SRC] = &gcc_usb4_1_phy_pcie_pipegmux_clk_src.clkr, + [GCC_USB4_1_PHY_RX0_CLK] = &gcc_usb4_1_phy_rx0_clk.clkr, + [GCC_USB4_1_PHY_RX0_CLK_SRC] = &gcc_usb4_1_phy_rx0_clk_src.clkr, + [GCC_USB4_1_PHY_RX1_CLK] = &gcc_usb4_1_phy_rx1_clk.clkr, + [GCC_USB4_1_PHY_RX1_CLK_SRC] = &gcc_usb4_1_phy_rx1_clk_src.clkr, + [GCC_USB4_1_PHY_SYS_CLK_SRC] = &gcc_usb4_1_phy_sys_clk_src.clkr, + [GCC_USB4_1_PHY_USB_PIPE_CLK] = &gcc_usb4_1_phy_usb_pipe_clk.clkr, + [GCC_USB4_1_SB_IF_CLK] = &gcc_usb4_1_sb_if_clk.clkr, + [GCC_USB4_1_SB_IF_CLK_SRC] = &gcc_usb4_1_sb_if_clk_src.clkr, + [GCC_USB4_1_SYS_CLK] = &gcc_usb4_1_sys_clk.clkr, + [GCC_USB4_1_TMU_CLK] = &gcc_usb4_1_tmu_clk.clkr, + [GCC_USB4_1_TMU_CLK_SRC] = &gcc_usb4_1_tmu_clk_src.clkr, + [GCC_USB4_CFG_AHB_CLK] = &gcc_usb4_cfg_ahb_clk.clkr, + [GCC_USB4_CLKREF_CLK] = &gcc_usb4_clkref_clk.clkr, + [GCC_USB4_DP_CLK] = &gcc_usb4_dp_clk.clkr, + [GCC_USB4_EUD_CLKREF_CLK] = &gcc_usb4_eud_clkref_clk.clkr, + [GCC_USB4_MASTER_CLK] = &gcc_usb4_master_clk.clkr, + [GCC_USB4_MASTER_CLK_SRC] = &gcc_usb4_master_clk_src.clkr, + [GCC_USB4_PHY_DP_CLK_SRC] = &gcc_usb4_phy_dp_clk_src.clkr, + [GCC_USB4_PHY_P2RR2P_PIPE_CLK] = &gcc_usb4_phy_p2rr2p_pipe_clk.clkr, + [GCC_USB4_PHY_P2RR2P_PIPE_CLK_SRC] = &gcc_usb4_phy_p2rr2p_pipe_clk_src.clkr, + [GCC_USB4_PHY_PCIE_PIPE_CLK] = &gcc_usb4_phy_pcie_pipe_clk.clkr, + [GCC_USB4_PHY_PCIE_PIPE_CLK_SRC] = &gcc_usb4_phy_pcie_pipe_clk_src.clkr, + [GCC_USB4_PHY_PCIE_PIPE_MUX_CLK_SRC] = &gcc_usb4_phy_pcie_pipe_mux_clk_src.clkr, + [GCC_USB4_PHY_PCIE_PIPEGMUX_CLK_SRC] = &gcc_usb4_phy_pcie_pipegmux_clk_src.clkr, + [GCC_USB4_PHY_RX0_CLK] = &gcc_usb4_phy_rx0_clk.clkr, + [GCC_USB4_PHY_RX0_CLK_SRC] = &gcc_usb4_phy_rx0_clk_src.clkr, + [GCC_USB4_PHY_RX1_CLK] = &gcc_usb4_phy_rx1_clk.clkr, + [GCC_USB4_PHY_RX1_CLK_SRC] = &gcc_usb4_phy_rx1_clk_src.clkr, + [GCC_USB4_PHY_SYS_CLK_SRC] = &gcc_usb4_phy_sys_clk_src.clkr, + [GCC_USB4_PHY_USB_PIPE_CLK] = &gcc_usb4_phy_usb_pipe_clk.clkr, + [GCC_USB4_SB_IF_CLK] = &gcc_usb4_sb_if_clk.clkr, + [GCC_USB4_SB_IF_CLK_SRC] = &gcc_usb4_sb_if_clk_src.clkr, + [GCC_USB4_SYS_CLK] = &gcc_usb4_sys_clk.clkr, + [GCC_USB4_TMU_CLK] = &gcc_usb4_tmu_clk.clkr, + [GCC_USB4_TMU_CLK_SRC] = &gcc_usb4_tmu_clk_src.clkr, + [GCC_VIDEO_AXI0_CLK] = &gcc_video_axi0_clk.clkr, + [GCC_VIDEO_AXI1_CLK] = &gcc_video_axi1_clk.clkr, + [GCC_VIDEO_CVP_THROTTLE_CLK] = &gcc_video_cvp_throttle_clk.clkr, + [GCC_VIDEO_VCODEC_THROTTLE_CLK] = &gcc_video_vcodec_throttle_clk.clkr, +}; + +static const struct qcom_reset_map gcc_sc8280xp_resets[] = { + [GCC_EMAC0_BCR] = { 0xaa000 }, + [GCC_EMAC1_BCR] = { 0xba000 }, + [GCC_PCIE_0_LINK_DOWN_BCR] = { 0x6c014 }, + [GCC_PCIE_0_NOCSR_COM_PHY_BCR] = { 0x6c020 }, + [GCC_PCIE_0_PHY_BCR] = { 0x6c01c }, + [GCC_PCIE_0_PHY_NOCSR_COM_PHY_BCR] = { 0x6c028 }, + [GCC_PCIE_0_TUNNEL_BCR] = { 0xa4000 }, + [GCC_PCIE_1_LINK_DOWN_BCR] = { 0x8e014 }, + [GCC_PCIE_1_NOCSR_COM_PHY_BCR] = { 0x8e020 }, + [GCC_PCIE_1_PHY_BCR] = { 0x8e01c }, + [GCC_PCIE_1_PHY_NOCSR_COM_PHY_BCR] = { 0x8e000 }, + [GCC_PCIE_1_TUNNEL_BCR] = { 0x8d000 }, + [GCC_PCIE_2A_BCR] = { 0x9d000 }, + [GCC_PCIE_2A_LINK_DOWN_BCR] = { 0x9d13c }, + [GCC_PCIE_2A_NOCSR_COM_PHY_BCR] = { 0x9d148 }, + [GCC_PCIE_2A_PHY_BCR] = { 0x9d144 }, + [GCC_PCIE_2A_PHY_NOCSR_COM_PHY_BCR] = { 0x9d14c }, + [GCC_PCIE_2B_BCR] = { 0x9e000 }, + [GCC_PCIE_2B_LINK_DOWN_BCR] = { 0x9e084 }, + [GCC_PCIE_2B_NOCSR_COM_PHY_BCR] = { 0x9e090 }, + [GCC_PCIE_2B_PHY_BCR] = { 0x9e08c }, + [GCC_PCIE_2B_PHY_NOCSR_COM_PHY_BCR] = { 0x9e094 }, + [GCC_PCIE_3A_BCR] = { 0xa0000 }, + [GCC_PCIE_3A_LINK_DOWN_BCR] = { 0xa00f0 }, + [GCC_PCIE_3A_NOCSR_COM_PHY_BCR] = { 0xa00fc }, + [GCC_PCIE_3A_PHY_BCR] = { 0xa00e0 }, + [GCC_PCIE_3A_PHY_NOCSR_COM_PHY_BCR] = { 0xa00e4 }, + [GCC_PCIE_3B_BCR] = { 0xa2000 }, + [GCC_PCIE_3B_LINK_DOWN_BCR] = { 0xa20e0 }, + [GCC_PCIE_3B_NOCSR_COM_PHY_BCR] = { 0xa20ec }, + [GCC_PCIE_3B_PHY_BCR] = { 0xa20e8 }, + [GCC_PCIE_3B_PHY_NOCSR_COM_PHY_BCR] = { 0xa20f0 }, + [GCC_PCIE_4_BCR] = { 0x6b000 }, + [GCC_PCIE_4_LINK_DOWN_BCR] = { 0x6b300 }, + [GCC_PCIE_4_NOCSR_COM_PHY_BCR] = { 0x6b30c }, + [GCC_PCIE_4_PHY_BCR] = { 0x6b308 }, + [GCC_PCIE_4_PHY_NOCSR_COM_PHY_BCR] = { 0x6b310 }, + [GCC_PCIE_PHY_CFG_AHB_BCR] = { 0x6f00c }, + [GCC_PCIE_PHY_COM_BCR] = { 0x6f010 }, + [GCC_PCIE_RSCC_BCR] = { 0xae000 }, + [GCC_QUSB2PHY_HS0_MP_BCR] = { 0x12008 }, + [GCC_QUSB2PHY_HS1_MP_BCR] = { 0x1200c }, + [GCC_QUSB2PHY_HS2_MP_BCR] = { 0x12010 }, + [GCC_QUSB2PHY_HS3_MP_BCR] = { 0x12014 }, + [GCC_QUSB2PHY_PRIM_BCR] = { 0x12000 }, + [GCC_QUSB2PHY_SEC_BCR] = { 0x12004 }, + [GCC_SDCC2_BCR] = { 0x14000 }, + [GCC_SDCC4_BCR] = { 0x16000 }, + [GCC_UFS_CARD_BCR] = { 0x75000 }, + [GCC_UFS_PHY_BCR] = { 0x77000 }, + [GCC_USB2_PHY_PRIM_BCR] = { 0x50028 }, + [GCC_USB2_PHY_SEC_BCR] = { 0x5002c }, + [GCC_USB30_MP_BCR] = { 0xab000 }, + [GCC_USB30_PRIM_BCR] = { 0xf000 }, + [GCC_USB30_SEC_BCR] = { 0x10000 }, + [GCC_USB3_DP_PHY_PRIM_BCR] = { 0x50008 }, + [GCC_USB3_DP_PHY_SEC_BCR] = { 0x50014 }, + [GCC_USB3_PHY_PRIM_BCR] = { 0x50000 }, + [GCC_USB3_PHY_SEC_BCR] = { 0x5000c }, + [GCC_USB3_UNIPHY_MP0_BCR] = { 0x50018 }, + [GCC_USB3_UNIPHY_MP1_BCR] = { 0x5001c }, + [GCC_USB3PHY_PHY_PRIM_BCR] = { 0x50004 }, + [GCC_USB3PHY_PHY_SEC_BCR] = { 0x50010 }, + [GCC_USB3UNIPHY_PHY_MP0_BCR] = { 0x50020 }, + [GCC_USB3UNIPHY_PHY_MP1_BCR] = { 0x50024 }, + [GCC_USB4_1_BCR] = { 0xb8000 }, + [GCC_USB4_1_DP_PHY_PRIM_BCR] = { 0xb9020 }, + [GCC_USB4_1_DPPHY_AUX_BCR] = { 0xb9024 }, + [GCC_USB4_1_PHY_PRIM_BCR] = { 0xb9018 }, + [GCC_USB4_BCR] = { 0x2a000 }, + [GCC_USB4_DP_PHY_PRIM_BCR] = { 0x4a008 }, + [GCC_USB4_DPPHY_AUX_BCR] = { 0x4a00c }, + [GCC_USB4_PHY_PRIM_BCR] = { 0x4a000 }, + [GCC_USB4PHY_1_PHY_PRIM_BCR] = { 0xb901c }, + [GCC_USB4PHY_PHY_PRIM_BCR] = { 0x4a004 }, + [GCC_USB_PHY_CFG_AHB2PHY_BCR] = { 0x6a000 }, + [GCC_VIDEO_BCR] = { 0x28000 }, + [GCC_VIDEO_AXI0_CLK_ARES] = { 0x28010, 2 }, + [GCC_VIDEO_AXI1_CLK_ARES] = { 0x28018, 2 }, +}; + +static struct gdsc *gcc_sc8280xp_gdscs[] = { + [PCIE_0_TUNNEL_GDSC] = &pcie_0_tunnel_gdsc, + [PCIE_1_TUNNEL_GDSC] = &pcie_1_tunnel_gdsc, + [PCIE_2A_GDSC] = &pcie_2a_gdsc, + [PCIE_2B_GDSC] = &pcie_2b_gdsc, + [PCIE_3A_GDSC] = &pcie_3a_gdsc, + [PCIE_3B_GDSC] = &pcie_3b_gdsc, + [PCIE_4_GDSC] = &pcie_4_gdsc, + [UFS_CARD_GDSC] = &ufs_card_gdsc, + [UFS_PHY_GDSC] = &ufs_phy_gdsc, + [USB30_MP_GDSC] = &usb30_mp_gdsc, + [USB30_PRIM_GDSC] = &usb30_prim_gdsc, + [USB30_SEC_GDSC] = &usb30_sec_gdsc, +}; + +static const struct clk_rcg_dfs_data gcc_dfs_clocks[] = { + DEFINE_RCG_DFS(gcc_qupv3_wrap0_s0_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap0_s1_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap0_s2_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap0_s3_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap0_s4_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap0_s5_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap0_s6_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap0_s7_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap1_s0_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap1_s1_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap1_s2_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap1_s3_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap1_s4_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap1_s5_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap1_s6_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap1_s7_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap2_s0_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap2_s1_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap2_s2_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap2_s3_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap2_s4_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap2_s5_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap2_s6_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap2_s7_clk_src), +}; + +static const struct regmap_config gcc_sc8280xp_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0xc3014, + .fast_io = true, +}; + +static const struct qcom_cc_desc gcc_sc8280xp_desc = { + .config = &gcc_sc8280xp_regmap_config, + .clks = gcc_sc8280xp_clocks, + .num_clks = ARRAY_SIZE(gcc_sc8280xp_clocks), + .resets = gcc_sc8280xp_resets, + .num_resets = ARRAY_SIZE(gcc_sc8280xp_resets), + .gdscs = gcc_sc8280xp_gdscs, + .num_gdscs = ARRAY_SIZE(gcc_sc8280xp_gdscs), +}; + +static int gcc_sc8280xp_probe(struct platform_device *pdev) +{ + struct regmap *regmap; + int ret; + + regmap = qcom_cc_map(pdev, &gcc_sc8280xp_desc); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + /* + * Keep the clocks always-ON + * GCC_CAMERA_AHB_CLK, GCC_CAMERA_XO_CLK, GCC_DISP_AHB_CLK, + * GCC_DISP_XO_CLK, GCC_GPU_CFG_AHB_CLK, GCC_VIDEO_AHB_CLK, + * GCC_VIDEO_XO_CLK, GCC_DISP1_AHB_CLK, GCC_DISP1_XO_CLK + */ + regmap_update_bits(regmap, 0x26004, BIT(0), BIT(0)); + regmap_update_bits(regmap, 0x26020, BIT(0), BIT(0)); + regmap_update_bits(regmap, 0x27004, BIT(0), BIT(0)); + regmap_update_bits(regmap, 0x27028, BIT(0), BIT(0)); + regmap_update_bits(regmap, 0x71004, BIT(0), BIT(0)); + regmap_update_bits(regmap, 0x28004, BIT(0), BIT(0)); + regmap_update_bits(regmap, 0x28028, BIT(0), BIT(0)); + regmap_update_bits(regmap, 0xbb004, BIT(0), BIT(0)); + regmap_update_bits(regmap, 0xbb028, BIT(0), BIT(0)); + + ret = qcom_cc_register_rcg_dfs(regmap, gcc_dfs_clocks, ARRAY_SIZE(gcc_dfs_clocks)); + if (ret) + return ret; + + return qcom_cc_really_probe(pdev, &gcc_sc8280xp_desc, regmap); +} + +static const struct of_device_id gcc_sc8280xp_match_table[] = { + { .compatible = "qcom,gcc-sc8280xp" }, + { } +}; +MODULE_DEVICE_TABLE(of, gcc_sc8280xp_match_table); + +static struct platform_driver gcc_sc8280xp_driver = { + .probe = gcc_sc8280xp_probe, + .driver = { + .name = "gcc-sc8280xp", + .of_match_table = gcc_sc8280xp_match_table, + }, +}; + +static int __init gcc_sc8280xp_init(void) +{ + return platform_driver_register(&gcc_sc8280xp_driver); +} +subsys_initcall(gcc_sc8280xp_init); + +static void __exit gcc_sc8280xp_exit(void) +{ + platform_driver_unregister(&gcc_sc8280xp_driver); +} +module_exit(gcc_sc8280xp_exit); + +MODULE_DESCRIPTION("Qualcomm SC8280XP GCC driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/qcom/lpassaudiocc-sc7280.c b/drivers/clk/qcom/lpassaudiocc-sc7280.c new file mode 100644 index 0000000000000000000000000000000000000000..6ab6e5a34c7243ba64f30d3c50f7bc4a1ba1fe9f --- /dev/null +++ b/drivers/clk/qcom/lpassaudiocc-sc7280.c @@ -0,0 +1,838 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2021, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "clk-alpha-pll.h" +#include "clk-branch.h" +#include "clk-rcg.h" +#include "clk-regmap.h" +#include "clk-regmap-divider.h" +#include "clk-regmap-mux.h" +#include "common.h" +#include "gdsc.h" + +enum { + P_BI_TCXO, + P_LPASS_AON_CC_PLL_OUT_EVEN, + P_LPASS_AON_CC_PLL_OUT_MAIN, + P_LPASS_AON_CC_PLL_OUT_MAIN_CDIV_DIV_CLK_SRC, + P_LPASS_AON_CC_PLL_OUT_ODD, + P_LPASS_AUDIO_CC_PLL_OUT_AUX, + P_LPASS_AUDIO_CC_PLL_OUT_AUX2_DIV_CLK_SRC, + P_LPASS_AUDIO_CC_PLL_MAIN_DIV_CLK, +}; + +static const struct pll_vco zonda_vco[] = { + { 595200000UL, 3600000000UL, 0 }, +}; + +/* 1128.96MHz configuration */ +static const struct alpha_pll_config lpass_audio_cc_pll_config = { + .l = 0x3a, + .alpha = 0xcccc, + .config_ctl_val = 0x08200920, + .config_ctl_hi_val = 0x05002001, + .config_ctl_hi1_val = 0x00000000, + .user_ctl_val = 0x03000101, +}; + +static struct clk_alpha_pll lpass_audio_cc_pll = { + .offset = 0x0, + .vco_table = zonda_vco, + .num_vco = ARRAY_SIZE(zonda_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_ZONDA], + .clkr = { + .hw.init = &(const struct clk_init_data){ + .name = "lpass_audio_cc_pll", + .parent_data = &(const struct clk_parent_data){ + .index = 0, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_zonda_ops, + }, + }, +}; + +static const struct clk_div_table post_div_table_lpass_audio_cc_pll_out_aux2[] = { + { 0x1, 2 }, + { } +}; + +static struct clk_alpha_pll_postdiv lpass_audio_cc_pll_out_aux2 = { + .offset = 0x0, + .post_div_shift = 8, + .post_div_table = post_div_table_lpass_audio_cc_pll_out_aux2, + .num_post_div = ARRAY_SIZE(post_div_table_lpass_audio_cc_pll_out_aux2), + .width = 2, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_ZONDA], + .clkr.hw.init = &(const struct clk_init_data){ + .name = "lpass_audio_cc_pll_out_aux2", + .parent_hws = (const struct clk_hw*[]){ + &lpass_audio_cc_pll.clkr.hw, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_postdiv_zonda_ops, + }, +}; + +static const struct pll_vco lucid_vco[] = { + { 249600000, 2000000000, 0 }, +}; + +/* 614.4 MHz configuration */ +static const struct alpha_pll_config lpass_aon_cc_pll_config = { + .l = 0x20, + .alpha = 0x0, + .config_ctl_val = 0x20485699, + .config_ctl_hi_val = 0x00002261, + .config_ctl_hi1_val = 0x329A299C, + .user_ctl_val = 0x00005100, + .user_ctl_hi_val = 0x00000805, + .user_ctl_hi1_val = 0x00000000, +}; + +static struct clk_alpha_pll lpass_aon_cc_pll = { + .offset = 0x0, + .vco_table = lucid_vco, + .num_vco = ARRAY_SIZE(lucid_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID], + .clkr = { + .hw.init = &(const struct clk_init_data){ + .name = "lpass_aon_cc_pll", + .parent_data = &(const struct clk_parent_data){ + .index = 0, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_lucid_ops, + }, + }, +}; + +static const struct clk_div_table post_div_table_lpass_aon_cc_pll_out_even[] = { + { 0x1, 2 }, + { } +}; + +static struct clk_alpha_pll_postdiv lpass_aon_cc_pll_out_even = { + .offset = 0x0, + .post_div_shift = 8, + .post_div_table = post_div_table_lpass_aon_cc_pll_out_even, + .num_post_div = ARRAY_SIZE(post_div_table_lpass_aon_cc_pll_out_even), + .width = 4, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID], + .clkr.hw.init = &(const struct clk_init_data){ + .name = "lpass_aon_cc_pll_out_even", + .parent_hws = (const struct clk_hw*[]){ + &lpass_aon_cc_pll.clkr.hw, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_postdiv_lucid_ops, + }, +}; + +static const struct clk_div_table post_div_table_lpass_aon_cc_pll_out_odd[] = { + { 0x5, 5 }, + { } +}; + +static struct clk_alpha_pll_postdiv lpass_aon_cc_pll_out_odd = { + .offset = 0x0, + .post_div_shift = 12, + .post_div_table = post_div_table_lpass_aon_cc_pll_out_odd, + .num_post_div = ARRAY_SIZE(post_div_table_lpass_aon_cc_pll_out_odd), + .width = 4, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID], + .clkr.hw.init = &(const struct clk_init_data){ + .name = "lpass_aon_cc_pll_out_odd", + .parent_hws = (const struct clk_hw*[]){ + &lpass_aon_cc_pll.clkr.hw, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_postdiv_lucid_ops, + }, +}; + +static const struct parent_map lpass_audio_cc_parent_map_0[] = { + { P_BI_TCXO, 0 }, + { P_LPASS_AUDIO_CC_PLL_OUT_AUX, 3 }, + { P_LPASS_AON_CC_PLL_OUT_ODD, 5 }, + { P_LPASS_AUDIO_CC_PLL_OUT_AUX2_DIV_CLK_SRC, 6 }, +}; + +static struct clk_regmap_div lpass_audio_cc_pll_out_aux2_div_clk_src; +static struct clk_regmap_div lpass_audio_cc_pll_out_main_div_clk_src; + +static const struct clk_parent_data lpass_audio_cc_parent_data_0[] = { + { .index = 0 }, + { .hw = &lpass_audio_cc_pll.clkr.hw }, + { .hw = &lpass_aon_cc_pll_out_odd.clkr.hw }, + { .hw = &lpass_audio_cc_pll_out_aux2_div_clk_src.clkr.hw }, +}; + +static const struct parent_map lpass_aon_cc_parent_map_0[] = { + { P_BI_TCXO, 0 }, + { P_LPASS_AON_CC_PLL_OUT_EVEN, 4 }, +}; + +static const struct clk_parent_data lpass_aon_cc_parent_data_0[] = { + { .index = 0 }, + { .hw = &lpass_aon_cc_pll_out_even.clkr.hw }, +}; + +static const struct parent_map lpass_aon_cc_parent_map_1[] = { + { P_BI_TCXO, 0 }, + { P_LPASS_AON_CC_PLL_OUT_ODD, 1 }, + { P_LPASS_AUDIO_CC_PLL_MAIN_DIV_CLK, 6 }, +}; + +static const struct clk_parent_data lpass_aon_cc_parent_data_1[] = { + { .index = 0 }, + { .hw = &lpass_aon_cc_pll_out_odd.clkr.hw }, + { .hw = &lpass_audio_cc_pll_out_main_div_clk_src.clkr.hw }, +}; + +static const struct freq_tbl ftbl_lpass_aon_cc_main_rcg_clk_src[] = { + F(38400000, P_LPASS_AON_CC_PLL_OUT_EVEN, 8, 0, 0), + F(76800000, P_LPASS_AON_CC_PLL_OUT_EVEN, 4, 0, 0), + F(153600000, P_LPASS_AON_CC_PLL_OUT_EVEN, 2, 0, 0), + { } +}; + +static struct clk_rcg2 lpass_aon_cc_main_rcg_clk_src = { + .cmd_rcgr = 0x1000, + .mnd_width = 0, + .hid_width = 5, + .parent_map = lpass_aon_cc_parent_map_0, + .freq_tbl = ftbl_lpass_aon_cc_main_rcg_clk_src, + .clkr.hw.init = &(const struct clk_init_data){ + .name = "lpass_aon_cc_main_rcg_clk_src", + .parent_data = lpass_aon_cc_parent_data_0, + .num_parents = ARRAY_SIZE(lpass_aon_cc_parent_data_0), + .flags = CLK_OPS_PARENT_ENABLE, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_lpass_aon_cc_tx_mclk_rcg_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(24576000, P_LPASS_AON_CC_PLL_OUT_ODD, 5, 0, 0), + { } +}; + +static struct clk_rcg2 lpass_aon_cc_tx_mclk_rcg_clk_src = { + .cmd_rcgr = 0x13004, + .mnd_width = 0, + .hid_width = 5, + .parent_map = lpass_aon_cc_parent_map_1, + .freq_tbl = ftbl_lpass_aon_cc_tx_mclk_rcg_clk_src, + .clkr.hw.init = &(const struct clk_init_data){ + .name = "lpass_aon_cc_tx_mclk_rcg_clk_src", + .parent_data = lpass_aon_cc_parent_data_1, + .num_parents = ARRAY_SIZE(lpass_aon_cc_parent_data_1), + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_regmap_div lpass_audio_cc_pll_out_aux2_div_clk_src = { + .reg = 0x48, + .shift = 0, + .width = 4, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "lpass_audio_cc_pll_out_aux2_div_clk_src", + .parent_hws = (const struct clk_hw*[]){ + &lpass_audio_cc_pll_out_aux2.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ro_ops, + }, +}; + +static struct clk_regmap_div lpass_audio_cc_pll_out_main_div_clk_src = { + .reg = 0x3c, + .shift = 0, + .width = 4, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "lpass_audio_cc_pll_out_main_div_clk_src", + .parent_hws = (const struct clk_hw*[]){ + &lpass_audio_cc_pll.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ro_ops, + }, +}; + +static struct clk_regmap_div lpass_aon_cc_cdiv_tx_mclk_div_clk_src = { + .reg = 0x13010, + .shift = 0, + .width = 4, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "lpass_aon_cc_cdiv_tx_mclk_div_clk_src", + .parent_hws = (const struct clk_hw*[]){ + &lpass_aon_cc_tx_mclk_rcg_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ro_ops, + }, +}; + +static struct clk_regmap_div lpass_aon_cc_pll_out_main_cdiv_div_clk_src = { + .reg = 0x80, + .shift = 0, + .width = 4, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "lpass_aon_cc_pll_out_main_cdiv_div_clk_src", + .parent_hws = (const struct clk_hw*[]){ + &lpass_aon_cc_pll.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ro_ops, + }, +}; + +static const struct freq_tbl ftbl_lpass_audio_cc_ext_mclk0_clk_src[] = { + F(256000, P_LPASS_AON_CC_PLL_OUT_ODD, 15, 1, 32), + F(352800, P_LPASS_AUDIO_CC_PLL_OUT_AUX2_DIV_CLK_SRC, 10, 1, 32), + F(512000, P_LPASS_AON_CC_PLL_OUT_ODD, 15, 1, 16), + F(705600, P_LPASS_AUDIO_CC_PLL_OUT_AUX2_DIV_CLK_SRC, 10, 1, 16), + F(768000, P_LPASS_AON_CC_PLL_OUT_ODD, 10, 1, 16), + F(1024000, P_LPASS_AON_CC_PLL_OUT_ODD, 15, 1, 8), + F(1411200, P_LPASS_AUDIO_CC_PLL_OUT_AUX2_DIV_CLK_SRC, 10, 1, 8), + F(1536000, P_LPASS_AON_CC_PLL_OUT_ODD, 10, 1, 8), + F(2048000, P_LPASS_AON_CC_PLL_OUT_ODD, 15, 1, 4), + F(2822400, P_LPASS_AUDIO_CC_PLL_OUT_AUX2_DIV_CLK_SRC, 10, 1, 4), + F(3072000, P_LPASS_AON_CC_PLL_OUT_ODD, 10, 1, 4), + F(4096000, P_LPASS_AON_CC_PLL_OUT_ODD, 15, 1, 2), + F(5644800, P_LPASS_AUDIO_CC_PLL_OUT_AUX2_DIV_CLK_SRC, 10, 1, 2), + F(6144000, P_LPASS_AON_CC_PLL_OUT_ODD, 10, 1, 2), + F(8192000, P_LPASS_AON_CC_PLL_OUT_ODD, 15, 0, 0), + F(9600000, P_BI_TCXO, 2, 0, 0), + F(11289600, P_LPASS_AUDIO_CC_PLL_OUT_AUX2_DIV_CLK_SRC, 10, 0, 0), + F(12288000, P_LPASS_AON_CC_PLL_OUT_ODD, 10, 0, 0), + F(19200000, P_BI_TCXO, 1, 0, 0), + F(22579200, P_LPASS_AUDIO_CC_PLL_OUT_AUX2_DIV_CLK_SRC, 5, 0, 0), + F(24576000, P_LPASS_AON_CC_PLL_OUT_ODD, 5, 0, 0), + { } +}; + +static struct clk_rcg2 lpass_audio_cc_ext_mclk0_clk_src = { + .cmd_rcgr = 0x20004, + .mnd_width = 8, + .hid_width = 5, + .parent_map = lpass_audio_cc_parent_map_0, + .freq_tbl = ftbl_lpass_audio_cc_ext_mclk0_clk_src, + .clkr.hw.init = &(const struct clk_init_data){ + .name = "lpass_audio_cc_ext_mclk0_clk_src", + .parent_data = lpass_audio_cc_parent_data_0, + .num_parents = ARRAY_SIZE(lpass_audio_cc_parent_data_0), + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 lpass_audio_cc_ext_mclk1_clk_src = { + .cmd_rcgr = 0x21004, + .mnd_width = 8, + .hid_width = 5, + .parent_map = lpass_audio_cc_parent_map_0, + .freq_tbl = ftbl_lpass_audio_cc_ext_mclk0_clk_src, + .clkr.hw.init = &(const struct clk_init_data){ + .name = "lpass_audio_cc_ext_mclk1_clk_src", + .parent_data = lpass_audio_cc_parent_data_0, + .num_parents = ARRAY_SIZE(lpass_audio_cc_parent_data_0), + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 lpass_audio_cc_rx_mclk_clk_src = { + .cmd_rcgr = 0x24004, + .mnd_width = 8, + .hid_width = 5, + .parent_map = lpass_audio_cc_parent_map_0, + .freq_tbl = ftbl_lpass_audio_cc_ext_mclk0_clk_src, + .clkr.hw.init = &(const struct clk_init_data){ + .name = "lpass_audio_cc_rx_mclk_clk_src", + .parent_data = lpass_audio_cc_parent_data_0, + .num_parents = ARRAY_SIZE(lpass_audio_cc_parent_data_0), + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_regmap_div lpass_audio_cc_cdiv_rx_mclk_div_clk_src = { + .reg = 0x240d0, + .shift = 0, + .width = 4, + .clkr.hw.init = &(const struct clk_init_data) { + .name = "lpass_audio_cc_cdiv_rx_mclk_div_clk_src", + .parent_hws = (const struct clk_hw*[]){ + &lpass_audio_cc_rx_mclk_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ro_ops, + }, +}; + +static struct clk_branch lpass_aon_cc_audio_hm_h_clk; + +static struct clk_branch lpass_audio_cc_codec_mem0_clk = { + .halt_reg = 0x1e004, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1e004, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data){ + .name = "lpass_audio_cc_codec_mem0_clk", + .parent_hws = (const struct clk_hw*[]){ + &lpass_aon_cc_audio_hm_h_clk.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch lpass_audio_cc_codec_mem1_clk = { + .halt_reg = 0x1e008, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1e008, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data){ + .name = "lpass_audio_cc_codec_mem1_clk", + .parent_hws = (const struct clk_hw*[]){ + &lpass_aon_cc_audio_hm_h_clk.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch lpass_audio_cc_codec_mem2_clk = { + .halt_reg = 0x1e00c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1e00c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data){ + .name = "lpass_audio_cc_codec_mem2_clk", + .parent_hws = (const struct clk_hw*[]){ + &lpass_aon_cc_audio_hm_h_clk.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch lpass_audio_cc_codec_mem_clk = { + .halt_reg = 0x1e000, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1e000, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data){ + .name = "lpass_audio_cc_codec_mem_clk", + .parent_hws = (const struct clk_hw*[]){ + &lpass_aon_cc_audio_hm_h_clk.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch lpass_audio_cc_ext_mclk0_clk = { + .halt_reg = 0x20018, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x20018, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data){ + .name = "lpass_audio_cc_ext_mclk0_clk", + .parent_hws = (const struct clk_hw*[]){ + &lpass_audio_cc_ext_mclk0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch lpass_audio_cc_ext_mclk1_clk = { + .halt_reg = 0x21018, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x21018, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data){ + .name = "lpass_audio_cc_ext_mclk1_clk", + .parent_hws = (const struct clk_hw*[]){ + &lpass_audio_cc_ext_mclk1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch lpass_audio_cc_rx_mclk_2x_clk = { + .halt_reg = 0x240cc, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x240cc, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data){ + .name = "lpass_audio_cc_rx_mclk_2x_clk", + .parent_hws = (const struct clk_hw*[]){ + &lpass_audio_cc_rx_mclk_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch lpass_audio_cc_rx_mclk_clk = { + .halt_reg = 0x240d4, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x240d4, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data){ + .name = "lpass_audio_cc_rx_mclk_clk", + .parent_hws = (const struct clk_hw*[]){ + &lpass_audio_cc_cdiv_rx_mclk_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch lpass_aon_cc_audio_hm_h_clk = { + .halt_reg = 0x9014, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x9014, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data){ + .name = "lpass_aon_cc_audio_hm_h_clk", + .parent_hws = (const struct clk_hw*[]){ + &lpass_aon_cc_main_rcg_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_aon_ops, + }, + }, +}; + +static struct clk_branch lpass_aon_cc_va_mem0_clk = { + .halt_reg = 0x9028, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x9028, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data){ + .name = "lpass_aon_cc_va_mem0_clk", + .parent_hws = (const struct clk_hw*[]){ + &lpass_aon_cc_main_rcg_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch lpass_aon_cc_tx_mclk_2x_clk = { + .halt_reg = 0x1300c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1300c, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data){ + .name = "lpass_aon_cc_tx_mclk_2x_clk", + .parent_hws = (const struct clk_hw*[]){ + &lpass_aon_cc_tx_mclk_rcg_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch lpass_aon_cc_tx_mclk_clk = { + .halt_reg = 0x13014, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x13014, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data){ + .name = "lpass_aon_cc_tx_mclk_clk", + .parent_hws = (const struct clk_hw*[]){ + &lpass_aon_cc_cdiv_tx_mclk_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct gdsc lpass_aon_cc_lpass_audio_hm_gdsc = { + .gdscr = 0x9090, + .pd = { + .name = "lpass_aon_cc_lpass_audio_hm_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = RETAIN_FF_ENABLE, +}; + +static struct clk_regmap *lpass_aon_cc_sc7280_clocks[] = { + [LPASS_AON_CC_AUDIO_HM_H_CLK] = &lpass_aon_cc_audio_hm_h_clk.clkr, + [LPASS_AON_CC_VA_MEM0_CLK] = &lpass_aon_cc_va_mem0_clk.clkr, + [LPASS_AON_CC_CDIV_TX_MCLK_DIV_CLK_SRC] = &lpass_aon_cc_cdiv_tx_mclk_div_clk_src.clkr, + [LPASS_AON_CC_MAIN_RCG_CLK_SRC] = &lpass_aon_cc_main_rcg_clk_src.clkr, + [LPASS_AON_CC_PLL] = &lpass_aon_cc_pll.clkr, + [LPASS_AON_CC_PLL_OUT_EVEN] = &lpass_aon_cc_pll_out_even.clkr, + [LPASS_AON_CC_PLL_OUT_MAIN_CDIV_DIV_CLK_SRC] = + &lpass_aon_cc_pll_out_main_cdiv_div_clk_src.clkr, + [LPASS_AON_CC_PLL_OUT_ODD] = &lpass_aon_cc_pll_out_odd.clkr, + [LPASS_AON_CC_TX_MCLK_2X_CLK] = &lpass_aon_cc_tx_mclk_2x_clk.clkr, + [LPASS_AON_CC_TX_MCLK_CLK] = &lpass_aon_cc_tx_mclk_clk.clkr, + [LPASS_AON_CC_TX_MCLK_RCG_CLK_SRC] = &lpass_aon_cc_tx_mclk_rcg_clk_src.clkr, +}; + +static struct gdsc *lpass_aon_cc_sc7280_gdscs[] = { + [LPASS_AON_CC_LPASS_AUDIO_HM_GDSC] = &lpass_aon_cc_lpass_audio_hm_gdsc, +}; + +static struct clk_regmap *lpass_audio_cc_sc7280_clocks[] = { + [LPASS_AUDIO_CC_CDIV_RX_MCLK_DIV_CLK_SRC] = &lpass_audio_cc_cdiv_rx_mclk_div_clk_src.clkr, + [LPASS_AUDIO_CC_CODEC_MEM0_CLK] = &lpass_audio_cc_codec_mem0_clk.clkr, + [LPASS_AUDIO_CC_CODEC_MEM1_CLK] = &lpass_audio_cc_codec_mem1_clk.clkr, + [LPASS_AUDIO_CC_CODEC_MEM2_CLK] = &lpass_audio_cc_codec_mem2_clk.clkr, + [LPASS_AUDIO_CC_CODEC_MEM_CLK] = &lpass_audio_cc_codec_mem_clk.clkr, + [LPASS_AUDIO_CC_EXT_MCLK0_CLK] = &lpass_audio_cc_ext_mclk0_clk.clkr, + [LPASS_AUDIO_CC_EXT_MCLK0_CLK_SRC] = &lpass_audio_cc_ext_mclk0_clk_src.clkr, + [LPASS_AUDIO_CC_EXT_MCLK1_CLK] = &lpass_audio_cc_ext_mclk1_clk.clkr, + [LPASS_AUDIO_CC_EXT_MCLK1_CLK_SRC] = &lpass_audio_cc_ext_mclk1_clk_src.clkr, + [LPASS_AUDIO_CC_PLL] = &lpass_audio_cc_pll.clkr, + [LPASS_AUDIO_CC_PLL_OUT_AUX2] = &lpass_audio_cc_pll_out_aux2.clkr, + [LPASS_AUDIO_CC_PLL_OUT_AUX2_DIV_CLK_SRC] = &lpass_audio_cc_pll_out_aux2_div_clk_src.clkr, + [LPASS_AUDIO_CC_PLL_OUT_MAIN_DIV_CLK_SRC] = &lpass_audio_cc_pll_out_main_div_clk_src.clkr, + [LPASS_AUDIO_CC_RX_MCLK_2X_CLK] = &lpass_audio_cc_rx_mclk_2x_clk.clkr, + [LPASS_AUDIO_CC_RX_MCLK_CLK] = &lpass_audio_cc_rx_mclk_clk.clkr, + [LPASS_AUDIO_CC_RX_MCLK_CLK_SRC] = &lpass_audio_cc_rx_mclk_clk_src.clkr, +}; + +static struct regmap_config lpass_audio_cc_sc7280_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .fast_io = true, +}; + +static const struct qcom_cc_desc lpass_audio_cc_sc7280_desc = { + .config = &lpass_audio_cc_sc7280_regmap_config, + .clks = lpass_audio_cc_sc7280_clocks, + .num_clks = ARRAY_SIZE(lpass_audio_cc_sc7280_clocks), +}; + +static const struct of_device_id lpass_audio_cc_sc7280_match_table[] = { + { .compatible = "qcom,sc7280-lpassaudiocc" }, + { } +}; +MODULE_DEVICE_TABLE(of, lpass_audio_cc_sc7280_match_table); + +static void lpassaudio_pm_runtime_disable(void *data) +{ + pm_runtime_disable(data); +} + +static void lpassaudio_pm_clk_destroy(void *data) +{ + pm_clk_destroy(data); +} + +static int lpassaudio_create_pm_clks(struct platform_device *pdev) +{ + int ret; + + pm_runtime_use_autosuspend(&pdev->dev); + pm_runtime_set_autosuspend_delay(&pdev->dev, 50); + pm_runtime_enable(&pdev->dev); + + ret = devm_add_action_or_reset(&pdev->dev, lpassaudio_pm_runtime_disable, &pdev->dev); + if (ret) + return ret; + + ret = pm_clk_create(&pdev->dev); + if (ret) + return ret; + + ret = devm_add_action_or_reset(&pdev->dev, lpassaudio_pm_clk_destroy, &pdev->dev); + if (ret) + return ret; + + ret = pm_clk_add(&pdev->dev, "iface"); + if (ret < 0) + dev_err(&pdev->dev, "failed to acquire iface clock\n"); + + return ret; +} + +static int lpass_audio_cc_sc7280_probe(struct platform_device *pdev) +{ + const struct qcom_cc_desc *desc; + struct regmap *regmap; + int ret; + + ret = lpassaudio_create_pm_clks(pdev); + if (ret) + return ret; + + lpass_audio_cc_sc7280_regmap_config.name = "lpassaudio_cc"; + lpass_audio_cc_sc7280_regmap_config.max_register = 0x2f000; + desc = &lpass_audio_cc_sc7280_desc; + + regmap = qcom_cc_map(pdev, desc); + if (IS_ERR(regmap)) { + pm_runtime_disable(&pdev->dev); + return PTR_ERR(regmap); + } + + clk_zonda_pll_configure(&lpass_audio_cc_pll, regmap, &lpass_audio_cc_pll_config); + + /* PLL settings */ + regmap_write(regmap, 0x4, 0x3b); + regmap_write(regmap, 0x8, 0xff05); + + ret = qcom_cc_really_probe(pdev, &lpass_audio_cc_sc7280_desc, regmap); + if (ret) { + dev_err(&pdev->dev, "Failed to register LPASS AUDIO CC clocks\n"); + pm_runtime_disable(&pdev->dev); + return ret; + } + + pm_runtime_mark_last_busy(&pdev->dev); + pm_runtime_put_autosuspend(&pdev->dev); + pm_runtime_put_sync(&pdev->dev); + + return ret; +} + +static const struct dev_pm_ops lpass_audio_cc_pm_ops = { + SET_RUNTIME_PM_OPS(pm_clk_suspend, pm_clk_resume, NULL) +}; + +static struct platform_driver lpass_audio_cc_sc7280_driver = { + .probe = lpass_audio_cc_sc7280_probe, + .driver = { + .name = "lpass_audio_cc-sc7280", + .of_match_table = lpass_audio_cc_sc7280_match_table, + .pm = &lpass_audio_cc_pm_ops, + }, +}; + +static const struct qcom_cc_desc lpass_aon_cc_sc7280_desc = { + .config = &lpass_audio_cc_sc7280_regmap_config, + .clks = lpass_aon_cc_sc7280_clocks, + .num_clks = ARRAY_SIZE(lpass_aon_cc_sc7280_clocks), + .gdscs = lpass_aon_cc_sc7280_gdscs, + .num_gdscs = ARRAY_SIZE(lpass_aon_cc_sc7280_gdscs), +}; + +static const struct of_device_id lpass_aon_cc_sc7280_match_table[] = { + { .compatible = "qcom,sc7280-lpassaoncc" }, + { } +}; +MODULE_DEVICE_TABLE(of, lpass_aon_cc_sc7280_match_table); + +static int lpass_aon_cc_sc7280_probe(struct platform_device *pdev) +{ + const struct qcom_cc_desc *desc; + struct regmap *regmap; + int ret; + + ret = lpassaudio_create_pm_clks(pdev); + if (ret) + return ret; + + lpass_audio_cc_sc7280_regmap_config.name = "lpasscc_aon"; + lpass_audio_cc_sc7280_regmap_config.max_register = 0xa0008; + desc = &lpass_aon_cc_sc7280_desc; + + regmap = qcom_cc_map(pdev, desc); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + clk_lucid_pll_configure(&lpass_aon_cc_pll, regmap, &lpass_aon_cc_pll_config); + + ret = qcom_cc_really_probe(pdev, &lpass_aon_cc_sc7280_desc, regmap); + if (ret) + dev_err(&pdev->dev, "Failed to register LPASS AON CC clocks\n"); + + pm_runtime_mark_last_busy(&pdev->dev); + pm_runtime_put_autosuspend(&pdev->dev); + pm_runtime_put_sync(&pdev->dev); + + return ret; +} + +static struct platform_driver lpass_aon_cc_sc7280_driver = { + .probe = lpass_aon_cc_sc7280_probe, + .driver = { + .name = "lpass_aon_cc-sc7280", + .of_match_table = lpass_aon_cc_sc7280_match_table, + .pm = &lpass_audio_cc_pm_ops, + }, +}; + +static int __init lpass_audio_cc_sc7280_init(void) +{ + int ret; + + ret = platform_driver_register(&lpass_aon_cc_sc7280_driver); + if (ret) + return ret; + + return platform_driver_register(&lpass_audio_cc_sc7280_driver); +} +subsys_initcall(lpass_audio_cc_sc7280_init); + +static void __exit lpass_audio_cc_sc7280_exit(void) +{ + platform_driver_unregister(&lpass_audio_cc_sc7280_driver); + platform_driver_unregister(&lpass_aon_cc_sc7280_driver); +} +module_exit(lpass_audio_cc_sc7280_exit); + +MODULE_DESCRIPTION("QTI LPASS_AUDIO_CC SC7280 Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/clk/qcom/lpasscorecc-sc7280.c b/drivers/clk/qcom/lpasscorecc-sc7280.c new file mode 100644 index 0000000000000000000000000000000000000000..1f1f1bd1b68ef3a96c8c7c0eac5716a78384e6fa --- /dev/null +++ b/drivers/clk/qcom/lpasscorecc-sc7280.c @@ -0,0 +1,431 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2021, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "clk-alpha-pll.h" +#include "clk-branch.h" +#include "clk-rcg.h" +#include "clk-regmap.h" +#include "clk-regmap-divider.h" +#include "common.h" +#include "gdsc.h" + +enum { + P_BI_TCXO, + P_LPASS_CORE_CC_DIG_PLL_OUT_MAIN, + P_LPASS_CORE_CC_DIG_PLL_OUT_MAIN_DIV_CLK_SRC, + P_LPASS_CORE_CC_DIG_PLL_OUT_ODD, +}; + +static const struct pll_vco lucid_vco[] = { + { 249600000, 2000000000, 0 }, +}; + +/* 614.4MHz configuration */ +static const struct alpha_pll_config lpass_core_cc_dig_pll_config = { + .l = 0x20, + .alpha = 0x0, + .config_ctl_val = 0x20485699, + .config_ctl_hi_val = 0x00002261, + .config_ctl_hi1_val = 0xB2923BBC, + .user_ctl_val = 0x00005100, + .user_ctl_hi_val = 0x00050805, + .user_ctl_hi1_val = 0x00000000, +}; + +static struct clk_alpha_pll lpass_core_cc_dig_pll = { + .offset = 0x1000, + .vco_table = lucid_vco, + .num_vco = ARRAY_SIZE(lucid_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID], + .clkr = { + .hw.init = &(struct clk_init_data){ + .name = "lpass_core_cc_dig_pll", + .parent_data = &(const struct clk_parent_data){ + .index = 0, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_lucid_ops, + }, + }, +}; + +static const struct clk_div_table post_div_table_lpass_core_cc_dig_pll_out_odd[] = { + { 0x5, 5 }, + { } +}; + +static struct clk_alpha_pll_postdiv lpass_core_cc_dig_pll_out_odd = { + .offset = 0x1000, + .post_div_shift = 12, + .post_div_table = post_div_table_lpass_core_cc_dig_pll_out_odd, + .num_post_div = ARRAY_SIZE(post_div_table_lpass_core_cc_dig_pll_out_odd), + .width = 4, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID], + .clkr.hw.init = &(struct clk_init_data){ + .name = "lpass_core_cc_dig_pll_out_odd", + .parent_hws = (const struct clk_hw*[]){ + &lpass_core_cc_dig_pll.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_alpha_pll_postdiv_lucid_ops, + }, +}; + +static struct clk_regmap_div lpass_core_cc_dig_pll_out_main_div_clk_src = { + .reg = 0x1054, + .shift = 0, + .width = 4, + .clkr.hw.init = &(struct clk_init_data) { + .name = "lpass_core_cc_dig_pll_out_main_div_clk_src", + .parent_hws = (const struct clk_hw*[]){ + &lpass_core_cc_dig_pll.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ro_ops, + }, +}; + + +static const struct parent_map lpass_core_cc_parent_map_0[] = { + { P_BI_TCXO, 0 }, + { P_LPASS_CORE_CC_DIG_PLL_OUT_ODD, 5 }, +}; + +static const struct clk_parent_data lpass_core_cc_parent_data_0[] = { + { .index = 0 }, + { .hw = &lpass_core_cc_dig_pll_out_odd.clkr.hw }, +}; + +static const struct parent_map lpass_core_cc_parent_map_2[] = { + { P_BI_TCXO, 0 }, + { P_LPASS_CORE_CC_DIG_PLL_OUT_MAIN, 1 }, + { P_LPASS_CORE_CC_DIG_PLL_OUT_MAIN_DIV_CLK_SRC, 2 }, +}; + +static const struct clk_parent_data lpass_core_cc_parent_data_ao_2[] = { + { .index = 1 }, + { .hw = &lpass_core_cc_dig_pll.clkr.hw }, + { .hw = &lpass_core_cc_dig_pll_out_main_div_clk_src.clkr.hw }, +}; + +static const struct freq_tbl ftbl_lpass_core_cc_core_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(51200000, P_LPASS_CORE_CC_DIG_PLL_OUT_MAIN_DIV_CLK_SRC, 6, 0, 0), + F(102400000, P_LPASS_CORE_CC_DIG_PLL_OUT_MAIN_DIV_CLK_SRC, 3, 0, 0), + F(204800000, P_LPASS_CORE_CC_DIG_PLL_OUT_MAIN, 3, 0, 0), + { } +}; + +static struct clk_rcg2 lpass_core_cc_core_clk_src = { + .cmd_rcgr = 0x1d000, + .mnd_width = 8, + .hid_width = 5, + .parent_map = lpass_core_cc_parent_map_2, + .freq_tbl = ftbl_lpass_core_cc_core_clk_src, + .clkr.hw.init = &(const struct clk_init_data){ + .name = "lpass_core_cc_core_clk_src", + .parent_data = lpass_core_cc_parent_data_ao_2, + .num_parents = ARRAY_SIZE(lpass_core_cc_parent_data_ao_2), + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_lpass_core_cc_ext_if0_clk_src[] = { + F(256000, P_LPASS_CORE_CC_DIG_PLL_OUT_ODD, 15, 1, 32), + F(512000, P_LPASS_CORE_CC_DIG_PLL_OUT_ODD, 15, 1, 16), + F(768000, P_LPASS_CORE_CC_DIG_PLL_OUT_ODD, 10, 1, 16), + F(1024000, P_LPASS_CORE_CC_DIG_PLL_OUT_ODD, 15, 1, 8), + F(1536000, P_LPASS_CORE_CC_DIG_PLL_OUT_ODD, 10, 1, 8), + F(2048000, P_LPASS_CORE_CC_DIG_PLL_OUT_ODD, 15, 1, 4), + F(3072000, P_LPASS_CORE_CC_DIG_PLL_OUT_ODD, 10, 1, 4), + F(4096000, P_LPASS_CORE_CC_DIG_PLL_OUT_ODD, 15, 1, 2), + F(6144000, P_LPASS_CORE_CC_DIG_PLL_OUT_ODD, 10, 1, 2), + F(8192000, P_LPASS_CORE_CC_DIG_PLL_OUT_ODD, 15, 0, 0), + F(9600000, P_BI_TCXO, 2, 0, 0), + F(12288000, P_LPASS_CORE_CC_DIG_PLL_OUT_ODD, 10, 0, 0), + F(19200000, P_BI_TCXO, 1, 0, 0), + F(24576000, P_LPASS_CORE_CC_DIG_PLL_OUT_ODD, 5, 0, 0), + { } +}; + +static struct clk_rcg2 lpass_core_cc_ext_if0_clk_src = { + .cmd_rcgr = 0x10000, + .mnd_width = 16, + .hid_width = 5, + .parent_map = lpass_core_cc_parent_map_0, + .freq_tbl = ftbl_lpass_core_cc_ext_if0_clk_src, + .clkr.hw.init = &(const struct clk_init_data){ + .name = "lpass_core_cc_ext_if0_clk_src", + .parent_data = lpass_core_cc_parent_data_0, + .num_parents = ARRAY_SIZE(lpass_core_cc_parent_data_0), + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 lpass_core_cc_ext_if1_clk_src = { + .cmd_rcgr = 0x11000, + .mnd_width = 16, + .hid_width = 5, + .parent_map = lpass_core_cc_parent_map_0, + .freq_tbl = ftbl_lpass_core_cc_ext_if0_clk_src, + .clkr.hw.init = &(const struct clk_init_data){ + .name = "lpass_core_cc_ext_if1_clk_src", + .parent_data = lpass_core_cc_parent_data_0, + .num_parents = ARRAY_SIZE(lpass_core_cc_parent_data_0), + .ops = &clk_rcg2_ops, + }, +}; + + +static struct clk_branch lpass_core_cc_core_clk = { + .halt_reg = 0x1f000, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x1f000, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x1f000, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data){ + .name = "lpass_core_cc_core_clk", + .parent_hws = (const struct clk_hw*[]){ + &lpass_core_cc_core_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_aon_ops, + }, + }, +}; + +static struct clk_branch lpass_core_cc_ext_if0_ibit_clk = { + .halt_reg = 0x10018, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x10018, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data){ + .name = "lpass_core_cc_ext_if0_ibit_clk", + .parent_hws = (const struct clk_hw*[]){ + &lpass_core_cc_ext_if0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch lpass_core_cc_ext_if1_ibit_clk = { + .halt_reg = 0x11018, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x11018, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data){ + .name = "lpass_core_cc_ext_if1_ibit_clk", + .parent_hws = (const struct clk_hw*[]){ + &lpass_core_cc_ext_if1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch lpass_core_cc_lpm_core_clk = { + .halt_reg = 0x1e000, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1e000, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data){ + .name = "lpass_core_cc_lpm_core_clk", + .parent_hws = (const struct clk_hw*[]){ + &lpass_core_cc_core_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch lpass_core_cc_lpm_mem0_core_clk = { + .halt_reg = 0x1e004, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1e004, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data){ + .name = "lpass_core_cc_lpm_mem0_core_clk", + .parent_hws = (const struct clk_hw*[]){ + &lpass_core_cc_core_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch lpass_core_cc_sysnoc_mport_core_clk = { + .halt_reg = 0x23000, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x23000, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x23000, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data){ + .name = "lpass_core_cc_sysnoc_mport_core_clk", + .parent_hws = (const struct clk_hw*[]){ + &lpass_core_cc_core_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct gdsc lpass_core_cc_lpass_core_hm_gdsc = { + .gdscr = 0x0, + .pd = { + .name = "lpass_core_cc_lpass_core_hm_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = RETAIN_FF_ENABLE, +}; + +static struct clk_regmap *lpass_core_cc_sc7280_clocks[] = { + [LPASS_CORE_CC_CORE_CLK] = &lpass_core_cc_core_clk.clkr, + [LPASS_CORE_CC_CORE_CLK_SRC] = &lpass_core_cc_core_clk_src.clkr, + [LPASS_CORE_CC_DIG_PLL] = &lpass_core_cc_dig_pll.clkr, + [LPASS_CORE_CC_DIG_PLL_OUT_MAIN_DIV_CLK_SRC] = + &lpass_core_cc_dig_pll_out_main_div_clk_src.clkr, + [LPASS_CORE_CC_DIG_PLL_OUT_ODD] = &lpass_core_cc_dig_pll_out_odd.clkr, + [LPASS_CORE_CC_EXT_IF0_CLK_SRC] = &lpass_core_cc_ext_if0_clk_src.clkr, + [LPASS_CORE_CC_EXT_IF0_IBIT_CLK] = &lpass_core_cc_ext_if0_ibit_clk.clkr, + [LPASS_CORE_CC_EXT_IF1_CLK_SRC] = &lpass_core_cc_ext_if1_clk_src.clkr, + [LPASS_CORE_CC_EXT_IF1_IBIT_CLK] = &lpass_core_cc_ext_if1_ibit_clk.clkr, + [LPASS_CORE_CC_LPM_CORE_CLK] = &lpass_core_cc_lpm_core_clk.clkr, + [LPASS_CORE_CC_LPM_MEM0_CORE_CLK] = &lpass_core_cc_lpm_mem0_core_clk.clkr, + [LPASS_CORE_CC_SYSNOC_MPORT_CORE_CLK] = &lpass_core_cc_sysnoc_mport_core_clk.clkr, +}; + +static struct regmap_config lpass_core_cc_sc7280_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .fast_io = true, +}; + +static const struct qcom_cc_desc lpass_core_cc_sc7280_desc = { + .config = &lpass_core_cc_sc7280_regmap_config, + .clks = lpass_core_cc_sc7280_clocks, + .num_clks = ARRAY_SIZE(lpass_core_cc_sc7280_clocks), +}; + +static const struct of_device_id lpass_core_cc_sc7280_match_table[] = { + { .compatible = "qcom,sc7280-lpasscorecc" }, + { } +}; +MODULE_DEVICE_TABLE(of, lpass_core_cc_sc7280_match_table); + +static struct gdsc *lpass_core_hm_sc7280_gdscs[] = { + [LPASS_CORE_CC_LPASS_CORE_HM_GDSC] = &lpass_core_cc_lpass_core_hm_gdsc, +}; + +static const struct qcom_cc_desc lpass_core_hm_sc7280_desc = { + .config = &lpass_core_cc_sc7280_regmap_config, + .gdscs = lpass_core_hm_sc7280_gdscs, + .num_gdscs = ARRAY_SIZE(lpass_core_hm_sc7280_gdscs), +}; + +static int lpass_core_cc_sc7280_probe(struct platform_device *pdev) +{ + const struct qcom_cc_desc *desc; + struct regmap *regmap; + + lpass_core_cc_sc7280_regmap_config.name = "lpass_core_cc"; + lpass_core_cc_sc7280_regmap_config.max_register = 0x4f004; + desc = &lpass_core_cc_sc7280_desc; + + regmap = qcom_cc_map(pdev, desc); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + clk_lucid_pll_configure(&lpass_core_cc_dig_pll, regmap, &lpass_core_cc_dig_pll_config); + + return qcom_cc_really_probe(pdev, &lpass_core_cc_sc7280_desc, regmap); +} + +static struct platform_driver lpass_core_cc_sc7280_driver = { + .probe = lpass_core_cc_sc7280_probe, + .driver = { + .name = "lpass_core_cc-sc7280", + .of_match_table = lpass_core_cc_sc7280_match_table, + }, +}; + +static int lpass_hm_core_probe(struct platform_device *pdev) +{ + const struct qcom_cc_desc *desc; + + lpass_core_cc_sc7280_regmap_config.name = "lpass_hm_core"; + lpass_core_cc_sc7280_regmap_config.max_register = 0x24; + desc = &lpass_core_hm_sc7280_desc; + + return qcom_cc_probe_by_index(pdev, 0, desc); +} + +static const struct of_device_id lpass_hm_sc7280_match_table[] = { + { .compatible = "qcom,sc7280-lpasshm" }, + { } +}; +MODULE_DEVICE_TABLE(of, lpass_hm_sc7280_match_table); + +static struct platform_driver lpass_hm_sc7280_driver = { + .probe = lpass_hm_core_probe, + .driver = { + .name = "lpass_hm-sc7280", + .of_match_table = lpass_hm_sc7280_match_table, + }, +}; + +static int __init lpass_core_cc_sc7280_init(void) +{ + int ret; + + ret = platform_driver_register(&lpass_hm_sc7280_driver); + if (ret) + return ret; + + return platform_driver_register(&lpass_core_cc_sc7280_driver); +} +subsys_initcall(lpass_core_cc_sc7280_init); + +static void __exit lpass_core_cc_sc7280_exit(void) +{ + platform_driver_unregister(&lpass_core_cc_sc7280_driver); + platform_driver_unregister(&lpass_hm_sc7280_driver); +} +module_exit(lpass_core_cc_sc7280_exit); + +MODULE_DESCRIPTION("QTI LPASS_CORE_CC SC7280 Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/clk/renesas/Kconfig b/drivers/clk/renesas/Kconfig index c281f3af57169afdbbc421c1e287e865ddf01530..cacaf9b87d264fc0f7a5e56583daf8616254c363 100644 --- a/drivers/clk/renesas/Kconfig +++ b/drivers/clk/renesas/Kconfig @@ -32,9 +32,12 @@ config CLK_RENESAS select CLK_R8A77995 if ARCH_R8A77995 select CLK_R8A779A0 if ARCH_R8A779A0 select CLK_R8A779F0 if ARCH_R8A779F0 + select CLK_R8A779G0 if ARCH_R8A779G0 select CLK_R9A06G032 if ARCH_R9A06G032 + select CLK_R9A07G043 if ARCH_R9A07G043 select CLK_R9A07G044 if ARCH_R9A07G044 select CLK_R9A07G054 if ARCH_R9A07G054 + select CLK_R9A09G011 if ARCH_R9A09G011 select CLK_SH73A0 if ARCH_SH73A0 if CLK_RENESAS @@ -157,9 +160,17 @@ config CLK_R8A779F0 bool "R-Car S4-8 clock support" if COMPILE_TEST select CLK_RCAR_GEN4_CPG +config CLK_R8A779G0 + bool "R-Car V4H clock support" if COMPILE_TEST + select CLK_RCAR_GEN4_CPG + config CLK_R9A06G032 bool "RZ/N1D clock support" if COMPILE_TEST +config CLK_R9A07G043 + bool "RZ/G2UL clock support" if COMPILE_TEST + select CLK_RZG2L + config CLK_R9A07G044 bool "RZ/G2L clock support" if COMPILE_TEST select CLK_RZG2L @@ -168,6 +179,10 @@ config CLK_R9A07G054 bool "RZ/V2L clock support" if COMPILE_TEST select CLK_RZG2L +config CLK_R9A09G011 + bool "RZ/V2M clock support" if COMPILE_TEST + select CLK_RZG2L + config CLK_SH73A0 bool "SH-Mobile AG5 clock support" if COMPILE_TEST select CLK_RENESAS_CPG_MSTP @@ -200,7 +215,7 @@ config CLK_RCAR_USB2_CLOCK_SEL This is a driver for R-Car USB2 clock selector config CLK_RZG2L - bool "Renesas RZ/{G2L,V2L} family clock support" if COMPILE_TEST + bool "Renesas RZ/{G2L,G2UL,V2L} family clock support" if COMPILE_TEST select RESET_CONTROLLER # Generic diff --git a/drivers/clk/renesas/Makefile b/drivers/clk/renesas/Makefile index d5e571699a30601c7576d60af5745178d684e60d..de907623fe3f8658a2daf078719628e6637d9d9e 100644 --- a/drivers/clk/renesas/Makefile +++ b/drivers/clk/renesas/Makefile @@ -29,9 +29,12 @@ obj-$(CONFIG_CLK_R8A77990) += r8a77990-cpg-mssr.o obj-$(CONFIG_CLK_R8A77995) += r8a77995-cpg-mssr.o obj-$(CONFIG_CLK_R8A779A0) += r8a779a0-cpg-mssr.o obj-$(CONFIG_CLK_R8A779F0) += r8a779f0-cpg-mssr.o +obj-$(CONFIG_CLK_R8A779G0) += r8a779g0-cpg-mssr.o obj-$(CONFIG_CLK_R9A06G032) += r9a06g032-clocks.o +obj-$(CONFIG_CLK_R9A07G043) += r9a07g043-cpg.o obj-$(CONFIG_CLK_R9A07G044) += r9a07g044-cpg.o obj-$(CONFIG_CLK_R9A07G054) += r9a07g044-cpg.o +obj-$(CONFIG_CLK_R9A09G011) += r9a09g011-cpg.o obj-$(CONFIG_CLK_SH73A0) += clk-sh73a0.o # Family diff --git a/drivers/clk/renesas/r8a774a1-cpg-mssr.c b/drivers/clk/renesas/r8a774a1-cpg-mssr.c index 95dd56b64d6409b5deac5232f68f93afdcbcc32e..ad03c09ebc1f97cefd6cb56adf6b3d2997bea921 100644 --- a/drivers/clk/renesas/r8a774a1-cpg-mssr.c +++ b/drivers/clk/renesas/r8a774a1-cpg-mssr.c @@ -68,12 +68,8 @@ static const struct cpg_core_clk r8a774a1_core_clks[] __initconst = { DEF_FIXED(".s2", CLK_S2, CLK_PLL1_DIV2, 4, 1), DEF_FIXED(".s3", CLK_S3, CLK_PLL1_DIV2, 6, 1), DEF_FIXED(".sdsrc", CLK_SDSRC, CLK_PLL1_DIV2, 2, 1), - DEF_BASE(".rpcsrc", CLK_RPCSRC, CLK_TYPE_GEN3_RPCSRC, CLK_PLL1), - DEF_BASE("rpc", R8A774A1_CLK_RPC, CLK_TYPE_GEN3_RPC, - CLK_RPCSRC), - DEF_BASE("rpcd2", R8A774A1_CLK_RPCD2, CLK_TYPE_GEN3_RPCD2, - R8A774A1_CLK_RPC), + DEF_BASE(".rpcsrc", CLK_RPCSRC, CLK_TYPE_GEN3_RPCSRC, CLK_PLL1), DEF_GEN3_OSC(".r", CLK_RINT, CLK_EXTAL, 32), @@ -109,6 +105,9 @@ static const struct cpg_core_clk r8a774a1_core_clks[] __initconst = { DEF_GEN3_SD("sd2", R8A774A1_CLK_SD2, R8A774A1_CLK_SD2H, 0x268), DEF_GEN3_SD("sd3", R8A774A1_CLK_SD3, R8A774A1_CLK_SD3H, 0x26c), + DEF_BASE("rpc", R8A774A1_CLK_RPC, CLK_TYPE_GEN3_RPC, CLK_RPCSRC), + DEF_BASE("rpcd2", R8A774A1_CLK_RPCD2, CLK_TYPE_GEN3_RPCD2, R8A774A1_CLK_RPC), + DEF_FIXED("cl", R8A774A1_CLK_CL, CLK_PLL1_DIV2, 48, 1), DEF_FIXED("cp", R8A774A1_CLK_CP, CLK_EXTAL, 2, 1), DEF_FIXED("cpex", R8A774A1_CLK_CPEX, CLK_EXTAL, 2, 1), diff --git a/drivers/clk/renesas/r8a774b1-cpg-mssr.c b/drivers/clk/renesas/r8a774b1-cpg-mssr.c index 56061b9b8437d24bc06e1b3679b5ff216c9c2096..ab087b02ef90e98be94f83b6e0b567c58edf8e9e 100644 --- a/drivers/clk/renesas/r8a774b1-cpg-mssr.c +++ b/drivers/clk/renesas/r8a774b1-cpg-mssr.c @@ -66,12 +66,8 @@ static const struct cpg_core_clk r8a774b1_core_clks[] __initconst = { DEF_FIXED(".s2", CLK_S2, CLK_PLL1_DIV2, 4, 1), DEF_FIXED(".s3", CLK_S3, CLK_PLL1_DIV2, 6, 1), DEF_FIXED(".sdsrc", CLK_SDSRC, CLK_PLL1_DIV2, 2, 1), - DEF_BASE(".rpcsrc", CLK_RPCSRC, CLK_TYPE_GEN3_RPCSRC, CLK_PLL1), - DEF_BASE("rpc", R8A774B1_CLK_RPC, CLK_TYPE_GEN3_RPC, - CLK_RPCSRC), - DEF_BASE("rpcd2", R8A774B1_CLK_RPCD2, CLK_TYPE_GEN3_RPCD2, - R8A774B1_CLK_RPC), + DEF_BASE(".rpcsrc", CLK_RPCSRC, CLK_TYPE_GEN3_RPCSRC, CLK_PLL1), DEF_GEN3_OSC(".r", CLK_RINT, CLK_EXTAL, 32), @@ -106,6 +102,9 @@ static const struct cpg_core_clk r8a774b1_core_clks[] __initconst = { DEF_GEN3_SD("sd2", R8A774B1_CLK_SD2, R8A774B1_CLK_SD2H, 0x268), DEF_GEN3_SD("sd3", R8A774B1_CLK_SD3, R8A774B1_CLK_SD3H, 0x26c), + DEF_BASE("rpc", R8A774B1_CLK_RPC, CLK_TYPE_GEN3_RPC, CLK_RPCSRC), + DEF_BASE("rpcd2", R8A774B1_CLK_RPCD2, CLK_TYPE_GEN3_RPCD2, R8A774B1_CLK_RPC), + DEF_FIXED("cl", R8A774B1_CLK_CL, CLK_PLL1_DIV2, 48, 1), DEF_FIXED("cp", R8A774B1_CLK_CP, CLK_EXTAL, 2, 1), DEF_FIXED("cpex", R8A774B1_CLK_CPEX, CLK_EXTAL, 2, 1), diff --git a/drivers/clk/renesas/r8a774c0-cpg-mssr.c b/drivers/clk/renesas/r8a774c0-cpg-mssr.c index b5eb5dc45d62eb517626e3976ed1fd3d350831c5..c9c8fde0f0a6c1224924c35cb7abc1ef62bf3b4a 100644 --- a/drivers/clk/renesas/r8a774c0-cpg-mssr.c +++ b/drivers/clk/renesas/r8a774c0-cpg-mssr.c @@ -77,11 +77,6 @@ static const struct cpg_core_clk r8a774c0_core_clks[] __initconst = { DEF_FIXED_RPCSRC_E3(".rpcsrc", CLK_RPCSRC, CLK_PLL0, CLK_PLL1), - DEF_BASE("rpc", R8A774C0_CLK_RPC, CLK_TYPE_GEN3_RPC, - CLK_RPCSRC), - DEF_BASE("rpcd2", R8A774C0_CLK_RPCD2, CLK_TYPE_GEN3_RPCD2, - R8A774C0_CLK_RPC), - DEF_DIV6_RO(".r", CLK_RINT, CLK_EXTAL, CPG_RCKCR, 32), DEF_RATE(".oco", CLK_OCO, 8 * 1000 * 1000), @@ -108,6 +103,9 @@ static const struct cpg_core_clk r8a774c0_core_clks[] __initconst = { DEF_FIXED("s3d2", R8A774C0_CLK_S3D2, CLK_S3, 2, 1), DEF_FIXED("s3d4", R8A774C0_CLK_S3D4, CLK_S3, 4, 1), + DEF_BASE("rpc", R8A774C0_CLK_RPC, CLK_TYPE_GEN3_RPC, CLK_RPCSRC), + DEF_BASE("rpcd2", R8A774C0_CLK_RPCD2, CLK_TYPE_GEN3_RPCD2, R8A774C0_CLK_RPC), + DEF_GEN3_SDH("sd0h", R8A774C0_CLK_SD0H, CLK_SDSRC, 0x0074), DEF_GEN3_SDH("sd1h", R8A774C0_CLK_SD1H, CLK_SDSRC, 0x0078), DEF_GEN3_SDH("sd3h", R8A774C0_CLK_SD3H, CLK_SDSRC, 0x026c), diff --git a/drivers/clk/renesas/r8a774e1-cpg-mssr.c b/drivers/clk/renesas/r8a774e1-cpg-mssr.c index 2950f0db90aeb2852a78395684271617bbb40adb..a790061db877cc9b9e7c3dcda70cfa0216f03a32 100644 --- a/drivers/clk/renesas/r8a774e1-cpg-mssr.c +++ b/drivers/clk/renesas/r8a774e1-cpg-mssr.c @@ -68,12 +68,8 @@ static const struct cpg_core_clk r8a774e1_core_clks[] __initconst = { DEF_FIXED(".s2", CLK_S2, CLK_PLL1_DIV2, 4, 1), DEF_FIXED(".s3", CLK_S3, CLK_PLL1_DIV2, 6, 1), DEF_FIXED(".sdsrc", CLK_SDSRC, CLK_PLL1_DIV2, 2, 1), - DEF_BASE(".rpcsrc", CLK_RPCSRC, CLK_TYPE_GEN3_RPCSRC, CLK_PLL1), - DEF_BASE("rpc", R8A774E1_CLK_RPC, CLK_TYPE_GEN3_RPC, - CLK_RPCSRC), - DEF_BASE("rpcd2", R8A774E1_CLK_RPCD2, CLK_TYPE_GEN3_RPCD2, - R8A774E1_CLK_RPC), + DEF_BASE(".rpcsrc", CLK_RPCSRC, CLK_TYPE_GEN3_RPCSRC, CLK_PLL1), DEF_GEN3_OSC(".r", CLK_RINT, CLK_EXTAL, 32), @@ -109,6 +105,9 @@ static const struct cpg_core_clk r8a774e1_core_clks[] __initconst = { DEF_GEN3_SD("sd2", R8A774E1_CLK_SD2, R8A774E1_CLK_SD2H, 0x268), DEF_GEN3_SD("sd3", R8A774E1_CLK_SD3, R8A774E1_CLK_SD3H, 0x26c), + DEF_BASE("rpc", R8A774E1_CLK_RPC, CLK_TYPE_GEN3_RPC, CLK_RPCSRC), + DEF_BASE("rpcd2", R8A774E1_CLK_RPCD2, CLK_TYPE_GEN3_RPCD2, R8A774E1_CLK_RPC), + DEF_FIXED("cl", R8A774E1_CLK_CL, CLK_PLL1_DIV2, 48, 1), DEF_FIXED("cr", R8A774E1_CLK_CR, CLK_PLL1_DIV4, 2, 1), DEF_FIXED("cp", R8A774E1_CLK_CP, CLK_EXTAL, 2, 1), diff --git a/drivers/clk/renesas/r8a7795-cpg-mssr.c b/drivers/clk/renesas/r8a7795-cpg-mssr.c index 991a44315d715024fc86d9b5810853e1efc4ef39..301475c74f500181dbb90959f16ef8f72a54ebb6 100644 --- a/drivers/clk/renesas/r8a7795-cpg-mssr.c +++ b/drivers/clk/renesas/r8a7795-cpg-mssr.c @@ -71,12 +71,8 @@ static struct cpg_core_clk r8a7795_core_clks[] __initdata = { DEF_FIXED(".s2", CLK_S2, CLK_PLL1_DIV2, 4, 1), DEF_FIXED(".s3", CLK_S3, CLK_PLL1_DIV2, 6, 1), DEF_FIXED(".sdsrc", CLK_SDSRC, CLK_PLL1_DIV2, 2, 1), - DEF_BASE(".rpcsrc", CLK_RPCSRC, CLK_TYPE_GEN3_RPCSRC, CLK_PLL1), - DEF_BASE("rpc", R8A7795_CLK_RPC, CLK_TYPE_GEN3_RPC, - CLK_RPCSRC), - DEF_BASE("rpcd2", R8A7795_CLK_RPCD2, CLK_TYPE_GEN3_RPCD2, - R8A7795_CLK_RPC), + DEF_BASE(".rpcsrc", CLK_RPCSRC, CLK_TYPE_GEN3_RPCSRC, CLK_PLL1), DEF_GEN3_OSC(".r", CLK_RINT, CLK_EXTAL, 32), @@ -113,6 +109,9 @@ static struct cpg_core_clk r8a7795_core_clks[] __initdata = { DEF_GEN3_SD("sd2", R8A7795_CLK_SD2, R8A7795_CLK_SD2H, 0x268), DEF_GEN3_SD("sd3", R8A7795_CLK_SD3, R8A7795_CLK_SD3H, 0x26c), + DEF_BASE("rpc", R8A7795_CLK_RPC, CLK_TYPE_GEN3_RPC, CLK_RPCSRC), + DEF_BASE("rpcd2", R8A7795_CLK_RPCD2, CLK_TYPE_GEN3_RPCD2, R8A7795_CLK_RPC), + DEF_FIXED("cl", R8A7795_CLK_CL, CLK_PLL1_DIV2, 48, 1), DEF_FIXED("cr", R8A7795_CLK_CR, CLK_PLL1_DIV4, 2, 1), DEF_FIXED("cp", R8A7795_CLK_CP, CLK_EXTAL, 2, 1), diff --git a/drivers/clk/renesas/r8a7796-cpg-mssr.c b/drivers/clk/renesas/r8a7796-cpg-mssr.c index 7950313611efa526d632a56c9de53df316889332..c4969318508eb44df48054ac1ee8ed5d9893a61d 100644 --- a/drivers/clk/renesas/r8a7796-cpg-mssr.c +++ b/drivers/clk/renesas/r8a7796-cpg-mssr.c @@ -73,12 +73,8 @@ static const struct cpg_core_clk r8a7796_core_clks[] __initconst = { DEF_FIXED(".s2", CLK_S2, CLK_PLL1_DIV2, 4, 1), DEF_FIXED(".s3", CLK_S3, CLK_PLL1_DIV2, 6, 1), DEF_FIXED(".sdsrc", CLK_SDSRC, CLK_PLL1_DIV2, 2, 1), - DEF_BASE(".rpcsrc", CLK_RPCSRC, CLK_TYPE_GEN3_RPCSRC, CLK_PLL1), - DEF_BASE("rpc", R8A7796_CLK_RPC, CLK_TYPE_GEN3_RPC, - CLK_RPCSRC), - DEF_BASE("rpcd2", R8A7796_CLK_RPCD2, CLK_TYPE_GEN3_RPCD2, - R8A7796_CLK_RPC), + DEF_BASE(".rpcsrc", CLK_RPCSRC, CLK_TYPE_GEN3_RPCSRC, CLK_PLL1), DEF_GEN3_OSC(".r", CLK_RINT, CLK_EXTAL, 32), @@ -115,6 +111,9 @@ static const struct cpg_core_clk r8a7796_core_clks[] __initconst = { DEF_GEN3_SD("sd2", R8A7796_CLK_SD2, R8A7796_CLK_SD2H, 0x268), DEF_GEN3_SD("sd3", R8A7796_CLK_SD3, R8A7796_CLK_SD3H, 0x26c), + DEF_BASE("rpc", R8A7796_CLK_RPC, CLK_TYPE_GEN3_RPC, CLK_RPCSRC), + DEF_BASE("rpcd2", R8A7796_CLK_RPCD2, CLK_TYPE_GEN3_RPCD2, R8A7796_CLK_RPC), + DEF_FIXED("cl", R8A7796_CLK_CL, CLK_PLL1_DIV2, 48, 1), DEF_FIXED("cr", R8A7796_CLK_CR, CLK_PLL1_DIV4, 2, 1), DEF_FIXED("cp", R8A7796_CLK_CP, CLK_EXTAL, 2, 1), diff --git a/drivers/clk/renesas/r8a77965-cpg-mssr.c b/drivers/clk/renesas/r8a77965-cpg-mssr.c index d687c29efa3cec9b0741b196400dfa6a361c33aa..78f6e530848ecc6e83fb0627076a06bc3944dd82 100644 --- a/drivers/clk/renesas/r8a77965-cpg-mssr.c +++ b/drivers/clk/renesas/r8a77965-cpg-mssr.c @@ -69,12 +69,8 @@ static const struct cpg_core_clk r8a77965_core_clks[] __initconst = { DEF_FIXED(".s2", CLK_S2, CLK_PLL1_DIV2, 4, 1), DEF_FIXED(".s3", CLK_S3, CLK_PLL1_DIV2, 6, 1), DEF_FIXED(".sdsrc", CLK_SDSRC, CLK_PLL1_DIV2, 2, 1), - DEF_BASE(".rpcsrc", CLK_RPCSRC, CLK_TYPE_GEN3_RPCSRC, CLK_PLL1), - DEF_BASE("rpc", R8A77965_CLK_RPC, CLK_TYPE_GEN3_RPC, - CLK_RPCSRC), - DEF_BASE("rpcd2", R8A77965_CLK_RPCD2, CLK_TYPE_GEN3_RPCD2, - R8A77965_CLK_RPC), + DEF_BASE(".rpcsrc", CLK_RPCSRC, CLK_TYPE_GEN3_RPCSRC, CLK_PLL1), DEF_GEN3_OSC(".r", CLK_RINT, CLK_EXTAL, 32), @@ -110,6 +106,9 @@ static const struct cpg_core_clk r8a77965_core_clks[] __initconst = { DEF_GEN3_SD("sd2", R8A77965_CLK_SD2, R8A77965_CLK_SD2H, 0x268), DEF_GEN3_SD("sd3", R8A77965_CLK_SD3, R8A77965_CLK_SD3H, 0x26c), + DEF_BASE("rpc", R8A77965_CLK_RPC, CLK_TYPE_GEN3_RPC, CLK_RPCSRC), + DEF_BASE("rpcd2", R8A77965_CLK_RPCD2, CLK_TYPE_GEN3_RPCD2, R8A77965_CLK_RPC), + DEF_FIXED("cl", R8A77965_CLK_CL, CLK_PLL1_DIV2, 48, 1), DEF_FIXED("cr", R8A77965_CLK_CR, CLK_PLL1_DIV4, 2, 1), DEF_FIXED("cp", R8A77965_CLK_CP, CLK_EXTAL, 2, 1), diff --git a/drivers/clk/renesas/r8a77980-cpg-mssr.c b/drivers/clk/renesas/r8a77980-cpg-mssr.c index f3cd64de4dc6e0a8b7a235c5a434a58c3d7ca8e3..06f925aff407b1c1ac7ae1c4f62d55159f4edd83 100644 --- a/drivers/clk/renesas/r8a77980-cpg-mssr.c +++ b/drivers/clk/renesas/r8a77980-cpg-mssr.c @@ -66,13 +66,10 @@ static const struct cpg_core_clk r8a77980_core_clks[] __initconst = { DEF_FIXED(".s2", CLK_S2, CLK_PLL1_DIV2, 4, 1), DEF_FIXED(".s3", CLK_S3, CLK_PLL1_DIV2, 6, 1), DEF_FIXED(".sdsrc", CLK_SDSRC, CLK_PLL1_DIV2, 2, 1), + DEF_BASE(".rpcsrc", CLK_RPCSRC, CLK_TYPE_GEN3_RPCSRC, CLK_PLL1), - DEF_RATE(".oco", CLK_OCO, 32768), - DEF_BASE("rpc", R8A77980_CLK_RPC, CLK_TYPE_GEN3_RPC, - CLK_RPCSRC), - DEF_BASE("rpcd2", R8A77980_CLK_RPCD2, CLK_TYPE_GEN3_RPCD2, - R8A77980_CLK_RPC), + DEF_RATE(".oco", CLK_OCO, 32768), /* Core Clock Outputs */ DEF_FIXED("ztr", R8A77980_CLK_ZTR, CLK_PLL1_DIV2, 6, 1), @@ -99,6 +96,9 @@ static const struct cpg_core_clk r8a77980_core_clks[] __initconst = { DEF_GEN3_SDH("sd0h", R8A77980_CLK_SD0H, CLK_SDSRC, 0x0074), DEF_GEN3_SD("sd0", R8A77980_CLK_SD0, R8A77980_CLK_SD0H, 0x0074), + DEF_BASE("rpc", R8A77980_CLK_RPC, CLK_TYPE_GEN3_RPC, CLK_RPCSRC), + DEF_BASE("rpcd2", R8A77980_CLK_RPCD2, CLK_TYPE_GEN3_RPCD2, R8A77980_CLK_RPC), + DEF_FIXED("cl", R8A77980_CLK_CL, CLK_PLL1_DIV2, 48, 1), DEF_FIXED("cp", R8A77980_CLK_CP, CLK_EXTAL, 2, 1), DEF_FIXED("cpex", R8A77980_CLK_CPEX, CLK_EXTAL, 2, 1), diff --git a/drivers/clk/renesas/r8a77990-cpg-mssr.c b/drivers/clk/renesas/r8a77990-cpg-mssr.c index d34d97baab35f3be58d44a7342ed20bad7207bd9..b666d099365ef01d4116e69d0461eeac99bf6f2d 100644 --- a/drivers/clk/renesas/r8a77990-cpg-mssr.c +++ b/drivers/clk/renesas/r8a77990-cpg-mssr.c @@ -44,6 +44,7 @@ enum clk_ids { CLK_S2, CLK_S3, CLK_SDSRC, + CLK_RPCSRC, CLK_RINT, CLK_OCO, @@ -74,6 +75,8 @@ static const struct cpg_core_clk r8a77990_core_clks[] __initconst = { DEF_FIXED(".s3", CLK_S3, CLK_PLL1, 6, 1), DEF_FIXED(".sdsrc", CLK_SDSRC, CLK_PLL1, 2, 1), + DEF_FIXED_RPCSRC_E3(".rpcsrc", CLK_RPCSRC, CLK_PLL0, CLK_PLL1), + DEF_DIV6_RO(".r", CLK_RINT, CLK_EXTAL, CPG_RCKCR, 32), DEF_RATE(".oco", CLK_OCO, 8 * 1000 * 1000), @@ -107,6 +110,9 @@ static const struct cpg_core_clk r8a77990_core_clks[] __initconst = { DEF_GEN3_SD("sd1", R8A77990_CLK_SD1, R8A77990_CLK_SD1H, 0x0078), DEF_GEN3_SD("sd3", R8A77990_CLK_SD3, R8A77990_CLK_SD3H, 0x026c), + DEF_BASE("rpc", R8A77990_CLK_RPC, CLK_TYPE_GEN3_RPC, CLK_RPCSRC), + DEF_BASE("rpcd2", R8A77990_CLK_RPCD2, CLK_TYPE_GEN3_RPCD2, R8A77990_CLK_RPC), + DEF_FIXED("cl", R8A77990_CLK_CL, CLK_PLL1, 48, 1), DEF_FIXED("cr", R8A77990_CLK_CR, CLK_PLL1D2, 2, 1), DEF_FIXED("cp", R8A77990_CLK_CP, CLK_EXTAL, 2, 1), @@ -215,6 +221,7 @@ static const struct mssr_mod_clk r8a77990_mod_clks[] __initconst = { DEF_MOD("can-fd", 914, R8A77990_CLK_S3D2), DEF_MOD("can-if1", 915, R8A77990_CLK_S3D4), DEF_MOD("can-if0", 916, R8A77990_CLK_S3D4), + DEF_MOD("rpc-if", 917, R8A77990_CLK_RPCD2), DEF_MOD("i2c6", 918, R8A77990_CLK_S3D2), DEF_MOD("i2c5", 919, R8A77990_CLK_S3D2), DEF_MOD("i2c-dvfs", 926, R8A77990_CLK_CP), diff --git a/drivers/clk/renesas/r8a77995-cpg-mssr.c b/drivers/clk/renesas/r8a77995-cpg-mssr.c index 525eef197fd9a9ab2c0118cab2f6357b15fa4b88..24ba9093a72f7341ab79c27182732cbf60ad1f9c 100644 --- a/drivers/clk/renesas/r8a77995-cpg-mssr.c +++ b/drivers/clk/renesas/r8a77995-cpg-mssr.c @@ -42,6 +42,7 @@ enum clk_ids { CLK_S2, CLK_S3, CLK_SDSRC, + CLK_RPCSRC, CLK_RINT, CLK_OCO, @@ -70,6 +71,8 @@ static const struct cpg_core_clk r8a77995_core_clks[] __initconst = { DEF_FIXED(".s3", CLK_S3, CLK_PLL1, 6, 1), DEF_FIXED(".sdsrc", CLK_SDSRC, CLK_PLL1, 2, 1), + DEF_FIXED_RPCSRC_D3(".rpcsrc", CLK_RPCSRC, CLK_PLL0, CLK_PLL1), + DEF_DIV6_RO(".r", CLK_RINT, CLK_EXTAL, CPG_RCKCR, 32), DEF_RATE(".oco", CLK_OCO, 8 * 1000 * 1000), @@ -103,8 +106,11 @@ static const struct cpg_core_clk r8a77995_core_clks[] __initconst = { DEF_GEN3_PE("s3d2c", R8A77995_CLK_S3D2C, CLK_S3, 2, CLK_PE, 2), DEF_GEN3_PE("s3d4c", R8A77995_CLK_S3D4C, CLK_S3, 4, CLK_PE, 4), - DEF_GEN3_SDH("sd0h", R8A77995_CLK_SD0H, CLK_SDSRC, 0x268), - DEF_GEN3_SD("sd0", R8A77995_CLK_SD0, R8A77995_CLK_SD0H, 0x268), + DEF_GEN3_SDH("sd0h", R8A77995_CLK_SD0H, CLK_SDSRC, 0x268), + DEF_GEN3_SD("sd0", R8A77995_CLK_SD0, R8A77995_CLK_SD0H, 0x268), + + DEF_BASE("rpc", R8A77995_CLK_RPC, CLK_TYPE_GEN3_RPC, CLK_RPCSRC), + DEF_BASE("rpcd2", R8A77995_CLK_RPCD2, CLK_TYPE_GEN3_RPCD2, R8A77995_CLK_RPC), DEF_DIV6P1("canfd", R8A77995_CLK_CANFD, CLK_PLL0D3, 0x244), DEF_DIV6P1("mso", R8A77995_CLK_MSO, CLK_PLL1D2, 0x014), @@ -174,6 +180,7 @@ static const struct mssr_mod_clk r8a77995_mod_clks[] __initconst = { DEF_MOD("can-fd", 914, R8A77995_CLK_S3D2), DEF_MOD("can-if1", 915, R8A77995_CLK_S3D4), DEF_MOD("can-if0", 916, R8A77995_CLK_S3D4), + DEF_MOD("rpc-if", 917, R8A77995_CLK_RPCD2), DEF_MOD("i2c3", 928, R8A77995_CLK_S3D2), DEF_MOD("i2c2", 929, R8A77995_CLK_S3D2), DEF_MOD("i2c1", 930, R8A77995_CLK_S3D2), diff --git a/drivers/clk/renesas/r8a779a0-cpg-mssr.c b/drivers/clk/renesas/r8a779a0-cpg-mssr.c index fadd8a1718c66cbf4361301b17818ff7419fa88f..d74d46833012ffcff91dc50141d66f21de9ddc85 100644 --- a/drivers/clk/renesas/r8a779a0-cpg-mssr.c +++ b/drivers/clk/renesas/r8a779a0-cpg-mssr.c @@ -85,11 +85,10 @@ static const struct cpg_core_clk r8a779a0_core_clks[] __initconst = { DEF_FIXED(".s1", CLK_S1, CLK_PLL1_DIV2, 2, 1), DEF_FIXED(".s3", CLK_S3, CLK_PLL1_DIV2, 4, 1), DEF_FIXED(".sdsrc", CLK_SDSRC, CLK_PLL5_DIV4, 1, 1), + DEF_RATE(".oco", CLK_OCO, 32768), - DEF_BASE(".rpcsrc", CLK_RPCSRC, CLK_TYPE_GEN4_RPCSRC, CLK_PLL5), - DEF_BASE("rpc", R8A779A0_CLK_RPC, CLK_TYPE_GEN4_RPC, CLK_RPCSRC), - DEF_BASE("rpcd2", R8A779A0_CLK_RPCD2, CLK_TYPE_GEN4_RPCD2, - R8A779A0_CLK_RPC), + + DEF_BASE(".rpcsrc", CLK_RPCSRC, CLK_TYPE_GEN4_RPCSRC, CLK_PLL5), /* Core Clock Outputs */ DEF_GEN4_Z("z0", R8A779A0_CLK_Z0, CLK_TYPE_GEN4_Z, CLK_PLL20, 2, 0), @@ -120,6 +119,10 @@ static const struct cpg_core_clk r8a779a0_core_clks[] __initconst = { DEF_GEN4_SDH("sdh0", R8A779A0_CLK_SD0H, CLK_SDSRC, 0x870), DEF_GEN4_SD("sd0", R8A779A0_CLK_SD0, R8A779A0_CLK_SD0H, 0x870), + DEF_BASE("rpc", R8A779A0_CLK_RPC, CLK_TYPE_GEN4_RPC, CLK_RPCSRC), + DEF_BASE("rpcd2", R8A779A0_CLK_RPCD2, CLK_TYPE_GEN4_RPCD2, + R8A779A0_CLK_RPC), + DEF_DIV6P1("mso", R8A779A0_CLK_MSO, CLK_PLL5_DIV4, 0x87c), DEF_DIV6P1("canfd", R8A779A0_CLK_CANFD, CLK_PLL5_DIV4, 0x878), DEF_DIV6P1("csi0", R8A779A0_CLK_CSI0, CLK_PLL5_DIV4, 0x880), @@ -241,7 +244,7 @@ static const unsigned int r8a779a0_crit_mod_clks[] __initconst = { /* * MD EXTAL PLL1 PLL20 PLL30 PLL4 PLL5 OSC * 14 13 (MHz) 21 31 - * -------------------------------------------------------- + * ---------------------------------------------------------------- * 0 0 16.66 x 1 x128 x216 x128 x144 x192 /16 * 0 1 20 x 1 x106 x180 x106 x120 x160 /19 * 1 0 Prohibited setting @@ -250,11 +253,11 @@ static const unsigned int r8a779a0_crit_mod_clks[] __initconst = { #define CPG_PLL_CONFIG_INDEX(md) ((((md) & BIT(14)) >> 13) | \ (((md) & BIT(13)) >> 13)) static const struct rcar_gen4_cpg_pll_config cpg_pll_configs[4] = { - /* EXTAL div PLL1 mult/div PLL2 mult/div PLL3 mult/div PLL5 mult/div PLL6 mult/div OSC prediv */ - { 1, 128, 1, 0, 0, 0, 0, 192, 1, 0, 0, 16, }, - { 1, 106, 1, 0, 0, 0, 0, 160, 1, 0, 0, 19, }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, - { 2, 128, 1, 0, 0, 0, 0, 192, 1, 0, 0, 32, }, + /* EXTAL div PLL1 mult/div PLL2 mult/div PLL3 mult/div PLL4 mult/div PLL5 mult/div PLL6 mult/div OSC prediv */ + { 1, 128, 1, 0, 0, 0, 0, 144, 1, 192, 1, 0, 0, 16, }, + { 1, 106, 1, 0, 0, 0, 0, 120, 1, 160, 1, 0, 0, 19, }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, + { 2, 128, 1, 0, 0, 0, 0, 144, 1, 192, 1, 0, 0, 32, }, }; diff --git a/drivers/clk/renesas/r8a779f0-cpg-mssr.c b/drivers/clk/renesas/r8a779f0-cpg-mssr.c index 76b441965037798d713eeea3c9fe4b11ee9a7ff4..c17ebe6b59921104ef1a5d2bc1d315c98d3fa51a 100644 --- a/drivers/clk/renesas/r8a779f0-cpg-mssr.c +++ b/drivers/clk/renesas/r8a779f0-cpg-mssr.c @@ -70,12 +70,11 @@ static const struct cpg_core_clk r8a779f0_core_clks[] __initconst = { DEF_FIXED(".pll5_div4", CLK_PLL5_DIV4, CLK_PLL5_DIV2, 2, 1), DEF_FIXED(".pll6_div2", CLK_PLL6_DIV2, CLK_PLL6, 2, 1), DEF_FIXED(".s0", CLK_S0, CLK_PLL1_DIV2, 2, 1), + DEF_BASE(".sdsrc", CLK_SDSRC, CLK_TYPE_GEN4_SDSRC, CLK_PLL5), DEF_RATE(".oco", CLK_OCO, 32768), - DEF_BASE(".rpcsrc", CLK_RPCSRC, CLK_TYPE_GEN4_RPCSRC, CLK_PLL5), - DEF_BASE(".rpc", R8A779F0_CLK_RPC, CLK_TYPE_GEN4_RPC, CLK_RPCSRC), - DEF_BASE("rpcd2", R8A779F0_CLK_RPCD2, CLK_TYPE_GEN4_RPCD2, R8A779F0_CLK_RPC), + DEF_BASE(".rpcsrc", CLK_RPCSRC, CLK_TYPE_GEN4_RPCSRC, CLK_PLL5), /* Core Clock Outputs */ DEF_FIXED("s0d2", R8A779F0_CLK_S0D2, CLK_S0, 2, 1), @@ -108,6 +107,10 @@ static const struct cpg_core_clk r8a779f0_core_clks[] __initconst = { DEF_FIXED("cpex", R8A779F0_CLK_CPEX, CLK_EXTAL, 2, 1), DEF_GEN4_SD("sd0", R8A779F0_CLK_SD0, CLK_SDSRC, 0x870), + + DEF_BASE("rpc", R8A779F0_CLK_RPC, CLK_TYPE_GEN4_RPC, CLK_RPCSRC), + DEF_BASE("rpcd2", R8A779F0_CLK_RPCD2, CLK_TYPE_GEN4_RPCD2, R8A779F0_CLK_RPC), + DEF_DIV6P1("mso", R8A779F0_CLK_MSO, CLK_PLL5_DIV4, 0x87c), DEF_GEN4_OSC("osc", R8A779F0_CLK_OSC, CLK_EXTAL, 8), @@ -129,6 +132,7 @@ static const struct mssr_mod_clk r8a779f0_mod_clks[] __initconst = { DEF_MOD("sys-dmac1", 710, R8A779F0_CLK_S0D3_PER), DEF_MOD("wdt", 907, R8A779F0_CLK_R), DEF_MOD("pfc0", 915, R8A779F0_CLK_CL16M), + DEF_MOD("ufs", 1514, R8A779F0_CLK_S0D4_HSC), }; static const unsigned int r8a779f0_crit_mod_clks[] __initconst = { @@ -139,23 +143,23 @@ static const unsigned int r8a779f0_crit_mod_clks[] __initconst = { * CPG Clock Data */ /* - * MD EXTAL PLL1 PLL2 PLL3 PLL5 PLL6 OSC + * MD EXTAL PLL1 PLL2 PLL3 PLL4 PLL5 PLL6 OSC * 14 13 (MHz) - * ---------------------------------------------------------------- - * 0 0 16 / 1 x200 x150 x200 x200 x134 /15 - * 0 1 20 / 1 x160 x120 x160 x160 x106 /19 + * ------------------------------------------------------------------------ + * 0 0 16 / 1 x200 x150 x200 n/a x200 x134 /15 + * 0 1 20 / 1 x160 x120 x160 n/a x160 x106 /19 * 1 0 Prohibited setting - * 1 1 40 / 2 x160 x120 x160 x160 x106 /38 + * 1 1 40 / 2 x160 x120 x160 n/a x160 x106 /38 */ #define CPG_PLL_CONFIG_INDEX(md) ((((md) & BIT(14)) >> 13) | \ (((md) & BIT(13)) >> 13)) static const struct rcar_gen4_cpg_pll_config cpg_pll_configs[4] = { - /* EXTAL div PLL1 mult/div PLL2 mult/div PLL3 mult/div PLL5 mult/div PLL6 mult/div OSC prediv */ - { 1, 200, 1, 150, 1, 200, 1, 200, 1, 134, 1, 15, }, - { 1, 160, 1, 120, 1, 160, 1, 160, 1, 106, 1, 19, }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, - { 2, 160, 1, 120, 1, 160, 1, 160, 1, 106, 1, 38, }, + /* EXTAL div PLL1 mult/div PLL2 mult/div PLL3 mult/div PLL4 mult/div PLL5 mult/div PLL6 mult/div OSC prediv */ + { 1, 200, 1, 150, 1, 200, 1, 0, 0, 200, 1, 134, 1, 15, }, + { 1, 160, 1, 120, 1, 160, 1, 0, 0, 160, 1, 106, 1, 19, }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, + { 2, 160, 1, 120, 1, 160, 1, 0, 0, 160, 1, 106, 1, 38, }, }; static int __init r8a779f0_cpg_mssr_init(struct device *dev) diff --git a/drivers/clk/renesas/r8a779g0-cpg-mssr.c b/drivers/clk/renesas/r8a779g0-cpg-mssr.c new file mode 100644 index 0000000000000000000000000000000000000000..3fc4233b1ead87c5c15244184ff797f6f3e8b1c5 --- /dev/null +++ b/drivers/clk/renesas/r8a779g0-cpg-mssr.c @@ -0,0 +1,218 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * r8a779g0 Clock Pulse Generator / Module Standby and Software Reset + * + * Copyright (C) 2022 Renesas Electronics Corp. + * + * Based on r8a779f0-cpg-mssr.c + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "renesas-cpg-mssr.h" +#include "rcar-gen4-cpg.h" + +enum clk_ids { + /* Core Clock Outputs exported to DT */ + LAST_DT_CORE_CLK = R8A779G0_CLK_R, + + /* External Input Clocks */ + CLK_EXTAL, + CLK_EXTALR, + + /* Internal Core Clocks */ + CLK_MAIN, + CLK_PLL1, + CLK_PLL2, + CLK_PLL3, + CLK_PLL4, + CLK_PLL5, + CLK_PLL6, + CLK_PLL1_DIV2, + CLK_PLL2_DIV2, + CLK_PLL3_DIV2, + CLK_PLL4_DIV2, + CLK_PLL5_DIV2, + CLK_PLL5_DIV4, + CLK_PLL6_DIV2, + CLK_S0, + CLK_S0_VIO, + CLK_S0_VC, + CLK_S0_HSC, + CLK_SV_VIP, + CLK_SV_IR, + CLK_SDSRC, + CLK_RPCSRC, + CLK_VIO, + CLK_VC, + CLK_OCO, + + /* Module Clocks */ + MOD_CLK_BASE +}; + +static const struct cpg_core_clk r8a779g0_core_clks[] __initconst = { + /* External Clock Inputs */ + DEF_INPUT("extal", CLK_EXTAL), + DEF_INPUT("extalr", CLK_EXTALR), + + /* Internal Core Clocks */ + DEF_BASE(".main", CLK_MAIN, CLK_TYPE_GEN4_MAIN, CLK_EXTAL), + DEF_BASE(".pll1", CLK_PLL1, CLK_TYPE_GEN4_PLL1, CLK_MAIN), + DEF_BASE(".pll2", CLK_PLL2, CLK_TYPE_GEN4_PLL2, CLK_MAIN), + DEF_BASE(".pll3", CLK_PLL3, CLK_TYPE_GEN4_PLL3, CLK_MAIN), + DEF_BASE(".pll4", CLK_PLL4, CLK_TYPE_GEN4_PLL4, CLK_MAIN), + DEF_BASE(".pll5", CLK_PLL5, CLK_TYPE_GEN4_PLL5, CLK_MAIN), + DEF_BASE(".pll6", CLK_PLL6, CLK_TYPE_GEN4_PLL6, CLK_MAIN), + + DEF_FIXED(".pll1_div2", CLK_PLL1_DIV2, CLK_PLL1, 2, 1), + DEF_FIXED(".pll2_div2", CLK_PLL2_DIV2, CLK_PLL2, 2, 1), + DEF_FIXED(".pll3_div2", CLK_PLL3_DIV2, CLK_PLL3, 2, 1), + DEF_FIXED(".pll4_div2", CLK_PLL4_DIV2, CLK_PLL4, 2, 1), + DEF_FIXED(".pll5_div2", CLK_PLL5_DIV2, CLK_PLL5, 2, 1), + DEF_FIXED(".pll5_div4", CLK_PLL5_DIV4, CLK_PLL5_DIV2, 2, 1), + DEF_FIXED(".pll6_div2", CLK_PLL6_DIV2, CLK_PLL6, 2, 1), + DEF_FIXED(".s0", CLK_S0, CLK_PLL1_DIV2, 2, 1), + DEF_FIXED(".s0_vio", CLK_S0_VIO, CLK_PLL1_DIV2, 2, 1), + DEF_FIXED(".s0_vc", CLK_S0_VC, CLK_PLL1_DIV2, 2, 1), + DEF_FIXED(".s0_hsc", CLK_S0_HSC, CLK_PLL1_DIV2, 2, 1), + DEF_FIXED(".sv_vip", CLK_SV_VIP, CLK_PLL1, 5, 1), + DEF_FIXED(".sv_ir", CLK_SV_IR, CLK_PLL1, 5, 1), + DEF_BASE(".sdsrc", CLK_SDSRC, CLK_TYPE_GEN4_SDSRC, CLK_PLL5), + DEF_RATE(".oco", CLK_OCO, 32768), + + DEF_BASE(".rpcsrc", CLK_RPCSRC, CLK_TYPE_GEN4_RPCSRC, CLK_PLL5), + DEF_FIXED(".vio", CLK_VIO, CLK_PLL5_DIV2, 3, 1), + DEF_FIXED(".vc", CLK_VC, CLK_PLL5_DIV2, 3, 1), + + /* Core Clock Outputs */ + DEF_FIXED("s0d2", R8A779G0_CLK_S0D2, CLK_S0, 2, 1), + DEF_FIXED("s0d3", R8A779G0_CLK_S0D3, CLK_S0, 3, 1), + DEF_FIXED("s0d4", R8A779G0_CLK_S0D4, CLK_S0, 4, 1), + DEF_FIXED("cl16m", R8A779G0_CLK_CL16M, CLK_S0, 48, 1), + DEF_FIXED("s0d1_vio", R8A779G0_CLK_S0D1_VIO, CLK_S0_VIO, 1, 1), + DEF_FIXED("s0d2_vio", R8A779G0_CLK_S0D2_VIO, CLK_S0_VIO, 2, 1), + DEF_FIXED("s0d4_vio", R8A779G0_CLK_S0D4_VIO, CLK_S0_VIO, 4, 1), + DEF_FIXED("s0d8_vio", R8A779G0_CLK_S0D8_VIO, CLK_S0_VIO, 8, 1), + DEF_FIXED("s0d1_vc", R8A779G0_CLK_S0D1_VC, CLK_S0_VC, 1, 1), + DEF_FIXED("s0d2_vc", R8A779G0_CLK_S0D2_VC, CLK_S0_VC, 2, 1), + DEF_FIXED("s0d4_vc", R8A779G0_CLK_S0D4_VC, CLK_S0_VC, 4, 1), + DEF_FIXED("s0d2_mm", R8A779G0_CLK_S0D2_MM, CLK_S0, 2, 1), + DEF_FIXED("s0d4_mm", R8A779G0_CLK_S0D4_MM, CLK_S0, 4, 1), + DEF_FIXED("cl16m_mm", R8A779G0_CLK_CL16M_MM, CLK_S0, 48, 1), + DEF_FIXED("s0d2_u3dg", R8A779G0_CLK_S0D2_U3DG, CLK_S0, 2, 1), + DEF_FIXED("s0d4_u3dg", R8A779G0_CLK_S0D4_U3DG, CLK_S0, 4, 1), + DEF_FIXED("s0d2_rt", R8A779G0_CLK_S0D2_RT, CLK_S0, 2, 1), + DEF_FIXED("s0d3_rt", R8A779G0_CLK_S0D3_RT, CLK_S0, 3, 1), + DEF_FIXED("s0d4_rt", R8A779G0_CLK_S0D4_RT, CLK_S0, 4, 1), + DEF_FIXED("s0d6_rt", R8A779G0_CLK_S0D6_RT, CLK_S0, 6, 1), + DEF_FIXED("s0d24_rt", R8A779G0_CLK_S0D24_RT, CLK_S0, 24, 1), + DEF_FIXED("cl16m_rt", R8A779G0_CLK_CL16M_RT, CLK_S0, 48, 1), + DEF_FIXED("s0d2_per", R8A779G0_CLK_S0D2_PER, CLK_S0, 2, 1), + DEF_FIXED("s0d3_per", R8A779G0_CLK_S0D3_PER, CLK_S0, 3, 1), + DEF_FIXED("s0d4_per", R8A779G0_CLK_S0D4_PER, CLK_S0, 4, 1), + DEF_FIXED("s0d6_per", R8A779G0_CLK_S0D6_PER, CLK_S0, 6, 1), + DEF_FIXED("s0d12_per", R8A779G0_CLK_S0D12_PER, CLK_S0, 12, 1), + DEF_FIXED("s0d24_per", R8A779G0_CLK_S0D24_PER, CLK_S0, 24, 1), + DEF_FIXED("cl16m_per", R8A779G0_CLK_CL16M_PER, CLK_S0, 48, 1), + DEF_FIXED("s0d1_hsc", R8A779G0_CLK_S0D1_HSC, CLK_S0_HSC, 1, 1), + DEF_FIXED("s0d2_hsc", R8A779G0_CLK_S0D2_HSC, CLK_S0_HSC, 2, 1), + DEF_FIXED("s0d4_hsc", R8A779G0_CLK_S0D4_HSC, CLK_S0_HSC, 4, 1), + DEF_FIXED("cl16m_hsc", R8A779G0_CLK_CL16M_HSC, CLK_S0_HSC, 48, 1), + DEF_FIXED("s0d2_cc", R8A779G0_CLK_S0D2_CC, CLK_S0, 2, 1), + DEF_FIXED("svd1_ir", R8A779G0_CLK_SVD1_IR, CLK_SV_IR, 1, 1), + DEF_FIXED("svd2_ir", R8A779G0_CLK_SVD2_IR, CLK_SV_IR, 2, 1), + DEF_FIXED("svd1_vip", R8A779G0_CLK_SVD1_VIP, CLK_SV_VIP, 1, 1), + DEF_FIXED("svd2_vip", R8A779G0_CLK_SVD2_VIP, CLK_SV_VIP, 2, 1), + DEF_FIXED("cbfusa", R8A779G0_CLK_CBFUSA, CLK_EXTAL, 2, 1), + DEF_FIXED("cpex", R8A779G0_CLK_CPEX, CLK_EXTAL, 2, 1), + DEF_FIXED("viobus", R8A779G0_CLK_VIOBUS, CLK_VIO, 1, 1), + DEF_FIXED("viobusd2", R8A779G0_CLK_VIOBUSD2, CLK_VIO, 2, 1), + DEF_FIXED("vcbus", R8A779G0_CLK_VCBUS, CLK_VC, 1, 1), + DEF_FIXED("vcbusd2", R8A779G0_CLK_VCBUSD2, CLK_VC, 2, 1), + + DEF_GEN4_SD("sd0", R8A779G0_CLK_SD0, CLK_SDSRC, 0x870), + DEF_DIV6P1("mso", R8A779G0_CLK_MSO, CLK_PLL5_DIV4, 0x87c), + + DEF_BASE("rpc", R8A779G0_CLK_RPC, CLK_TYPE_GEN4_RPC, CLK_RPCSRC), + DEF_BASE("rpcd2", R8A779G0_CLK_RPCD2, CLK_TYPE_GEN4_RPCD2, R8A779G0_CLK_RPC), + + DEF_GEN4_OSC("osc", R8A779G0_CLK_OSC, CLK_EXTAL, 8), + DEF_GEN4_MDSEL("r", R8A779G0_CLK_R, 29, CLK_EXTALR, 1, CLK_OCO, 1), +}; + +static const struct mssr_mod_clk r8a779g0_mod_clks[] __initconst = { + DEF_MOD("hscif0", 514, R8A779G0_CLK_S0D3_PER), + DEF_MOD("hscif1", 515, R8A779G0_CLK_S0D3_PER), + DEF_MOD("hscif2", 516, R8A779G0_CLK_S0D3_PER), + DEF_MOD("hscif3", 517, R8A779G0_CLK_S0D3_PER), +}; + +/* + * CPG Clock Data + */ +/* + * MD EXTAL PLL1 PLL2 PLL3 PLL4 PLL5 PLL6 OSC + * 14 13 (MHz) + * ------------------------------------------------------------------------ + * 0 0 16.66 / 1 x192 x204 x192 x144 x192 x168 /15 + * 0 1 20 / 1 x160 x170 x160 x120 x160 x140 /19 + * 1 0 Prohibited setting + * 1 1 33.33 / 2 x192 x204 x192 x144 x192 x168 /38 + */ +#define CPG_PLL_CONFIG_INDEX(md) ((((md) & BIT(14)) >> 13) | \ + (((md) & BIT(13)) >> 13)) + +static const struct rcar_gen4_cpg_pll_config cpg_pll_configs[4] = { + /* EXTAL div PLL1 mult/div PLL2 mult/div PLL3 mult/div PLL4 mult/div PLL5 mult/div PLL6 mult/div OSC prediv */ + { 1, 192, 1, 204, 1, 192, 1, 144, 1, 192, 1, 168, 1, 15, }, + { 1, 160, 1, 170, 1, 160, 1, 120, 1, 160, 1, 140, 1, 19, }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, + { 2, 192, 1, 204, 1, 192, 1, 144, 1, 192, 1, 168, 1, 38, }, +}; + +static int __init r8a779g0_cpg_mssr_init(struct device *dev) +{ + const struct rcar_gen4_cpg_pll_config *cpg_pll_config; + u32 cpg_mode; + int error; + + error = rcar_rst_read_mode_pins(&cpg_mode); + if (error) + return error; + + cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)]; + if (!cpg_pll_config->extal_div) { + dev_err(dev, "Prohibited setting (cpg_mode=0x%x)\n", cpg_mode); + return -EINVAL; + } + + return rcar_gen4_cpg_init(cpg_pll_config, CLK_EXTALR, cpg_mode); +} + +const struct cpg_mssr_info r8a779g0_cpg_mssr_info __initconst = { + /* Core Clocks */ + .core_clks = r8a779g0_core_clks, + .num_core_clks = ARRAY_SIZE(r8a779g0_core_clks), + .last_dt_core_clk = LAST_DT_CORE_CLK, + .num_total_core_clks = MOD_CLK_BASE, + + /* Module Clocks */ + .mod_clks = r8a779g0_mod_clks, + .num_mod_clks = ARRAY_SIZE(r8a779g0_mod_clks), + .num_hw_mod_clks = 30 * 32, + + /* Callbacks */ + .init = r8a779g0_cpg_mssr_init, + .cpg_clk_register = rcar_gen4_cpg_clk_register, + + .reg_layout = CLK_REG_LAYOUT_RCAR_GEN4, +}; diff --git a/drivers/clk/renesas/r9a06g032-clocks.c b/drivers/clk/renesas/r9a06g032-clocks.c index c99942f0e4d4c75157739a6efb2fe32cd97482ed..35ffc462af1ae3aec2dd07a9f3ef4bafcad2763f 100644 --- a/drivers/clk/renesas/r9a06g032-clocks.c +++ b/drivers/clk/renesas/r9a06g032-clocks.c @@ -16,13 +16,17 @@ #include #include #include +#include #include #include #include #include +#include #include #include +#define R9A06G032_SYSCTRL_DMAMUX 0xA0 + struct r9a06g032_gate { u16 gate, reset, ready, midle, scon, mirack, mistat; @@ -256,7 +260,7 @@ static const struct r9a06g032_clkdesc r9a06g032_clocks[] = { D_MODULE(HCLK_QSPI0, "hclk_qspi0", CLK_REF_SYNC_D4, 0x2a0, 0x2a1, 0x2a2, 0x2a3, 0x300, 0x301, 0x302), D_MODULE(HCLK_QSPI1, "hclk_qspi1", CLK_REF_SYNC_D4, 0x480, 0x481, 0x482, 0x483, 0x4c0, 0x4c1, 0x4c2), D_MODULE(HCLK_ROM, "hclk_rom", CLK_REF_SYNC_D4, 0xaa0, 0xaa1, 0xaa2, 0, 0xb80, 0, 0), - D_MODULE(HCLK_RTC, "hclk_rtc", CLK_REF_SYNC_D8, 0xa00, 0, 0, 0, 0, 0, 0), + D_MODULE(HCLK_RTC, "hclk_rtc", CLK_REF_SYNC_D8, 0xa00, 0xa03, 0, 0xa02, 0, 0, 0), D_MODULE(HCLK_SDIO0, "hclk_sdio0", CLK_REF_SYNC_D4, 0x60, 0x61, 0x62, 0x63, 0x80, 0x81, 0x82), D_MODULE(HCLK_SDIO1, "hclk_sdio1", CLK_REF_SYNC_D4, 0x640, 0x641, 0x642, 0x643, 0x660, 0x661, 0x662), D_MODULE(HCLK_SEMAP, "hclk_semap", CLK_REF_SYNC_D4, 0x7a3, 0x7a4, 0x7a5, 0, 0xb21, 0, 0), @@ -315,6 +319,30 @@ struct r9a06g032_priv { void __iomem *reg; }; +static struct r9a06g032_priv *sysctrl_priv; + +/* Exported helper to access the DMAMUX register */ +int r9a06g032_sysctrl_set_dmamux(u32 mask, u32 val) +{ + unsigned long flags; + u32 dmamux; + + if (!sysctrl_priv) + return -EPROBE_DEFER; + + spin_lock_irqsave(&sysctrl_priv->lock, flags); + + dmamux = readl(sysctrl_priv->reg + R9A06G032_SYSCTRL_DMAMUX); + dmamux &= ~mask; + dmamux |= val & mask; + writel(dmamux, sysctrl_priv->reg + R9A06G032_SYSCTRL_DMAMUX); + + spin_unlock_irqrestore(&sysctrl_priv->lock, flags); + + return 0; +} +EXPORT_SYMBOL_GPL(r9a06g032_sysctrl_set_dmamux); + /* register/bit pairs are encoded as an uint16_t */ static void clk_rdesc_set(struct r9a06g032_priv *clocks, @@ -963,7 +991,17 @@ static int __init r9a06g032_clocks_probe(struct platform_device *pdev) if (error) return error; - return r9a06g032_add_clk_domain(dev); + error = r9a06g032_add_clk_domain(dev); + if (error) + return error; + + sysctrl_priv = clocks; + + error = of_platform_populate(np, NULL, NULL, dev); + if (error) + dev_err(dev, "Failed to populate children (%d)\n", error); + + return 0; } static const struct of_device_id r9a06g032_match[] = { diff --git a/drivers/clk/renesas/r9a07g043-cpg.c b/drivers/clk/renesas/r9a07g043-cpg.c new file mode 100644 index 0000000000000000000000000000000000000000..33c2bd8df2e52bf2e7c75b9656a8a3ea57d2acb5 --- /dev/null +++ b/drivers/clk/renesas/r9a07g043-cpg.c @@ -0,0 +1,320 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * RZ/G2UL CPG driver + * + * Copyright (C) 2022 Renesas Electronics Corp. + */ + +#include +#include +#include +#include + +#include + +#include "rzg2l-cpg.h" + +enum clk_ids { + /* Core Clock Outputs exported to DT */ + LAST_DT_CORE_CLK = R9A07G043_CLK_P0_DIV2, + + /* External Input Clocks */ + CLK_EXTAL, + + /* Internal Core Clocks */ + CLK_OSC_DIV1000, + CLK_PLL1, + CLK_PLL2, + CLK_PLL2_DIV2, + CLK_PLL2_DIV2_8, + CLK_PLL2_DIV2_10, + CLK_PLL3, + CLK_PLL3_400, + CLK_PLL3_533, + CLK_PLL3_DIV2, + CLK_PLL3_DIV2_4, + CLK_PLL3_DIV2_4_2, + CLK_SEL_PLL3_3, + CLK_DIV_PLL3_C, + CLK_PLL5, + CLK_PLL5_500, + CLK_PLL5_250, + CLK_PLL6, + CLK_PLL6_250, + CLK_P1_DIV2, + CLK_PLL2_800, + CLK_PLL2_SDHI_533, + CLK_PLL2_SDHI_400, + CLK_PLL2_SDHI_266, + CLK_SD0_DIV4, + CLK_SD1_DIV4, + + /* Module Clocks */ + MOD_CLK_BASE, +}; + +/* Divider tables */ +static const struct clk_div_table dtable_1_8[] = { + {0, 1}, + {1, 2}, + {2, 4}, + {3, 8}, + {0, 0}, +}; + +static const struct clk_div_table dtable_1_32[] = { + {0, 1}, + {1, 2}, + {2, 4}, + {3, 8}, + {4, 32}, + {0, 0}, +}; + +/* Mux clock tables */ +static const char * const sel_pll3_3[] = { ".pll3_533", ".pll3_400" }; +static const char * const sel_pll6_2[] = { ".pll6_250", ".pll5_250" }; +static const char * const sel_shdi[] = { ".clk_533", ".clk_400", ".clk_266" }; + +static const struct cpg_core_clk r9a07g043_core_clks[] __initconst = { + /* External Clock Inputs */ + DEF_INPUT("extal", CLK_EXTAL), + + /* Internal Core Clocks */ + DEF_FIXED(".osc", R9A07G043_OSCCLK, CLK_EXTAL, 1, 1), + DEF_FIXED(".osc_div1000", CLK_OSC_DIV1000, CLK_EXTAL, 1, 1000), + DEF_SAMPLL(".pll1", CLK_PLL1, CLK_EXTAL, PLL146_CONF(0)), + DEF_FIXED(".pll2", CLK_PLL2, CLK_EXTAL, 200, 3), + DEF_FIXED(".pll2_div2", CLK_PLL2_DIV2, CLK_PLL2, 1, 2), + DEF_FIXED(".clk_800", CLK_PLL2_800, CLK_PLL2, 1, 2), + DEF_FIXED(".clk_533", CLK_PLL2_SDHI_533, CLK_PLL2, 1, 3), + DEF_FIXED(".clk_400", CLK_PLL2_SDHI_400, CLK_PLL2_800, 1, 2), + DEF_FIXED(".clk_266", CLK_PLL2_SDHI_266, CLK_PLL2_SDHI_533, 1, 2), + DEF_FIXED(".pll2_div2_8", CLK_PLL2_DIV2_8, CLK_PLL2_DIV2, 1, 8), + DEF_FIXED(".pll2_div2_10", CLK_PLL2_DIV2_10, CLK_PLL2_DIV2, 1, 10), + DEF_FIXED(".pll3", CLK_PLL3, CLK_EXTAL, 200, 3), + DEF_FIXED(".pll3_div2", CLK_PLL3_DIV2, CLK_PLL3, 1, 2), + DEF_FIXED(".pll3_div2_4", CLK_PLL3_DIV2_4, CLK_PLL3_DIV2, 1, 4), + DEF_FIXED(".pll3_div2_4_2", CLK_PLL3_DIV2_4_2, CLK_PLL3_DIV2_4, 1, 2), + DEF_FIXED(".pll3_400", CLK_PLL3_400, CLK_PLL3, 1, 4), + DEF_FIXED(".pll3_533", CLK_PLL3_533, CLK_PLL3, 1, 3), + DEF_MUX_RO(".sel_pll3_3", CLK_SEL_PLL3_3, SEL_PLL3_3, sel_pll3_3), + DEF_DIV("divpl3c", CLK_DIV_PLL3_C, CLK_SEL_PLL3_3, DIVPL3C, dtable_1_32), + DEF_FIXED(".pll5", CLK_PLL5, CLK_EXTAL, 125, 1), + DEF_FIXED(".pll5_500", CLK_PLL5_500, CLK_PLL5, 1, 6), + DEF_FIXED(".pll5_250", CLK_PLL5_250, CLK_PLL5_500, 1, 2), + DEF_FIXED(".pll6", CLK_PLL6, CLK_EXTAL, 125, 6), + DEF_FIXED(".pll6_250", CLK_PLL6_250, CLK_PLL6, 1, 2), + + /* Core output clk */ + DEF_DIV("I", R9A07G043_CLK_I, CLK_PLL1, DIVPL1A, dtable_1_8), + DEF_DIV("P0", R9A07G043_CLK_P0, CLK_PLL2_DIV2_8, DIVPL2A, dtable_1_32), + DEF_FIXED("P0_DIV2", R9A07G043_CLK_P0_DIV2, R9A07G043_CLK_P0, 1, 2), + DEF_FIXED("TSU", R9A07G043_CLK_TSU, CLK_PLL2_DIV2_10, 1, 1), + DEF_DIV("P1", R9A07G043_CLK_P1, CLK_PLL3_DIV2_4, DIVPL3B, dtable_1_32), + DEF_FIXED("P1_DIV2", CLK_P1_DIV2, R9A07G043_CLK_P1, 1, 2), + DEF_DIV("P2", R9A07G043_CLK_P2, CLK_PLL3_DIV2_4_2, DIVPL3A, dtable_1_32), + DEF_FIXED("M0", R9A07G043_CLK_M0, CLK_PLL3_DIV2_4, 1, 1), + DEF_FIXED("ZT", R9A07G043_CLK_ZT, CLK_PLL3_DIV2_4_2, 1, 1), + DEF_MUX("HP", R9A07G043_CLK_HP, SEL_PLL6_2, sel_pll6_2), + DEF_FIXED("SPI0", R9A07G043_CLK_SPI0, CLK_DIV_PLL3_C, 1, 2), + DEF_FIXED("SPI1", R9A07G043_CLK_SPI1, CLK_DIV_PLL3_C, 1, 4), + DEF_SD_MUX("SD0", R9A07G043_CLK_SD0, SEL_SDHI0, sel_shdi), + DEF_SD_MUX("SD1", R9A07G043_CLK_SD1, SEL_SDHI1, sel_shdi), + DEF_FIXED("SD0_DIV4", CLK_SD0_DIV4, R9A07G043_CLK_SD0, 1, 4), + DEF_FIXED("SD1_DIV4", CLK_SD1_DIV4, R9A07G043_CLK_SD1, 1, 4), +}; + +static struct rzg2l_mod_clk r9a07g043_mod_clks[] = { + DEF_MOD("gic", R9A07G043_GIC600_GICCLK, R9A07G043_CLK_P1, + 0x514, 0), + DEF_MOD("ia55_pclk", R9A07G043_IA55_PCLK, R9A07G043_CLK_P2, + 0x518, 0), + DEF_MOD("ia55_clk", R9A07G043_IA55_CLK, R9A07G043_CLK_P1, + 0x518, 1), + DEF_MOD("dmac_aclk", R9A07G043_DMAC_ACLK, R9A07G043_CLK_P1, + 0x52c, 0), + DEF_MOD("dmac_pclk", R9A07G043_DMAC_PCLK, CLK_P1_DIV2, + 0x52c, 1), + DEF_MOD("ostm0_pclk", R9A07G043_OSTM0_PCLK, R9A07G043_CLK_P0, + 0x534, 0), + DEF_MOD("ostm1_pclk", R9A07G043_OSTM1_PCLK, R9A07G043_CLK_P0, + 0x534, 1), + DEF_MOD("ostm2_pclk", R9A07G043_OSTM2_PCLK, R9A07G043_CLK_P0, + 0x534, 2), + DEF_MOD("wdt0_pclk", R9A07G043_WDT0_PCLK, R9A07G043_CLK_P0, + 0x548, 0), + DEF_MOD("wdt0_clk", R9A07G043_WDT0_CLK, R9A07G043_OSCCLK, + 0x548, 1), + DEF_MOD("wdt2_pclk", R9A07G043_WDT2_PCLK, R9A07G043_CLK_P0, + 0x548, 4), + DEF_MOD("wdt2_clk", R9A07G043_WDT2_CLK, R9A07G043_OSCCLK, + 0x548, 5), + DEF_MOD("spi_clk2", R9A07G043_SPI_CLK2, R9A07G043_CLK_SPI1, + 0x550, 0), + DEF_MOD("spi_clk", R9A07G043_SPI_CLK, R9A07G043_CLK_SPI0, + 0x550, 1), + DEF_MOD("sdhi0_imclk", R9A07G043_SDHI0_IMCLK, CLK_SD0_DIV4, + 0x554, 0), + DEF_MOD("sdhi0_imclk2", R9A07G043_SDHI0_IMCLK2, CLK_SD0_DIV4, + 0x554, 1), + DEF_MOD("sdhi0_clk_hs", R9A07G043_SDHI0_CLK_HS, R9A07G043_CLK_SD0, + 0x554, 2), + DEF_MOD("sdhi0_aclk", R9A07G043_SDHI0_ACLK, R9A07G043_CLK_P1, + 0x554, 3), + DEF_MOD("sdhi1_imclk", R9A07G043_SDHI1_IMCLK, CLK_SD1_DIV4, + 0x554, 4), + DEF_MOD("sdhi1_imclk2", R9A07G043_SDHI1_IMCLK2, CLK_SD1_DIV4, + 0x554, 5), + DEF_MOD("sdhi1_clk_hs", R9A07G043_SDHI1_CLK_HS, R9A07G043_CLK_SD1, + 0x554, 6), + DEF_MOD("sdhi1_aclk", R9A07G043_SDHI1_ACLK, R9A07G043_CLK_P1, + 0x554, 7), + DEF_MOD("ssi0_pclk", R9A07G043_SSI0_PCLK2, R9A07G043_CLK_P0, + 0x570, 0), + DEF_MOD("ssi0_sfr", R9A07G043_SSI0_PCLK_SFR, R9A07G043_CLK_P0, + 0x570, 1), + DEF_MOD("ssi1_pclk", R9A07G043_SSI1_PCLK2, R9A07G043_CLK_P0, + 0x570, 2), + DEF_MOD("ssi1_sfr", R9A07G043_SSI1_PCLK_SFR, R9A07G043_CLK_P0, + 0x570, 3), + DEF_MOD("ssi2_pclk", R9A07G043_SSI2_PCLK2, R9A07G043_CLK_P0, + 0x570, 4), + DEF_MOD("ssi2_sfr", R9A07G043_SSI2_PCLK_SFR, R9A07G043_CLK_P0, + 0x570, 5), + DEF_MOD("ssi3_pclk", R9A07G043_SSI3_PCLK2, R9A07G043_CLK_P0, + 0x570, 6), + DEF_MOD("ssi3_sfr", R9A07G043_SSI3_PCLK_SFR, R9A07G043_CLK_P0, + 0x570, 7), + DEF_MOD("usb0_host", R9A07G043_USB_U2H0_HCLK, R9A07G043_CLK_P1, + 0x578, 0), + DEF_MOD("usb1_host", R9A07G043_USB_U2H1_HCLK, R9A07G043_CLK_P1, + 0x578, 1), + DEF_MOD("usb0_func", R9A07G043_USB_U2P_EXR_CPUCLK, R9A07G043_CLK_P1, + 0x578, 2), + DEF_MOD("usb_pclk", R9A07G043_USB_PCLK, R9A07G043_CLK_P1, + 0x578, 3), + DEF_COUPLED("eth0_axi", R9A07G043_ETH0_CLK_AXI, R9A07G043_CLK_M0, + 0x57c, 0), + DEF_COUPLED("eth0_chi", R9A07G043_ETH0_CLK_CHI, R9A07G043_CLK_ZT, + 0x57c, 0), + DEF_COUPLED("eth1_axi", R9A07G043_ETH1_CLK_AXI, R9A07G043_CLK_M0, + 0x57c, 1), + DEF_COUPLED("eth1_chi", R9A07G043_ETH1_CLK_CHI, R9A07G043_CLK_ZT, + 0x57c, 1), + DEF_MOD("i2c0", R9A07G043_I2C0_PCLK, R9A07G043_CLK_P0, + 0x580, 0), + DEF_MOD("i2c1", R9A07G043_I2C1_PCLK, R9A07G043_CLK_P0, + 0x580, 1), + DEF_MOD("i2c2", R9A07G043_I2C2_PCLK, R9A07G043_CLK_P0, + 0x580, 2), + DEF_MOD("i2c3", R9A07G043_I2C3_PCLK, R9A07G043_CLK_P0, + 0x580, 3), + DEF_MOD("scif0", R9A07G043_SCIF0_CLK_PCK, R9A07G043_CLK_P0, + 0x584, 0), + DEF_MOD("scif1", R9A07G043_SCIF1_CLK_PCK, R9A07G043_CLK_P0, + 0x584, 1), + DEF_MOD("scif2", R9A07G043_SCIF2_CLK_PCK, R9A07G043_CLK_P0, + 0x584, 2), + DEF_MOD("scif3", R9A07G043_SCIF3_CLK_PCK, R9A07G043_CLK_P0, + 0x584, 3), + DEF_MOD("scif4", R9A07G043_SCIF4_CLK_PCK, R9A07G043_CLK_P0, + 0x584, 4), + DEF_MOD("sci0", R9A07G043_SCI0_CLKP, R9A07G043_CLK_P0, + 0x588, 0), + DEF_MOD("sci1", R9A07G043_SCI1_CLKP, R9A07G043_CLK_P0, + 0x588, 1), + DEF_MOD("rspi0", R9A07G043_RSPI0_CLKB, R9A07G043_CLK_P0, + 0x590, 0), + DEF_MOD("rspi1", R9A07G043_RSPI1_CLKB, R9A07G043_CLK_P0, + 0x590, 1), + DEF_MOD("rspi2", R9A07G043_RSPI2_CLKB, R9A07G043_CLK_P0, + 0x590, 2), + DEF_MOD("canfd", R9A07G043_CANFD_PCLK, R9A07G043_CLK_P0, + 0x594, 0), + DEF_MOD("gpio", R9A07G043_GPIO_HCLK, R9A07G043_OSCCLK, + 0x598, 0), + DEF_MOD("adc_adclk", R9A07G043_ADC_ADCLK, R9A07G043_CLK_TSU, + 0x5a8, 0), + DEF_MOD("adc_pclk", R9A07G043_ADC_PCLK, R9A07G043_CLK_P0, + 0x5a8, 1), + DEF_MOD("tsu_pclk", R9A07G043_TSU_PCLK, R9A07G043_CLK_TSU, + 0x5ac, 0), +}; + +static struct rzg2l_reset r9a07g043_resets[] = { + DEF_RST(R9A07G043_GIC600_GICRESET_N, 0x814, 0), + DEF_RST(R9A07G043_GIC600_DBG_GICRESET_N, 0x814, 1), + DEF_RST(R9A07G043_IA55_RESETN, 0x818, 0), + DEF_RST(R9A07G043_DMAC_ARESETN, 0x82c, 0), + DEF_RST(R9A07G043_DMAC_RST_ASYNC, 0x82c, 1), + DEF_RST(R9A07G043_OSTM0_PRESETZ, 0x834, 0), + DEF_RST(R9A07G043_OSTM1_PRESETZ, 0x834, 1), + DEF_RST(R9A07G043_OSTM2_PRESETZ, 0x834, 2), + DEF_RST(R9A07G043_WDT0_PRESETN, 0x848, 0), + DEF_RST(R9A07G043_WDT2_PRESETN, 0x848, 2), + DEF_RST(R9A07G043_SPI_RST, 0x850, 0), + DEF_RST(R9A07G043_SDHI0_IXRST, 0x854, 0), + DEF_RST(R9A07G043_SDHI1_IXRST, 0x854, 1), + DEF_RST(R9A07G043_SSI0_RST_M2_REG, 0x870, 0), + DEF_RST(R9A07G043_SSI1_RST_M2_REG, 0x870, 1), + DEF_RST(R9A07G043_SSI2_RST_M2_REG, 0x870, 2), + DEF_RST(R9A07G043_SSI3_RST_M2_REG, 0x870, 3), + DEF_RST(R9A07G043_USB_U2H0_HRESETN, 0x878, 0), + DEF_RST(R9A07G043_USB_U2H1_HRESETN, 0x878, 1), + DEF_RST(R9A07G043_USB_U2P_EXL_SYSRST, 0x878, 2), + DEF_RST(R9A07G043_USB_PRESETN, 0x878, 3), + DEF_RST(R9A07G043_ETH0_RST_HW_N, 0x87c, 0), + DEF_RST(R9A07G043_ETH1_RST_HW_N, 0x87c, 1), + DEF_RST(R9A07G043_I2C0_MRST, 0x880, 0), + DEF_RST(R9A07G043_I2C1_MRST, 0x880, 1), + DEF_RST(R9A07G043_I2C2_MRST, 0x880, 2), + DEF_RST(R9A07G043_I2C3_MRST, 0x880, 3), + DEF_RST(R9A07G043_SCIF0_RST_SYSTEM_N, 0x884, 0), + DEF_RST(R9A07G043_SCIF1_RST_SYSTEM_N, 0x884, 1), + DEF_RST(R9A07G043_SCIF2_RST_SYSTEM_N, 0x884, 2), + DEF_RST(R9A07G043_SCIF3_RST_SYSTEM_N, 0x884, 3), + DEF_RST(R9A07G043_SCIF4_RST_SYSTEM_N, 0x884, 4), + DEF_RST(R9A07G043_SCI0_RST, 0x888, 0), + DEF_RST(R9A07G043_SCI1_RST, 0x888, 1), + DEF_RST(R9A07G043_RSPI0_RST, 0x890, 0), + DEF_RST(R9A07G043_RSPI1_RST, 0x890, 1), + DEF_RST(R9A07G043_RSPI2_RST, 0x890, 2), + DEF_RST(R9A07G043_CANFD_RSTP_N, 0x894, 0), + DEF_RST(R9A07G043_CANFD_RSTC_N, 0x894, 1), + DEF_RST(R9A07G043_GPIO_RSTN, 0x898, 0), + DEF_RST(R9A07G043_GPIO_PORT_RESETN, 0x898, 1), + DEF_RST(R9A07G043_GPIO_SPARE_RESETN, 0x898, 2), + DEF_RST(R9A07G043_ADC_PRESETN, 0x8a8, 0), + DEF_RST(R9A07G043_ADC_ADRST_N, 0x8a8, 1), + DEF_RST(R9A07G043_TSU_PRESETN, 0x8ac, 0), +}; + +static const unsigned int r9a07g043_crit_mod_clks[] __initconst = { + MOD_CLK_BASE + R9A07G043_GIC600_GICCLK, + MOD_CLK_BASE + R9A07G043_IA55_CLK, + MOD_CLK_BASE + R9A07G043_DMAC_ACLK, +}; + +const struct rzg2l_cpg_info r9a07g043_cpg_info = { + /* Core Clocks */ + .core_clks = r9a07g043_core_clks, + .num_core_clks = ARRAY_SIZE(r9a07g043_core_clks), + .last_dt_core_clk = LAST_DT_CORE_CLK, + .num_total_core_clks = MOD_CLK_BASE, + + /* Critical Module Clocks */ + .crit_mod_clks = r9a07g043_crit_mod_clks, + .num_crit_mod_clks = ARRAY_SIZE(r9a07g043_crit_mod_clks), + + /* Module Clocks */ + .mod_clks = r9a07g043_mod_clks, + .num_mod_clks = ARRAY_SIZE(r9a07g043_mod_clks), + .num_hw_mod_clks = R9A07G043_TSU_PCLK + 1, + + /* Resets */ + .resets = r9a07g043_resets, + .num_resets = R9A07G043_TSU_PRESETN + 1, /* Last reset ID + 1 */ + + .has_clk_mon_regs = true, +}; diff --git a/drivers/clk/renesas/r9a07g044-cpg.c b/drivers/clk/renesas/r9a07g044-cpg.c index bdfabb992a20782dfe058ab9e0f3166e57a2579e..b288897852c744a59c552c014af754238ae8a4b7 100644 --- a/drivers/clk/renesas/r9a07g044-cpg.c +++ b/drivers/clk/renesas/r9a07g044-cpg.c @@ -32,6 +32,7 @@ enum clk_ids { CLK_PLL3, CLK_PLL3_400, CLK_PLL3_533, + CLK_M2_DIV2, CLK_PLL3_DIV2, CLK_PLL3_DIV2_2, CLK_PLL3_DIV2_4, @@ -40,6 +41,8 @@ enum clk_ids { CLK_DIV_PLL3_C, CLK_PLL4, CLK_PLL5, + CLK_PLL5_FOUTPOSTDIV, + CLK_PLL5_FOUT1PH0, CLK_PLL5_FOUT3, CLK_PLL5_250, CLK_PLL6, @@ -52,6 +55,11 @@ enum clk_ids { CLK_SD0_DIV4, CLK_SD1_DIV4, CLK_SEL_GPU2, + CLK_SEL_PLL5_4, + CLK_DSI_DIV, + CLK_PLL2_533, + CLK_PLL2_533_DIV2, + CLK_DIV_DSI_LPCLK, /* Module Clocks */ MOD_CLK_BASE, @@ -75,14 +83,23 @@ static const struct clk_div_table dtable_1_32[] = { {0, 0}, }; +static const struct clk_div_table dtable_16_128[] = { + {0, 16}, + {1, 32}, + {2, 64}, + {3, 128}, + {0, 0}, +}; + /* Mux clock tables */ static const char * const sel_pll3_3[] = { ".pll3_533", ".pll3_400" }; +static const char * const sel_pll5_4[] = { ".pll5_foutpostdiv", ".pll5_fout1ph0" }; static const char * const sel_pll6_2[] = { ".pll6_250", ".pll5_250" }; static const char * const sel_shdi[] = { ".clk_533", ".clk_400", ".clk_266" }; static const char * const sel_gpu2[] = { ".pll6", ".pll3_div2_2" }; static const struct { - struct cpg_core_clk common[44]; + struct cpg_core_clk common[56]; #ifdef CONFIG_CLK_R9A07G054 struct cpg_core_clk drp[0]; #endif @@ -96,6 +113,7 @@ static const struct { DEF_FIXED(".osc_div1000", CLK_OSC_DIV1000, CLK_EXTAL, 1, 1000), DEF_SAMPLL(".pll1", CLK_PLL1, CLK_EXTAL, PLL146_CONF(0)), DEF_FIXED(".pll2", CLK_PLL2, CLK_EXTAL, 200, 3), + DEF_FIXED(".pll2_533", CLK_PLL2_533, CLK_PLL2, 1, 3), DEF_FIXED(".pll3", CLK_PLL3, CLK_EXTAL, 200, 3), DEF_FIXED(".pll3_400", CLK_PLL3_400, CLK_PLL3, 1, 4), DEF_FIXED(".pll3_533", CLK_PLL3_533, CLK_PLL3, 1, 3), @@ -114,46 +132,48 @@ static const struct { DEF_FIXED(".pll2_div2_8", CLK_PLL2_DIV2_8, CLK_PLL2_DIV2, 1, 8), DEF_FIXED(".pll2_div2_10", CLK_PLL2_DIV2_10, CLK_PLL2_DIV2, 1, 10), + DEF_FIXED(".pll2_533_div2", CLK_PLL2_533_DIV2, CLK_PLL2_533, 1, 2), + DEF_FIXED(".pll3_div2", CLK_PLL3_DIV2, CLK_PLL3, 1, 2), DEF_FIXED(".pll3_div2_2", CLK_PLL3_DIV2_2, CLK_PLL3_DIV2, 1, 2), DEF_FIXED(".pll3_div2_4", CLK_PLL3_DIV2_4, CLK_PLL3_DIV2, 1, 4), DEF_FIXED(".pll3_div2_4_2", CLK_PLL3_DIV2_4_2, CLK_PLL3_DIV2_4, 1, 2), - DEF_MUX(".sel_pll3_3", CLK_SEL_PLL3_3, SEL_PLL3_3, - sel_pll3_3, ARRAY_SIZE(sel_pll3_3), 0, CLK_MUX_READ_ONLY), - DEF_DIV("divpl3c", CLK_DIV_PLL3_C, CLK_SEL_PLL3_3, - DIVPL3C, dtable_1_32, CLK_DIVIDER_HIWORD_MASK), + DEF_MUX_RO(".sel_pll3_3", CLK_SEL_PLL3_3, SEL_PLL3_3, sel_pll3_3), + DEF_DIV("divpl3c", CLK_DIV_PLL3_C, CLK_SEL_PLL3_3, DIVPL3C, dtable_1_32), DEF_FIXED(".pll5_250", CLK_PLL5_250, CLK_PLL5_FOUT3, 1, 2), DEF_FIXED(".pll6_250", CLK_PLL6_250, CLK_PLL6, 1, 2), - DEF_MUX(".sel_gpu2", CLK_SEL_GPU2, SEL_GPU2, - sel_gpu2, ARRAY_SIZE(sel_gpu2), 0, CLK_MUX_READ_ONLY), + DEF_MUX_RO(".sel_gpu2", CLK_SEL_GPU2, SEL_GPU2, sel_gpu2), + DEF_PLL5_FOUTPOSTDIV(".pll5_foutpostdiv", CLK_PLL5_FOUTPOSTDIV, CLK_EXTAL), + DEF_FIXED(".pll5_fout1ph0", CLK_PLL5_FOUT1PH0, CLK_PLL5_FOUTPOSTDIV, 1, 2), + DEF_PLL5_4_MUX(".sel_pll5_4", CLK_SEL_PLL5_4, SEL_PLL5_4, sel_pll5_4), + DEF_DIV(".div_dsi_lpclk", CLK_DIV_DSI_LPCLK, CLK_PLL2_533_DIV2, + DIVDSILPCLK, dtable_16_128), /* Core output clk */ - DEF_DIV("I", R9A07G044_CLK_I, CLK_PLL1, DIVPL1A, dtable_1_8, - CLK_DIVIDER_HIWORD_MASK), - DEF_DIV("P0", R9A07G044_CLK_P0, CLK_PLL2_DIV2_8, DIVPL2A, - dtable_1_32, CLK_DIVIDER_HIWORD_MASK), + DEF_DIV("I", R9A07G044_CLK_I, CLK_PLL1, DIVPL1A, dtable_1_8), + DEF_DIV("P0", R9A07G044_CLK_P0, CLK_PLL2_DIV2_8, DIVPL2A, dtable_1_32), DEF_FIXED("P0_DIV2", R9A07G044_CLK_P0_DIV2, R9A07G044_CLK_P0, 1, 2), DEF_FIXED("TSU", R9A07G044_CLK_TSU, CLK_PLL2_DIV2_10, 1, 1), - DEF_DIV("P1", R9A07G044_CLK_P1, CLK_PLL3_DIV2_4, - DIVPL3B, dtable_1_32, CLK_DIVIDER_HIWORD_MASK), + DEF_DIV("P1", R9A07G044_CLK_P1, CLK_PLL3_DIV2_4, DIVPL3B, dtable_1_32), DEF_FIXED("P1_DIV2", CLK_P1_DIV2, R9A07G044_CLK_P1, 1, 2), - DEF_DIV("P2", R9A07G044_CLK_P2, CLK_PLL3_DIV2_4_2, - DIVPL3A, dtable_1_32, CLK_DIVIDER_HIWORD_MASK), + DEF_DIV("P2", R9A07G044_CLK_P2, CLK_PLL3_DIV2_4_2, DIVPL3A, dtable_1_32), DEF_FIXED("M0", R9A07G044_CLK_M0, CLK_PLL3_DIV2_4, 1, 1), DEF_FIXED("ZT", R9A07G044_CLK_ZT, CLK_PLL3_DIV2_4_2, 1, 1), - DEF_MUX("HP", R9A07G044_CLK_HP, SEL_PLL6_2, - sel_pll6_2, ARRAY_SIZE(sel_pll6_2), 0, CLK_MUX_HIWORD_MASK), + DEF_MUX("HP", R9A07G044_CLK_HP, SEL_PLL6_2, sel_pll6_2), DEF_FIXED("SPI0", R9A07G044_CLK_SPI0, CLK_DIV_PLL3_C, 1, 2), DEF_FIXED("SPI1", R9A07G044_CLK_SPI1, CLK_DIV_PLL3_C, 1, 4), - DEF_SD_MUX("SD0", R9A07G044_CLK_SD0, SEL_SDHI0, - sel_shdi, ARRAY_SIZE(sel_shdi)), - DEF_SD_MUX("SD1", R9A07G044_CLK_SD1, SEL_SDHI1, - sel_shdi, ARRAY_SIZE(sel_shdi)), + DEF_SD_MUX("SD0", R9A07G044_CLK_SD0, SEL_SDHI0, sel_shdi), + DEF_SD_MUX("SD1", R9A07G044_CLK_SD1, SEL_SDHI1, sel_shdi), DEF_FIXED("SD0_DIV4", CLK_SD0_DIV4, R9A07G044_CLK_SD0, 1, 4), DEF_FIXED("SD1_DIV4", CLK_SD1_DIV4, R9A07G044_CLK_SD1, 1, 4), - DEF_DIV("G", R9A07G044_CLK_G, CLK_SEL_GPU2, DIVGPU, dtable_1_8, - CLK_DIVIDER_HIWORD_MASK), + DEF_DIV("G", R9A07G044_CLK_G, CLK_SEL_GPU2, DIVGPU, dtable_1_8), + DEF_FIXED("M1", R9A07G044_CLK_M1, CLK_PLL5_FOUTPOSTDIV, 1, 1), + DEF_FIXED("M2", R9A07G044_CLK_M2, CLK_PLL3_533, 1, 2), + DEF_FIXED("M2_DIV2", CLK_M2_DIV2, R9A07G044_CLK_M2, 1, 2), + DEF_DSI_DIV("DSI_DIV", CLK_DSI_DIV, CLK_SEL_PLL5_4, CLK_SET_RATE_PARENT), + DEF_FIXED("M3", R9A07G044_CLK_M3, CLK_DSI_DIV, 1, 1), + DEF_FIXED("M4", R9A07G044_CLK_M4, CLK_DIV_DSI_LPCLK, 1, 1), }, #ifdef CONFIG_CLK_R9A07G054 .drp = { @@ -162,7 +182,7 @@ static const struct { }; static const struct { - struct rzg2l_mod_clk common[62]; + struct rzg2l_mod_clk common[71]; #ifdef CONFIG_CLK_R9A07G054 struct rzg2l_mod_clk drp[0]; #endif @@ -180,7 +200,7 @@ static const struct { 0x52c, 1), DEF_MOD("ostm0_pclk", R9A07G044_OSTM0_PCLK, R9A07G044_CLK_P0, 0x534, 0), - DEF_MOD("ostm1_clk", R9A07G044_OSTM1_PCLK, R9A07G044_CLK_P0, + DEF_MOD("ostm1_pclk", R9A07G044_OSTM1_PCLK, R9A07G044_CLK_P0, 0x534, 1), DEF_MOD("ostm2_pclk", R9A07G044_OSTM2_PCLK, R9A07G044_CLK_P0, 0x534, 2), @@ -222,6 +242,24 @@ static const struct { 0x558, 1), DEF_MOD("gpu_ace_clk", R9A07G044_GPU_ACE_CLK, R9A07G044_CLK_P1, 0x558, 2), + DEF_MOD("dsi_pll_clk", R9A07G044_MIPI_DSI_PLLCLK, R9A07G044_CLK_M1, + 0x568, 0), + DEF_MOD("dsi_sys_clk", R9A07G044_MIPI_DSI_SYSCLK, CLK_M2_DIV2, + 0x568, 1), + DEF_MOD("dsi_aclk", R9A07G044_MIPI_DSI_ACLK, R9A07G044_CLK_P1, + 0x568, 2), + DEF_MOD("dsi_pclk", R9A07G044_MIPI_DSI_PCLK, R9A07G044_CLK_P2, + 0x568, 3), + DEF_MOD("dsi_vclk", R9A07G044_MIPI_DSI_VCLK, R9A07G044_CLK_M3, + 0x568, 4), + DEF_MOD("dsi_lpclk", R9A07G044_MIPI_DSI_LPCLK, R9A07G044_CLK_M4, + 0x568, 5), + DEF_COUPLED("lcdc_a", R9A07G044_LCDC_CLK_A, R9A07G044_CLK_M0, + 0x56c, 0), + DEF_COUPLED("lcdc_p", R9A07G044_LCDC_CLK_P, R9A07G044_CLK_ZT, + 0x56c, 0), + DEF_MOD("lcdc_clk_d", R9A07G044_LCDC_CLK_D, R9A07G044_CLK_M3, + 0x56c, 1), DEF_MOD("ssi0_pclk", R9A07G044_SSI0_PCLK2, R9A07G044_CLK_P0, 0x570, 0), DEF_MOD("ssi0_sfr", R9A07G044_SSI0_PCLK_SFR, R9A07G044_CLK_P0, @@ -317,6 +355,10 @@ static struct rzg2l_reset r9a07g044_resets[] = { DEF_RST(R9A07G044_GPU_RESETN, 0x858, 0), DEF_RST(R9A07G044_GPU_AXI_RESETN, 0x858, 1), DEF_RST(R9A07G044_GPU_ACE_RESETN, 0x858, 2), + DEF_RST(R9A07G044_MIPI_DSI_CMN_RSTB, 0x868, 0), + DEF_RST(R9A07G044_MIPI_DSI_ARESET_N, 0x868, 1), + DEF_RST(R9A07G044_MIPI_DSI_PRESET_N, 0x868, 2), + DEF_RST(R9A07G044_LCDC_RESET_N, 0x86c, 0), DEF_RST(R9A07G044_SSI0_RST_M2_REG, 0x870, 0), DEF_RST(R9A07G044_SSI1_RST_M2_REG, 0x870, 1), DEF_RST(R9A07G044_SSI2_RST_M2_REG, 0x870, 2), @@ -376,6 +418,8 @@ const struct rzg2l_cpg_info r9a07g044_cpg_info = { /* Resets */ .resets = r9a07g044_resets, .num_resets = R9A07G044_TSU_PRESETN + 1, /* Last reset ID + 1 */ + + .has_clk_mon_regs = true, }; #ifdef CONFIG_CLK_R9A07G054 @@ -398,5 +442,7 @@ const struct rzg2l_cpg_info r9a07g054_cpg_info = { /* Resets */ .resets = r9a07g044_resets, .num_resets = R9A07G054_STPAI_ARESETN + 1, /* Last reset ID + 1 */ + + .has_clk_mon_regs = true, }; #endif diff --git a/drivers/clk/renesas/r9a09g011-cpg.c b/drivers/clk/renesas/r9a09g011-cpg.c new file mode 100644 index 0000000000000000000000000000000000000000..40693bb85b801e4b0a42286a93c6440a78428850 --- /dev/null +++ b/drivers/clk/renesas/r9a09g011-cpg.c @@ -0,0 +1,172 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * RZ/V2M Clock Pulse Generator / Module Standby and Software Reset + * + * Copyright (C) 2022 Renesas Electronics Corp. + * + * Based on r9a07g044-cpg.c + */ + +#include +#include +#include +#include + +#include + +#include "rzg2l-cpg.h" + +#define RZV2M_SAMPLL4_CLK1 0x104 +#define RZV2M_SAMPLL4_CLK2 0x108 + +#define PLL4_CONF (RZV2M_SAMPLL4_CLK1 << 22 | RZV2M_SAMPLL4_CLK2 << 12) + +#define DIV_A DDIV_PACK(0x200, 0, 3) +#define DIV_B DDIV_PACK(0x204, 0, 2) +#define DIV_E DDIV_PACK(0x204, 8, 1) +#define DIV_W DDIV_PACK(0x328, 0, 3) + +#define SEL_B SEL_PLL_PACK(0x214, 0, 1) +#define SEL_E SEL_PLL_PACK(0x214, 2, 1) +#define SEL_W0 SEL_PLL_PACK(0x32C, 0, 1) + +enum clk_ids { + /* Core Clock Outputs exported to DT */ + LAST_DT_CORE_CLK = 0, + + /* External Input Clocks */ + CLK_EXTAL, + + /* Internal Core Clocks */ + CLK_MAIN, + CLK_MAIN_24, + CLK_MAIN_2, + CLK_PLL1, + CLK_PLL2, + CLK_PLL2_800, + CLK_PLL2_400, + CLK_PLL2_200, + CLK_PLL2_100, + CLK_PLL4, + CLK_DIV_A, + CLK_DIV_B, + CLK_DIV_E, + CLK_DIV_W, + CLK_SEL_B, + CLK_SEL_B_D2, + CLK_SEL_E, + CLK_SEL_W0, + + /* Module Clocks */ + MOD_CLK_BASE +}; + +/* Divider tables */ +static const struct clk_div_table dtable_diva[] = { + {0, 1}, + {1, 2}, + {2, 3}, + {3, 4}, + {4, 6}, + {5, 12}, + {6, 24}, + {0, 0}, +}; + +static const struct clk_div_table dtable_divb[] = { + {0, 1}, + {1, 2}, + {2, 4}, + {3, 8}, + {0, 0}, +}; + +static const struct clk_div_table dtable_divw[] = { + {0, 6}, + {1, 7}, + {2, 8}, + {3, 9}, + {4, 10}, + {5, 11}, + {6, 12}, + {0, 0}, +}; + +/* Mux clock tables */ +static const char * const sel_b[] = { ".main", ".divb" }; +static const char * const sel_e[] = { ".main", ".dive" }; +static const char * const sel_w[] = { ".main", ".divw" }; + +static const struct cpg_core_clk r9a09g011_core_clks[] __initconst = { + /* External Clock Inputs */ + DEF_INPUT("extal", CLK_EXTAL), + + /* Internal Core Clocks */ + DEF_FIXED(".main", CLK_MAIN, CLK_EXTAL, 1, 1), + DEF_FIXED(".main_24", CLK_MAIN_24, CLK_MAIN, 1, 2), + DEF_FIXED(".main_2", CLK_MAIN_2, CLK_MAIN, 1, 24), + DEF_FIXED(".pll1", CLK_PLL1, CLK_MAIN_2, 498, 1), + DEF_FIXED(".pll2", CLK_PLL2, CLK_MAIN_2, 800, 1), + DEF_FIXED(".pll2_800", CLK_PLL2_800, CLK_PLL2, 1, 2), + DEF_FIXED(".pll2_400", CLK_PLL2_400, CLK_PLL2_800, 1, 2), + DEF_FIXED(".pll2_200", CLK_PLL2_200, CLK_PLL2_800, 1, 4), + DEF_FIXED(".pll2_100", CLK_PLL2_100, CLK_PLL2_800, 1, 8), + DEF_SAMPLL(".pll4", CLK_PLL4, CLK_MAIN_2, PLL4_CONF), + + DEF_DIV_RO(".diva", CLK_DIV_A, CLK_PLL1, DIV_A, dtable_diva), + DEF_DIV_RO(".divb", CLK_DIV_B, CLK_PLL2_400, DIV_B, dtable_divb), + DEF_DIV_RO(".dive", CLK_DIV_E, CLK_PLL2_100, DIV_E, NULL), + DEF_DIV_RO(".divw", CLK_DIV_W, CLK_PLL4, DIV_W, dtable_divw), + + DEF_MUX_RO(".selb", CLK_SEL_B, SEL_B, sel_b), + DEF_MUX_RO(".sele", CLK_SEL_E, SEL_E, sel_e), + DEF_MUX(".selw0", CLK_SEL_W0, SEL_W0, sel_w), + + DEF_FIXED(".selb_d2", CLK_SEL_B_D2, CLK_SEL_B, 1, 2), +}; + +static const struct rzg2l_mod_clk r9a09g011_mod_clks[] __initconst = { + DEF_MOD("gic", R9A09G011_GIC_CLK, CLK_SEL_B_D2, 0x400, 5), + DEF_COUPLED("eth_axi", R9A09G011_ETH0_CLK_AXI, CLK_PLL2_200, 0x40c, 8), + DEF_COUPLED("eth_chi", R9A09G011_ETH0_CLK_CHI, CLK_PLL2_100, 0x40c, 8), + DEF_MOD("eth_clk_gptp", R9A09G011_ETH0_GPTP_EXT, CLK_PLL2_100, 0x40c, 9), + DEF_MOD("syc_cnt_clk", R9A09G011_SYC_CNT_CLK, CLK_MAIN_24, 0x41c, 12), + DEF_MOD("urt_pclk", R9A09G011_URT_PCLK, CLK_SEL_E, 0x438, 4), + DEF_MOD("urt0_clk", R9A09G011_URT0_CLK, CLK_SEL_W0, 0x438, 5), + DEF_MOD("ca53", R9A09G011_CA53_CLK, CLK_DIV_A, 0x448, 0), +}; + +static const struct rzg2l_reset r9a09g011_resets[] = { + DEF_RST_MON(R9A09G011_ETH0_RST_HW_N, 0x608, 11, 11), + DEF_RST_MON(R9A09G011_SYC_RST_N, 0x610, 9, 13), +}; + +static const unsigned int r9a09g011_crit_mod_clks[] __initconst = { + MOD_CLK_BASE + R9A09G011_CA53_CLK, + MOD_CLK_BASE + R9A09G011_GIC_CLK, + MOD_CLK_BASE + R9A09G011_SYC_CNT_CLK, + MOD_CLK_BASE + R9A09G011_URT_PCLK, +}; + +const struct rzg2l_cpg_info r9a09g011_cpg_info = { + /* Core Clocks */ + .core_clks = r9a09g011_core_clks, + .num_core_clks = ARRAY_SIZE(r9a09g011_core_clks), + .last_dt_core_clk = LAST_DT_CORE_CLK, + .num_total_core_clks = MOD_CLK_BASE, + + /* Critical Module Clocks */ + .crit_mod_clks = r9a09g011_crit_mod_clks, + .num_crit_mod_clks = ARRAY_SIZE(r9a09g011_crit_mod_clks), + + /* Module Clocks */ + .mod_clks = r9a09g011_mod_clks, + .num_mod_clks = ARRAY_SIZE(r9a09g011_mod_clks), + .num_hw_mod_clks = R9A09G011_CA53_CLK + 1, + + /* Resets */ + .resets = r9a09g011_resets, + .num_resets = ARRAY_SIZE(r9a09g011_resets), + + .has_clk_mon_regs = false, +}; diff --git a/drivers/clk/renesas/rcar-gen3-cpg.h b/drivers/clk/renesas/rcar-gen3-cpg.h index 2bc0afadf60413d25ff7a33dafe83f0620af183e..9028bf4295ce03d3dd7733b0fdaa5f920b22f999 100644 --- a/drivers/clk/renesas/rcar-gen3-cpg.h +++ b/drivers/clk/renesas/rcar-gen3-cpg.h @@ -25,7 +25,7 @@ enum rcar_gen3_clk_types { CLK_TYPE_GEN3_OSC, /* OSC EXTAL predivider and fixed divider */ CLK_TYPE_GEN3_RCKSEL, /* Select parent/divider using RCKCR.CKSEL */ CLK_TYPE_GEN3_RPCSRC, - CLK_TYPE_GEN3_E3_RPCSRC, + CLK_TYPE_GEN3_E3_RPCSRC,/* Select parent/divider using RPCCKCR.DIV */ CLK_TYPE_GEN3_RPC, CLK_TYPE_GEN3_RPCD2, @@ -62,6 +62,9 @@ enum rcar_gen3_clk_types { #define DEF_FIXED_RPCSRC_E3(_name, _id, _parent0, _parent1) \ DEF_BASE(_name, _id, CLK_TYPE_GEN3_E3_RPCSRC, \ (_parent0) << 16 | (_parent1), .div = 8) +#define DEF_FIXED_RPCSRC_D3(_name, _id, _parent0, _parent1) \ + DEF_BASE(_name, _id, CLK_TYPE_GEN3_E3_RPCSRC, \ + (_parent0) << 16 | (_parent1), .div = 5) struct rcar_gen3_cpg_pll_config { u8 extal_div; diff --git a/drivers/clk/renesas/rcar-gen4-cpg.c b/drivers/clk/renesas/rcar-gen4-cpg.c index 54ebf4b3c1284a49f9aba673865090c1efbc7c06..c7ed43d6aa67dcfd0e2ff4d8ee3ba96e4f00411a 100644 --- a/drivers/clk/renesas/rcar-gen4-cpg.c +++ b/drivers/clk/renesas/rcar-gen4-cpg.c @@ -215,6 +215,11 @@ struct clk * __init rcar_gen4_cpg_clk_register(struct device *dev, div = cpg_pll_config->pll3_div; break; + case CLK_TYPE_GEN4_PLL4: + mult = cpg_pll_config->pll4_mult; + div = cpg_pll_config->pll4_div; + break; + case CLK_TYPE_GEN4_PLL5: mult = cpg_pll_config->pll5_mult; div = cpg_pll_config->pll5_div; diff --git a/drivers/clk/renesas/rcar-gen4-cpg.h b/drivers/clk/renesas/rcar-gen4-cpg.h index afc8c024d538ac108cdec2febf850e0455c58065..0b15dcfdca7b5af7c973476704c4f8d0f7841c4a 100644 --- a/drivers/clk/renesas/rcar-gen4-cpg.h +++ b/drivers/clk/renesas/rcar-gen4-cpg.h @@ -16,6 +16,7 @@ enum rcar_gen4_clk_types { CLK_TYPE_GEN4_PLL2X_3X, /* r8a779a0 only */ CLK_TYPE_GEN4_PLL3, CLK_TYPE_GEN4_PLL5, + CLK_TYPE_GEN4_PLL4, CLK_TYPE_GEN4_PLL6, CLK_TYPE_GEN4_SDSRC, CLK_TYPE_GEN4_SDH, @@ -56,6 +57,8 @@ struct rcar_gen4_cpg_pll_config { u8 pll2_div; u8 pll3_mult; u8 pll3_div; + u8 pll4_mult; + u8 pll4_div; u8 pll5_mult; u8 pll5_div; u8 pll6_mult; diff --git a/drivers/clk/renesas/renesas-cpg-mssr.c b/drivers/clk/renesas/renesas-cpg-mssr.c index 5d2c3edbaa142249b2f079fc0235574a71484804..1a0cdf001b2f27ca13f6c65ba38a3252ebf11eca 100644 --- a/drivers/clk/renesas/renesas-cpg-mssr.c +++ b/drivers/clk/renesas/renesas-cpg-mssr.c @@ -853,6 +853,12 @@ static const struct of_device_id cpg_mssr_match[] = { .compatible = "renesas,r8a779f0-cpg-mssr", .data = &r8a779f0_cpg_mssr_info, }, +#endif +#ifdef CONFIG_CLK_R8A779G0 + { + .compatible = "renesas,r8a779g0-cpg-mssr", + .data = &r8a779g0_cpg_mssr_info, + }, #endif { /* sentinel */ } }; diff --git a/drivers/clk/renesas/renesas-cpg-mssr.h b/drivers/clk/renesas/renesas-cpg-mssr.h index 16810dd4e6acf209823ec4f2696c93bb9da59399..1c3c057d17f536cdbffa6dbd107c17d6931de7df 100644 --- a/drivers/clk/renesas/renesas-cpg-mssr.h +++ b/drivers/clk/renesas/renesas-cpg-mssr.h @@ -179,6 +179,7 @@ extern const struct cpg_mssr_info r8a77990_cpg_mssr_info; extern const struct cpg_mssr_info r8a77995_cpg_mssr_info; extern const struct cpg_mssr_info r8a779a0_cpg_mssr_info; extern const struct cpg_mssr_info r8a779f0_cpg_mssr_info; +extern const struct cpg_mssr_info r8a779g0_cpg_mssr_info; void __init cpg_mssr_early_init(struct device_node *np, const struct cpg_mssr_info *info); diff --git a/drivers/clk/renesas/rzg2l-cpg.c b/drivers/clk/renesas/rzg2l-cpg.c index 486d0656c58ac442ccc9bd9c0f51cbe9bf788f62..e2999ab2b53c4dfb8d38da141aa09af2a99b08bc 100644 --- a/drivers/clk/renesas/rzg2l-cpg.c +++ b/drivers/clk/renesas/rzg2l-cpg.c @@ -27,6 +27,7 @@ #include #include #include +#include #include @@ -56,6 +57,8 @@ #define GET_REG_SAMPLL_CLK1(val) ((val >> 22) & 0xfff) #define GET_REG_SAMPLL_CLK2(val) ((val >> 12) & 0xfff) +#define MAX_VCLK_FREQ (148500000) + struct sd_hw_data { struct clk_hw hw; u32 conf; @@ -64,6 +67,21 @@ struct sd_hw_data { #define to_sd_hw_data(_hw) container_of(_hw, struct sd_hw_data, hw) +struct rzg2l_pll5_param { + u32 pl5_fracin; + u8 pl5_refdiv; + u8 pl5_intin; + u8 pl5_postdiv1; + u8 pl5_postdiv2; + u8 pl5_spread; +}; + +struct rzg2l_pll5_mux_dsi_div_param { + u8 clksrc; + u8 dsi_div_a; + u8 dsi_div_b; +}; + /** * struct rzg2l_cpg_priv - Clock Pulse Generator Private Data * @@ -76,8 +94,8 @@ struct sd_hw_data { * @num_mod_clks: Number of Module Clocks in clks[] * @num_resets: Number of Module Resets in info->resets[] * @last_dt_core_clk: ID of the last Core Clock exported to DT - * @notifiers: Notifier chain to save/restore clock state for system resume * @info: Pointer to platform data + * @pll5_mux_dsi_div_params: pll5 mux and dsi div parameters */ struct rzg2l_cpg_priv { struct reset_controller_dev rcdev; @@ -91,8 +109,9 @@ struct rzg2l_cpg_priv { unsigned int num_resets; unsigned int last_dt_core_clk; - struct raw_notifier_head notifiers; const struct rzg2l_cpg_info *info; + + struct rzg2l_pll5_mux_dsi_div_param mux_dsi_div_params; }; static void rzg2l_cpg_del_clk_provider(void *data) @@ -266,6 +285,406 @@ rzg2l_cpg_sd_mux_clk_register(const struct cpg_core_clk *core, return clk_hw->clk; } +static unsigned long +rzg2l_cpg_get_foutpostdiv_rate(struct rzg2l_pll5_param *params, + unsigned long rate) +{ + unsigned long foutpostdiv_rate; + + params->pl5_intin = rate / MEGA; + params->pl5_fracin = div_u64(((u64)rate % MEGA) << 24, MEGA); + params->pl5_refdiv = 2; + params->pl5_postdiv1 = 1; + params->pl5_postdiv2 = 1; + params->pl5_spread = 0x16; + + foutpostdiv_rate = + EXTAL_FREQ_IN_MEGA_HZ * MEGA / params->pl5_refdiv * + ((((params->pl5_intin << 24) + params->pl5_fracin)) >> 24) / + (params->pl5_postdiv1 * params->pl5_postdiv2); + + return foutpostdiv_rate; +} + +struct dsi_div_hw_data { + struct clk_hw hw; + u32 conf; + unsigned long rate; + struct rzg2l_cpg_priv *priv; +}; + +#define to_dsi_div_hw_data(_hw) container_of(_hw, struct dsi_div_hw_data, hw) + +static unsigned long rzg2l_cpg_dsi_div_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct dsi_div_hw_data *dsi_div = to_dsi_div_hw_data(hw); + unsigned long rate = dsi_div->rate; + + if (!rate) + rate = parent_rate; + + return rate; +} + +static unsigned long rzg2l_cpg_get_vclk_parent_rate(struct clk_hw *hw, + unsigned long rate) +{ + struct dsi_div_hw_data *dsi_div = to_dsi_div_hw_data(hw); + struct rzg2l_cpg_priv *priv = dsi_div->priv; + struct rzg2l_pll5_param params; + unsigned long parent_rate; + + parent_rate = rzg2l_cpg_get_foutpostdiv_rate(¶ms, rate); + + if (priv->mux_dsi_div_params.clksrc) + parent_rate /= 2; + + return parent_rate; +} + +static int rzg2l_cpg_dsi_div_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) +{ + if (req->rate > MAX_VCLK_FREQ) + req->rate = MAX_VCLK_FREQ; + + req->best_parent_rate = rzg2l_cpg_get_vclk_parent_rate(hw, req->rate); + + return 0; +} + +static int rzg2l_cpg_dsi_div_set_rate(struct clk_hw *hw, + unsigned long rate, + unsigned long parent_rate) +{ + struct dsi_div_hw_data *dsi_div = to_dsi_div_hw_data(hw); + struct rzg2l_cpg_priv *priv = dsi_div->priv; + + /* + * MUX -->DIV_DSI_{A,B} -->M3 -->VCLK + * + * Based on the dot clock, the DSI divider clock sets the divider value, + * calculates the pll parameters for generating FOUTPOSTDIV and the clk + * source for the MUX and propagates that info to the parents. + */ + + if (!rate || rate > MAX_VCLK_FREQ) + return -EINVAL; + + dsi_div->rate = rate; + writel(CPG_PL5_SDIV_DIV_DSI_A_WEN | CPG_PL5_SDIV_DIV_DSI_B_WEN | + (priv->mux_dsi_div_params.dsi_div_a << 0) | + (priv->mux_dsi_div_params.dsi_div_b << 8), + priv->base + CPG_PL5_SDIV); + + return 0; +} + +static const struct clk_ops rzg2l_cpg_dsi_div_ops = { + .recalc_rate = rzg2l_cpg_dsi_div_recalc_rate, + .determine_rate = rzg2l_cpg_dsi_div_determine_rate, + .set_rate = rzg2l_cpg_dsi_div_set_rate, +}; + +static struct clk * __init +rzg2l_cpg_dsi_div_clk_register(const struct cpg_core_clk *core, + struct clk **clks, + struct rzg2l_cpg_priv *priv) +{ + struct dsi_div_hw_data *clk_hw_data; + const struct clk *parent; + const char *parent_name; + struct clk_init_data init; + struct clk_hw *clk_hw; + int ret; + + parent = clks[core->parent & 0xffff]; + if (IS_ERR(parent)) + return ERR_CAST(parent); + + clk_hw_data = devm_kzalloc(priv->dev, sizeof(*clk_hw_data), GFP_KERNEL); + if (!clk_hw_data) + return ERR_PTR(-ENOMEM); + + clk_hw_data->priv = priv; + + parent_name = __clk_get_name(parent); + init.name = core->name; + init.ops = &rzg2l_cpg_dsi_div_ops; + init.flags = CLK_SET_RATE_PARENT; + init.parent_names = &parent_name; + init.num_parents = 1; + + clk_hw = &clk_hw_data->hw; + clk_hw->init = &init; + + ret = devm_clk_hw_register(priv->dev, clk_hw); + if (ret) + return ERR_PTR(ret); + + return clk_hw->clk; +} + +struct pll5_mux_hw_data { + struct clk_hw hw; + u32 conf; + unsigned long rate; + struct rzg2l_cpg_priv *priv; +}; + +#define to_pll5_mux_hw_data(_hw) container_of(_hw, struct pll5_mux_hw_data, hw) + +static int rzg2l_cpg_pll5_4_clk_mux_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) +{ + struct clk_hw *parent; + struct pll5_mux_hw_data *hwdata = to_pll5_mux_hw_data(hw); + struct rzg2l_cpg_priv *priv = hwdata->priv; + + parent = clk_hw_get_parent_by_index(hw, priv->mux_dsi_div_params.clksrc); + req->best_parent_hw = parent; + req->best_parent_rate = req->rate; + + return 0; +} + +static int rzg2l_cpg_pll5_4_clk_mux_set_parent(struct clk_hw *hw, u8 index) +{ + struct pll5_mux_hw_data *hwdata = to_pll5_mux_hw_data(hw); + struct rzg2l_cpg_priv *priv = hwdata->priv; + + /* + * FOUTPOSTDIV--->| + * | | -->MUX -->DIV_DSIA_B -->M3 -->VCLK + * |--FOUT1PH0-->| + * + * Based on the dot clock, the DSI divider clock calculates the parent + * rate and clk source for the MUX. It propagates that info to + * pll5_4_clk_mux which sets the clock source for DSI divider clock. + */ + + writel(CPG_OTHERFUNC1_REG_RES0_ON_WEN | index, + priv->base + CPG_OTHERFUNC1_REG); + + return 0; +} + +static u8 rzg2l_cpg_pll5_4_clk_mux_get_parent(struct clk_hw *hw) +{ + struct pll5_mux_hw_data *hwdata = to_pll5_mux_hw_data(hw); + struct rzg2l_cpg_priv *priv = hwdata->priv; + + return readl(priv->base + GET_REG_OFFSET(hwdata->conf)); +} + +static const struct clk_ops rzg2l_cpg_pll5_4_clk_mux_ops = { + .determine_rate = rzg2l_cpg_pll5_4_clk_mux_determine_rate, + .set_parent = rzg2l_cpg_pll5_4_clk_mux_set_parent, + .get_parent = rzg2l_cpg_pll5_4_clk_mux_get_parent, +}; + +static struct clk * __init +rzg2l_cpg_pll5_4_mux_clk_register(const struct cpg_core_clk *core, + struct rzg2l_cpg_priv *priv) +{ + struct pll5_mux_hw_data *clk_hw_data; + struct clk_init_data init; + struct clk_hw *clk_hw; + int ret; + + clk_hw_data = devm_kzalloc(priv->dev, sizeof(*clk_hw_data), GFP_KERNEL); + if (!clk_hw_data) + return ERR_PTR(-ENOMEM); + + clk_hw_data->priv = priv; + clk_hw_data->conf = core->conf; + + init.name = core->name; + init.ops = &rzg2l_cpg_pll5_4_clk_mux_ops; + init.flags = CLK_SET_RATE_PARENT; + init.num_parents = core->num_parents; + init.parent_names = core->parent_names; + + clk_hw = &clk_hw_data->hw; + clk_hw->init = &init; + + ret = devm_clk_hw_register(priv->dev, clk_hw); + if (ret) + return ERR_PTR(ret); + + return clk_hw->clk; +} + +struct sipll5 { + struct clk_hw hw; + u32 conf; + unsigned long foutpostdiv_rate; + struct rzg2l_cpg_priv *priv; +}; + +#define to_sipll5(_hw) container_of(_hw, struct sipll5, hw) + +static unsigned long rzg2l_cpg_get_vclk_rate(struct clk_hw *hw, + unsigned long rate) +{ + struct sipll5 *sipll5 = to_sipll5(hw); + struct rzg2l_cpg_priv *priv = sipll5->priv; + unsigned long vclk; + + vclk = rate / ((1 << priv->mux_dsi_div_params.dsi_div_a) * + (priv->mux_dsi_div_params.dsi_div_b + 1)); + + if (priv->mux_dsi_div_params.clksrc) + vclk /= 2; + + return vclk; +} + +static unsigned long rzg2l_cpg_sipll5_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct sipll5 *sipll5 = to_sipll5(hw); + unsigned long pll5_rate = sipll5->foutpostdiv_rate; + + if (!pll5_rate) + pll5_rate = parent_rate; + + return pll5_rate; +} + +static long rzg2l_cpg_sipll5_round_rate(struct clk_hw *hw, + unsigned long rate, + unsigned long *parent_rate) +{ + return rate; +} + +static int rzg2l_cpg_sipll5_set_rate(struct clk_hw *hw, + unsigned long rate, + unsigned long parent_rate) +{ + struct sipll5 *sipll5 = to_sipll5(hw); + struct rzg2l_cpg_priv *priv = sipll5->priv; + struct rzg2l_pll5_param params; + unsigned long vclk_rate; + int ret; + u32 val; + + /* + * OSC --> PLL5 --> FOUTPOSTDIV-->| + * | | -->MUX -->DIV_DSIA_B -->M3 -->VCLK + * |--FOUT1PH0-->| + * + * Based on the dot clock, the DSI divider clock calculates the parent + * rate and the pll5 parameters for generating FOUTPOSTDIV. It propagates + * that info to sipll5 which sets parameters for generating FOUTPOSTDIV. + * + * OSC --> PLL5 --> FOUTPOSTDIV + */ + + if (!rate) + return -EINVAL; + + vclk_rate = rzg2l_cpg_get_vclk_rate(hw, rate); + sipll5->foutpostdiv_rate = + rzg2l_cpg_get_foutpostdiv_rate(¶ms, vclk_rate); + + /* Put PLL5 into standby mode */ + writel(CPG_SIPLL5_STBY_RESETB_WEN, priv->base + CPG_SIPLL5_STBY); + ret = readl_poll_timeout(priv->base + CPG_SIPLL5_MON, val, + !(val & CPG_SIPLL5_MON_PLL5_LOCK), 100, 250000); + if (ret) { + dev_err(priv->dev, "failed to release pll5 lock"); + return ret; + } + + /* Output clock setting 1 */ + writel(CPG_SIPLL5_CLK1_POSTDIV1_WEN | CPG_SIPLL5_CLK1_POSTDIV2_WEN | + CPG_SIPLL5_CLK1_REFDIV_WEN | (params.pl5_postdiv1 << 0) | + (params.pl5_postdiv2 << 4) | (params.pl5_refdiv << 8), + priv->base + CPG_SIPLL5_CLK1); + + /* Output clock setting, SSCG modulation value setting 3 */ + writel((params.pl5_fracin << 8), priv->base + CPG_SIPLL5_CLK3); + + /* Output clock setting 4 */ + writel(CPG_SIPLL5_CLK4_RESV_LSB | (params.pl5_intin << 16), + priv->base + CPG_SIPLL5_CLK4); + + /* Output clock setting 5 */ + writel(params.pl5_spread, priv->base + CPG_SIPLL5_CLK5); + + /* PLL normal mode setting */ + writel(CPG_SIPLL5_STBY_DOWNSPREAD_WEN | CPG_SIPLL5_STBY_SSCG_EN_WEN | + CPG_SIPLL5_STBY_RESETB_WEN | CPG_SIPLL5_STBY_RESETB, + priv->base + CPG_SIPLL5_STBY); + + /* PLL normal mode transition, output clock stability check */ + ret = readl_poll_timeout(priv->base + CPG_SIPLL5_MON, val, + (val & CPG_SIPLL5_MON_PLL5_LOCK), 100, 250000); + if (ret) { + dev_err(priv->dev, "failed to lock pll5"); + return ret; + } + + return 0; +} + +static const struct clk_ops rzg2l_cpg_sipll5_ops = { + .recalc_rate = rzg2l_cpg_sipll5_recalc_rate, + .round_rate = rzg2l_cpg_sipll5_round_rate, + .set_rate = rzg2l_cpg_sipll5_set_rate, +}; + +static struct clk * __init +rzg2l_cpg_sipll5_register(const struct cpg_core_clk *core, + struct clk **clks, + struct rzg2l_cpg_priv *priv) +{ + const struct clk *parent; + struct clk_init_data init; + const char *parent_name; + struct sipll5 *sipll5; + struct clk_hw *clk_hw; + int ret; + + parent = clks[core->parent & 0xffff]; + if (IS_ERR(parent)) + return ERR_CAST(parent); + + sipll5 = devm_kzalloc(priv->dev, sizeof(*sipll5), GFP_KERNEL); + if (!sipll5) + return ERR_PTR(-ENOMEM); + + init.name = core->name; + parent_name = __clk_get_name(parent); + init.ops = &rzg2l_cpg_sipll5_ops; + init.flags = 0; + init.parent_names = &parent_name; + init.num_parents = 1; + + sipll5->hw.init = &init; + sipll5->conf = core->conf; + sipll5->priv = priv; + + writel(CPG_SIPLL5_STBY_SSCG_EN_WEN | CPG_SIPLL5_STBY_RESETB_WEN | + CPG_SIPLL5_STBY_RESETB, priv->base + CPG_SIPLL5_STBY); + + clk_hw = &sipll5->hw; + clk_hw->init = &init; + + ret = devm_clk_hw_register(priv->dev, clk_hw); + if (ret) + return ERR_PTR(ret); + + priv->mux_dsi_div_params.clksrc = 1; /* Use clk src 1 for DSI */ + priv->mux_dsi_div_params.dsi_div_a = 1; /* Divided by 2 */ + priv->mux_dsi_div_params.dsi_div_b = 2; /* Divided by 3 */ + + return clk_hw->clk; +} + struct pll_clk { struct clk_hw hw; unsigned int conf; @@ -291,7 +710,7 @@ static unsigned long rzg2l_cpg_pll_clk_recalc_rate(struct clk_hw *hw, val1 = readl(priv->base + GET_REG_SAMPLL_CLK1(pll_clk->conf)); val2 = readl(priv->base + GET_REG_SAMPLL_CLK2(pll_clk->conf)); mult = MDIV(val1) + KDIV(val1) / 65536; - div = PDIV(val1) * (1 << SDIV(val2)); + div = PDIV(val1) << SDIV(val2); return DIV_ROUND_CLOSEST_ULL((u64)parent_rate * mult, div); } @@ -420,6 +839,9 @@ rzg2l_cpg_register_core_clk(const struct cpg_core_clk *core, clk = rzg2l_cpg_pll_clk_register(core, priv->clks, priv->base, priv); break; + case CLK_TYPE_SIPLL5: + clk = rzg2l_cpg_sipll5_register(core, priv->clks, priv); + break; case CLK_TYPE_DIV: clk = rzg2l_cpg_div_clk_register(core, priv->clks, priv->base, priv); @@ -430,6 +852,12 @@ rzg2l_cpg_register_core_clk(const struct cpg_core_clk *core, case CLK_TYPE_SD_MUX: clk = rzg2l_cpg_sd_mux_clk_register(core, priv->base, priv); break; + case CLK_TYPE_PLL5_4_MUX: + clk = rzg2l_cpg_pll5_4_mux_clk_register(core, priv); + break; + case CLK_TYPE_DSI_DIV: + clk = rzg2l_cpg_dsi_div_clk_register(core, priv->clks, priv); + break; default: goto fail; } @@ -498,6 +926,9 @@ static int rzg2l_mod_clock_endisable(struct clk_hw *hw, bool enable) if (!enable) return 0; + if (!priv->info->has_clk_mon_regs) + return 0; + for (i = 1000; i > 0; --i) { if (((readl(priv->base + CLK_MON_R(reg))) & bitmask)) break; @@ -568,7 +999,10 @@ static int rzg2l_mod_clock_is_enabled(struct clk_hw *hw) if (clock->sibling) return clock->enabled; - value = readl(priv->base + CLK_MON_R(clock->off)); + if (priv->info->has_clk_mon_regs) + value = readl(priv->base + CLK_MON_R(clock->off)); + else + value = readl(priv->base + clock->off); return value & bitmask; } @@ -743,8 +1177,16 @@ static int rzg2l_cpg_status(struct reset_controller_dev *rcdev, const struct rzg2l_cpg_info *info = priv->info; unsigned int reg = info->resets[id].off; u32 bitmask = BIT(info->resets[id].bit); + s8 monbit = info->resets[id].monbit; + + if (info->has_clk_mon_regs) { + return !(readl(priv->base + CLK_MRST_R(reg)) & bitmask); + } else if (monbit >= 0) { + u32 monbitmask = BIT(monbit); - return !(readl(priv->base + CLK_MRST_R(reg)) & bitmask); + return !!(readl(priv->base + CPG_RST_MON) & monbitmask); + } + return -ENOTSUPP; } static const struct reset_control_ops rzg2l_cpg_reset_ops = { @@ -947,6 +1389,12 @@ static int __init rzg2l_cpg_probe(struct platform_device *pdev) } static const struct of_device_id rzg2l_cpg_match[] = { +#ifdef CONFIG_CLK_R9A07G043 + { + .compatible = "renesas,r9a07g043-cpg", + .data = &r9a07g043_cpg_info, + }, +#endif #ifdef CONFIG_CLK_R9A07G044 { .compatible = "renesas,r9a07g044-cpg", @@ -958,6 +1406,12 @@ static const struct of_device_id rzg2l_cpg_match[] = { .compatible = "renesas,r9a07g054-cpg", .data = &r9a07g054_cpg_info, }, +#endif +#ifdef CONFIG_CLK_R9A09G011 + { + .compatible = "renesas,r9a09g011-cpg", + .data = &r9a09g011_cpg_info, + }, #endif { /* sentinel */ } }; diff --git a/drivers/clk/renesas/rzg2l-cpg.h b/drivers/clk/renesas/rzg2l-cpg.h index ce657beaf1601bcff612a264f882dfea2edfe9a3..cecbdf5e4f93ab72c35d540b0827bad6a6d48f08 100644 --- a/drivers/clk/renesas/rzg2l-cpg.h +++ b/drivers/clk/renesas/rzg2l-cpg.h @@ -9,6 +9,12 @@ #ifndef __RENESAS_RZG2L_CPG_H__ #define __RENESAS_RZG2L_CPG_H__ +#define CPG_SIPLL5_STBY (0x140) +#define CPG_SIPLL5_CLK1 (0x144) +#define CPG_SIPLL5_CLK3 (0x14C) +#define CPG_SIPLL5_CLK4 (0x150) +#define CPG_SIPLL5_CLK5 (0x154) +#define CPG_SIPLL5_MON (0x15C) #define CPG_PL1_DDIV (0x200) #define CPG_PL2_DDIV (0x204) #define CPG_PL3A_DDIV (0x208) @@ -18,6 +24,24 @@ #define CPG_PL3_SSEL (0x408) #define CPG_PL6_SSEL (0x414) #define CPG_PL6_ETH_SSEL (0x418) +#define CPG_PL5_SDIV (0x420) +#define CPG_RST_MON (0x680) +#define CPG_OTHERFUNC1_REG (0xBE8) + +#define CPG_SIPLL5_STBY_RESETB BIT(0) +#define CPG_SIPLL5_STBY_RESETB_WEN BIT(16) +#define CPG_SIPLL5_STBY_SSCG_EN_WEN BIT(18) +#define CPG_SIPLL5_STBY_DOWNSPREAD_WEN BIT(20) +#define CPG_SIPLL5_CLK1_POSTDIV1_WEN BIT(16) +#define CPG_SIPLL5_CLK1_POSTDIV2_WEN BIT(20) +#define CPG_SIPLL5_CLK1_REFDIV_WEN BIT(24) +#define CPG_SIPLL5_CLK4_RESV_LSB (0xFF) +#define CPG_SIPLL5_MON_PLL5_LOCK BIT(4) + +#define CPG_OTHERFUNC1_REG_RES0_ON_WEN BIT(16) + +#define CPG_PL5_SDIV_DIV_DSI_A_WEN BIT(16) +#define CPG_PL5_SDIV_DIV_DSI_B_WEN BIT(24) #define CPG_CLKSTATUS_SELSDHI0_STS BIT(28) #define CPG_CLKSTATUS_SELSDHI1_STS BIT(29) @@ -34,6 +58,7 @@ (((offset) << 20) | ((bitpos) << 12) | ((size) << 8)) #define DIVPL1A DDIV_PACK(CPG_PL1_DDIV, 0, 2) #define DIVPL2A DDIV_PACK(CPG_PL2_DDIV, 0, 3) +#define DIVDSILPCLK DDIV_PACK(CPG_PL2_DDIV, 12, 2) #define DIVPL3A DDIV_PACK(CPG_PL3A_DDIV, 0, 3) #define DIVPL3B DDIV_PACK(CPG_PL3A_DDIV, 4, 3) #define DIVPL3C DDIV_PACK(CPG_PL3A_DDIV, 8, 3) @@ -43,12 +68,15 @@ (((offset) << 20) | ((bitpos) << 12) | ((size) << 8)) #define SEL_PLL3_3 SEL_PLL_PACK(CPG_PL3_SSEL, 8, 1) +#define SEL_PLL5_4 SEL_PLL_PACK(CPG_OTHERFUNC1_REG, 0, 1) #define SEL_PLL6_2 SEL_PLL_PACK(CPG_PL6_ETH_SSEL, 0, 1) #define SEL_GPU2 SEL_PLL_PACK(CPG_PL6_SSEL, 12, 1) #define SEL_SDHI0 DDIV_PACK(CPG_PL2SDHI_DSEL, 0, 2) #define SEL_SDHI1 DDIV_PACK(CPG_PL2SDHI_DSEL, 4, 2) +#define EXTAL_FREQ_IN_MEGA_HZ (24) + /** * Definitions of CPG Core Clocks * @@ -86,6 +114,16 @@ enum clk_types { /* Clock with SD clock source selector */ CLK_TYPE_SD_MUX, + + /* Clock for SIPLL5 */ + CLK_TYPE_SIPLL5, + + /* Clock for PLL5_4 clock source selector */ + CLK_TYPE_PLL5_4_MUX, + + /* Clock for DSI divider */ + CLK_TYPE_DSI_DIV, + }; #define DEF_TYPE(_name, _id, _type...) \ @@ -98,17 +136,36 @@ enum clk_types { DEF_TYPE(_name, _id, CLK_TYPE_IN) #define DEF_FIXED(_name, _id, _parent, _mult, _div) \ DEF_BASE(_name, _id, CLK_TYPE_FF, _parent, .div = _div, .mult = _mult) -#define DEF_DIV(_name, _id, _parent, _conf, _dtable, _flag) \ +#define DEF_DIV(_name, _id, _parent, _conf, _dtable) \ + DEF_TYPE(_name, _id, CLK_TYPE_DIV, .conf = _conf, \ + .parent = _parent, .dtable = _dtable, \ + .flag = CLK_DIVIDER_HIWORD_MASK) +#define DEF_DIV_RO(_name, _id, _parent, _conf, _dtable) \ DEF_TYPE(_name, _id, CLK_TYPE_DIV, .conf = _conf, \ - .parent = _parent, .dtable = _dtable, .flag = _flag) -#define DEF_MUX(_name, _id, _conf, _parent_names, _num_parents, _flag, \ - _mux_flags) \ + .parent = _parent, .dtable = _dtable, \ + .flag = CLK_DIVIDER_READ_ONLY) +#define DEF_MUX(_name, _id, _conf, _parent_names) \ DEF_TYPE(_name, _id, CLK_TYPE_MUX, .conf = _conf, \ - .parent_names = _parent_names, .num_parents = _num_parents, \ - .flag = _flag, .mux_flags = _mux_flags) -#define DEF_SD_MUX(_name, _id, _conf, _parent_names, _num_parents) \ + .parent_names = _parent_names, \ + .num_parents = ARRAY_SIZE(_parent_names), \ + .mux_flags = CLK_MUX_HIWORD_MASK) +#define DEF_MUX_RO(_name, _id, _conf, _parent_names) \ + DEF_TYPE(_name, _id, CLK_TYPE_MUX, .conf = _conf, \ + .parent_names = _parent_names, \ + .num_parents = ARRAY_SIZE(_parent_names), \ + .mux_flags = CLK_MUX_READ_ONLY) +#define DEF_SD_MUX(_name, _id, _conf, _parent_names) \ DEF_TYPE(_name, _id, CLK_TYPE_SD_MUX, .conf = _conf, \ - .parent_names = _parent_names, .num_parents = _num_parents) + .parent_names = _parent_names, \ + .num_parents = ARRAY_SIZE(_parent_names)) +#define DEF_PLL5_FOUTPOSTDIV(_name, _id, _parent) \ + DEF_TYPE(_name, _id, CLK_TYPE_SIPLL5, .parent = _parent) +#define DEF_PLL5_4_MUX(_name, _id, _conf, _parent_names) \ + DEF_TYPE(_name, _id, CLK_TYPE_PLL5_4_MUX, .conf = _conf, \ + .parent_names = _parent_names, \ + .num_parents = ARRAY_SIZE(_parent_names)) +#define DEF_DSI_DIV(_name, _id, _parent, _flag) \ + DEF_TYPE(_name, _id, CLK_TYPE_DSI_DIV, .parent = _parent, .flag = _flag) /** * struct rzg2l_mod_clk - Module Clocks definitions @@ -150,17 +207,22 @@ struct rzg2l_mod_clk { * * @off: register offset * @bit: reset bit + * @monbit: monitor bit in CPG_RST_MON register, -1 if none */ struct rzg2l_reset { u16 off; u8 bit; + s8 monbit; }; -#define DEF_RST(_id, _off, _bit) \ +#define DEF_RST_MON(_id, _off, _bit, _monbit) \ [_id] = { \ .off = (_off), \ - .bit = (_bit) \ + .bit = (_bit), \ + .monbit = (_monbit) \ } +#define DEF_RST(_id, _off, _bit) \ + DEF_RST_MON(_id, _off, _bit, -1) /** * struct rzg2l_cpg_info - SoC-specific CPG Description @@ -180,6 +242,7 @@ struct rzg2l_reset { * @crit_mod_clks: Array with Module Clock IDs of critical clocks that * should not be disabled without a knowledgeable driver * @num_crit_mod_clks: Number of entries in crit_mod_clks[] + * @has_clk_mon_regs: Flag indicating whether the SoC has CLK_MON registers */ struct rzg2l_cpg_info { /* Core Clocks */ @@ -200,9 +263,13 @@ struct rzg2l_cpg_info { /* Critical Module Clocks that should not be disabled */ const unsigned int *crit_mod_clks; unsigned int num_crit_mod_clks; + + bool has_clk_mon_regs; }; +extern const struct rzg2l_cpg_info r9a07g043_cpg_info; extern const struct rzg2l_cpg_info r9a07g044_cpg_info; extern const struct rzg2l_cpg_info r9a07g054_cpg_info; +extern const struct rzg2l_cpg_info r9a09g011_cpg_info; #endif diff --git a/drivers/clk/rockchip/clk-rk3568.c b/drivers/clk/rockchip/clk-rk3568.c index 606ae6cd918b24b52bdd24f7bf5ed9153d4fff57..f85902e2590c7feaad6884dbf9d6400148676494 100644 --- a/drivers/clk/rockchip/clk-rk3568.c +++ b/drivers/clk/rockchip/clk-rk3568.c @@ -1591,6 +1591,7 @@ static const char *const rk3568_cru_critical_clocks[] __initconst = { "hclk_php", "pclk_php", "hclk_usb", + "hclk_vo", }; static const char *const rk3568_pmucru_critical_clocks[] __initconst = { diff --git a/drivers/clk/samsung/Makefile b/drivers/clk/samsung/Makefile index 17e5d1cb9da2ff1e81c917dfd56c605acbbc8ed3..239d9eead77f145b2a75326bffc4e1fb117f446f 100644 --- a/drivers/clk/samsung/Makefile +++ b/drivers/clk/samsung/Makefile @@ -20,6 +20,7 @@ obj-$(CONFIG_EXYNOS_ARM64_COMMON_CLK) += clk-exynos-arm64.o obj-$(CONFIG_EXYNOS_ARM64_COMMON_CLK) += clk-exynos7.o obj-$(CONFIG_EXYNOS_ARM64_COMMON_CLK) += clk-exynos7885.o obj-$(CONFIG_EXYNOS_ARM64_COMMON_CLK) += clk-exynos850.o +obj-$(CONFIG_EXYNOS_ARM64_COMMON_CLK) += clk-exynosautov9.o obj-$(CONFIG_S3C2410_COMMON_CLK)+= clk-s3c2410.o obj-$(CONFIG_S3C2410_COMMON_DCLK)+= clk-s3c2410-dclk.o obj-$(CONFIG_S3C2412_COMMON_CLK)+= clk-s3c2412.o diff --git a/drivers/clk/samsung/clk-exynosautov9.c b/drivers/clk/samsung/clk-exynosautov9.c new file mode 100644 index 0000000000000000000000000000000000000000..d9e1f8e4a7b4555581ba7dec49533677d0bbd41d --- /dev/null +++ b/drivers/clk/samsung/clk-exynosautov9.c @@ -0,0 +1,1733 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2022 Samsung Electronics Co., Ltd. + * Author: Chanho Park + * + * Common Clock Framework support for ExynosAuto V9 SoC. + */ + +#include +#include +#include +#include +#include +#include + +#include + +#include "clk.h" +#include "clk-exynos-arm64.h" + +/* ---- CMU_TOP ------------------------------------------------------------ */ + +/* Register Offset definitions for CMU_TOP (0x1b240000) */ +#define PLL_LOCKTIME_PLL_SHARED0 0x0000 +#define PLL_LOCKTIME_PLL_SHARED1 0x0004 +#define PLL_LOCKTIME_PLL_SHARED2 0x0008 +#define PLL_LOCKTIME_PLL_SHARED3 0x000c +#define PLL_LOCKTIME_PLL_SHARED4 0x0010 +#define PLL_CON0_PLL_SHARED0 0x0100 +#define PLL_CON3_PLL_SHARED0 0x010c +#define PLL_CON0_PLL_SHARED1 0x0140 +#define PLL_CON3_PLL_SHARED1 0x014c +#define PLL_CON0_PLL_SHARED2 0x0180 +#define PLL_CON3_PLL_SHARED2 0x018c +#define PLL_CON0_PLL_SHARED3 0x01c0 +#define PLL_CON3_PLL_SHARED3 0x01cc +#define PLL_CON0_PLL_SHARED4 0x0200 +#define PLL_CON3_PLL_SHARED4 0x020c + +/* MUX */ +#define CLK_CON_MUX_MUX_CLKCMU_ACC_BUS 0x1000 +#define CLK_CON_MUX_MUX_CLKCMU_APM_BUS 0x1004 +#define CLK_CON_MUX_MUX_CLKCMU_AUD_BUS 0x1008 +#define CLK_CON_MUX_MUX_CLKCMU_AUD_CPU 0x100c +#define CLK_CON_MUX_MUX_CLKCMU_BUSC_BUS 0x1010 +#define CLK_CON_MUX_MUX_CLKCMU_BUSMC_BUS 0x1018 +#define CLK_CON_MUX_MUX_CLKCMU_CMU_BOOST 0x101c +#define CLK_CON_MUX_MUX_CLKCMU_CORE_BUS 0x1020 +#define CLK_CON_MUX_MUX_CLKCMU_CPUCL0_CLUSTER 0x1024 +#define CLK_CON_MUX_MUX_CLKCMU_CPUCL0_SWITCH 0x102c +#define CLK_CON_MUX_MUX_CLKCMU_CPUCL1_CLUSTER 0x1030 +#define CLK_CON_MUX_MUX_CLKCMU_CPUCL1_SWITCH 0x1034 +#define CLK_CON_MUX_MUX_CLKCMU_DPTX_BUS 0x1040 +#define CLK_CON_MUX_MUX_CLKCMU_DPTX_DPGTC 0x1044 +#define CLK_CON_MUX_MUX_CLKCMU_DPUM_BUS 0x1048 +#define CLK_CON_MUX_MUX_CLKCMU_DPUS0_BUS 0x104c +#define CLK_CON_MUX_MUX_CLKCMU_DPUS1_BUS 0x1050 +#define CLK_CON_MUX_MUX_CLKCMU_FSYS0_BUS 0x1054 +#define CLK_CON_MUX_MUX_CLKCMU_FSYS0_PCIE 0x1058 +#define CLK_CON_MUX_MUX_CLKCMU_FSYS1_BUS 0x105c +#define CLK_CON_MUX_MUX_CLKCMU_FSYS1_MMC_CARD 0x1060 +#define CLK_CON_MUX_MUX_CLKCMU_FSYS1_USBDRD 0x1064 +#define CLK_CON_MUX_MUX_CLKCMU_FSYS2_BUS 0x1068 +#define CLK_CON_MUX_MUX_CLKCMU_FSYS2_ETHERNET 0x106c +#define CLK_CON_MUX_MUX_CLKCMU_FSYS2_UFS_EMBD 0x1070 +#define CLK_CON_MUX_MUX_CLKCMU_G2D_G2D 0x1074 +#define CLK_CON_MUX_MUX_CLKCMU_G2D_MSCL 0x1078 +#define CLK_CON_MUX_MUX_CLKCMU_G3D00_SWITCH 0x107c +#define CLK_CON_MUX_MUX_CLKCMU_G3D01_SWITCH 0x1080 +#define CLK_CON_MUX_MUX_CLKCMU_G3D1_SWITCH 0x1084 +#define CLK_CON_MUX_MUX_CLKCMU_ISPB_BUS 0x108c +#define CLK_CON_MUX_MUX_CLKCMU_MFC_MFC 0x1090 +#define CLK_CON_MUX_MUX_CLKCMU_MFC_WFD 0x1094 +#define CLK_CON_MUX_MUX_CLKCMU_MIF_SWITCH 0x109c +#define CLK_CON_MUX_MUX_CLKCMU_MIF_BUSP 0x1098 +#define CLK_CON_MUX_MUX_CLKCMU_MIF_SWITCH 0x109c +#define CLK_CON_MUX_MUX_CLKCMU_NPU_BUS 0x10a0 +#define CLK_CON_MUX_MUX_CLKCMU_PERIC0_BUS 0x10a4 +#define CLK_CON_MUX_MUX_CLKCMU_PERIC0_IP 0x10a8 +#define CLK_CON_MUX_MUX_CLKCMU_PERIC1_BUS 0x10ac +#define CLK_CON_MUX_MUX_CLKCMU_PERIC1_IP 0x10b0 +#define CLK_CON_MUX_MUX_CLKCMU_PERIS_BUS 0x10b4 +#define CLK_CON_MUX_MUX_CMU_CMUREF 0x10c0 + +/* DIV */ +#define CLK_CON_DIV_CLKCMU_ACC_BUS 0x1800 +#define CLK_CON_DIV_CLKCMU_APM_BUS 0x1804 +#define CLK_CON_DIV_CLKCMU_AUD_BUS 0x1808 +#define CLK_CON_DIV_CLKCMU_AUD_CPU 0x180c +#define CLK_CON_DIV_CLKCMU_BUSC_BUS 0x1810 +#define CLK_CON_DIV_CLKCMU_BUSMC_BUS 0x1818 +#define CLK_CON_DIV_CLKCMU_CORE_BUS 0x181c +#define CLK_CON_DIV_CLKCMU_CPUCL0_CLUSTER 0x1820 +#define CLK_CON_DIV_CLKCMU_CPUCL0_SWITCH 0x1828 +#define CLK_CON_DIV_CLKCMU_CPUCL1_CLUSTER 0x182c +#define CLK_CON_DIV_CLKCMU_CPUCL1_SWITCH 0x1830 +#define CLK_CON_DIV_CLKCMU_DPTX_BUS 0x183c +#define CLK_CON_DIV_CLKCMU_DPTX_DPGTC 0x1840 +#define CLK_CON_DIV_CLKCMU_DPUM_BUS 0x1844 +#define CLK_CON_DIV_CLKCMU_DPUS0_BUS 0x1848 +#define CLK_CON_DIV_CLKCMU_DPUS1_BUS 0x184c +#define CLK_CON_DIV_CLKCMU_FSYS0_BUS 0x1850 +#define CLK_CON_DIV_CLKCMU_FSYS0_PCIE 0x1854 +#define CLK_CON_DIV_CLKCMU_FSYS1_BUS 0x1858 +#define CLK_CON_DIV_CLKCMU_FSYS1_USBDRD 0x185c +#define CLK_CON_DIV_CLKCMU_FSYS2_BUS 0x1860 +#define CLK_CON_DIV_CLKCMU_FSYS2_ETHERNET 0x1864 +#define CLK_CON_DIV_CLKCMU_FSYS2_UFS_EMBD 0x1868 +#define CLK_CON_DIV_CLKCMU_G2D_G2D 0x186c +#define CLK_CON_DIV_CLKCMU_G2D_MSCL 0x1870 +#define CLK_CON_DIV_CLKCMU_G3D00_SWITCH 0x1874 +#define CLK_CON_DIV_CLKCMU_G3D01_SWITCH 0x1878 +#define CLK_CON_DIV_CLKCMU_G3D1_SWITCH 0x187c +#define CLK_CON_DIV_CLKCMU_ISPB_BUS 0x1884 +#define CLK_CON_DIV_CLKCMU_MFC_MFC 0x1888 +#define CLK_CON_DIV_CLKCMU_MFC_WFD 0x188c +#define CLK_CON_DIV_CLKCMU_MIF_BUSP 0x1890 +#define CLK_CON_DIV_CLKCMU_NPU_BUS 0x1894 +#define CLK_CON_DIV_CLKCMU_PERIC0_BUS 0x1898 +#define CLK_CON_DIV_CLKCMU_PERIC0_IP 0x189c +#define CLK_CON_DIV_CLKCMU_PERIC1_BUS 0x18a0 +#define CLK_CON_DIV_CLKCMU_PERIC1_IP 0x18a4 +#define CLK_CON_DIV_CLKCMU_PERIS_BUS 0x18a8 +#define CLK_CON_DIV_DIV_CLKCMU_CMU_BOOST 0x18b4 + +#define CLK_CON_DIV_PLL_SHARED0_DIV2 0x18b8 +#define CLK_CON_DIV_PLL_SHARED0_DIV3 0x18bc +#define CLK_CON_DIV_PLL_SHARED1_DIV2 0x18c0 +#define CLK_CON_DIV_PLL_SHARED1_DIV3 0x18c4 +#define CLK_CON_DIV_PLL_SHARED1_DIV4 0x18c8 +#define CLK_CON_DIV_PLL_SHARED2_DIV2 0x18cc +#define CLK_CON_DIV_PLL_SHARED2_DIV3 0x18d0 +#define CLK_CON_DIV_PLL_SHARED2_DIV4 0x18d4 +#define CLK_CON_DIV_PLL_SHARED4_DIV2 0x18d4 +#define CLK_CON_DIV_PLL_SHARED4_DIV4 0x18d8 + +/* GATE */ +#define CLK_CON_GAT_CLKCMU_CMU_BUSC_BOOST 0x2000 +#define CLK_CON_GAT_CLKCMU_CMU_BUSMC_BOOST 0x2004 +#define CLK_CON_GAT_CLKCMU_CMU_CORE_BOOST 0x2008 +#define CLK_CON_GAT_CLKCMU_CMU_CPUCL0_BOOST 0x2010 +#define CLK_CON_GAT_CLKCMU_CMU_CPUCL1_BOOST 0x2018 +#define CLK_CON_GAT_CLKCMU_CMU_MIF_BOOST 0x2020 +#define CLK_CON_GAT_GATE_CLKCMU_FSYS1_MMC_CARD 0x2024 +#define CLK_CON_GAT_GATE_CLKCMU_MIF_SWITCH 0x2028 +#define CLK_CON_GAT_GATE_CLKCMU_ACC_BUS 0x202c +#define CLK_CON_GAT_GATE_CLKCMU_APM_BUS 0x2030 +#define CLK_CON_GAT_GATE_CLKCMU_AUD_BUS 0x2034 +#define CLK_CON_GAT_GATE_CLKCMU_AUD_CPU 0x2038 +#define CLK_CON_GAT_GATE_CLKCMU_BUSC_BUS 0x203c +#define CLK_CON_GAT_GATE_CLKCMU_BUSMC_BUS 0x2044 +#define CLK_CON_GAT_GATE_CLKCMU_CMU_BOOST 0x2048 +#define CLK_CON_GAT_GATE_CLKCMU_CORE_BUS 0x204c +#define CLK_CON_GAT_GATE_CLKCMU_CPUCL0_CLUSTER 0x2050 +#define CLK_CON_GAT_GATE_CLKCMU_CPUCL0_SWITCH 0x2058 +#define CLK_CON_GAT_GATE_CLKCMU_CPUCL1_CLUSTER 0x205c +#define CLK_CON_GAT_GATE_CLKCMU_CPUCL1_SWITCH 0x2060 +#define CLK_CON_GAT_GATE_CLKCMU_DPTX_BUS 0x206c +#define CLK_CON_GAT_GATE_CLKCMU_DPTX_DPGTC 0x2070 +#define CLK_CON_GAT_GATE_CLKCMU_DPUM_BUS 0x2060 +#define CLK_CON_GAT_GATE_CLKCMU_DPUS0_BUS 0x2064 +#define CLK_CON_GAT_GATE_CLKCMU_DPUS1_BUS 0x207c +#define CLK_CON_GAT_GATE_CLKCMU_FSYS0_BUS 0x2080 +#define CLK_CON_GAT_GATE_CLKCMU_FSYS0_PCIE 0x2084 +#define CLK_CON_GAT_GATE_CLKCMU_FSYS1_BUS 0x2088 +#define CLK_CON_GAT_GATE_CLKCMU_FSYS1_USBDRD 0x208c +#define CLK_CON_GAT_GATE_CLKCMU_FSYS2_BUS 0x2090 +#define CLK_CON_GAT_GATE_CLKCMU_FSYS2_ETHERNET 0x2094 +#define CLK_CON_GAT_GATE_CLKCMU_FSYS2_UFS_EMBD 0x2098 +#define CLK_CON_GAT_GATE_CLKCMU_G2D_G2D 0x209c +#define CLK_CON_GAT_GATE_CLKCMU_G2D_MSCL 0x20a0 +#define CLK_CON_GAT_GATE_CLKCMU_G3D00_SWITCH 0x20a4 +#define CLK_CON_GAT_GATE_CLKCMU_G3D01_SWITCH 0x20a8 +#define CLK_CON_GAT_GATE_CLKCMU_G3D1_SWITCH 0x20ac +#define CLK_CON_GAT_GATE_CLKCMU_ISPB_BUS 0x20b4 +#define CLK_CON_GAT_GATE_CLKCMU_MFC_MFC 0x20b8 +#define CLK_CON_GAT_GATE_CLKCMU_MFC_WFD 0x20bc +#define CLK_CON_GAT_GATE_CLKCMU_MIF_BUSP 0x20c0 +#define CLK_CON_GAT_GATE_CLKCMU_NPU_BUS 0x20c4 +#define CLK_CON_GAT_GATE_CLKCMU_PERIC0_BUS 0x20c8 +#define CLK_CON_GAT_GATE_CLKCMU_PERIC0_IP 0x20cc +#define CLK_CON_GAT_GATE_CLKCMU_PERIC1_BUS 0x20d0 +#define CLK_CON_GAT_GATE_CLKCMU_PERIC1_IP 0x20d4 +#define CLK_CON_GAT_GATE_CLKCMU_PERIS_BUS 0x20d8 + +static const unsigned long top_clk_regs[] __initconst = { + PLL_LOCKTIME_PLL_SHARED0, + PLL_LOCKTIME_PLL_SHARED1, + PLL_LOCKTIME_PLL_SHARED2, + PLL_LOCKTIME_PLL_SHARED3, + PLL_LOCKTIME_PLL_SHARED4, + PLL_CON0_PLL_SHARED0, + PLL_CON3_PLL_SHARED0, + PLL_CON0_PLL_SHARED1, + PLL_CON3_PLL_SHARED1, + PLL_CON0_PLL_SHARED2, + PLL_CON3_PLL_SHARED2, + PLL_CON0_PLL_SHARED3, + PLL_CON3_PLL_SHARED3, + PLL_CON0_PLL_SHARED4, + PLL_CON3_PLL_SHARED4, + CLK_CON_MUX_MUX_CLKCMU_ACC_BUS, + CLK_CON_MUX_MUX_CLKCMU_APM_BUS, + CLK_CON_MUX_MUX_CLKCMU_AUD_BUS, + CLK_CON_MUX_MUX_CLKCMU_AUD_CPU, + CLK_CON_MUX_MUX_CLKCMU_BUSC_BUS, + CLK_CON_MUX_MUX_CLKCMU_CMU_BOOST, + CLK_CON_MUX_MUX_CLKCMU_CORE_BUS, + CLK_CON_MUX_MUX_CLKCMU_CPUCL0_CLUSTER, + CLK_CON_MUX_MUX_CLKCMU_CPUCL0_SWITCH, + CLK_CON_MUX_MUX_CLKCMU_CPUCL1_CLUSTER, + CLK_CON_MUX_MUX_CLKCMU_CPUCL1_SWITCH, + CLK_CON_MUX_MUX_CLKCMU_DPTX_BUS, + CLK_CON_MUX_MUX_CLKCMU_DPTX_DPGTC, + CLK_CON_MUX_MUX_CLKCMU_DPUM_BUS, + CLK_CON_MUX_MUX_CLKCMU_DPUS0_BUS, + CLK_CON_MUX_MUX_CLKCMU_DPUS1_BUS, + CLK_CON_MUX_MUX_CLKCMU_FSYS0_BUS, + CLK_CON_MUX_MUX_CLKCMU_FSYS0_PCIE, + CLK_CON_MUX_MUX_CLKCMU_FSYS1_BUS, + CLK_CON_MUX_MUX_CLKCMU_FSYS1_MMC_CARD, + CLK_CON_MUX_MUX_CLKCMU_FSYS1_USBDRD, + CLK_CON_MUX_MUX_CLKCMU_FSYS2_BUS, + CLK_CON_MUX_MUX_CLKCMU_FSYS2_ETHERNET, + CLK_CON_MUX_MUX_CLKCMU_FSYS2_UFS_EMBD, + CLK_CON_MUX_MUX_CLKCMU_G2D_G2D, + CLK_CON_MUX_MUX_CLKCMU_G2D_MSCL, + CLK_CON_MUX_MUX_CLKCMU_G3D00_SWITCH, + CLK_CON_MUX_MUX_CLKCMU_G3D01_SWITCH, + CLK_CON_MUX_MUX_CLKCMU_G3D1_SWITCH, + CLK_CON_MUX_MUX_CLKCMU_ISPB_BUS, + CLK_CON_MUX_MUX_CLKCMU_MFC_MFC, + CLK_CON_MUX_MUX_CLKCMU_MFC_WFD, + CLK_CON_MUX_MUX_CLKCMU_MIF_SWITCH, + CLK_CON_MUX_MUX_CLKCMU_MIF_BUSP, + CLK_CON_MUX_MUX_CLKCMU_MIF_SWITCH, + CLK_CON_MUX_MUX_CLKCMU_NPU_BUS, + CLK_CON_MUX_MUX_CLKCMU_PERIC0_BUS, + CLK_CON_MUX_MUX_CLKCMU_PERIC0_IP, + CLK_CON_MUX_MUX_CLKCMU_PERIC1_BUS, + CLK_CON_MUX_MUX_CLKCMU_PERIC1_IP, + CLK_CON_MUX_MUX_CLKCMU_PERIS_BUS, + CLK_CON_MUX_MUX_CMU_CMUREF, + CLK_CON_DIV_CLKCMU_ACC_BUS, + CLK_CON_DIV_CLKCMU_APM_BUS, + CLK_CON_DIV_CLKCMU_AUD_BUS, + CLK_CON_DIV_CLKCMU_AUD_CPU, + CLK_CON_DIV_CLKCMU_BUSC_BUS, + CLK_CON_DIV_CLKCMU_BUSMC_BUS, + CLK_CON_DIV_CLKCMU_CORE_BUS, + CLK_CON_DIV_CLKCMU_CPUCL0_CLUSTER, + CLK_CON_DIV_CLKCMU_CPUCL0_SWITCH, + CLK_CON_DIV_CLKCMU_CPUCL1_CLUSTER, + CLK_CON_DIV_CLKCMU_CPUCL1_SWITCH, + CLK_CON_DIV_CLKCMU_DPTX_BUS, + CLK_CON_DIV_CLKCMU_DPTX_DPGTC, + CLK_CON_DIV_CLKCMU_DPUM_BUS, + CLK_CON_DIV_CLKCMU_DPUS0_BUS, + CLK_CON_DIV_CLKCMU_DPUS1_BUS, + CLK_CON_DIV_CLKCMU_FSYS0_BUS, + CLK_CON_DIV_CLKCMU_FSYS0_PCIE, + CLK_CON_DIV_CLKCMU_FSYS1_BUS, + CLK_CON_DIV_CLKCMU_FSYS1_USBDRD, + CLK_CON_DIV_CLKCMU_FSYS2_BUS, + CLK_CON_DIV_CLKCMU_FSYS2_ETHERNET, + CLK_CON_DIV_CLKCMU_FSYS2_UFS_EMBD, + CLK_CON_DIV_CLKCMU_G2D_G2D, + CLK_CON_DIV_CLKCMU_G2D_MSCL, + CLK_CON_DIV_CLKCMU_G3D00_SWITCH, + CLK_CON_DIV_CLKCMU_G3D01_SWITCH, + CLK_CON_DIV_CLKCMU_G3D1_SWITCH, + CLK_CON_DIV_CLKCMU_ISPB_BUS, + CLK_CON_DIV_CLKCMU_MFC_MFC, + CLK_CON_DIV_CLKCMU_MFC_WFD, + CLK_CON_DIV_CLKCMU_MIF_BUSP, + CLK_CON_DIV_CLKCMU_NPU_BUS, + CLK_CON_DIV_CLKCMU_PERIC0_BUS, + CLK_CON_DIV_CLKCMU_PERIC0_IP, + CLK_CON_DIV_CLKCMU_PERIC1_BUS, + CLK_CON_DIV_CLKCMU_PERIC1_IP, + CLK_CON_DIV_CLKCMU_PERIS_BUS, + CLK_CON_DIV_DIV_CLKCMU_CMU_BOOST, + CLK_CON_DIV_PLL_SHARED0_DIV2, + CLK_CON_DIV_PLL_SHARED0_DIV3, + CLK_CON_DIV_PLL_SHARED1_DIV2, + CLK_CON_DIV_PLL_SHARED1_DIV3, + CLK_CON_DIV_PLL_SHARED1_DIV4, + CLK_CON_DIV_PLL_SHARED2_DIV2, + CLK_CON_DIV_PLL_SHARED2_DIV3, + CLK_CON_DIV_PLL_SHARED2_DIV4, + CLK_CON_DIV_PLL_SHARED4_DIV2, + CLK_CON_DIV_PLL_SHARED4_DIV4, + CLK_CON_GAT_CLKCMU_CMU_BUSC_BOOST, + CLK_CON_GAT_CLKCMU_CMU_BUSMC_BOOST, + CLK_CON_GAT_CLKCMU_CMU_CORE_BOOST, + CLK_CON_GAT_CLKCMU_CMU_CPUCL0_BOOST, + CLK_CON_GAT_CLKCMU_CMU_CPUCL1_BOOST, + CLK_CON_GAT_CLKCMU_CMU_MIF_BOOST, + CLK_CON_GAT_GATE_CLKCMU_FSYS1_MMC_CARD, + CLK_CON_GAT_GATE_CLKCMU_MIF_SWITCH, + CLK_CON_GAT_GATE_CLKCMU_ACC_BUS, + CLK_CON_GAT_GATE_CLKCMU_APM_BUS, + CLK_CON_GAT_GATE_CLKCMU_AUD_BUS, + CLK_CON_GAT_GATE_CLKCMU_AUD_CPU, + CLK_CON_GAT_GATE_CLKCMU_BUSC_BUS, + CLK_CON_GAT_GATE_CLKCMU_BUSMC_BUS, + CLK_CON_GAT_GATE_CLKCMU_CMU_BOOST, + CLK_CON_GAT_GATE_CLKCMU_CORE_BUS, + CLK_CON_GAT_GATE_CLKCMU_CPUCL0_CLUSTER, + CLK_CON_GAT_GATE_CLKCMU_CPUCL0_SWITCH, + CLK_CON_GAT_GATE_CLKCMU_CPUCL1_CLUSTER, + CLK_CON_GAT_GATE_CLKCMU_CPUCL1_SWITCH, + CLK_CON_GAT_GATE_CLKCMU_DPTX_BUS, + CLK_CON_GAT_GATE_CLKCMU_DPTX_DPGTC, + CLK_CON_GAT_GATE_CLKCMU_DPUM_BUS, + CLK_CON_GAT_GATE_CLKCMU_DPUS0_BUS, + CLK_CON_GAT_GATE_CLKCMU_DPUS1_BUS, + CLK_CON_GAT_GATE_CLKCMU_FSYS0_BUS, + CLK_CON_GAT_GATE_CLKCMU_FSYS0_PCIE, + CLK_CON_GAT_GATE_CLKCMU_FSYS1_BUS, + CLK_CON_GAT_GATE_CLKCMU_FSYS1_USBDRD, + CLK_CON_GAT_GATE_CLKCMU_FSYS2_BUS, + CLK_CON_GAT_GATE_CLKCMU_FSYS2_ETHERNET, + CLK_CON_GAT_GATE_CLKCMU_FSYS2_UFS_EMBD, + CLK_CON_GAT_GATE_CLKCMU_G2D_G2D, + CLK_CON_GAT_GATE_CLKCMU_G2D_MSCL, + CLK_CON_GAT_GATE_CLKCMU_G3D00_SWITCH, + CLK_CON_GAT_GATE_CLKCMU_G3D01_SWITCH, + CLK_CON_GAT_GATE_CLKCMU_G3D1_SWITCH, + CLK_CON_GAT_GATE_CLKCMU_ISPB_BUS, + CLK_CON_GAT_GATE_CLKCMU_MFC_MFC, + CLK_CON_GAT_GATE_CLKCMU_MFC_WFD, + CLK_CON_GAT_GATE_CLKCMU_MIF_BUSP, + CLK_CON_GAT_GATE_CLKCMU_NPU_BUS, + CLK_CON_GAT_GATE_CLKCMU_PERIC0_BUS, + CLK_CON_GAT_GATE_CLKCMU_PERIC0_IP, + CLK_CON_GAT_GATE_CLKCMU_PERIC1_BUS, + CLK_CON_GAT_GATE_CLKCMU_PERIC1_IP, + CLK_CON_GAT_GATE_CLKCMU_PERIS_BUS, +}; + +static const struct samsung_pll_clock top_pll_clks[] __initconst = { + /* CMU_TOP_PURECLKCOMP */ + PLL(pll_0822x, FOUT_SHARED0_PLL, "fout_shared0_pll", "oscclk", + PLL_LOCKTIME_PLL_SHARED0, PLL_CON3_PLL_SHARED0, NULL), + PLL(pll_0822x, FOUT_SHARED0_PLL, "fout_shared1_pll", "oscclk", + PLL_LOCKTIME_PLL_SHARED1, PLL_CON3_PLL_SHARED1, NULL), + PLL(pll_0822x, FOUT_SHARED0_PLL, "fout_shared2_pll", "oscclk", + PLL_LOCKTIME_PLL_SHARED2, PLL_CON3_PLL_SHARED2, NULL), + PLL(pll_0822x, FOUT_SHARED0_PLL, "fout_shared3_pll", "oscclk", + PLL_LOCKTIME_PLL_SHARED3, PLL_CON3_PLL_SHARED3, NULL), + PLL(pll_0822x, FOUT_SHARED0_PLL, "fout_shared4_pll", "oscclk", + PLL_LOCKTIME_PLL_SHARED4, PLL_CON3_PLL_SHARED4, NULL), +}; + +/* List of parent clocks for Muxes in CMU_TOP */ +PNAME(mout_shared0_pll_p) = { "oscclk", "fout_shared0_pll" }; +PNAME(mout_shared1_pll_p) = { "oscclk", "fout_shared1_pll" }; +PNAME(mout_shared2_pll_p) = { "oscclk", "fout_shared2_pll" }; +PNAME(mout_shared3_pll_p) = { "oscclk", "fout_shared3_pll" }; +PNAME(mout_shared4_pll_p) = { "oscclk", "fout_shared4_pll" }; + +PNAME(mout_clkcmu_cmu_boost_p) = { "dout_shared2_div3", "dout_shared1_div4", + "dout_shared2_div4", "dout_shared4_div4" }; +PNAME(mout_clkcmu_cmu_cmuref_p) = { "oscclk", "dout_cmu_boost" }; +PNAME(mout_clkcmu_acc_bus_p) = { "dout_shared1_div3", "dout_shared2_div3", + "dout_shared1_div4", "dout_shared2_div4" }; +PNAME(mout_clkcmu_apm_bus_p) = { "dout_shared2_div3", "dout_shared1_div4", + "dout_shared2_div4", "dout_shared4_div4" }; +PNAME(mout_clkcmu_aud_cpu_p) = { "dout_shared0_div2", "dout_shared1_div2", + "dout_shared2_div2", "dout_shared0_div3", + "dout_shared4_div2", "dout_shared1_div3", + "fout_shared3_pll" }; +PNAME(mout_clkcmu_aud_bus_p) = { "dout_shared4_div2", "dout_shared1_div3", + "dout_shared2_div3", "dout_shared1_div4" }; +PNAME(mout_clkcmu_busc_bus_p) = { "dout_shared2_div3", "dout_shared1_div4", + "dout_shared2_div4", "dout_shared4_div4" }; +PNAME(mout_clkcmu_core_bus_p) = { "dout_shared0_div2", "dout_shared1_div2", + "dout_shared2_div2", "dout_shared0_div3", + "dout_shared4_div2", "dout_shared1_div3", + "dout_shared2_div3", "fout_shared3_pll" }; +PNAME(mout_clkcmu_cpucl0_switch_p) = { + "dout_shared0_div2", "dout_shared1_div2", + "dout_shared2_div2", "dout_shared4_div2" }; +PNAME(mout_clkcmu_cpucl0_cluster_p) = { + "fout_shared2_pll", "fout_shared4_pll", + "dout_shared0_div2", "dout_shared1_div2", + "dout_shared2_div2", "dout_shared4_div2", + "dout_shared2_div3", "fout_shared3_pll" }; +PNAME(mout_clkcmu_dptx_bus_p) = { "dout_shared4_div2", "dout_shared2_div3", + "dout_shared1_div4", "dout_shared2_div4" }; +PNAME(mout_clkcmu_dptx_dpgtc_p) = { "oscclk", "dout_shared2_div3", + "dout_shared2_div4", "dout_shared4_div4" }; +PNAME(mout_clkcmu_dpum_bus_p) = { "dout_shared1_div3", "dout_shared2_div3", + "dout_shared1_div4", "dout_shared2_div4", + "dout_shared4_div4", "fout_shared3_pll" }; +PNAME(mout_clkcmu_fsys0_bus_p) = { + "dout_shared4_div2", "dout_shared2_div3", + "dout_shared1_div4", "dout_shared2_div4" }; +PNAME(mout_clkcmu_fsys0_pcie_p) = { "oscclk", "dout_shared2_div4" }; +PNAME(mout_clkcmu_fsys1_bus_p) = { "dout_shared2_div3", "dout_shared1_div4", + "dout_shared2_div4", "dout_shared4_div4" }; +PNAME(mout_clkcmu_fsys1_usbdrd_p) = { + "oscclk", "dout_shared2_div3", + "dout_shared2_div4", "dout_shared4_div4" }; +PNAME(mout_clkcmu_fsys1_mmc_card_p) = { + "oscclk", "dout_shared2_div2", + "dout_shared4_div2", "dout_shared2_div3" }; +PNAME(mout_clkcmu_fsys2_ethernet_p) = { + "oscclk", "dout_shared2_div2", + "dout_shared0_div3", "dout_shared2_div3", + "dout_shared1_div4", "fout_shared3_pll" }; +PNAME(mout_clkcmu_g2d_g2d_p) = { "dout_shared2_div2", "dout_shared0_div3", + "dout_shared4_div2", "dout_shared1_div3", + "dout_shared2_div3", "dout_shared1_div4", + "dout_shared2_div4", "dout_shared4_div4" }; +PNAME(mout_clkcmu_g3d0_switch_p) = { "dout_shared0_div2", "dout_shared1_div2", + "dout_shared2_div2", "dout_shared4_div2" }; +PNAME(mout_clkcmu_g3d1_switch_p) = { "dout_shared2_div2", "dout_shared4_div2", + "dout_shared2_div3", "dout_shared1_div4" }; +PNAME(mout_clkcmu_mif_switch_p) = { "fout_shared0_pll", "fout_shared1_pll", + "fout_shared2_pll", "fout_shared4_pll", + "dout_shared0_div2", "dout_shared1_div2", + "dout_shared2_div2", "fout_shared3_pll" }; +PNAME(mout_clkcmu_npu_bus_p) = { "dout_shared1_div2", "dout_shared2_div2", + "dout_shared0_div3", "dout_shared4_div2", + "dout_shared1_div3", "dout_shared2_div3", + "dout_shared1_div4", "fout_shared3_pll" }; +PNAME(mout_clkcmu_peric0_bus_p) = { "dout_shared2_div3", "dout_shared2_div4" }; + +static const struct samsung_mux_clock top_mux_clks[] __initconst = { + /* CMU_TOP_PURECLKCOMP */ + MUX(MOUT_SHARED0_PLL, "mout_shared0_pll", mout_shared0_pll_p, + PLL_CON0_PLL_SHARED0, 4, 1), + MUX(MOUT_SHARED1_PLL, "mout_shared1_pll", mout_shared1_pll_p, + PLL_CON0_PLL_SHARED1, 4, 1), + MUX(MOUT_SHARED2_PLL, "mout_shared2_pll", mout_shared2_pll_p, + PLL_CON0_PLL_SHARED2, 4, 1), + MUX(MOUT_SHARED3_PLL, "mout_shared3_pll", mout_shared3_pll_p, + PLL_CON0_PLL_SHARED3, 4, 1), + MUX(MOUT_SHARED4_PLL, "mout_shared4_pll", mout_shared4_pll_p, + PLL_CON0_PLL_SHARED4, 4, 1), + + /* BOOST */ + MUX(MOUT_CLKCMU_CMU_BOOST, "mout_clkcmu_cmu_boost", + mout_clkcmu_cmu_boost_p, CLK_CON_MUX_MUX_CLKCMU_CMU_BOOST, 0, 2), + MUX(MOUT_CLKCMU_CMU_CMUREF, "mout_clkcmu_cmu_cmuref", + mout_clkcmu_cmu_cmuref_p, CLK_CON_MUX_MUX_CMU_CMUREF, 0, 1), + + /* ACC */ + MUX(MOUT_CLKCMU_ACC_BUS, "mout_clkcmu_acc_bus", mout_clkcmu_acc_bus_p, + CLK_CON_MUX_MUX_CLKCMU_ACC_BUS, 0, 2), + + /* APM */ + MUX(MOUT_CLKCMU_APM_BUS, "mout_clkcmu_apm_bus", mout_clkcmu_apm_bus_p, + CLK_CON_MUX_MUX_CLKCMU_APM_BUS, 0, 2), + + /* AUD */ + MUX(MOUT_CLKCMU_AUD_CPU, "mout_clkcmu_aud_cpu", mout_clkcmu_aud_cpu_p, + CLK_CON_MUX_MUX_CLKCMU_AUD_CPU, 0, 3), + MUX(MOUT_CLKCMU_AUD_BUS, "mout_clkcmu_aud_bus", mout_clkcmu_aud_bus_p, + CLK_CON_MUX_MUX_CLKCMU_AUD_BUS, 0, 2), + + /* BUSC */ + MUX(MOUT_CLKCMU_BUSC_BUS, "mout_clkcmu_busc_bus", + mout_clkcmu_busc_bus_p, CLK_CON_MUX_MUX_CLKCMU_BUSC_BUS, 0, 2), + + /* BUSMC */ + MUX(MOUT_CLKCMU_BUSMC_BUS, "mout_clkcmu_busmc_bus", + mout_clkcmu_busc_bus_p, CLK_CON_MUX_MUX_CLKCMU_BUSMC_BUS, 0, 2), + + /* CORE */ + MUX(MOUT_CLKCMU_CORE_BUS, "mout_clkcmu_core_bus", + mout_clkcmu_core_bus_p, CLK_CON_MUX_MUX_CLKCMU_CORE_BUS, 0, 3), + + /* CPUCL0 */ + MUX(MOUT_CLKCMU_CPUCL0_SWITCH, "mout_clkcmu_cpucl0_switch", + mout_clkcmu_cpucl0_switch_p, CLK_CON_MUX_MUX_CLKCMU_CPUCL0_SWITCH, + 0, 2), + MUX(MOUT_CLKCMU_CPUCL0_CLUSTER, "mout_clkcmu_cpucl0_cluster", + mout_clkcmu_cpucl0_cluster_p, + CLK_CON_MUX_MUX_CLKCMU_CPUCL0_CLUSTER, 0, 3), + + /* CPUCL1 */ + MUX(MOUT_CLKCMU_CPUCL1_SWITCH, "mout_clkcmu_cpucl1_switch", + mout_clkcmu_cpucl0_switch_p, CLK_CON_MUX_MUX_CLKCMU_CPUCL1_SWITCH, + 0, 2), + MUX(MOUT_CLKCMU_CPUCL1_CLUSTER, "mout_clkcmu_cpucl1_cluster", + mout_clkcmu_cpucl0_cluster_p, + CLK_CON_MUX_MUX_CLKCMU_CPUCL1_CLUSTER, 0, 3), + + /* DPTX */ + MUX(MOUT_CLKCMU_DPTX_BUS, "mout_clkcmu_dptx_bus", + mout_clkcmu_dptx_bus_p, CLK_CON_MUX_MUX_CLKCMU_DPTX_BUS, 0, 2), + MUX(MOUT_CLKCMU_DPTX_DPGTC, "mout_clkcmu_dptx_dpgtc", + mout_clkcmu_dptx_dpgtc_p, CLK_CON_MUX_MUX_CLKCMU_DPTX_DPGTC, 0, 2), + + /* DPUM */ + MUX(MOUT_CLKCMU_DPUM_BUS, "mout_clkcmu_dpum_bus", + mout_clkcmu_dpum_bus_p, CLK_CON_MUX_MUX_CLKCMU_DPUM_BUS, 0, 3), + + /* DPUS */ + MUX(MOUT_CLKCMU_DPUS0_BUS, "mout_clkcmu_dpus0_bus", + mout_clkcmu_dpum_bus_p, CLK_CON_MUX_MUX_CLKCMU_DPUS0_BUS, 0, 3), + MUX(MOUT_CLKCMU_DPUS1_BUS, "mout_clkcmu_dpus1_bus", + mout_clkcmu_dpum_bus_p, CLK_CON_MUX_MUX_CLKCMU_DPUS1_BUS, 0, 3), + + /* FSYS0 */ + MUX(MOUT_CLKCMU_FSYS0_BUS, "mout_clkcmu_fsys0_bus", + mout_clkcmu_fsys0_bus_p, CLK_CON_MUX_MUX_CLKCMU_FSYS0_BUS, 0, 2), + MUX(MOUT_CLKCMU_FSYS0_PCIE, "mout_clkcmu_fsys0_pcie", + mout_clkcmu_fsys0_pcie_p, CLK_CON_MUX_MUX_CLKCMU_FSYS0_PCIE, 0, 1), + + /* FSYS1 */ + MUX(MOUT_CLKCMU_FSYS1_BUS, "mout_clkcmu_fsys1_bus", + mout_clkcmu_fsys1_bus_p, CLK_CON_MUX_MUX_CLKCMU_FSYS1_BUS, 0, 2), + MUX(MOUT_CLKCMU_FSYS1_USBDRD, "mout_clkcmu_fsys1_usbdrd", + mout_clkcmu_fsys1_usbdrd_p, CLK_CON_MUX_MUX_CLKCMU_FSYS1_USBDRD, + 0, 2), + MUX(MOUT_CLKCMU_FSYS1_MMC_CARD, "mout_clkcmu_fsys1_mmc_card", + mout_clkcmu_fsys1_mmc_card_p, + CLK_CON_MUX_MUX_CLKCMU_FSYS1_MMC_CARD, 0, 2), + + /* FSYS2 */ + MUX(MOUT_CLKCMU_FSYS2_BUS, "mout_clkcmu_fsys2_bus", + mout_clkcmu_fsys0_bus_p, CLK_CON_MUX_MUX_CLKCMU_FSYS2_BUS, 0, 2), + MUX(MOUT_CLKCMU_FSYS2_UFS_EMBD, "mout_clkcmu_fsys2_ufs_embd", + mout_clkcmu_fsys1_usbdrd_p, CLK_CON_MUX_MUX_CLKCMU_FSYS2_UFS_EMBD, + 0, 2), + MUX(MOUT_CLKCMU_FSYS2_ETHERNET, "mout_clkcmu_fsys2_ethernet", + mout_clkcmu_fsys2_ethernet_p, + CLK_CON_MUX_MUX_CLKCMU_FSYS2_ETHERNET, 0, 3), + + /* G2D */ + MUX(MOUT_CLKCMU_G2D_G2D, "mout_clkcmu_g2d_g2d", mout_clkcmu_g2d_g2d_p, + CLK_CON_MUX_MUX_CLKCMU_G2D_G2D, 0, 3), + MUX(MOUT_CLKCMU_G2D_MSCL, "mout_clkcmu_g2d_mscl", + mout_clkcmu_fsys1_bus_p, CLK_CON_MUX_MUX_CLKCMU_G2D_MSCL, 0, 2), + + /* G3D0 */ + MUX(MOUT_CLKCMU_G3D00_SWITCH, "mout_clkcmu_g3d00_switch", + mout_clkcmu_g3d0_switch_p, CLK_CON_MUX_MUX_CLKCMU_G3D00_SWITCH, + 0, 2), + MUX(MOUT_CLKCMU_G3D01_SWITCH, "mout_clkcmu_g3d01_switch", + mout_clkcmu_g3d0_switch_p, CLK_CON_MUX_MUX_CLKCMU_G3D01_SWITCH, + 0, 2), + + /* G3D1 */ + MUX(MOUT_CLKCMU_G3D1_SWITCH, "mout_clkcmu_g3d1_switch", + mout_clkcmu_g3d1_switch_p, CLK_CON_MUX_MUX_CLKCMU_G3D1_SWITCH, + 0, 2), + + /* ISPB */ + MUX(MOUT_CLKCMU_ISPB_BUS, "mout_clkcmu_ispb_bus", + mout_clkcmu_acc_bus_p, CLK_CON_MUX_MUX_CLKCMU_ISPB_BUS, 0, 2), + + /* MFC */ + MUX(MOUT_CLKCMU_MFC_MFC, "mout_clkcmu_mfc_mfc", + mout_clkcmu_g3d1_switch_p, CLK_CON_MUX_MUX_CLKCMU_MFC_MFC, 0, 2), + MUX(MOUT_CLKCMU_MFC_WFD, "mout_clkcmu_mfc_wfd", + mout_clkcmu_fsys0_bus_p, CLK_CON_MUX_MUX_CLKCMU_MFC_WFD, 0, 2), + + /* MIF */ + MUX(MOUT_CLKCMU_MIF_SWITCH, "mout_clkcmu_mif_switch", + mout_clkcmu_mif_switch_p, CLK_CON_MUX_MUX_CLKCMU_MIF_SWITCH, 0, 3), + MUX(MOUT_CLKCMU_MIF_BUSP, "mout_clkcmu_mif_busp", + mout_clkcmu_fsys1_bus_p, CLK_CON_MUX_MUX_CLKCMU_MIF_BUSP, 0, 2), + + /* NPU */ + MUX(MOUT_CLKCMU_NPU_BUS, "mout_clkcmu_npu_bus", mout_clkcmu_npu_bus_p, + CLK_CON_MUX_MUX_CLKCMU_NPU_BUS, 0, 3), + + /* PERIC0 */ + MUX(MOUT_CLKCMU_PERIC0_BUS, "mout_clkcmu_peric0_bus", + mout_clkcmu_peric0_bus_p, CLK_CON_MUX_MUX_CLKCMU_PERIC0_BUS, 0, 1), + MUX(MOUT_CLKCMU_PERIC0_IP, "mout_clkcmu_peric0_ip", + mout_clkcmu_peric0_bus_p, CLK_CON_MUX_MUX_CLKCMU_PERIC0_IP, 0, 1), + + /* PERIC1 */ + MUX(MOUT_CLKCMU_PERIC1_BUS, "mout_clkcmu_peric1_bus", + mout_clkcmu_peric0_bus_p, CLK_CON_MUX_MUX_CLKCMU_PERIC1_BUS, 0, 1), + MUX(MOUT_CLKCMU_PERIC1_IP, "mout_clkcmu_peric1_ip", + mout_clkcmu_peric0_bus_p, CLK_CON_MUX_MUX_CLKCMU_PERIC1_IP, 0, 1), + + /* PERIS */ + MUX(MOUT_CLKCMU_PERIS_BUS, "mout_clkcmu_peris_bus", + mout_clkcmu_peric0_bus_p, CLK_CON_MUX_MUX_CLKCMU_PERIS_BUS, 0, 1), +}; + +static const struct samsung_div_clock top_div_clks[] __initconst = { + /* CMU_TOP_PURECLKCOMP */ + DIV(DOUT_SHARED0_DIV3, "dout_shared0_div3", "mout_shared0_pll", + CLK_CON_DIV_PLL_SHARED0_DIV3, 0, 2), + DIV(DOUT_SHARED0_DIV2, "dout_shared0_div2", "mout_shared0_pll", + CLK_CON_DIV_PLL_SHARED0_DIV2, 0, 1), + + DIV(DOUT_SHARED1_DIV3, "dout_shared1_div3", "mout_shared1_pll", + CLK_CON_DIV_PLL_SHARED1_DIV3, 0, 2), + DIV(DOUT_SHARED1_DIV2, "dout_shared1_div2", "mout_shared1_pll", + CLK_CON_DIV_PLL_SHARED1_DIV2, 0, 1), + DIV(DOUT_SHARED1_DIV4, "dout_shared1_div4", "dout_shared1_div2", + CLK_CON_DIV_PLL_SHARED1_DIV4, 0, 1), + + DIV(DOUT_SHARED2_DIV3, "dout_shared2_div3", "mout_shared2_pll", + CLK_CON_DIV_PLL_SHARED2_DIV3, 0, 2), + DIV(DOUT_SHARED2_DIV2, "dout_shared2_div2", "mout_shared2_pll", + CLK_CON_DIV_PLL_SHARED2_DIV2, 0, 1), + DIV(DOUT_SHARED2_DIV4, "dout_shared2_div4", "dout_shared2_div2", + CLK_CON_DIV_PLL_SHARED2_DIV4, 0, 1), + + DIV(DOUT_SHARED4_DIV2, "dout_shared4_div2", "mout_shared4_pll", + CLK_CON_DIV_PLL_SHARED4_DIV2, 0, 1), + DIV(DOUT_SHARED4_DIV4, "dout_shared4_div4", "dout_shared4_div2", + CLK_CON_DIV_PLL_SHARED4_DIV4, 0, 1), + + /* BOOST */ + DIV(DOUT_CLKCMU_CMU_BOOST, "dout_clkcmu_cmu_boost", + "gout_clkcmu_cmu_boost", CLK_CON_DIV_DIV_CLKCMU_CMU_BOOST, 0, 2), + + /* ACC */ + DIV(DOUT_CLKCMU_ACC_BUS, "dout_clkcmu_acc_bus", "gout_clkcmu_acc_bus", + CLK_CON_DIV_CLKCMU_ACC_BUS, 0, 4), + + /* APM */ + DIV(DOUT_CLKCMU_APM_BUS, "dout_clkcmu_apm_bus", "gout_clkcmu_apm_bus", + CLK_CON_DIV_CLKCMU_APM_BUS, 0, 3), + + /* AUD */ + DIV(DOUT_CLKCMU_AUD_CPU, "dout_clkcmu_aud_cpu", "gout_clkcmu_aud_cpu", + CLK_CON_DIV_CLKCMU_AUD_CPU, 0, 3), + DIV(DOUT_CLKCMU_AUD_BUS, "dout_clkcmu_aud_bus", "gout_clkcmu_aud_bus", + CLK_CON_DIV_CLKCMU_AUD_BUS, 0, 4), + + /* BUSC */ + DIV(DOUT_CLKCMU_BUSC_BUS, "dout_clkcmu_busc_bus", + "gout_clkcmu_busc_bus", CLK_CON_DIV_CLKCMU_BUSC_BUS, 0, 4), + + /* BUSMC */ + DIV(DOUT_CLKCMU_BUSMC_BUS, "dout_clkcmu_busmc_bus", + "gout_clkcmu_busmc_bus", CLK_CON_DIV_CLKCMU_BUSMC_BUS, 0, 4), + + /* CORE */ + DIV(DOUT_CLKCMU_CORE_BUS, "dout_clkcmu_core_bus", + "gout_clkcmu_core_bus", CLK_CON_DIV_CLKCMU_CORE_BUS, 0, 4), + + /* CPUCL0 */ + DIV(DOUT_CLKCMU_CPUCL0_SWITCH, "dout_clkcmu_cpucl0_switch", + "gout_clkcmu_cpucl0_switch", CLK_CON_DIV_CLKCMU_CPUCL0_SWITCH, + 0, 3), + DIV(DOUT_CLKCMU_CPUCL0_CLUSTER, "dout_clkcmu_cpucl0_cluster", + "gout_clkcmu_cpucl0_cluster", CLK_CON_DIV_CLKCMU_CPUCL0_CLUSTER, + 0, 3), + + /* CPUCL1 */ + DIV(DOUT_CLKCMU_CPUCL1_SWITCH, "dout_clkcmu_cpucl1_switch", + "gout_clkcmu_cpucl1_switch", CLK_CON_DIV_CLKCMU_CPUCL1_SWITCH, + 0, 3), + DIV(DOUT_CLKCMU_CPUCL1_CLUSTER, "dout_clkcmu_cpucl1_cluster", + "gout_clkcmu_cpucl1_cluster", CLK_CON_DIV_CLKCMU_CPUCL1_CLUSTER, + 0, 3), + + /* DPTX */ + DIV(DOUT_CLKCMU_DPTX_BUS, "dout_clkcmu_dptx_bus", + "gout_clkcmu_dptx_bus", CLK_CON_DIV_CLKCMU_DPTX_BUS, 0, 4), + DIV(DOUT_CLKCMU_DPTX_DPGTC, "dout_clkcmu_dptx_dpgtc", + "gout_clkcmu_dptx_dpgtc", CLK_CON_DIV_CLKCMU_DPTX_DPGTC, 0, 3), + + /* DPUM */ + DIV(DOUT_CLKCMU_DPUM_BUS, "dout_clkcmu_dpum_bus", + "gout_clkcmu_dpum_bus", CLK_CON_DIV_CLKCMU_DPUM_BUS, 0, 4), + + /* DPUS */ + DIV(DOUT_CLKCMU_DPUS0_BUS, "dout_clkcmu_dpus0_bus", + "gout_clkcmu_dpus0_bus", CLK_CON_DIV_CLKCMU_DPUS0_BUS, 0, 4), + DIV(DOUT_CLKCMU_DPUS1_BUS, "dout_clkcmu_dpus1_bus", + "gout_clkcmu_dpus1_bus", CLK_CON_DIV_CLKCMU_DPUS1_BUS, 0, 4), + + /* FSYS0 */ + DIV(DOUT_CLKCMU_FSYS0_BUS, "dout_clkcmu_fsys0_bus", + "gout_clkcmu_fsys0_bus", CLK_CON_DIV_CLKCMU_FSYS0_BUS, 0, 4), + + /* FSYS1 */ + DIV(DOUT_CLKCMU_FSYS1_BUS, "dout_clkcmu_fsys1_bus", + "gout_clkcmu_fsys1_bus", CLK_CON_DIV_CLKCMU_FSYS1_BUS, 0, 4), + DIV(DOUT_CLKCMU_FSYS1_USBDRD, "dout_clkcmu_fsys1_usbdrd", + "gout_clkcmu_fsys1_usbdrd", CLK_CON_DIV_CLKCMU_FSYS1_USBDRD, 0, 4), + + /* FSYS2 */ + DIV(DOUT_CLKCMU_FSYS2_BUS, "dout_clkcmu_fsys2_bus", + "gout_clkcmu_fsys2_bus", CLK_CON_DIV_CLKCMU_FSYS2_BUS, 0, 4), + DIV(DOUT_CLKCMU_FSYS2_UFS_EMBD, "dout_clkcmu_fsys2_ufs_embd", + "gout_clkcmu_fsys2_ufs_embd", CLK_CON_DIV_CLKCMU_FSYS2_UFS_EMBD, + 0, 3), + DIV(DOUT_CLKCMU_FSYS2_ETHERNET, "dout_clkcmu_fsys2_ethernet", + "gout_clkcmu_fsys2_ethernet", CLK_CON_DIV_CLKCMU_FSYS2_ETHERNET, + 0, 3), + + /* G2D */ + DIV(DOUT_CLKCMU_G2D_G2D, "dout_clkcmu_g2d_g2d", "gout_clkcmu_g2d_g2d", + CLK_CON_DIV_CLKCMU_G2D_G2D, 0, 4), + DIV(DOUT_CLKCMU_G2D_MSCL, "dout_clkcmu_g2d_mscl", + "gout_clkcmu_g2d_mscl", CLK_CON_DIV_CLKCMU_G2D_MSCL, 0, 4), + + /* G3D0 */ + DIV(DOUT_CLKCMU_G3D00_SWITCH, "dout_clkcmu_g3d00_switch", + "gout_clkcmu_g3d00_switch", CLK_CON_DIV_CLKCMU_G3D00_SWITCH, 0, 3), + DIV(DOUT_CLKCMU_G3D01_SWITCH, "dout_clkcmu_g3d01_switch", + "gout_clkcmu_g3d01_switch", CLK_CON_DIV_CLKCMU_G3D01_SWITCH, 0, 3), + + /* G3D1 */ + DIV(DOUT_CLKCMU_G3D1_SWITCH, "dout_clkcmu_g3d1_switch", + "gout_clkcmu_g3d1_switch", CLK_CON_DIV_CLKCMU_G3D1_SWITCH, 0, 3), + + /* ISPB */ + DIV(DOUT_CLKCMU_ISPB_BUS, "dout_clkcmu_ispb_bus", + "gout_clkcmu_ispb_bus", CLK_CON_DIV_CLKCMU_ISPB_BUS, 0, 4), + + /* MFC */ + DIV(DOUT_CLKCMU_MFC_MFC, "dout_clkcmu_mfc_mfc", "gout_clkcmu_mfc_mfc", + CLK_CON_DIV_CLKCMU_MFC_MFC, 0, 4), + DIV(DOUT_CLKCMU_MFC_WFD, "dout_clkcmu_mfc_wfd", "gout_clkcmu_mfc_wfd", + CLK_CON_DIV_CLKCMU_MFC_WFD, 0, 4), + + /* MIF */ + DIV(DOUT_CLKCMU_MIF_BUSP, "dout_clkcmu_mif_busp", + "gout_clkcmu_mif_busp", CLK_CON_DIV_CLKCMU_MIF_BUSP, 0, 4), + + /* NPU */ + DIV(DOUT_CLKCMU_NPU_BUS, "dout_clkcmu_npu_bus", "gout_clkcmu_npu_bus", + CLK_CON_DIV_CLKCMU_NPU_BUS, 0, 4), + + /* PERIC0 */ + DIV(DOUT_CLKCMU_PERIC0_BUS, "dout_clkcmu_peric0_bus", + "gout_clkcmu_peric0_bus", CLK_CON_DIV_CLKCMU_PERIC0_BUS, 0, 4), + DIV(DOUT_CLKCMU_PERIC0_IP, "dout_clkcmu_peric0_ip", + "gout_clkcmu_peric0_ip", CLK_CON_DIV_CLKCMU_PERIC0_IP, 0, 4), + + /* PERIC1 */ + DIV(DOUT_CLKCMU_PERIC1_BUS, "dout_clkcmu_peric1_bus", + "gout_clkcmu_peric1_bus", CLK_CON_DIV_CLKCMU_PERIC1_BUS, 0, 4), + DIV(DOUT_CLKCMU_PERIC1_IP, "dout_clkcmu_peric1_ip", + "gout_clkcmu_peric1_ip", CLK_CON_DIV_CLKCMU_PERIC1_IP, 0, 4), + + /* PERIS */ + DIV(DOUT_CLKCMU_PERIS_BUS, "dout_clkcmu_peris_bus", + "gout_clkcmu_peris_bus", CLK_CON_DIV_CLKCMU_PERIS_BUS, 0, 4), +}; + +static const struct samsung_fixed_factor_clock top_fixed_factor_clks[] __initconst = { + FFACTOR(DOUT_CLKCMU_FSYS0_PCIE, "dout_clkcmu_fsys0_pcie", + "gout_clkcmu_fsys0_pcie", 1, 4, 0), +}; + +static const struct samsung_gate_clock top_gate_clks[] __initconst = { + /* BOOST */ + GATE(GOUT_CLKCMU_CMU_BOOST, "gout_clkcmu_cmu_boost", + "mout_clkcmu_cmu_boost", CLK_CON_GAT_GATE_CLKCMU_CMU_BOOST, + 21, 0, 0), + + GATE(GOUT_CLKCMU_CPUCL0_BOOST, "gout_clkcmu_cpucl0_boost", + "dout_cmu_boost", CLK_CON_GAT_CLKCMU_CMU_CPUCL0_BOOST, 21, 0, 0), + GATE(GOUT_CLKCMU_CPUCL1_BOOST, "gout_clkcmu_cpucl1_boost", + "dout_cmu_boost", CLK_CON_GAT_CLKCMU_CMU_CPUCL1_BOOST, 21, 0, 0), + GATE(GOUT_CLKCMU_CORE_BOOST, "gout_clkcmu_core_boost", + "dout_cmu_boost", CLK_CON_GAT_CLKCMU_CMU_CORE_BOOST, 21, 0, 0), + GATE(GOUT_CLKCMU_BUSC_BOOST, "gout_clkcmu_busc_boost", + "dout_cmu_boost", CLK_CON_GAT_CLKCMU_CMU_BUSC_BOOST, 21, 0, 0), + + GATE(GOUT_CLKCMU_BUSMC_BOOST, "gout_clkcmu_busmc_boost", + "dout_cmu_boost", CLK_CON_GAT_CLKCMU_CMU_BUSMC_BOOST, 21, 0, 0), + GATE(GOUT_CLKCMU_MIF_BOOST, "gout_clkcmu_mif_boost", "dout_cmu_boost", + CLK_CON_GAT_CLKCMU_CMU_MIF_BOOST, 21, 0, 0), + + /* ACC */ + GATE(GOUT_CLKCMU_ACC_BUS, "gout_clkcmu_acc_bus", "mout_clkcmu_acc_bus", + CLK_CON_GAT_GATE_CLKCMU_ACC_BUS, 21, 0, 0), + + /* APM */ + GATE(GOUT_CLKCMU_APM_BUS, "gout_clkcmu_apm_bus", "mout_clkcmu_apm_bus", + CLK_CON_GAT_GATE_CLKCMU_APM_BUS, 21, CLK_IGNORE_UNUSED, 0), + + /* AUD */ + GATE(GOUT_CLKCMU_AUD_CPU, "gout_clkcmu_aud_cpu", "mout_clkcmu_aud_cpu", + CLK_CON_GAT_GATE_CLKCMU_AUD_CPU, 21, 0, 0), + GATE(GOUT_CLKCMU_AUD_BUS, "gout_clkcmu_aud_bus", "mout_clkcmu_aud_bus", + CLK_CON_GAT_GATE_CLKCMU_AUD_BUS, 21, 0, 0), + + /* BUSC */ + GATE(GOUT_CLKCMU_BUSC_BUS, "gout_clkcmu_busc_bus", + "mout_clkcmu_busc_bus", CLK_CON_GAT_GATE_CLKCMU_BUSC_BUS, 21, + CLK_IS_CRITICAL, 0), + + /* BUSMC */ + GATE(GOUT_CLKCMU_BUSMC_BUS, "gout_clkcmu_busmc_bus", + "mout_clkcmu_busmc_bus", CLK_CON_GAT_GATE_CLKCMU_BUSMC_BUS, 21, + CLK_IS_CRITICAL, 0), + + /* CORE */ + GATE(GOUT_CLKCMU_CORE_BUS, "gout_clkcmu_core_bus", + "mout_clkcmu_core_bus", CLK_CON_GAT_GATE_CLKCMU_CORE_BUS, + 21, 0, 0), + + /* CPUCL0 */ + GATE(GOUT_CLKCMU_CPUCL0_SWITCH, "gout_clkcmu_cpucl0_switch", + "mout_clkcmu_cpucl0_switch", + CLK_CON_GAT_GATE_CLKCMU_CPUCL0_SWITCH, 21, CLK_IGNORE_UNUSED, 0), + GATE(GOUT_CLKCMU_CPUCL0_CLUSTER, "gout_clkcmu_cpucl0_cluster", + "mout_clkcmu_cpucl0_cluster", + CLK_CON_GAT_GATE_CLKCMU_CPUCL0_CLUSTER, 21, CLK_IGNORE_UNUSED, 0), + + /* CPUCL1 */ + GATE(GOUT_CLKCMU_CPUCL1_SWITCH, "gout_clkcmu_cpucl1_switch", + "mout_clkcmu_cpucl1_switch", + CLK_CON_GAT_GATE_CLKCMU_CPUCL1_SWITCH, 21, CLK_IGNORE_UNUSED, 0), + GATE(GOUT_CLKCMU_CPUCL1_CLUSTER, "gout_clkcmu_cpucl1_cluster", + "mout_clkcmu_cpucl1_cluster", + CLK_CON_GAT_GATE_CLKCMU_CPUCL1_CLUSTER, 21, CLK_IGNORE_UNUSED, 0), + + /* DPTX */ + GATE(GOUT_CLKCMU_DPTX_BUS, "gout_clkcmu_dptx_bus", + "mout_clkcmu_dptx_bus", CLK_CON_GAT_GATE_CLKCMU_DPTX_BUS, + 21, 0, 0), + GATE(GOUT_CLKCMU_DPTX_DPGTC, "gout_clkcmu_dptx_dpgtc", + "mout_clkcmu_dptx_dpgtc", CLK_CON_GAT_GATE_CLKCMU_DPTX_DPGTC, + 21, 0, 0), + + /* DPUM */ + GATE(GOUT_CLKCMU_DPUM_BUS, "gout_clkcmu_dpum_bus", + "mout_clkcmu_dpum_bus", CLK_CON_GAT_GATE_CLKCMU_DPUM_BUS, + 21, 0, 0), + + /* DPUS */ + GATE(GOUT_CLKCMU_DPUS0_BUS, "gout_clkcmu_dpus0_bus", + "mout_clkcmu_dpus0_bus", CLK_CON_GAT_GATE_CLKCMU_DPUS0_BUS, + 21, 0, 0), + GATE(GOUT_CLKCMU_DPUS1_BUS, "gout_clkcmu_dpus1_bus", + "mout_clkcmu_dpus1_bus", CLK_CON_GAT_GATE_CLKCMU_DPUS1_BUS, + 21, 0, 0), + + /* FSYS0 */ + GATE(GOUT_CLKCMU_FSYS0_BUS, "gout_clkcmu_fsys0_bus", + "mout_clkcmu_fsys0_bus", CLK_CON_GAT_GATE_CLKCMU_FSYS0_BUS, + 21, 0, 0), + GATE(GOUT_CLKCMU_FSYS0_PCIE, "gout_clkcmu_fsys0_pcie", + "mout_clkcmu_fsys0_pcie", CLK_CON_GAT_GATE_CLKCMU_FSYS0_PCIE, + 21, 0, 0), + + /* FSYS1 */ + GATE(GOUT_CLKCMU_FSYS1_BUS, "gout_clkcmu_fsys1_bus", + "mout_clkcmu_fsys1_bus", CLK_CON_GAT_GATE_CLKCMU_FSYS1_BUS, + 21, 0, 0), + GATE(GOUT_CLKCMU_FSYS1_USBDRD, "gout_clkcmu_fsys1_usbdrd", + "mout_clkcmu_fsys1_usbdrd", CLK_CON_GAT_GATE_CLKCMU_FSYS1_USBDRD, + 21, 0, 0), + GATE(GOUT_CLKCMU_FSYS1_MMC_CARD, "gout_clkcmu_fsys1_mmc_card", + "mout_clkcmu_fsys1_mmc_card", + CLK_CON_GAT_GATE_CLKCMU_FSYS1_MMC_CARD, 21, 0, 0), + + /* FSYS2 */ + GATE(GOUT_CLKCMU_FSYS2_BUS, "gout_clkcmu_fsys2_bus", + "mout_clkcmu_fsys2_bus", CLK_CON_GAT_GATE_CLKCMU_FSYS2_BUS, + 21, 0, 0), + GATE(GOUT_CLKCMU_FSYS2_UFS_EMBD, "gout_clkcmu_fsys2_ufs_embd", + "mout_clkcmu_fsys2_ufs_embd", + CLK_CON_GAT_GATE_CLKCMU_FSYS2_UFS_EMBD, 21, 0, 0), + GATE(GOUT_CLKCMU_FSYS2_ETHERNET, "gout_clkcmu_fsys2_ethernet", + "mout_clkcmu_fsys2_ethernet", + CLK_CON_GAT_GATE_CLKCMU_FSYS2_ETHERNET, 21, 0, 0), + + /* G2D */ + GATE(GOUT_CLKCMU_G2D_G2D, "gout_clkcmu_g2d_g2d", + "mout_clkcmu_g2d_g2d", CLK_CON_GAT_GATE_CLKCMU_G2D_G2D, 21, 0, 0), + GATE(GOUT_CLKCMU_G2D_MSCL, "gout_clkcmu_g2d_mscl", + "mout_clkcmu_g2d_mscl", CLK_CON_GAT_GATE_CLKCMU_G2D_MSCL, + 21, 0, 0), + + /* G3D0 */ + GATE(GOUT_CLKCMU_G3D00_SWITCH, "gout_clkcmu_g3d00_switch", + "mout_clkcmu_g3d00_switch", CLK_CON_GAT_GATE_CLKCMU_G3D00_SWITCH, + 21, 0, 0), + GATE(GOUT_CLKCMU_G3D01_SWITCH, "gout_clkcmu_g3d01_switch", + "mout_clkcmu_g3d01_switch", CLK_CON_GAT_GATE_CLKCMU_G3D01_SWITCH, + 21, 0, 0), + + /* G3D1 */ + GATE(GOUT_CLKCMU_G3D1_SWITCH, "gout_clkcmu_g3d1_switch", + "mout_clkcmu_g3d1_switch", CLK_CON_GAT_GATE_CLKCMU_G3D1_SWITCH, + 21, 0, 0), + + /* ISPB */ + GATE(GOUT_CLKCMU_ISPB_BUS, "gout_clkcmu_ispb_bus", + "mout_clkcmu_ispb_bus", CLK_CON_GAT_GATE_CLKCMU_ISPB_BUS, + 21, 0, 0), + + /* MFC */ + GATE(GOUT_CLKCMU_MFC_MFC, "gout_clkcmu_mfc_mfc", "mout_clkcmu_mfc_mfc", + CLK_CON_GAT_GATE_CLKCMU_MFC_MFC, 21, 0, 0), + GATE(GOUT_CLKCMU_MFC_WFD, "gout_clkcmu_mfc_wfd", "mout_clkcmu_mfc_wfd", + CLK_CON_GAT_GATE_CLKCMU_MFC_WFD, 21, 0, 0), + + /* MIF */ + GATE(GOUT_CLKCMU_MIF_SWITCH, "gout_clkcmu_mif_switch", + "mout_clkcmu_mif_switch", CLK_CON_GAT_GATE_CLKCMU_MIF_SWITCH, + 21, CLK_IGNORE_UNUSED, 0), + GATE(GOUT_CLKCMU_MIF_BUSP, "gout_clkcmu_mif_busp", + "mout_clkcmu_mif_busp", CLK_CON_GAT_GATE_CLKCMU_MIF_BUSP, + 21, CLK_IGNORE_UNUSED, 0), + + /* NPU */ + GATE(GOUT_CLKCMU_NPU_BUS, "gout_clkcmu_npu_bus", "mout_clkcmu_npu_bus", + CLK_CON_GAT_GATE_CLKCMU_NPU_BUS, 21, 0, 0), + + /* PERIC0 */ + GATE(GOUT_CLKCMU_PERIC0_BUS, "gout_clkcmu_peric0_bus", + "mout_clkcmu_peric0_bus", CLK_CON_GAT_GATE_CLKCMU_PERIC0_BUS, + 21, 0, 0), + GATE(GOUT_CLKCMU_PERIC0_IP, "gout_clkcmu_peric0_ip", + "mout_clkcmu_peric0_ip", CLK_CON_GAT_GATE_CLKCMU_PERIC0_IP, + 21, 0, 0), + + /* PERIC1 */ + GATE(GOUT_CLKCMU_PERIC1_BUS, "gout_clkcmu_peric1_bus", + "mout_clkcmu_peric1_bus", CLK_CON_GAT_GATE_CLKCMU_PERIC1_BUS, + 21, 0, 0), + GATE(GOUT_CLKCMU_PERIC1_IP, "gout_clkcmu_peric1_ip", + "mout_clkcmu_peric1_ip", CLK_CON_GAT_GATE_CLKCMU_PERIC1_IP, + 21, 0, 0), + + /* PERIS */ + GATE(GOUT_CLKCMU_PERIS_BUS, "gout_clkcmu_peris_bus", + "mout_clkcmu_peris_bus", CLK_CON_GAT_GATE_CLKCMU_PERIS_BUS, + 21, CLK_IGNORE_UNUSED, 0), +}; + +static const struct samsung_cmu_info top_cmu_info __initconst = { + .pll_clks = top_pll_clks, + .nr_pll_clks = ARRAY_SIZE(top_pll_clks), + .mux_clks = top_mux_clks, + .nr_mux_clks = ARRAY_SIZE(top_mux_clks), + .div_clks = top_div_clks, + .nr_div_clks = ARRAY_SIZE(top_div_clks), + .fixed_factor_clks = top_fixed_factor_clks, + .nr_fixed_factor_clks = ARRAY_SIZE(top_fixed_factor_clks), + .gate_clks = top_gate_clks, + .nr_gate_clks = ARRAY_SIZE(top_gate_clks), + .nr_clk_ids = TOP_NR_CLK, + .clk_regs = top_clk_regs, + .nr_clk_regs = ARRAY_SIZE(top_clk_regs), +}; + +static void __init exynosautov9_cmu_top_init(struct device_node *np) +{ + exynos_arm64_register_cmu(NULL, np, &top_cmu_info); +} + +/* Register CMU_TOP early, as it's a dependency for other early domains */ +CLK_OF_DECLARE(exynosautov9_cmu_top, "samsung,exynosautov9-cmu-top", + exynosautov9_cmu_top_init); + +/* ---- CMU_BUSMC ---------------------------------------------------------- */ + +/* Register Offset definitions for CMU_BUSMC (0x1b200000) */ +#define PLL_CON0_MUX_CLKCMU_BUSMC_BUS_USER 0x0600 +#define CLK_CON_DIV_DIV_CLK_BUSMC_BUSP 0x1800 +#define CLK_CON_GAT_GOUT_BLK_BUSMC_UID_QE_PDMA0_IPCLKPORT_PCLK 0x2078 +#define CLK_CON_GAT_GOUT_BLK_BUSMC_UID_QE_SPDMA_IPCLKPORT_PCLK 0x2080 + +static const unsigned long busmc_clk_regs[] __initconst = { + PLL_CON0_MUX_CLKCMU_BUSMC_BUS_USER, + CLK_CON_DIV_DIV_CLK_BUSMC_BUSP, + CLK_CON_GAT_GOUT_BLK_BUSMC_UID_QE_PDMA0_IPCLKPORT_PCLK, + CLK_CON_GAT_GOUT_BLK_BUSMC_UID_QE_SPDMA_IPCLKPORT_PCLK, +}; + +/* List of parent clocks for Muxes in CMU_BUSMC */ +PNAME(mout_busmc_bus_user_p) = { "oscclk", "dout_clkcmu_busmc_bus" }; + +static const struct samsung_mux_clock busmc_mux_clks[] __initconst = { + MUX(CLK_MOUT_BUSMC_BUS_USER, "mout_busmc_bus_user", + mout_busmc_bus_user_p, PLL_CON0_MUX_CLKCMU_BUSMC_BUS_USER, 4, 1), +}; + +static const struct samsung_div_clock busmc_div_clks[] __initconst = { + DIV(CLK_DOUT_BUSMC_BUSP, "dout_busmc_busp", "mout_busmc_bus_user", + CLK_CON_DIV_DIV_CLK_BUSMC_BUSP, 0, 3), +}; + +static const struct samsung_gate_clock busmc_gate_clks[] __initconst = { + GATE(CLK_GOUT_BUSMC_PDMA0_PCLK, "gout_busmc_pdma0_pclk", + "dout_busmc_busp", + CLK_CON_GAT_GOUT_BLK_BUSMC_UID_QE_PDMA0_IPCLKPORT_PCLK, 21, + 0, 0), + GATE(CLK_GOUT_BUSMC_SPDMA_PCLK, "gout_busmc_spdma_pclk", + "dout_busmc_busp", + CLK_CON_GAT_GOUT_BLK_BUSMC_UID_QE_SPDMA_IPCLKPORT_PCLK, 21, + 0, 0), +}; + +static const struct samsung_cmu_info busmc_cmu_info __initconst = { + .mux_clks = busmc_mux_clks, + .nr_mux_clks = ARRAY_SIZE(busmc_mux_clks), + .div_clks = busmc_div_clks, + .nr_div_clks = ARRAY_SIZE(busmc_div_clks), + .gate_clks = busmc_gate_clks, + .nr_gate_clks = ARRAY_SIZE(busmc_gate_clks), + .nr_clk_ids = BUSMC_NR_CLK, + .clk_regs = busmc_clk_regs, + .nr_clk_regs = ARRAY_SIZE(busmc_clk_regs), + .clk_name = "dout_clkcmu_busmc_bus", +}; + +/* ---- CMU_CORE ----------------------------------------------------------- */ + +/* Register Offset definitions for CMU_CORE (0x1b030000) */ +#define PLL_CON0_MUX_CLKCMU_CORE_BUS_USER 0x0600 +#define CLK_CON_MUX_MUX_CORE_CMUREF 0x1000 +#define CLK_CON_DIV_DIV_CLK_CORE_BUSP 0x1800 +#define CLK_CON_GAT_CLK_BLK_CORE_UID_CCI_IPCLKPORT_CLK 0x2000 +#define CLK_CON_GAT_CLK_BLK_CORE_UID_CCI_IPCLKPORT_PCLK 0x2004 +#define CLK_CON_GAT_CLK_BLK_CORE_UID_CORE_CMU_CORE_IPCLKPORT_PCLK 0x2008 + +static const unsigned long core_clk_regs[] __initconst = { + PLL_CON0_MUX_CLKCMU_CORE_BUS_USER, + CLK_CON_MUX_MUX_CORE_CMUREF, + CLK_CON_DIV_DIV_CLK_CORE_BUSP, + CLK_CON_GAT_CLK_BLK_CORE_UID_CCI_IPCLKPORT_CLK, + CLK_CON_GAT_CLK_BLK_CORE_UID_CCI_IPCLKPORT_PCLK, + CLK_CON_GAT_CLK_BLK_CORE_UID_CORE_CMU_CORE_IPCLKPORT_PCLK, +}; + +/* List of parent clocks for Muxes in CMU_CORE */ +PNAME(mout_core_bus_user_p) = { "oscclk", "dout_clkcmu_core_bus" }; + +static const struct samsung_mux_clock core_mux_clks[] __initconst = { + MUX(CLK_MOUT_CORE_BUS_USER, "mout_core_bus_user", mout_core_bus_user_p, + PLL_CON0_MUX_CLKCMU_CORE_BUS_USER, 4, 1), +}; + +static const struct samsung_div_clock core_div_clks[] __initconst = { + DIV(CLK_DOUT_CORE_BUSP, "dout_core_busp", "mout_core_bus_user", + CLK_CON_DIV_DIV_CLK_CORE_BUSP, 0, 3), +}; + +static const struct samsung_gate_clock core_gate_clks[] __initconst = { + GATE(CLK_GOUT_CORE_CCI_CLK, "gout_core_cci_clk", "mout_core_bus_user", + CLK_CON_GAT_CLK_BLK_CORE_UID_CCI_IPCLKPORT_CLK, 21, + CLK_IS_CRITICAL, 0), + GATE(CLK_GOUT_CORE_CCI_PCLK, "gout_core_cci_pclk", "dout_core_busp", + CLK_CON_GAT_CLK_BLK_CORE_UID_CCI_IPCLKPORT_PCLK, 21, + CLK_IS_CRITICAL, 0), + GATE(CLK_GOUT_CORE_CMU_CORE_PCLK, "gout_core_cmu_core_pclk", + "dout_core_busp", + CLK_CON_GAT_CLK_BLK_CORE_UID_CORE_CMU_CORE_IPCLKPORT_PCLK, 21, + CLK_IS_CRITICAL, 0), +}; + +static const struct samsung_cmu_info core_cmu_info __initconst = { + .mux_clks = core_mux_clks, + .nr_mux_clks = ARRAY_SIZE(core_mux_clks), + .div_clks = core_div_clks, + .nr_div_clks = ARRAY_SIZE(core_div_clks), + .gate_clks = core_gate_clks, + .nr_gate_clks = ARRAY_SIZE(core_gate_clks), + .nr_clk_ids = CORE_NR_CLK, + .clk_regs = core_clk_regs, + .nr_clk_regs = ARRAY_SIZE(core_clk_regs), + .clk_name = "dout_clkcmu_core_bus", +}; + +/* ---- CMU_FSYS2 ---------------------------------------------------------- */ + +/* Register Offset definitions for CMU_FSYS2 (0x17c00000) */ +#define PLL_CON0_MUX_CLKCMU_FSYS2_BUS_USER 0x0600 +#define PLL_CON0_MUX_CLKCMU_FSYS2_UFS_EMBD_USER 0x0620 +#define PLL_CON0_MUX_CLKCMU_FSYS2_ETHERNET_USER 0x0610 +#define CLK_CON_GAT_GOUT_BLK_FSYS2_UID_UFS_EMBD0_IPCLKPORT_I_ACLK 0x2098 +#define CLK_CON_GAT_GOUT_BLK_FSYS2_UID_UFS_EMBD0_IPCLKPORT_I_CLK_UNIPRO 0x209c +#define CLK_CON_GAT_GOUT_BLK_FSYS2_UID_UFS_EMBD1_IPCLKPORT_I_ACLK 0x20a4 +#define CLK_CON_GAT_GOUT_BLK_FSYS2_UID_UFS_EMBD1_IPCLKPORT_I_CLK_UNIPRO 0x20a8 + +static const unsigned long fsys2_clk_regs[] __initconst = { + PLL_CON0_MUX_CLKCMU_FSYS2_BUS_USER, + PLL_CON0_MUX_CLKCMU_FSYS2_UFS_EMBD_USER, + PLL_CON0_MUX_CLKCMU_FSYS2_ETHERNET_USER, + CLK_CON_GAT_GOUT_BLK_FSYS2_UID_UFS_EMBD0_IPCLKPORT_I_ACLK, + CLK_CON_GAT_GOUT_BLK_FSYS2_UID_UFS_EMBD0_IPCLKPORT_I_CLK_UNIPRO, + CLK_CON_GAT_GOUT_BLK_FSYS2_UID_UFS_EMBD1_IPCLKPORT_I_ACLK, + CLK_CON_GAT_GOUT_BLK_FSYS2_UID_UFS_EMBD1_IPCLKPORT_I_CLK_UNIPRO, +}; + +/* List of parent clocks for Muxes in CMU_FSYS2 */ +PNAME(mout_fsys2_bus_user_p) = { "oscclk", "dout_clkcmu_fsys2_bus" }; +PNAME(mout_fsys2_ufs_embd_user_p) = { "oscclk", "dout_clkcmu_fsys2_ufs_embd" }; +PNAME(mout_fsys2_ethernet_user_p) = { "oscclk", "dout_clkcmu_fsys2_ethernet" }; + +static const struct samsung_mux_clock fsys2_mux_clks[] __initconst = { + MUX(CLK_MOUT_FSYS2_BUS_USER, "mout_fsys2_bus_user", + mout_fsys2_bus_user_p, PLL_CON0_MUX_CLKCMU_FSYS2_BUS_USER, 4, 1), + MUX(CLK_MOUT_FSYS2_UFS_EMBD_USER, "mout_fsys2_ufs_embd_user", + mout_fsys2_ufs_embd_user_p, + PLL_CON0_MUX_CLKCMU_FSYS2_UFS_EMBD_USER, 4, 1), + MUX(CLK_MOUT_FSYS2_ETHERNET_USER, "mout_fsys2_ethernet_user", + mout_fsys2_ethernet_user_p, + PLL_CON0_MUX_CLKCMU_FSYS2_ETHERNET_USER, 4, 1), +}; + +static const struct samsung_gate_clock fsys2_gate_clks[] __initconst = { + GATE(CLK_GOUT_FSYS2_UFS_EMBD0_ACLK, "gout_fsys2_ufs_embd0_aclk", + "mout_fsys2_ufs_embd_user", + CLK_CON_GAT_GOUT_BLK_FSYS2_UID_UFS_EMBD0_IPCLKPORT_I_ACLK, 21, + 0, 0), + GATE(CLK_GOUT_FSYS2_UFS_EMBD0_UNIPRO, "gout_fsys2_ufs_embd0_unipro", + "mout_fsys2_ufs_embd_user", + CLK_CON_GAT_GOUT_BLK_FSYS2_UID_UFS_EMBD0_IPCLKPORT_I_CLK_UNIPRO, + 21, 0, 0), + GATE(CLK_GOUT_FSYS2_UFS_EMBD1_ACLK, "gout_fsys2_ufs_embd1_aclk", + "mout_fsys2_ufs_embd_user", + CLK_CON_GAT_GOUT_BLK_FSYS2_UID_UFS_EMBD1_IPCLKPORT_I_ACLK, 21, + 0, 0), + GATE(CLK_GOUT_FSYS2_UFS_EMBD1_UNIPRO, "gout_fsys2_ufs_embd1_unipro", + "mout_fsys2_ufs_embd_user", + CLK_CON_GAT_GOUT_BLK_FSYS2_UID_UFS_EMBD1_IPCLKPORT_I_CLK_UNIPRO, + 21, 0, 0), +}; + +static const struct samsung_cmu_info fsys2_cmu_info __initconst = { + .mux_clks = fsys2_mux_clks, + .nr_mux_clks = ARRAY_SIZE(fsys2_mux_clks), + .gate_clks = fsys2_gate_clks, + .nr_gate_clks = ARRAY_SIZE(fsys2_gate_clks), + .nr_clk_ids = FSYS2_NR_CLK, + .clk_regs = fsys2_clk_regs, + .nr_clk_regs = ARRAY_SIZE(fsys2_clk_regs), + .clk_name = "dout_clkcmu_fsys2_bus", +}; + +/* ---- CMU_PERIC0 --------------------------------------------------------- */ + +/* Register Offset definitions for CMU_PERIC0 (0x10200000) */ +#define PLL_CON0_MUX_CLKCMU_PERIC0_BUS_USER 0x0600 +#define PLL_CON0_MUX_CLKCMU_PERIC0_IP_USER 0x0610 +#define CLK_CON_MUX_MUX_CLK_PERIC0_USI00_USI 0x1000 +#define CLK_CON_MUX_MUX_CLK_PERIC0_USI01_USI 0x1004 +#define CLK_CON_MUX_MUX_CLK_PERIC0_USI02_USI 0x1008 +#define CLK_CON_MUX_MUX_CLK_PERIC0_USI03_USI 0x100c +#define CLK_CON_MUX_MUX_CLK_PERIC0_USI04_USI 0x1010 +#define CLK_CON_MUX_MUX_CLK_PERIC0_USI05_USI 0x1014 +#define CLK_CON_MUX_MUX_CLK_PERIC0_USI_I2C 0x1018 +#define CLK_CON_DIV_DIV_CLK_PERIC0_USI00_USI 0x1800 +#define CLK_CON_DIV_DIV_CLK_PERIC0_USI01_USI 0x1804 +#define CLK_CON_DIV_DIV_CLK_PERIC0_USI02_USI 0x1808 +#define CLK_CON_DIV_DIV_CLK_PERIC0_USI03_USI 0x180c +#define CLK_CON_DIV_DIV_CLK_PERIC0_USI04_USI 0x1810 +#define CLK_CON_DIV_DIV_CLK_PERIC0_USI05_USI 0x1814 +#define CLK_CON_DIV_DIV_CLK_PERIC0_USI_I2C 0x1818 +#define CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_IPCLK_0 0x2014 +#define CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_IPCLK_1 0x2018 +#define CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_IPCLK_2 0x2024 +#define CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_IPCLK_3 0x2028 +#define CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_IPCLK_4 0x202c +#define CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_IPCLK_5 0x2030 +#define CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_IPCLK_6 0x2034 +#define CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_IPCLK_7 0x2038 +#define CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_IPCLK_8 0x203c +#define CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_IPCLK_9 0x2040 +#define CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_IPCLK_10 0x201c +#define CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_IPCLK_11 0x2020 +#define CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_PCLK_0 0x2044 +#define CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_PCLK_1 0x2048 +#define CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_PCLK_2 0x2058 +#define CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_PCLK_3 0x205c +#define CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_PCLK_4 0x2060 +#define CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_PCLK_7 0x206c +#define CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_PCLK_5 0x2064 +#define CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_PCLK_6 0x2068 +#define CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_PCLK_8 0x2070 +#define CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_PCLK_9 0x2074 +#define CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_PCLK_10 0x204c +#define CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_PCLK_11 0x2050 + +static const unsigned long peric0_clk_regs[] __initconst = { + PLL_CON0_MUX_CLKCMU_PERIC0_BUS_USER, + PLL_CON0_MUX_CLKCMU_PERIC0_IP_USER, + CLK_CON_MUX_MUX_CLK_PERIC0_USI00_USI, + CLK_CON_MUX_MUX_CLK_PERIC0_USI01_USI, + CLK_CON_MUX_MUX_CLK_PERIC0_USI02_USI, + CLK_CON_MUX_MUX_CLK_PERIC0_USI03_USI, + CLK_CON_MUX_MUX_CLK_PERIC0_USI04_USI, + CLK_CON_MUX_MUX_CLK_PERIC0_USI05_USI, + CLK_CON_MUX_MUX_CLK_PERIC0_USI_I2C, + CLK_CON_DIV_DIV_CLK_PERIC0_USI00_USI, + CLK_CON_DIV_DIV_CLK_PERIC0_USI01_USI, + CLK_CON_DIV_DIV_CLK_PERIC0_USI02_USI, + CLK_CON_DIV_DIV_CLK_PERIC0_USI03_USI, + CLK_CON_DIV_DIV_CLK_PERIC0_USI04_USI, + CLK_CON_DIV_DIV_CLK_PERIC0_USI05_USI, + CLK_CON_DIV_DIV_CLK_PERIC0_USI_I2C, + CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_IPCLK_0, + CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_IPCLK_1, + CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_IPCLK_2, + CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_IPCLK_3, + CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_IPCLK_4, + CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_IPCLK_5, + CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_IPCLK_6, + CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_IPCLK_7, + CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_IPCLK_8, + CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_IPCLK_9, + CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_IPCLK_10, + CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_IPCLK_11, + CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_PCLK_0, + CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_PCLK_1, + CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_PCLK_2, + CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_PCLK_3, + CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_PCLK_4, + CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_PCLK_7, + CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_PCLK_5, + CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_PCLK_6, + CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_PCLK_8, + CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_PCLK_9, + CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_PCLK_10, + CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_PCLK_11, +}; + +/* List of parent clocks for Muxes in CMU_PERIC0 */ +PNAME(mout_peric0_bus_user_p) = { "oscclk", "dout_clkcmu_peric0_bus" }; +PNAME(mout_peric0_ip_user_p) = { "oscclk", "dout_clkcmu_peric0_ip" }; +PNAME(mout_peric0_usi_p) = { "oscclk", "mout_peric0_ip_user" }; + +static const struct samsung_mux_clock peric0_mux_clks[] __initconst = { + MUX(CLK_MOUT_PERIC0_BUS_USER, "mout_peric0_bus_user", + mout_peric0_bus_user_p, PLL_CON0_MUX_CLKCMU_PERIC0_BUS_USER, 4, 1), + MUX(CLK_MOUT_PERIC0_IP_USER, "mout_peric0_ip_user", + mout_peric0_ip_user_p, PLL_CON0_MUX_CLKCMU_PERIC0_IP_USER, 4, 1), + /* USI00 ~ USI05 */ + MUX(CLK_MOUT_PERIC0_USI00_USI, "mout_peric0_usi00_usi", + mout_peric0_usi_p, CLK_CON_MUX_MUX_CLK_PERIC0_USI00_USI, 0, 1), + MUX(CLK_MOUT_PERIC0_USI01_USI, "mout_peric0_usi01_usi", + mout_peric0_usi_p, CLK_CON_MUX_MUX_CLK_PERIC0_USI01_USI, 0, 1), + MUX(CLK_MOUT_PERIC0_USI02_USI, "mout_peric0_usi02_usi", + mout_peric0_usi_p, CLK_CON_MUX_MUX_CLK_PERIC0_USI02_USI, 0, 1), + MUX(CLK_MOUT_PERIC0_USI03_USI, "mout_peric0_usi03_usi", + mout_peric0_usi_p, CLK_CON_MUX_MUX_CLK_PERIC0_USI03_USI, 0, 1), + MUX(CLK_MOUT_PERIC0_USI04_USI, "mout_peric0_usi04_usi", + mout_peric0_usi_p, CLK_CON_MUX_MUX_CLK_PERIC0_USI04_USI, 0, 1), + MUX(CLK_MOUT_PERIC0_USI05_USI, "mout_peric0_usi05_usi", + mout_peric0_usi_p, CLK_CON_MUX_MUX_CLK_PERIC0_USI05_USI, 0, 1), + /* USI_I2C */ + MUX(CLK_MOUT_PERIC0_USI_I2C, "mout_peric0_usi_i2c", + mout_peric0_usi_p, CLK_CON_MUX_MUX_CLK_PERIC0_USI_I2C, 0, 1), +}; + +static const struct samsung_div_clock peric0_div_clks[] __initconst = { + /* USI00 ~ USI05 */ + DIV(CLK_DOUT_PERIC0_USI00_USI, "dout_peric0_usi00_usi", + "mout_peric0_usi00_usi", CLK_CON_DIV_DIV_CLK_PERIC0_USI00_USI, + 0, 4), + DIV(CLK_DOUT_PERIC0_USI01_USI, "dout_peric0_usi01_usi", + "mout_peric0_usi01_usi", CLK_CON_DIV_DIV_CLK_PERIC0_USI01_USI, + 0, 4), + DIV(CLK_DOUT_PERIC0_USI02_USI, "dout_peric0_usi02_usi", + "mout_peric0_usi02_usi", CLK_CON_DIV_DIV_CLK_PERIC0_USI02_USI, + 0, 4), + DIV(CLK_DOUT_PERIC0_USI03_USI, "dout_peric0_usi03_usi", + "mout_peric0_usi03_usi", CLK_CON_DIV_DIV_CLK_PERIC0_USI03_USI, + 0, 4), + DIV(CLK_DOUT_PERIC0_USI04_USI, "dout_peric0_usi04_usi", + "mout_peric0_usi04_usi", CLK_CON_DIV_DIV_CLK_PERIC0_USI04_USI, + 0, 4), + DIV(CLK_DOUT_PERIC0_USI05_USI, "dout_peric0_usi05_usi", + "mout_peric0_usi05_usi", CLK_CON_DIV_DIV_CLK_PERIC0_USI05_USI, + 0, 4), + /* USI_I2C */ + DIV(CLK_DOUT_PERIC0_USI_I2C, "dout_peric0_usi_i2c", + "mout_peric0_usi_i2c", CLK_CON_DIV_DIV_CLK_PERIC0_USI_I2C, 0, 4), +}; + +static const struct samsung_gate_clock peric0_gate_clks[] __initconst = { + /* IPCLK */ + GATE(CLK_GOUT_PERIC0_IPCLK_0, "gout_peric0_ipclk_0", + "dout_peric0_usi00_usi", + CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_IPCLK_0, + 21, 0, 0), + GATE(CLK_GOUT_PERIC0_IPCLK_1, "gout_peric0_ipclk_1", + "dout_peric0_usi_i2c", + CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_IPCLK_1, + 21, 0, 0), + GATE(CLK_GOUT_PERIC0_IPCLK_2, "gout_peric0_ipclk_2", + "dout_peric0_usi01_usi", + CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_IPCLK_2, + 21, 0, 0), + GATE(CLK_GOUT_PERIC0_IPCLK_3, "gout_peric0_ipclk_3", + "dout_peric0_usi_i2c", + CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_IPCLK_3, + 21, 0, 0), + GATE(CLK_GOUT_PERIC0_IPCLK_4, "gout_peric0_ipclk_4", + "dout_peric0_usi02_usi", + CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_IPCLK_4, + 21, 0, 0), + GATE(CLK_GOUT_PERIC0_IPCLK_5, "gout_peric0_ipclk_5", + "dout_peric0_usi_i2c", + CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_IPCLK_5, + 21, 0, 0), + GATE(CLK_GOUT_PERIC0_IPCLK_6, "gout_peric0_ipclk_6", + "dout_peric0_usi03_usi", + CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_IPCLK_6, + 21, 0, 0), + GATE(CLK_GOUT_PERIC0_IPCLK_7, "gout_peric0_ipclk_7", + "dout_peric0_usi_i2c", + CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_IPCLK_7, + 21, 0, 0), + GATE(CLK_GOUT_PERIC0_IPCLK_8, "gout_peric0_ipclk_8", + "dout_peric0_usi04_usi", + CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_IPCLK_8, + 21, 0, 0), + GATE(CLK_GOUT_PERIC0_IPCLK_9, "gout_peric0_ipclk_9", + "dout_peric0_usi_i2c", + CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_IPCLK_9, + 21, 0, 0), + GATE(CLK_GOUT_PERIC0_IPCLK_10, "gout_peric0_ipclk_10", + "dout_peric0_usi05_usi", + CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_IPCLK_10, + 21, 0, 0), + GATE(CLK_GOUT_PERIC0_IPCLK_11, "gout_peric0_ipclk_11", + "dout_peric0_usi_i2c", + CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_IPCLK_11, + 21, 0, 0), + + /* PCLK */ + GATE(CLK_GOUT_PERIC0_PCLK_0, "gout_peric0_pclk_0", + "mout_peric0_bus_user", + CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_PCLK_0, + 21, 0, 0), + GATE(CLK_GOUT_PERIC0_PCLK_2, "gout_peric0_pclk_2", + "mout_peric0_bus_user", + CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_PCLK_2, + 21, 0, 0), + GATE(CLK_GOUT_PERIC0_PCLK_3, "gout_peric0_pclk_3", + "mout_peric0_bus_user", + CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_PCLK_3, + 21, 0, 0), + GATE(CLK_GOUT_PERIC0_PCLK_4, "gout_peric0_pclk_4", + "mout_peric0_bus_user", + CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_PCLK_4, + 21, 0, 0), + GATE(CLK_GOUT_PERIC0_PCLK_5, "gout_peric0_pclk_5", + "mout_peric0_bus_user", + CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_PCLK_5, + 21, 0, 0), + GATE(CLK_GOUT_PERIC0_PCLK_6, "gout_peric0_pclk_6", + "mout_peric0_bus_user", + CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_PCLK_6, + 21, 0, 0), + GATE(CLK_GOUT_PERIC0_PCLK_7, "gout_peric0_pclk_7", + "mout_peric0_bus_user", + CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_PCLK_7, + 21, 0, 0), + GATE(CLK_GOUT_PERIC0_PCLK_8, "gout_peric0_pclk_8", + "mout_peric0_bus_user", + CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_PCLK_8, + 21, 0, 0), + GATE(CLK_GOUT_PERIC0_PCLK_9, "gout_peric0_pclk_9", + "mout_peric0_bus_user", + CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_PCLK_9, + 21, 0, 0), + GATE(CLK_GOUT_PERIC0_PCLK_10, "gout_peric0_pclk_10", + "mout_peric0_bus_user", + CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_PCLK_10, + 21, 0, 0), + GATE(CLK_GOUT_PERIC0_PCLK_11, "gout_peric0_pclk_11", + "mout_peric0_bus_user", + CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_PCLK_11, + 21, 0, 0), +}; + +static const struct samsung_cmu_info peric0_cmu_info __initconst = { + .mux_clks = peric0_mux_clks, + .nr_mux_clks = ARRAY_SIZE(peric0_mux_clks), + .div_clks = peric0_div_clks, + .nr_div_clks = ARRAY_SIZE(peric0_div_clks), + .gate_clks = peric0_gate_clks, + .nr_gate_clks = ARRAY_SIZE(peric0_gate_clks), + .nr_clk_ids = PERIC0_NR_CLK, + .clk_regs = peric0_clk_regs, + .nr_clk_regs = ARRAY_SIZE(peric0_clk_regs), + .clk_name = "dout_clkcmu_peric0_bus", +}; + +/* ---- CMU_PERIC1 --------------------------------------------------------- */ + +/* Register Offset definitions for CMU_PERIC1 (0x10800000) */ +#define PLL_CON0_MUX_CLKCMU_PERIC1_BUS_USER 0x0600 +#define PLL_CON0_MUX_CLKCMU_PERIC1_IP_USER 0x0610 +#define CLK_CON_MUX_MUX_CLK_PERIC1_USI06_USI 0x1000 +#define CLK_CON_MUX_MUX_CLK_PERIC1_USI07_USI 0x1004 +#define CLK_CON_MUX_MUX_CLK_PERIC1_USI08_USI 0x1008 +#define CLK_CON_MUX_MUX_CLK_PERIC1_USI09_USI 0x100c +#define CLK_CON_MUX_MUX_CLK_PERIC1_USI10_USI 0x1010 +#define CLK_CON_MUX_MUX_CLK_PERIC1_USI11_USI 0x1014 +#define CLK_CON_MUX_MUX_CLK_PERIC1_USI_I2C 0x1018 +#define CLK_CON_DIV_DIV_CLK_PERIC1_USI06_USI 0x1800 +#define CLK_CON_DIV_DIV_CLK_PERIC1_USI07_USI 0x1804 +#define CLK_CON_DIV_DIV_CLK_PERIC1_USI08_USI 0x1808 +#define CLK_CON_DIV_DIV_CLK_PERIC1_USI09_USI 0x180c +#define CLK_CON_DIV_DIV_CLK_PERIC1_USI10_USI 0x1810 +#define CLK_CON_DIV_DIV_CLK_PERIC1_USI11_USI 0x1814 +#define CLK_CON_DIV_DIV_CLK_PERIC1_USI_I2C 0x1818 +#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_IPCLK_0 0x2014 +#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_IPCLK_1 0x2018 +#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_IPCLK_2 0x2024 +#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_IPCLK_3 0x2028 +#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_IPCLK_4 0x202c +#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_IPCLK_5 0x2030 +#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_IPCLK_6 0x2034 +#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_IPCLK_7 0x2038 +#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_IPCLK_8 0x203c +#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_IPCLK_9 0x2040 +#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_IPCLK_10 0x201c +#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_IPCLK_11 0x2020 +#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_PCLK_0 0x2044 +#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_PCLK_1 0x2048 +#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_PCLK_2 0x2058 +#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_PCLK_3 0x205c +#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_PCLK_4 0x2060 +#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_PCLK_7 0x206c +#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_PCLK_5 0x2064 +#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_PCLK_6 0x2068 +#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_PCLK_8 0x2070 +#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_PCLK_9 0x2074 +#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_PCLK_10 0x204c +#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_PCLK_11 0x2050 + +static const unsigned long peric1_clk_regs[] __initconst = { + PLL_CON0_MUX_CLKCMU_PERIC1_BUS_USER, + PLL_CON0_MUX_CLKCMU_PERIC1_IP_USER, + CLK_CON_MUX_MUX_CLK_PERIC1_USI06_USI, + CLK_CON_MUX_MUX_CLK_PERIC1_USI07_USI, + CLK_CON_MUX_MUX_CLK_PERIC1_USI08_USI, + CLK_CON_MUX_MUX_CLK_PERIC1_USI09_USI, + CLK_CON_MUX_MUX_CLK_PERIC1_USI10_USI, + CLK_CON_MUX_MUX_CLK_PERIC1_USI11_USI, + CLK_CON_MUX_MUX_CLK_PERIC1_USI_I2C, + CLK_CON_DIV_DIV_CLK_PERIC1_USI06_USI, + CLK_CON_DIV_DIV_CLK_PERIC1_USI07_USI, + CLK_CON_DIV_DIV_CLK_PERIC1_USI08_USI, + CLK_CON_DIV_DIV_CLK_PERIC1_USI09_USI, + CLK_CON_DIV_DIV_CLK_PERIC1_USI10_USI, + CLK_CON_DIV_DIV_CLK_PERIC1_USI11_USI, + CLK_CON_DIV_DIV_CLK_PERIC1_USI_I2C, + CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_IPCLK_0, + CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_IPCLK_1, + CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_IPCLK_2, + CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_IPCLK_3, + CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_IPCLK_4, + CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_IPCLK_5, + CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_IPCLK_6, + CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_IPCLK_7, + CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_IPCLK_8, + CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_IPCLK_9, + CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_IPCLK_10, + CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_IPCLK_11, + CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_PCLK_0, + CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_PCLK_1, + CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_PCLK_2, + CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_PCLK_3, + CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_PCLK_4, + CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_PCLK_7, + CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_PCLK_5, + CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_PCLK_6, + CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_PCLK_8, + CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_PCLK_9, + CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_PCLK_10, + CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_PCLK_11, +}; + +/* List of parent clocks for Muxes in CMU_PERIC1 */ +PNAME(mout_peric1_bus_user_p) = { "oscclk", "dout_clkcmu_peric1_bus" }; +PNAME(mout_peric1_ip_user_p) = { "oscclk", "dout_clkcmu_peric1_ip" }; +PNAME(mout_peric1_usi_p) = { "oscclk", "mout_peric1_ip_user" }; + +static const struct samsung_mux_clock peric1_mux_clks[] __initconst = { + MUX(CLK_MOUT_PERIC1_BUS_USER, "mout_peric1_bus_user", + mout_peric1_bus_user_p, PLL_CON0_MUX_CLKCMU_PERIC1_BUS_USER, 4, 1), + MUX(CLK_MOUT_PERIC1_IP_USER, "mout_peric1_ip_user", + mout_peric1_ip_user_p, PLL_CON0_MUX_CLKCMU_PERIC1_IP_USER, 4, 1), + /* USI06 ~ USI11 */ + MUX(CLK_MOUT_PERIC1_USI06_USI, "mout_peric1_usi06_usi", + mout_peric1_usi_p, CLK_CON_MUX_MUX_CLK_PERIC1_USI06_USI, 0, 1), + MUX(CLK_MOUT_PERIC1_USI07_USI, "mout_peric1_usi07_usi", + mout_peric1_usi_p, CLK_CON_MUX_MUX_CLK_PERIC1_USI07_USI, 0, 1), + MUX(CLK_MOUT_PERIC1_USI08_USI, "mout_peric1_usi08_usi", + mout_peric1_usi_p, CLK_CON_MUX_MUX_CLK_PERIC1_USI08_USI, 0, 1), + MUX(CLK_MOUT_PERIC1_USI09_USI, "mout_peric1_usi09_usi", + mout_peric1_usi_p, CLK_CON_MUX_MUX_CLK_PERIC1_USI09_USI, 0, 1), + MUX(CLK_MOUT_PERIC1_USI10_USI, "mout_peric1_usi10_usi", + mout_peric1_usi_p, CLK_CON_MUX_MUX_CLK_PERIC1_USI10_USI, 0, 1), + MUX(CLK_MOUT_PERIC1_USI11_USI, "mout_peric1_usi11_usi", + mout_peric1_usi_p, CLK_CON_MUX_MUX_CLK_PERIC1_USI11_USI, 0, 1), + /* USI_I2C */ + MUX(CLK_MOUT_PERIC1_USI_I2C, "mout_peric1_usi_i2c", + mout_peric1_usi_p, CLK_CON_MUX_MUX_CLK_PERIC1_USI_I2C, 0, 1), +}; + +static const struct samsung_div_clock peric1_div_clks[] __initconst = { + /* USI06 ~ USI11 */ + DIV(CLK_DOUT_PERIC1_USI06_USI, "dout_peric1_usi06_usi", + "mout_peric1_usi06_usi", CLK_CON_DIV_DIV_CLK_PERIC1_USI06_USI, + 0, 4), + DIV(CLK_DOUT_PERIC1_USI07_USI, "dout_peric1_usi07_usi", + "mout_peric1_usi07_usi", CLK_CON_DIV_DIV_CLK_PERIC1_USI07_USI, + 0, 4), + DIV(CLK_DOUT_PERIC1_USI08_USI, "dout_peric1_usi08_usi", + "mout_peric1_usi08_usi", CLK_CON_DIV_DIV_CLK_PERIC1_USI08_USI, + 0, 4), + DIV(CLK_DOUT_PERIC1_USI09_USI, "dout_peric1_usi09_usi", + "mout_peric1_usi09_usi", CLK_CON_DIV_DIV_CLK_PERIC1_USI09_USI, + 0, 4), + DIV(CLK_DOUT_PERIC1_USI10_USI, "dout_peric1_usi10_usi", + "mout_peric1_usi10_usi", CLK_CON_DIV_DIV_CLK_PERIC1_USI10_USI, + 0, 4), + DIV(CLK_DOUT_PERIC1_USI11_USI, "dout_peric1_usi11_usi", + "mout_peric1_usi11_usi", CLK_CON_DIV_DIV_CLK_PERIC1_USI11_USI, + 0, 4), + /* USI_I2C */ + DIV(CLK_DOUT_PERIC1_USI_I2C, "dout_peric1_usi_i2c", + "mout_peric1_usi_i2c", CLK_CON_DIV_DIV_CLK_PERIC1_USI_I2C, 0, 4), +}; + +static const struct samsung_gate_clock peric1_gate_clks[] __initconst = { + /* IPCLK */ + GATE(CLK_GOUT_PERIC1_IPCLK_0, "gout_peric1_ipclk_0", + "dout_peric1_usi06_usi", + CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_IPCLK_0, + 21, 0, 0), + GATE(CLK_GOUT_PERIC1_IPCLK_1, "gout_peric1_ipclk_1", + "dout_peric1_usi_i2c", + CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_IPCLK_1, + 21, 0, 0), + GATE(CLK_GOUT_PERIC1_IPCLK_2, "gout_peric1_ipclk_2", + "dout_peric1_usi07_usi", + CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_IPCLK_2, + 21, 0, 0), + GATE(CLK_GOUT_PERIC1_IPCLK_3, "gout_peric1_ipclk_3", + "dout_peric1_usi_i2c", + CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_IPCLK_3, + 21, 0, 0), + GATE(CLK_GOUT_PERIC1_IPCLK_4, "gout_peric1_ipclk_4", + "dout_peric1_usi08_usi", + CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_IPCLK_4, + 21, 0, 0), + GATE(CLK_GOUT_PERIC1_IPCLK_5, "gout_peric1_ipclk_5", + "dout_peric1_usi_i2c", + CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_IPCLK_5, + 21, 0, 0), + GATE(CLK_GOUT_PERIC1_IPCLK_6, "gout_peric1_ipclk_6", + "dout_peric1_usi09_usi", + CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_IPCLK_6, + 21, 0, 0), + GATE(CLK_GOUT_PERIC1_IPCLK_7, "gout_peric1_ipclk_7", + "dout_peric1_usi_i2c", + CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_IPCLK_7, + 21, 0, 0), + GATE(CLK_GOUT_PERIC1_IPCLK_8, "gout_peric1_ipclk_8", + "dout_peric1_usi10_usi", + CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_IPCLK_8, + 21, 0, 0), + GATE(CLK_GOUT_PERIC1_IPCLK_9, "gout_peric1_ipclk_9", + "dout_peric1_usi_i2c", + CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_IPCLK_9, + 21, 0, 0), + GATE(CLK_GOUT_PERIC1_IPCLK_10, "gout_peric1_ipclk_10", + "dout_peric1_usi11_usi", + CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_IPCLK_10, + 21, 0, 0), + GATE(CLK_GOUT_PERIC1_IPCLK_11, "gout_peric1_ipclk_11", + "dout_peric1_usi_i2c", + CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_IPCLK_11, + 21, 0, 0), + + /* PCLK */ + GATE(CLK_GOUT_PERIC1_PCLK_0, "gout_peric1_pclk_0", + "mout_peric1_bus_user", + CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_PCLK_0, + 21, 0, 0), + GATE(CLK_GOUT_PERIC1_PCLK_2, "gout_peric1_pclk_2", + "mout_peric1_bus_user", + CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_PCLK_2, + 21, 0, 0), + GATE(CLK_GOUT_PERIC1_PCLK_3, "gout_peric1_pclk_3", + "mout_peric1_bus_user", + CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_PCLK_3, + 21, 0, 0), + GATE(CLK_GOUT_PERIC1_PCLK_4, "gout_peric1_pclk_4", + "mout_peric1_bus_user", + CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_PCLK_4, + 21, 0, 0), + GATE(CLK_GOUT_PERIC1_PCLK_5, "gout_peric1_pclk_5", + "mout_peric1_bus_user", + CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_PCLK_5, + 21, 0, 0), + GATE(CLK_GOUT_PERIC1_PCLK_6, "gout_peric1_pclk_6", + "mout_peric1_bus_user", + CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_PCLK_6, + 21, 0, 0), + GATE(CLK_GOUT_PERIC1_PCLK_7, "gout_peric1_pclk_7", + "mout_peric1_bus_user", + CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_PCLK_7, + 21, 0, 0), + GATE(CLK_GOUT_PERIC1_PCLK_8, "gout_peric1_pclk_8", + "mout_peric1_bus_user", + CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_PCLK_8, + 21, 0, 0), + GATE(CLK_GOUT_PERIC1_PCLK_9, "gout_peric1_pclk_9", + "mout_peric1_bus_user", + CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_PCLK_9, + 21, 0, 0), + GATE(CLK_GOUT_PERIC1_PCLK_10, "gout_peric1_pclk_10", + "mout_peric1_bus_user", + CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_PCLK_10, + 21, 0, 0), + GATE(CLK_GOUT_PERIC1_PCLK_11, "gout_peric1_pclk_11", + "mout_peric1_bus_user", + CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_PCLK_11, + 21, 0, 0), +}; + +static const struct samsung_cmu_info peric1_cmu_info __initconst = { + .mux_clks = peric1_mux_clks, + .nr_mux_clks = ARRAY_SIZE(peric1_mux_clks), + .div_clks = peric1_div_clks, + .nr_div_clks = ARRAY_SIZE(peric1_div_clks), + .gate_clks = peric1_gate_clks, + .nr_gate_clks = ARRAY_SIZE(peric1_gate_clks), + .nr_clk_ids = PERIC1_NR_CLK, + .clk_regs = peric1_clk_regs, + .nr_clk_regs = ARRAY_SIZE(peric1_clk_regs), + .clk_name = "dout_clkcmu_peric1_bus", +}; + +/* ---- CMU_PERIS ---------------------------------------------------------- */ + +/* Register Offset definitions for CMU_PERIS (0x10020000) */ +#define PLL_CON0_MUX_CLKCMU_PERIS_BUS_USER 0x0600 +#define CLK_CON_GAT_GOUT_BLK_PERIS_UID_SYSREG_PERIS_IPCLKPORT_PCLK 0x2058 +#define CLK_CON_GAT_GOUT_BLK_PERIS_UID_WDT_CLUSTER0_IPCLKPORT_PCLK 0x205c +#define CLK_CON_GAT_GOUT_BLK_PERIS_UID_WDT_CLUSTER1_IPCLKPORT_PCLK 0x2060 + +static const unsigned long peris_clk_regs[] __initconst = { + PLL_CON0_MUX_CLKCMU_PERIS_BUS_USER, + CLK_CON_GAT_GOUT_BLK_PERIS_UID_SYSREG_PERIS_IPCLKPORT_PCLK, + CLK_CON_GAT_GOUT_BLK_PERIS_UID_WDT_CLUSTER0_IPCLKPORT_PCLK, + CLK_CON_GAT_GOUT_BLK_PERIS_UID_WDT_CLUSTER1_IPCLKPORT_PCLK, +}; + +/* List of parent clocks for Muxes in CMU_PERIS */ +PNAME(mout_peris_bus_user_p) = { "oscclk", "dout_clkcmu_peris_bus" }; + +static const struct samsung_mux_clock peris_mux_clks[] __initconst = { + MUX(CLK_MOUT_PERIS_BUS_USER, "mout_peris_bus_user", + mout_peris_bus_user_p, PLL_CON0_MUX_CLKCMU_PERIS_BUS_USER, 4, 1), +}; + +static const struct samsung_gate_clock peris_gate_clks[] __initconst = { + GATE(CLK_GOUT_SYSREG_PERIS_PCLK, "gout_sysreg_peris_pclk", + "mout_peris_bus_user", + CLK_CON_GAT_GOUT_BLK_PERIS_UID_SYSREG_PERIS_IPCLKPORT_PCLK, + 21, CLK_IGNORE_UNUSED, 0), + GATE(CLK_GOUT_WDT_CLUSTER0, "gout_wdt_cluster0", "mout_peris_bus_user", + CLK_CON_GAT_GOUT_BLK_PERIS_UID_WDT_CLUSTER0_IPCLKPORT_PCLK, + 21, 0, 0), + GATE(CLK_GOUT_WDT_CLUSTER1, "gout_wdt_cluster1", "mout_peris_bus_user", + CLK_CON_GAT_GOUT_BLK_PERIS_UID_WDT_CLUSTER1_IPCLKPORT_PCLK, + 21, 0, 0), +}; + +static const struct samsung_cmu_info peris_cmu_info __initconst = { + .mux_clks = peris_mux_clks, + .nr_mux_clks = ARRAY_SIZE(peris_mux_clks), + .gate_clks = peris_gate_clks, + .nr_gate_clks = ARRAY_SIZE(peris_gate_clks), + .nr_clk_ids = PERIS_NR_CLK, + .clk_regs = peris_clk_regs, + .nr_clk_regs = ARRAY_SIZE(peris_clk_regs), + .clk_name = "dout_clkcmu_peris_bus", +}; + +static int __init exynosautov9_cmu_probe(struct platform_device *pdev) +{ + const struct samsung_cmu_info *info; + struct device *dev = &pdev->dev; + + info = of_device_get_match_data(dev); + exynos_arm64_register_cmu(dev, dev->of_node, info); + + return 0; +} + +static const struct of_device_id exynosautov9_cmu_of_match[] = { + { + .compatible = "samsung,exynosautov9-cmu-busmc", + .data = &busmc_cmu_info, + }, { + .compatible = "samsung,exynosautov9-cmu-core", + .data = &core_cmu_info, + }, { + .compatible = "samsung,exynosautov9-cmu-fsys2", + .data = &fsys2_cmu_info, + }, { + .compatible = "samsung,exynosautov9-cmu-peric0", + .data = &peric0_cmu_info, + }, { + .compatible = "samsung,exynosautov9-cmu-peric1", + .data = &peric1_cmu_info, + }, { + .compatible = "samsung,exynosautov9-cmu-peris", + .data = &peris_cmu_info, + }, { + }, +}; + +static struct platform_driver exynosautov9_cmu_driver __refdata = { + .driver = { + .name = "exynosautov9-cmu", + .of_match_table = exynosautov9_cmu_of_match, + .suppress_bind_attrs = true, + }, + .probe = exynosautov9_cmu_probe, +}; + +static int __init exynosautov9_cmu_init(void) +{ + return platform_driver_register(&exynosautov9_cmu_driver); +} +core_initcall(exynosautov9_cmu_init); diff --git a/drivers/clk/stm32/Makefile b/drivers/clk/stm32/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..95bd2230bba07383ac6d3c5346b71aafa761ba18 --- /dev/null +++ b/drivers/clk/stm32/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_COMMON_CLK_STM32MP135) += clk-stm32mp13.o clk-stm32-core.o reset-stm32.o diff --git a/drivers/clk/stm32/clk-stm32-core.c b/drivers/clk/stm32/clk-stm32-core.c new file mode 100644 index 0000000000000000000000000000000000000000..45a279e73779e6f5abb5d0e662a5c5b19737bd04 --- /dev/null +++ b/drivers/clk/stm32/clk-stm32-core.c @@ -0,0 +1,695 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) STMicroelectronics 2022 - All Rights Reserved + * Author: Gabriel Fernandez for STMicroelectronics. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "clk-stm32-core.h" +#include "reset-stm32.h" + +static DEFINE_SPINLOCK(rlock); + +static int stm32_rcc_clock_init(struct device *dev, + const struct of_device_id *match, + void __iomem *base) +{ + const struct stm32_rcc_match_data *data = match->data; + struct clk_hw_onecell_data *clk_data = data->hw_clks; + struct device_node *np = dev_of_node(dev); + struct clk_hw **hws; + int n, max_binding; + + max_binding = data->maxbinding; + + clk_data = devm_kzalloc(dev, struct_size(clk_data, hws, max_binding), GFP_KERNEL); + if (!clk_data) + return -ENOMEM; + + clk_data->num = max_binding; + + hws = clk_data->hws; + + for (n = 0; n < max_binding; n++) + hws[n] = ERR_PTR(-ENOENT); + + for (n = 0; n < data->num_clocks; n++) { + const struct clock_config *cfg_clock = &data->tab_clocks[n]; + struct clk_hw *hw = ERR_PTR(-ENOENT); + + if (data->check_security && + data->check_security(base, cfg_clock)) + continue; + + if (cfg_clock->func) + hw = (*cfg_clock->func)(dev, data, base, &rlock, + cfg_clock); + + if (IS_ERR(hw)) { + dev_err(dev, "Can't register clk %d: %ld\n", n, + PTR_ERR(hw)); + return PTR_ERR(hw); + } + + if (cfg_clock->id != NO_ID) + hws[cfg_clock->id] = hw; + } + + return of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_data); +} + +int stm32_rcc_init(struct device *dev, const struct of_device_id *match_data, + void __iomem *base) +{ + const struct of_device_id *match; + int err; + + match = of_match_node(match_data, dev_of_node(dev)); + if (!match) { + dev_err(dev, "match data not found\n"); + return -ENODEV; + } + + /* RCC Reset Configuration */ + err = stm32_rcc_reset_init(dev, match, base); + if (err) { + pr_err("stm32 reset failed to initialize\n"); + return err; + } + + /* RCC Clock Configuration */ + err = stm32_rcc_clock_init(dev, match, base); + if (err) { + pr_err("stm32 clock failed to initialize\n"); + return err; + } + + return 0; +} + +static u8 stm32_mux_get_parent(void __iomem *base, + struct clk_stm32_clock_data *data, + u16 mux_id) +{ + const struct stm32_mux_cfg *mux = &data->muxes[mux_id]; + u32 mask = BIT(mux->width) - 1; + u32 val; + + val = readl(base + mux->offset) >> mux->shift; + val &= mask; + + return val; +} + +static int stm32_mux_set_parent(void __iomem *base, + struct clk_stm32_clock_data *data, + u16 mux_id, u8 index) +{ + const struct stm32_mux_cfg *mux = &data->muxes[mux_id]; + + u32 mask = BIT(mux->width) - 1; + u32 reg = readl(base + mux->offset); + u32 val = index << mux->shift; + + reg &= ~(mask << mux->shift); + reg |= val; + + writel(reg, base + mux->offset); + + return 0; +} + +static void stm32_gate_endisable(void __iomem *base, + struct clk_stm32_clock_data *data, + u16 gate_id, int enable) +{ + const struct stm32_gate_cfg *gate = &data->gates[gate_id]; + void __iomem *addr = base + gate->offset; + + if (enable) { + if (data->gate_cpt[gate_id]++ > 0) + return; + + if (gate->set_clr != 0) + writel(BIT(gate->bit_idx), addr); + else + writel(readl(addr) | BIT(gate->bit_idx), addr); + } else { + if (--data->gate_cpt[gate_id] > 0) + return; + + if (gate->set_clr != 0) + writel(BIT(gate->bit_idx), addr + gate->set_clr); + else + writel(readl(addr) & ~BIT(gate->bit_idx), addr); + } +} + +static void stm32_gate_disable_unused(void __iomem *base, + struct clk_stm32_clock_data *data, + u16 gate_id) +{ + const struct stm32_gate_cfg *gate = &data->gates[gate_id]; + void __iomem *addr = base + gate->offset; + + if (data->gate_cpt[gate_id] > 0) + return; + + if (gate->set_clr != 0) + writel(BIT(gate->bit_idx), addr + gate->set_clr); + else + writel(readl(addr) & ~BIT(gate->bit_idx), addr); +} + +static int stm32_gate_is_enabled(void __iomem *base, + struct clk_stm32_clock_data *data, + u16 gate_id) +{ + const struct stm32_gate_cfg *gate = &data->gates[gate_id]; + + return (readl(base + gate->offset) & BIT(gate->bit_idx)) != 0; +} + +static unsigned int _get_table_div(const struct clk_div_table *table, + unsigned int val) +{ + const struct clk_div_table *clkt; + + for (clkt = table; clkt->div; clkt++) + if (clkt->val == val) + return clkt->div; + return 0; +} + +static unsigned int _get_div(const struct clk_div_table *table, + unsigned int val, unsigned long flags, u8 width) +{ + if (flags & CLK_DIVIDER_ONE_BASED) + return val; + if (flags & CLK_DIVIDER_POWER_OF_TWO) + return 1 << val; + if (table) + return _get_table_div(table, val); + return val + 1; +} + +static unsigned long stm32_divider_get_rate(void __iomem *base, + struct clk_stm32_clock_data *data, + u16 div_id, + unsigned long parent_rate) +{ + const struct stm32_div_cfg *divider = &data->dividers[div_id]; + unsigned int val; + unsigned int div; + + val = readl(base + divider->offset) >> divider->shift; + val &= clk_div_mask(divider->width); + div = _get_div(divider->table, val, divider->flags, divider->width); + + if (!div) { + WARN(!(divider->flags & CLK_DIVIDER_ALLOW_ZERO), + "%d: Zero divisor and CLK_DIVIDER_ALLOW_ZERO not set\n", + div_id); + return parent_rate; + } + + return DIV_ROUND_UP_ULL((u64)parent_rate, div); +} + +static int stm32_divider_set_rate(void __iomem *base, + struct clk_stm32_clock_data *data, + u16 div_id, unsigned long rate, + unsigned long parent_rate) +{ + const struct stm32_div_cfg *divider = &data->dividers[div_id]; + int value; + u32 val; + + value = divider_get_val(rate, parent_rate, divider->table, + divider->width, divider->flags); + if (value < 0) + return value; + + if (divider->flags & CLK_DIVIDER_HIWORD_MASK) { + val = clk_div_mask(divider->width) << (divider->shift + 16); + } else { + val = readl(base + divider->offset); + val &= ~(clk_div_mask(divider->width) << divider->shift); + } + + val |= (u32)value << divider->shift; + + writel(val, base + divider->offset); + + return 0; +} + +static u8 clk_stm32_mux_get_parent(struct clk_hw *hw) +{ + struct clk_stm32_mux *mux = to_clk_stm32_mux(hw); + + return stm32_mux_get_parent(mux->base, mux->clock_data, mux->mux_id); +} + +static int clk_stm32_mux_set_parent(struct clk_hw *hw, u8 index) +{ + struct clk_stm32_mux *mux = to_clk_stm32_mux(hw); + unsigned long flags = 0; + + spin_lock_irqsave(mux->lock, flags); + + stm32_mux_set_parent(mux->base, mux->clock_data, mux->mux_id, index); + + spin_unlock_irqrestore(mux->lock, flags); + + return 0; +} + +const struct clk_ops clk_stm32_mux_ops = { + .get_parent = clk_stm32_mux_get_parent, + .set_parent = clk_stm32_mux_set_parent, +}; + +static void clk_stm32_gate_endisable(struct clk_hw *hw, int enable) +{ + struct clk_stm32_gate *gate = to_clk_stm32_gate(hw); + unsigned long flags = 0; + + spin_lock_irqsave(gate->lock, flags); + + stm32_gate_endisable(gate->base, gate->clock_data, gate->gate_id, enable); + + spin_unlock_irqrestore(gate->lock, flags); +} + +static int clk_stm32_gate_enable(struct clk_hw *hw) +{ + clk_stm32_gate_endisable(hw, 1); + + return 0; +} + +static void clk_stm32_gate_disable(struct clk_hw *hw) +{ + clk_stm32_gate_endisable(hw, 0); +} + +static int clk_stm32_gate_is_enabled(struct clk_hw *hw) +{ + struct clk_stm32_gate *gate = to_clk_stm32_gate(hw); + + return stm32_gate_is_enabled(gate->base, gate->clock_data, gate->gate_id); +} + +static void clk_stm32_gate_disable_unused(struct clk_hw *hw) +{ + struct clk_stm32_gate *gate = to_clk_stm32_gate(hw); + unsigned long flags = 0; + + spin_lock_irqsave(gate->lock, flags); + + stm32_gate_disable_unused(gate->base, gate->clock_data, gate->gate_id); + + spin_unlock_irqrestore(gate->lock, flags); +} + +const struct clk_ops clk_stm32_gate_ops = { + .enable = clk_stm32_gate_enable, + .disable = clk_stm32_gate_disable, + .is_enabled = clk_stm32_gate_is_enabled, + .disable_unused = clk_stm32_gate_disable_unused, +}; + +static int clk_stm32_divider_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct clk_stm32_div *div = to_clk_stm32_divider(hw); + unsigned long flags = 0; + int ret; + + if (div->div_id == NO_STM32_DIV) + return rate; + + spin_lock_irqsave(div->lock, flags); + + ret = stm32_divider_set_rate(div->base, div->clock_data, div->div_id, rate, parent_rate); + + spin_unlock_irqrestore(div->lock, flags); + + return ret; +} + +static long clk_stm32_divider_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *prate) +{ + struct clk_stm32_div *div = to_clk_stm32_divider(hw); + const struct stm32_div_cfg *divider; + + if (div->div_id == NO_STM32_DIV) + return rate; + + divider = &div->clock_data->dividers[div->div_id]; + + /* if read only, just return current value */ + if (divider->flags & CLK_DIVIDER_READ_ONLY) { + u32 val; + + val = readl(div->base + divider->offset) >> divider->shift; + val &= clk_div_mask(divider->width); + + return divider_ro_round_rate(hw, rate, prate, divider->table, + divider->width, divider->flags, + val); + } + + return divider_round_rate_parent(hw, clk_hw_get_parent(hw), + rate, prate, divider->table, + divider->width, divider->flags); +} + +static unsigned long clk_stm32_divider_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct clk_stm32_div *div = to_clk_stm32_divider(hw); + + if (div->div_id == NO_STM32_DIV) + return parent_rate; + + return stm32_divider_get_rate(div->base, div->clock_data, div->div_id, parent_rate); +} + +const struct clk_ops clk_stm32_divider_ops = { + .recalc_rate = clk_stm32_divider_recalc_rate, + .round_rate = clk_stm32_divider_round_rate, + .set_rate = clk_stm32_divider_set_rate, +}; + +static int clk_stm32_composite_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct clk_stm32_composite *composite = to_clk_stm32_composite(hw); + unsigned long flags = 0; + int ret; + + if (composite->div_id == NO_STM32_DIV) + return rate; + + spin_lock_irqsave(composite->lock, flags); + + ret = stm32_divider_set_rate(composite->base, composite->clock_data, + composite->div_id, rate, parent_rate); + + spin_unlock_irqrestore(composite->lock, flags); + + return ret; +} + +static unsigned long clk_stm32_composite_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct clk_stm32_composite *composite = to_clk_stm32_composite(hw); + + if (composite->div_id == NO_STM32_DIV) + return parent_rate; + + return stm32_divider_get_rate(composite->base, composite->clock_data, + composite->div_id, parent_rate); +} + +static long clk_stm32_composite_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *prate) +{ + struct clk_stm32_composite *composite = to_clk_stm32_composite(hw); + + const struct stm32_div_cfg *divider; + + if (composite->div_id == NO_STM32_DIV) + return rate; + + divider = &composite->clock_data->dividers[composite->div_id]; + + /* if read only, just return current value */ + if (divider->flags & CLK_DIVIDER_READ_ONLY) { + u32 val; + + val = readl(composite->base + divider->offset) >> divider->shift; + val &= clk_div_mask(divider->width); + + return divider_ro_round_rate(hw, rate, prate, divider->table, + divider->width, divider->flags, + val); + } + + return divider_round_rate_parent(hw, clk_hw_get_parent(hw), + rate, prate, divider->table, + divider->width, divider->flags); +} + +static u8 clk_stm32_composite_get_parent(struct clk_hw *hw) +{ + struct clk_stm32_composite *composite = to_clk_stm32_composite(hw); + + return stm32_mux_get_parent(composite->base, composite->clock_data, composite->mux_id); +} + +static int clk_stm32_composite_set_parent(struct clk_hw *hw, u8 index) +{ + struct clk_stm32_composite *composite = to_clk_stm32_composite(hw); + unsigned long flags = 0; + + spin_lock_irqsave(composite->lock, flags); + + stm32_mux_set_parent(composite->base, composite->clock_data, composite->mux_id, index); + + spin_unlock_irqrestore(composite->lock, flags); + + if (composite->clock_data->is_multi_mux) { + struct clk_hw *other_mux_hw = composite->clock_data->is_multi_mux(hw); + + if (other_mux_hw) { + struct clk_hw *hwp = clk_hw_get_parent_by_index(hw, index); + + clk_hw_reparent(other_mux_hw, hwp); + } + } + + return 0; +} + +static int clk_stm32_composite_is_enabled(struct clk_hw *hw) +{ + struct clk_stm32_composite *composite = to_clk_stm32_composite(hw); + + if (composite->gate_id == NO_STM32_GATE) + return (__clk_get_enable_count(hw->clk) > 0); + + return stm32_gate_is_enabled(composite->base, composite->clock_data, composite->gate_id); +} + +#define MUX_SAFE_POSITION 0 + +static int clk_stm32_has_safe_mux(struct clk_hw *hw) +{ + struct clk_stm32_composite *composite = to_clk_stm32_composite(hw); + const struct stm32_mux_cfg *mux = &composite->clock_data->muxes[composite->mux_id]; + + return !!(mux->flags & MUX_SAFE); +} + +static void clk_stm32_set_safe_position_mux(struct clk_hw *hw) +{ + struct clk_stm32_composite *composite = to_clk_stm32_composite(hw); + + if (!clk_stm32_composite_is_enabled(hw)) { + unsigned long flags = 0; + + if (composite->clock_data->is_multi_mux) { + struct clk_hw *other_mux_hw = NULL; + + other_mux_hw = composite->clock_data->is_multi_mux(hw); + + if (!other_mux_hw || clk_stm32_composite_is_enabled(other_mux_hw)) + return; + } + + spin_lock_irqsave(composite->lock, flags); + + stm32_mux_set_parent(composite->base, composite->clock_data, + composite->mux_id, MUX_SAFE_POSITION); + + spin_unlock_irqrestore(composite->lock, flags); + } +} + +static void clk_stm32_safe_restore_position_mux(struct clk_hw *hw) +{ + struct clk_stm32_composite *composite = to_clk_stm32_composite(hw); + int sel = clk_hw_get_parent_index(hw); + unsigned long flags = 0; + + spin_lock_irqsave(composite->lock, flags); + + stm32_mux_set_parent(composite->base, composite->clock_data, composite->mux_id, sel); + + spin_unlock_irqrestore(composite->lock, flags); +} + +static void clk_stm32_composite_gate_endisable(struct clk_hw *hw, int enable) +{ + struct clk_stm32_composite *composite = to_clk_stm32_composite(hw); + unsigned long flags = 0; + + spin_lock_irqsave(composite->lock, flags); + + stm32_gate_endisable(composite->base, composite->clock_data, composite->gate_id, enable); + + spin_unlock_irqrestore(composite->lock, flags); +} + +static int clk_stm32_composite_gate_enable(struct clk_hw *hw) +{ + struct clk_stm32_composite *composite = to_clk_stm32_composite(hw); + + if (composite->gate_id == NO_STM32_GATE) + return 0; + + clk_stm32_composite_gate_endisable(hw, 1); + + if (composite->mux_id != NO_STM32_MUX && clk_stm32_has_safe_mux(hw)) + clk_stm32_safe_restore_position_mux(hw); + + return 0; +} + +static void clk_stm32_composite_gate_disable(struct clk_hw *hw) +{ + struct clk_stm32_composite *composite = to_clk_stm32_composite(hw); + + if (composite->gate_id == NO_STM32_GATE) + return; + + clk_stm32_composite_gate_endisable(hw, 0); + + if (composite->mux_id != NO_STM32_MUX && clk_stm32_has_safe_mux(hw)) + clk_stm32_set_safe_position_mux(hw); +} + +static void clk_stm32_composite_disable_unused(struct clk_hw *hw) +{ + struct clk_stm32_composite *composite = to_clk_stm32_composite(hw); + unsigned long flags = 0; + + if (composite->gate_id == NO_STM32_GATE) + return; + + spin_lock_irqsave(composite->lock, flags); + + stm32_gate_disable_unused(composite->base, composite->clock_data, composite->gate_id); + + spin_unlock_irqrestore(composite->lock, flags); +} + +const struct clk_ops clk_stm32_composite_ops = { + .set_rate = clk_stm32_composite_set_rate, + .recalc_rate = clk_stm32_composite_recalc_rate, + .round_rate = clk_stm32_composite_round_rate, + .get_parent = clk_stm32_composite_get_parent, + .set_parent = clk_stm32_composite_set_parent, + .enable = clk_stm32_composite_gate_enable, + .disable = clk_stm32_composite_gate_disable, + .is_enabled = clk_stm32_composite_is_enabled, + .disable_unused = clk_stm32_composite_disable_unused, +}; + +struct clk_hw *clk_stm32_mux_register(struct device *dev, + const struct stm32_rcc_match_data *data, + void __iomem *base, + spinlock_t *lock, + const struct clock_config *cfg) +{ + struct clk_stm32_mux *mux = cfg->clock_cfg; + struct clk_hw *hw = &mux->hw; + int err; + + mux->base = base; + mux->lock = lock; + mux->clock_data = data->clock_data; + + err = clk_hw_register(dev, hw); + if (err) + return ERR_PTR(err); + + return hw; +} + +struct clk_hw *clk_stm32_gate_register(struct device *dev, + const struct stm32_rcc_match_data *data, + void __iomem *base, + spinlock_t *lock, + const struct clock_config *cfg) +{ + struct clk_stm32_gate *gate = cfg->clock_cfg; + struct clk_hw *hw = &gate->hw; + int err; + + gate->base = base; + gate->lock = lock; + gate->clock_data = data->clock_data; + + err = clk_hw_register(dev, hw); + if (err) + return ERR_PTR(err); + + return hw; +} + +struct clk_hw *clk_stm32_div_register(struct device *dev, + const struct stm32_rcc_match_data *data, + void __iomem *base, + spinlock_t *lock, + const struct clock_config *cfg) +{ + struct clk_stm32_div *div = cfg->clock_cfg; + struct clk_hw *hw = &div->hw; + int err; + + div->base = base; + div->lock = lock; + div->clock_data = data->clock_data; + + err = clk_hw_register(dev, hw); + if (err) + return ERR_PTR(err); + + return hw; +} + +struct clk_hw *clk_stm32_composite_register(struct device *dev, + const struct stm32_rcc_match_data *data, + void __iomem *base, + spinlock_t *lock, + const struct clock_config *cfg) +{ + struct clk_stm32_composite *composite = cfg->clock_cfg; + struct clk_hw *hw = &composite->hw; + int err; + + composite->base = base; + composite->lock = lock; + composite->clock_data = data->clock_data; + + err = clk_hw_register(dev, hw); + if (err) + return ERR_PTR(err); + + return hw; +} diff --git a/drivers/clk/stm32/clk-stm32-core.h b/drivers/clk/stm32/clk-stm32-core.h new file mode 100644 index 0000000000000000000000000000000000000000..76cffda0230848f4fbe4e9a5eab5e4c4782beffb --- /dev/null +++ b/drivers/clk/stm32/clk-stm32-core.h @@ -0,0 +1,188 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) STMicroelectronics 2022 - All Rights Reserved + * Author: Gabriel Fernandez for STMicroelectronics. + */ + +#include + +struct stm32_rcc_match_data; + +struct stm32_mux_cfg { + u16 offset; + u8 shift; + u8 width; + u8 flags; + u32 *table; + u8 ready; +}; + +struct stm32_gate_cfg { + u16 offset; + u8 bit_idx; + u8 set_clr; +}; + +struct stm32_div_cfg { + u16 offset; + u8 shift; + u8 width; + u8 flags; + u8 ready; + const struct clk_div_table *table; +}; + +struct stm32_composite_cfg { + int mux; + int gate; + int div; +}; + +#define NO_ID 0xFFFFFFFF + +#define NO_STM32_MUX 0xFFFF +#define NO_STM32_DIV 0xFFFF +#define NO_STM32_GATE 0xFFFF + +struct clock_config { + unsigned long id; + int sec_id; + void *clock_cfg; + + struct clk_hw *(*func)(struct device *dev, + const struct stm32_rcc_match_data *data, + void __iomem *base, + spinlock_t *lock, + const struct clock_config *cfg); +}; + +struct clk_stm32_clock_data { + u16 *gate_cpt; + const struct stm32_gate_cfg *gates; + const struct stm32_mux_cfg *muxes; + const struct stm32_div_cfg *dividers; + struct clk_hw *(*is_multi_mux)(struct clk_hw *hw); +}; + +struct stm32_rcc_match_data { + struct clk_hw_onecell_data *hw_clks; + unsigned int num_clocks; + const struct clock_config *tab_clocks; + unsigned int maxbinding; + struct clk_stm32_clock_data *clock_data; + u32 clear_offset; + int (*check_security)(void __iomem *base, + const struct clock_config *cfg); + int (*multi_mux)(void __iomem *base, const struct clock_config *cfg); +}; + +int stm32_rcc_reset_init(struct device *dev, const struct of_device_id *match, + void __iomem *base); + +int stm32_rcc_init(struct device *dev, const struct of_device_id *match_data, + void __iomem *base); + +/* MUX define */ +#define MUX_NO_RDY 0xFF +#define MUX_SAFE BIT(7) + +/* DIV define */ +#define DIV_NO_RDY 0xFF + +/* Definition of clock structure */ +struct clk_stm32_mux { + u16 mux_id; + struct clk_hw hw; + void __iomem *base; + struct clk_stm32_clock_data *clock_data; + spinlock_t *lock; /* spin lock */ +}; + +#define to_clk_stm32_mux(_hw) container_of(_hw, struct clk_stm32_mux, hw) + +struct clk_stm32_gate { + u16 gate_id; + struct clk_hw hw; + void __iomem *base; + struct clk_stm32_clock_data *clock_data; + spinlock_t *lock; /* spin lock */ +}; + +#define to_clk_stm32_gate(_hw) container_of(_hw, struct clk_stm32_gate, hw) + +struct clk_stm32_div { + u16 div_id; + struct clk_hw hw; + void __iomem *base; + struct clk_stm32_clock_data *clock_data; + spinlock_t *lock; /* spin lock */ +}; + +#define to_clk_stm32_divider(_hw) container_of(_hw, struct clk_stm32_div, hw) + +struct clk_stm32_composite { + u16 gate_id; + u16 mux_id; + u16 div_id; + struct clk_hw hw; + void __iomem *base; + struct clk_stm32_clock_data *clock_data; + spinlock_t *lock; /* spin lock */ +}; + +#define to_clk_stm32_composite(_hw) container_of(_hw, struct clk_stm32_composite, hw) + +/* Clock operators */ +extern const struct clk_ops clk_stm32_mux_ops; +extern const struct clk_ops clk_stm32_gate_ops; +extern const struct clk_ops clk_stm32_divider_ops; +extern const struct clk_ops clk_stm32_composite_ops; + +/* Clock registering */ +struct clk_hw *clk_stm32_mux_register(struct device *dev, + const struct stm32_rcc_match_data *data, + void __iomem *base, + spinlock_t *lock, + const struct clock_config *cfg); + +struct clk_hw *clk_stm32_gate_register(struct device *dev, + const struct stm32_rcc_match_data *data, + void __iomem *base, + spinlock_t *lock, + const struct clock_config *cfg); + +struct clk_hw *clk_stm32_div_register(struct device *dev, + const struct stm32_rcc_match_data *data, + void __iomem *base, + spinlock_t *lock, + const struct clock_config *cfg); + +struct clk_hw *clk_stm32_composite_register(struct device *dev, + const struct stm32_rcc_match_data *data, + void __iomem *base, + spinlock_t *lock, + const struct clock_config *cfg); + +#define STM32_CLOCK_CFG(_binding, _clk, _sec_id, _struct, _register)\ +{\ + .id = (_binding),\ + .sec_id = (_sec_id),\ + .clock_cfg = (_struct) {_clk},\ + .func = (_register),\ +} + +#define STM32_MUX_CFG(_binding, _clk, _sec_id)\ + STM32_CLOCK_CFG(_binding, &(_clk), _sec_id, struct clk_stm32_mux *,\ + &clk_stm32_mux_register) + +#define STM32_GATE_CFG(_binding, _clk, _sec_id)\ + STM32_CLOCK_CFG(_binding, &(_clk), _sec_id, struct clk_stm32_gate *,\ + &clk_stm32_gate_register) + +#define STM32_DIV_CFG(_binding, _clk, _sec_id)\ + STM32_CLOCK_CFG(_binding, &(_clk), _sec_id, struct clk_stm32_div *,\ + &clk_stm32_div_register) + +#define STM32_COMPOSITE_CFG(_binding, _clk, _sec_id)\ + STM32_CLOCK_CFG(_binding, &(_clk), _sec_id, struct clk_stm32_composite *,\ + &clk_stm32_composite_register) diff --git a/drivers/clk/stm32/clk-stm32mp13.c b/drivers/clk/stm32/clk-stm32mp13.c new file mode 100644 index 0000000000000000000000000000000000000000..1192eee8abe48082828df6c09e4bd915fa341318 --- /dev/null +++ b/drivers/clk/stm32/clk-stm32mp13.c @@ -0,0 +1,1620 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) STMicroelectronics 2022 - All Rights Reserved + * Author: Gabriel Fernandez for STMicroelectronics. + */ + +#include +#include +#include +#include +#include +#include "clk-stm32-core.h" +#include "stm32mp13_rcc.h" + +#define RCC_CLR_OFFSET 0x4 + +/* STM32 Gates definition */ +enum enum_gate_cfg { + GATE_MCO1, + GATE_MCO2, + GATE_DBGCK, + GATE_TRACECK, + GATE_DDRC1, + GATE_DDRC1LP, + GATE_DDRPHYC, + GATE_DDRPHYCLP, + GATE_DDRCAPB, + GATE_DDRCAPBLP, + GATE_AXIDCG, + GATE_DDRPHYCAPB, + GATE_DDRPHYCAPBLP, + GATE_TIM2, + GATE_TIM3, + GATE_TIM4, + GATE_TIM5, + GATE_TIM6, + GATE_TIM7, + GATE_LPTIM1, + GATE_SPI2, + GATE_SPI3, + GATE_USART3, + GATE_UART4, + GATE_UART5, + GATE_UART7, + GATE_UART8, + GATE_I2C1, + GATE_I2C2, + GATE_SPDIF, + GATE_TIM1, + GATE_TIM8, + GATE_SPI1, + GATE_USART6, + GATE_SAI1, + GATE_SAI2, + GATE_DFSDM, + GATE_ADFSDM, + GATE_FDCAN, + GATE_LPTIM2, + GATE_LPTIM3, + GATE_LPTIM4, + GATE_LPTIM5, + GATE_VREF, + GATE_DTS, + GATE_PMBCTRL, + GATE_HDP, + GATE_SYSCFG, + GATE_DCMIPP, + GATE_DDRPERFM, + GATE_IWDG2APB, + GATE_USBPHY, + GATE_STGENRO, + GATE_LTDC, + GATE_RTCAPB, + GATE_TZC, + GATE_ETZPC, + GATE_IWDG1APB, + GATE_BSEC, + GATE_STGENC, + GATE_USART1, + GATE_USART2, + GATE_SPI4, + GATE_SPI5, + GATE_I2C3, + GATE_I2C4, + GATE_I2C5, + GATE_TIM12, + GATE_TIM13, + GATE_TIM14, + GATE_TIM15, + GATE_TIM16, + GATE_TIM17, + GATE_DMA1, + GATE_DMA2, + GATE_DMAMUX1, + GATE_DMA3, + GATE_DMAMUX2, + GATE_ADC1, + GATE_ADC2, + GATE_USBO, + GATE_TSC, + GATE_GPIOA, + GATE_GPIOB, + GATE_GPIOC, + GATE_GPIOD, + GATE_GPIOE, + GATE_GPIOF, + GATE_GPIOG, + GATE_GPIOH, + GATE_GPIOI, + GATE_PKA, + GATE_SAES, + GATE_CRYP1, + GATE_HASH1, + GATE_RNG1, + GATE_BKPSRAM, + GATE_AXIMC, + GATE_MCE, + GATE_ETH1CK, + GATE_ETH1TX, + GATE_ETH1RX, + GATE_ETH1MAC, + GATE_FMC, + GATE_QSPI, + GATE_SDMMC1, + GATE_SDMMC2, + GATE_CRC1, + GATE_USBH, + GATE_ETH2CK, + GATE_ETH2TX, + GATE_ETH2RX, + GATE_ETH2MAC, + GATE_ETH1STP, + GATE_ETH2STP, + GATE_MDMA, + GATE_NB +}; + +#define _CFG_GATE(_id, _offset, _bit_idx, _offset_clr)\ + [(_id)] = {\ + .offset = (_offset),\ + .bit_idx = (_bit_idx),\ + .set_clr = (_offset_clr),\ + } + +#define CFG_GATE(_id, _offset, _bit_idx)\ + _CFG_GATE(_id, _offset, _bit_idx, 0) + +#define CFG_GATE_SETCLR(_id, _offset, _bit_idx)\ + _CFG_GATE(_id, _offset, _bit_idx, RCC_CLR_OFFSET) + +static struct stm32_gate_cfg stm32mp13_gates[] = { + CFG_GATE(GATE_MCO1, RCC_MCO1CFGR, 12), + CFG_GATE(GATE_MCO2, RCC_MCO2CFGR, 12), + CFG_GATE(GATE_DBGCK, RCC_DBGCFGR, 8), + CFG_GATE(GATE_TRACECK, RCC_DBGCFGR, 9), + CFG_GATE(GATE_DDRC1, RCC_DDRITFCR, 0), + CFG_GATE(GATE_DDRC1LP, RCC_DDRITFCR, 1), + CFG_GATE(GATE_DDRPHYC, RCC_DDRITFCR, 4), + CFG_GATE(GATE_DDRPHYCLP, RCC_DDRITFCR, 5), + CFG_GATE(GATE_DDRCAPB, RCC_DDRITFCR, 6), + CFG_GATE(GATE_DDRCAPBLP, RCC_DDRITFCR, 7), + CFG_GATE(GATE_AXIDCG, RCC_DDRITFCR, 8), + CFG_GATE(GATE_DDRPHYCAPB, RCC_DDRITFCR, 9), + CFG_GATE(GATE_DDRPHYCAPBLP, RCC_DDRITFCR, 10), + CFG_GATE_SETCLR(GATE_TIM2, RCC_MP_APB1ENSETR, 0), + CFG_GATE_SETCLR(GATE_TIM3, RCC_MP_APB1ENSETR, 1), + CFG_GATE_SETCLR(GATE_TIM4, RCC_MP_APB1ENSETR, 2), + CFG_GATE_SETCLR(GATE_TIM5, RCC_MP_APB1ENSETR, 3), + CFG_GATE_SETCLR(GATE_TIM6, RCC_MP_APB1ENSETR, 4), + CFG_GATE_SETCLR(GATE_TIM7, RCC_MP_APB1ENSETR, 5), + CFG_GATE_SETCLR(GATE_LPTIM1, RCC_MP_APB1ENSETR, 9), + CFG_GATE_SETCLR(GATE_SPI2, RCC_MP_APB1ENSETR, 11), + CFG_GATE_SETCLR(GATE_SPI3, RCC_MP_APB1ENSETR, 12), + CFG_GATE_SETCLR(GATE_USART3, RCC_MP_APB1ENSETR, 15), + CFG_GATE_SETCLR(GATE_UART4, RCC_MP_APB1ENSETR, 16), + CFG_GATE_SETCLR(GATE_UART5, RCC_MP_APB1ENSETR, 17), + CFG_GATE_SETCLR(GATE_UART7, RCC_MP_APB1ENSETR, 18), + CFG_GATE_SETCLR(GATE_UART8, RCC_MP_APB1ENSETR, 19), + CFG_GATE_SETCLR(GATE_I2C1, RCC_MP_APB1ENSETR, 21), + CFG_GATE_SETCLR(GATE_I2C2, RCC_MP_APB1ENSETR, 22), + CFG_GATE_SETCLR(GATE_SPDIF, RCC_MP_APB1ENSETR, 26), + CFG_GATE_SETCLR(GATE_TIM1, RCC_MP_APB2ENSETR, 0), + CFG_GATE_SETCLR(GATE_TIM8, RCC_MP_APB2ENSETR, 1), + CFG_GATE_SETCLR(GATE_SPI1, RCC_MP_APB2ENSETR, 8), + CFG_GATE_SETCLR(GATE_USART6, RCC_MP_APB2ENSETR, 13), + CFG_GATE_SETCLR(GATE_SAI1, RCC_MP_APB2ENSETR, 16), + CFG_GATE_SETCLR(GATE_SAI2, RCC_MP_APB2ENSETR, 17), + CFG_GATE_SETCLR(GATE_DFSDM, RCC_MP_APB2ENSETR, 20), + CFG_GATE_SETCLR(GATE_ADFSDM, RCC_MP_APB2ENSETR, 21), + CFG_GATE_SETCLR(GATE_FDCAN, RCC_MP_APB2ENSETR, 24), + CFG_GATE_SETCLR(GATE_LPTIM2, RCC_MP_APB3ENSETR, 0), + CFG_GATE_SETCLR(GATE_LPTIM3, RCC_MP_APB3ENSETR, 1), + CFG_GATE_SETCLR(GATE_LPTIM4, RCC_MP_APB3ENSETR, 2), + CFG_GATE_SETCLR(GATE_LPTIM5, RCC_MP_APB3ENSETR, 3), + CFG_GATE_SETCLR(GATE_VREF, RCC_MP_APB3ENSETR, 13), + CFG_GATE_SETCLR(GATE_DTS, RCC_MP_APB3ENSETR, 16), + CFG_GATE_SETCLR(GATE_PMBCTRL, RCC_MP_APB3ENSETR, 17), + CFG_GATE_SETCLR(GATE_HDP, RCC_MP_APB3ENSETR, 20), + CFG_GATE_SETCLR(GATE_SYSCFG, RCC_MP_NS_APB3ENSETR, 0), + CFG_GATE_SETCLR(GATE_DCMIPP, RCC_MP_APB4ENSETR, 1), + CFG_GATE_SETCLR(GATE_DDRPERFM, RCC_MP_APB4ENSETR, 8), + CFG_GATE_SETCLR(GATE_IWDG2APB, RCC_MP_APB4ENSETR, 15), + CFG_GATE_SETCLR(GATE_USBPHY, RCC_MP_APB4ENSETR, 16), + CFG_GATE_SETCLR(GATE_STGENRO, RCC_MP_APB4ENSETR, 20), + CFG_GATE_SETCLR(GATE_LTDC, RCC_MP_NS_APB4ENSETR, 0), + CFG_GATE_SETCLR(GATE_RTCAPB, RCC_MP_APB5ENSETR, 8), + CFG_GATE_SETCLR(GATE_TZC, RCC_MP_APB5ENSETR, 11), + CFG_GATE_SETCLR(GATE_ETZPC, RCC_MP_APB5ENSETR, 13), + CFG_GATE_SETCLR(GATE_IWDG1APB, RCC_MP_APB5ENSETR, 15), + CFG_GATE_SETCLR(GATE_BSEC, RCC_MP_APB5ENSETR, 16), + CFG_GATE_SETCLR(GATE_STGENC, RCC_MP_APB5ENSETR, 20), + CFG_GATE_SETCLR(GATE_USART1, RCC_MP_APB6ENSETR, 0), + CFG_GATE_SETCLR(GATE_USART2, RCC_MP_APB6ENSETR, 1), + CFG_GATE_SETCLR(GATE_SPI4, RCC_MP_APB6ENSETR, 2), + CFG_GATE_SETCLR(GATE_SPI5, RCC_MP_APB6ENSETR, 3), + CFG_GATE_SETCLR(GATE_I2C3, RCC_MP_APB6ENSETR, 4), + CFG_GATE_SETCLR(GATE_I2C4, RCC_MP_APB6ENSETR, 5), + CFG_GATE_SETCLR(GATE_I2C5, RCC_MP_APB6ENSETR, 6), + CFG_GATE_SETCLR(GATE_TIM12, RCC_MP_APB6ENSETR, 7), + CFG_GATE_SETCLR(GATE_TIM13, RCC_MP_APB6ENSETR, 8), + CFG_GATE_SETCLR(GATE_TIM14, RCC_MP_APB6ENSETR, 9), + CFG_GATE_SETCLR(GATE_TIM15, RCC_MP_APB6ENSETR, 10), + CFG_GATE_SETCLR(GATE_TIM16, RCC_MP_APB6ENSETR, 11), + CFG_GATE_SETCLR(GATE_TIM17, RCC_MP_APB6ENSETR, 12), + CFG_GATE_SETCLR(GATE_DMA1, RCC_MP_AHB2ENSETR, 0), + CFG_GATE_SETCLR(GATE_DMA2, RCC_MP_AHB2ENSETR, 1), + CFG_GATE_SETCLR(GATE_DMAMUX1, RCC_MP_AHB2ENSETR, 2), + CFG_GATE_SETCLR(GATE_DMA3, RCC_MP_AHB2ENSETR, 3), + CFG_GATE_SETCLR(GATE_DMAMUX2, RCC_MP_AHB2ENSETR, 4), + CFG_GATE_SETCLR(GATE_ADC1, RCC_MP_AHB2ENSETR, 5), + CFG_GATE_SETCLR(GATE_ADC2, RCC_MP_AHB2ENSETR, 6), + CFG_GATE_SETCLR(GATE_USBO, RCC_MP_AHB2ENSETR, 8), + CFG_GATE_SETCLR(GATE_TSC, RCC_MP_AHB4ENSETR, 15), + CFG_GATE_SETCLR(GATE_GPIOA, RCC_MP_NS_AHB4ENSETR, 0), + CFG_GATE_SETCLR(GATE_GPIOB, RCC_MP_NS_AHB4ENSETR, 1), + CFG_GATE_SETCLR(GATE_GPIOC, RCC_MP_NS_AHB4ENSETR, 2), + CFG_GATE_SETCLR(GATE_GPIOD, RCC_MP_NS_AHB4ENSETR, 3), + CFG_GATE_SETCLR(GATE_GPIOE, RCC_MP_NS_AHB4ENSETR, 4), + CFG_GATE_SETCLR(GATE_GPIOF, RCC_MP_NS_AHB4ENSETR, 5), + CFG_GATE_SETCLR(GATE_GPIOG, RCC_MP_NS_AHB4ENSETR, 6), + CFG_GATE_SETCLR(GATE_GPIOH, RCC_MP_NS_AHB4ENSETR, 7), + CFG_GATE_SETCLR(GATE_GPIOI, RCC_MP_NS_AHB4ENSETR, 8), + CFG_GATE_SETCLR(GATE_PKA, RCC_MP_AHB5ENSETR, 2), + CFG_GATE_SETCLR(GATE_SAES, RCC_MP_AHB5ENSETR, 3), + CFG_GATE_SETCLR(GATE_CRYP1, RCC_MP_AHB5ENSETR, 4), + CFG_GATE_SETCLR(GATE_HASH1, RCC_MP_AHB5ENSETR, 5), + CFG_GATE_SETCLR(GATE_RNG1, RCC_MP_AHB5ENSETR, 6), + CFG_GATE_SETCLR(GATE_BKPSRAM, RCC_MP_AHB5ENSETR, 8), + CFG_GATE_SETCLR(GATE_AXIMC, RCC_MP_AHB5ENSETR, 16), + CFG_GATE_SETCLR(GATE_MCE, RCC_MP_AHB6ENSETR, 1), + CFG_GATE_SETCLR(GATE_ETH1CK, RCC_MP_AHB6ENSETR, 7), + CFG_GATE_SETCLR(GATE_ETH1TX, RCC_MP_AHB6ENSETR, 8), + CFG_GATE_SETCLR(GATE_ETH1RX, RCC_MP_AHB6ENSETR, 9), + CFG_GATE_SETCLR(GATE_ETH1MAC, RCC_MP_AHB6ENSETR, 10), + CFG_GATE_SETCLR(GATE_FMC, RCC_MP_AHB6ENSETR, 12), + CFG_GATE_SETCLR(GATE_QSPI, RCC_MP_AHB6ENSETR, 14), + CFG_GATE_SETCLR(GATE_SDMMC1, RCC_MP_AHB6ENSETR, 16), + CFG_GATE_SETCLR(GATE_SDMMC2, RCC_MP_AHB6ENSETR, 17), + CFG_GATE_SETCLR(GATE_CRC1, RCC_MP_AHB6ENSETR, 20), + CFG_GATE_SETCLR(GATE_USBH, RCC_MP_AHB6ENSETR, 24), + CFG_GATE_SETCLR(GATE_ETH2CK, RCC_MP_AHB6ENSETR, 27), + CFG_GATE_SETCLR(GATE_ETH2TX, RCC_MP_AHB6ENSETR, 28), + CFG_GATE_SETCLR(GATE_ETH2RX, RCC_MP_AHB6ENSETR, 29), + CFG_GATE_SETCLR(GATE_ETH2MAC, RCC_MP_AHB6ENSETR, 30), + CFG_GATE_SETCLR(GATE_ETH1STP, RCC_MP_AHB6LPENSETR, 11), + CFG_GATE_SETCLR(GATE_ETH2STP, RCC_MP_AHB6LPENSETR, 31), + CFG_GATE_SETCLR(GATE_MDMA, RCC_MP_NS_AHB6ENSETR, 0), +}; + +/* STM32 Divivers definition */ +enum enum_div_cfg { + DIV_RTC, + DIV_HSI, + DIV_MCO1, + DIV_MCO2, + DIV_TRACE, + DIV_ETH1PTP, + DIV_ETH2PTP, + DIV_NB +}; + +static const struct clk_div_table ck_trace_div_table[] = { + { 0, 1 }, { 1, 2 }, { 2, 4 }, { 3, 8 }, + { 4, 16 }, { 5, 16 }, { 6, 16 }, { 7, 16 }, + { 0 }, +}; + +#define CFG_DIV(_id, _offset, _shift, _width, _flags, _table, _ready)\ + [(_id)] = {\ + .offset = (_offset),\ + .shift = (_shift),\ + .width = (_width),\ + .flags = (_flags),\ + .table = (_table),\ + .ready = (_ready),\ + } + +static const struct stm32_div_cfg stm32mp13_dividers[DIV_NB] = { + CFG_DIV(DIV_RTC, RCC_RTCDIVR, 0, 6, 0, NULL, DIV_NO_RDY), + CFG_DIV(DIV_MCO1, RCC_MCO1CFGR, 4, 4, 0, NULL, DIV_NO_RDY), + CFG_DIV(DIV_MCO2, RCC_MCO2CFGR, 4, 4, 0, NULL, DIV_NO_RDY), + CFG_DIV(DIV_TRACE, RCC_DBGCFGR, 0, 3, 0, ck_trace_div_table, DIV_NO_RDY), + CFG_DIV(DIV_ETH1PTP, RCC_ETH12CKSELR, 4, 4, 0, NULL, DIV_NO_RDY), + CFG_DIV(DIV_ETH2PTP, RCC_ETH12CKSELR, 12, 4, 0, NULL, DIV_NO_RDY), +}; + +/* STM32 Muxes definition */ +enum enum_mux_cfg { + MUX_ADC1, + MUX_ADC2, + MUX_DCMIPP, + MUX_ETH1, + MUX_ETH2, + MUX_FDCAN, + MUX_FMC, + MUX_I2C12, + MUX_I2C3, + MUX_I2C4, + MUX_I2C5, + MUX_LPTIM1, + MUX_LPTIM2, + MUX_LPTIM3, + MUX_LPTIM45, + MUX_MCO1, + MUX_MCO2, + MUX_QSPI, + MUX_RNG1, + MUX_SAES, + MUX_SAI1, + MUX_SAI2, + MUX_SDMMC1, + MUX_SDMMC2, + MUX_SPDIF, + MUX_SPI1, + MUX_SPI23, + MUX_SPI4, + MUX_SPI5, + MUX_STGEN, + MUX_UART1, + MUX_UART2, + MUX_UART4, + MUX_UART6, + MUX_UART35, + MUX_UART78, + MUX_USBO, + MUX_USBPHY, + MUX_NB +}; + +#define _CFG_MUX(_id, _offset, _shift, _witdh, _ready, _flags)\ + [_id] = {\ + .offset = (_offset),\ + .shift = (_shift),\ + .width = (_witdh),\ + .ready = (_ready),\ + .flags = (_flags),\ + } + +#define CFG_MUX(_id, _offset, _shift, _witdh)\ + _CFG_MUX(_id, _offset, _shift, _witdh, MUX_NO_RDY, 0) + +#define CFG_MUX_SAFE(_id, _offset, _shift, _witdh)\ + _CFG_MUX(_id, _offset, _shift, _witdh, MUX_NO_RDY, MUX_SAFE) + +static const struct stm32_mux_cfg stm32mp13_muxes[] = { + CFG_MUX(MUX_I2C12, RCC_I2C12CKSELR, 0, 3), + CFG_MUX(MUX_LPTIM45, RCC_LPTIM45CKSELR, 0, 3), + CFG_MUX(MUX_SPI23, RCC_SPI2S23CKSELR, 0, 3), + CFG_MUX(MUX_UART35, RCC_UART35CKSELR, 0, 3), + CFG_MUX(MUX_UART78, RCC_UART78CKSELR, 0, 3), + CFG_MUX(MUX_ADC1, RCC_ADC12CKSELR, 0, 2), + CFG_MUX(MUX_ADC2, RCC_ADC12CKSELR, 2, 2), + CFG_MUX(MUX_DCMIPP, RCC_DCMIPPCKSELR, 0, 2), + CFG_MUX(MUX_ETH1, RCC_ETH12CKSELR, 0, 2), + CFG_MUX(MUX_ETH2, RCC_ETH12CKSELR, 8, 2), + CFG_MUX(MUX_FDCAN, RCC_FDCANCKSELR, 0, 2), + CFG_MUX(MUX_I2C3, RCC_I2C345CKSELR, 0, 3), + CFG_MUX(MUX_I2C4, RCC_I2C345CKSELR, 3, 3), + CFG_MUX(MUX_I2C5, RCC_I2C345CKSELR, 6, 3), + CFG_MUX(MUX_LPTIM1, RCC_LPTIM1CKSELR, 0, 3), + CFG_MUX(MUX_LPTIM2, RCC_LPTIM23CKSELR, 0, 3), + CFG_MUX(MUX_LPTIM3, RCC_LPTIM23CKSELR, 3, 3), + CFG_MUX(MUX_MCO1, RCC_MCO1CFGR, 0, 3), + CFG_MUX(MUX_MCO2, RCC_MCO2CFGR, 0, 3), + CFG_MUX(MUX_RNG1, RCC_RNG1CKSELR, 0, 2), + CFG_MUX(MUX_SAES, RCC_SAESCKSELR, 0, 2), + CFG_MUX(MUX_SAI1, RCC_SAI1CKSELR, 0, 3), + CFG_MUX(MUX_SAI2, RCC_SAI2CKSELR, 0, 3), + CFG_MUX(MUX_SPDIF, RCC_SPDIFCKSELR, 0, 2), + CFG_MUX(MUX_SPI1, RCC_SPI2S1CKSELR, 0, 3), + CFG_MUX(MUX_SPI4, RCC_SPI45CKSELR, 0, 3), + CFG_MUX(MUX_SPI5, RCC_SPI45CKSELR, 3, 3), + CFG_MUX(MUX_STGEN, RCC_STGENCKSELR, 0, 2), + CFG_MUX(MUX_UART1, RCC_UART12CKSELR, 0, 3), + CFG_MUX(MUX_UART2, RCC_UART12CKSELR, 3, 3), + CFG_MUX(MUX_UART4, RCC_UART4CKSELR, 0, 3), + CFG_MUX(MUX_UART6, RCC_UART6CKSELR, 0, 3), + CFG_MUX(MUX_USBO, RCC_USBCKSELR, 4, 1), + CFG_MUX(MUX_USBPHY, RCC_USBCKSELR, 0, 2), + CFG_MUX_SAFE(MUX_FMC, RCC_FMCCKSELR, 0, 2), + CFG_MUX_SAFE(MUX_QSPI, RCC_QSPICKSELR, 0, 2), + CFG_MUX_SAFE(MUX_SDMMC1, RCC_SDMMC12CKSELR, 0, 3), + CFG_MUX_SAFE(MUX_SDMMC2, RCC_SDMMC12CKSELR, 3, 3), +}; + +struct clk_stm32_securiy { + u32 offset; + u8 bit_idx; + unsigned long scmi_id; +}; + +enum security_clk { + SECF_NONE, + SECF_LPTIM2, + SECF_LPTIM3, + SECF_VREF, + SECF_DCMIPP, + SECF_USBPHY, + SECF_TZC, + SECF_ETZPC, + SECF_IWDG1, + SECF_BSEC, + SECF_STGENC, + SECF_STGENRO, + SECF_USART1, + SECF_USART2, + SECF_SPI4, + SECF_SPI5, + SECF_I2C3, + SECF_I2C4, + SECF_I2C5, + SECF_TIM12, + SECF_TIM13, + SECF_TIM14, + SECF_TIM15, + SECF_TIM16, + SECF_TIM17, + SECF_DMA3, + SECF_DMAMUX2, + SECF_ADC1, + SECF_ADC2, + SECF_USBO, + SECF_TSC, + SECF_PKA, + SECF_SAES, + SECF_CRYP1, + SECF_HASH1, + SECF_RNG1, + SECF_BKPSRAM, + SECF_MCE, + SECF_FMC, + SECF_QSPI, + SECF_SDMMC1, + SECF_SDMMC2, + SECF_ETH1CK, + SECF_ETH1TX, + SECF_ETH1RX, + SECF_ETH1MAC, + SECF_ETH1STP, + SECF_ETH2CK, + SECF_ETH2TX, + SECF_ETH2RX, + SECF_ETH2MAC, + SECF_ETH2STP, + SECF_MCO1, + SECF_MCO2 +}; + +#define SECF(_sec_id, _offset, _bit_idx)[_sec_id] = {\ + .offset = _offset,\ + .bit_idx = _bit_idx,\ + .scmi_id = -1,\ +} + +static const struct clk_stm32_securiy stm32mp13_security[] = { + SECF(SECF_LPTIM2, RCC_APB3SECSR, RCC_APB3SECSR_LPTIM2SECF), + SECF(SECF_LPTIM3, RCC_APB3SECSR, RCC_APB3SECSR_LPTIM3SECF), + SECF(SECF_VREF, RCC_APB3SECSR, RCC_APB3SECSR_VREFSECF), + SECF(SECF_DCMIPP, RCC_APB4SECSR, RCC_APB4SECSR_DCMIPPSECF), + SECF(SECF_USBPHY, RCC_APB4SECSR, RCC_APB4SECSR_USBPHYSECF), + SECF(SECF_TZC, RCC_APB5SECSR, RCC_APB5SECSR_TZCSECF), + SECF(SECF_ETZPC, RCC_APB5SECSR, RCC_APB5SECSR_ETZPCSECF), + SECF(SECF_IWDG1, RCC_APB5SECSR, RCC_APB5SECSR_IWDG1SECF), + SECF(SECF_BSEC, RCC_APB5SECSR, RCC_APB5SECSR_BSECSECF), + SECF(SECF_STGENC, RCC_APB5SECSR, RCC_APB5SECSR_STGENCSECF), + SECF(SECF_STGENRO, RCC_APB5SECSR, RCC_APB5SECSR_STGENROSECF), + SECF(SECF_USART1, RCC_APB6SECSR, RCC_APB6SECSR_USART1SECF), + SECF(SECF_USART2, RCC_APB6SECSR, RCC_APB6SECSR_USART2SECF), + SECF(SECF_SPI4, RCC_APB6SECSR, RCC_APB6SECSR_SPI4SECF), + SECF(SECF_SPI5, RCC_APB6SECSR, RCC_APB6SECSR_SPI5SECF), + SECF(SECF_I2C3, RCC_APB6SECSR, RCC_APB6SECSR_I2C3SECF), + SECF(SECF_I2C4, RCC_APB6SECSR, RCC_APB6SECSR_I2C4SECF), + SECF(SECF_I2C5, RCC_APB6SECSR, RCC_APB6SECSR_I2C5SECF), + SECF(SECF_TIM12, RCC_APB6SECSR, RCC_APB6SECSR_TIM12SECF), + SECF(SECF_TIM13, RCC_APB6SECSR, RCC_APB6SECSR_TIM13SECF), + SECF(SECF_TIM14, RCC_APB6SECSR, RCC_APB6SECSR_TIM14SECF), + SECF(SECF_TIM15, RCC_APB6SECSR, RCC_APB6SECSR_TIM15SECF), + SECF(SECF_TIM16, RCC_APB6SECSR, RCC_APB6SECSR_TIM16SECF), + SECF(SECF_TIM17, RCC_APB6SECSR, RCC_APB6SECSR_TIM17SECF), + SECF(SECF_DMA3, RCC_AHB2SECSR, RCC_AHB2SECSR_DMA3SECF), + SECF(SECF_DMAMUX2, RCC_AHB2SECSR, RCC_AHB2SECSR_DMAMUX2SECF), + SECF(SECF_ADC1, RCC_AHB2SECSR, RCC_AHB2SECSR_ADC1SECF), + SECF(SECF_ADC2, RCC_AHB2SECSR, RCC_AHB2SECSR_ADC2SECF), + SECF(SECF_USBO, RCC_AHB2SECSR, RCC_AHB2SECSR_USBOSECF), + SECF(SECF_TSC, RCC_AHB4SECSR, RCC_AHB4SECSR_TSCSECF), + SECF(SECF_PKA, RCC_AHB5SECSR, RCC_AHB5SECSR_PKASECF), + SECF(SECF_SAES, RCC_AHB5SECSR, RCC_AHB5SECSR_SAESSECF), + SECF(SECF_CRYP1, RCC_AHB5SECSR, RCC_AHB5SECSR_CRYP1SECF), + SECF(SECF_HASH1, RCC_AHB5SECSR, RCC_AHB5SECSR_HASH1SECF), + SECF(SECF_RNG1, RCC_AHB5SECSR, RCC_AHB5SECSR_RNG1SECF), + SECF(SECF_BKPSRAM, RCC_AHB5SECSR, RCC_AHB5SECSR_BKPSRAMSECF), + SECF(SECF_MCE, RCC_AHB6SECSR, RCC_AHB6SECSR_MCESECF), + SECF(SECF_FMC, RCC_AHB6SECSR, RCC_AHB6SECSR_FMCSECF), + SECF(SECF_QSPI, RCC_AHB6SECSR, RCC_AHB6SECSR_QSPISECF), + SECF(SECF_SDMMC1, RCC_AHB6SECSR, RCC_AHB6SECSR_SDMMC1SECF), + SECF(SECF_SDMMC2, RCC_AHB6SECSR, RCC_AHB6SECSR_SDMMC2SECF), + SECF(SECF_ETH1CK, RCC_AHB6SECSR, RCC_AHB6SECSR_ETH1CKSECF), + SECF(SECF_ETH1TX, RCC_AHB6SECSR, RCC_AHB6SECSR_ETH1TXSECF), + SECF(SECF_ETH1RX, RCC_AHB6SECSR, RCC_AHB6SECSR_ETH1RXSECF), + SECF(SECF_ETH1MAC, RCC_AHB6SECSR, RCC_AHB6SECSR_ETH1MACSECF), + SECF(SECF_ETH1STP, RCC_AHB6SECSR, RCC_AHB6SECSR_ETH1STPSECF), + SECF(SECF_ETH2CK, RCC_AHB6SECSR, RCC_AHB6SECSR_ETH2CKSECF), + SECF(SECF_ETH2TX, RCC_AHB6SECSR, RCC_AHB6SECSR_ETH2TXSECF), + SECF(SECF_ETH2RX, RCC_AHB6SECSR, RCC_AHB6SECSR_ETH2RXSECF), + SECF(SECF_ETH2MAC, RCC_AHB6SECSR, RCC_AHB6SECSR_ETH2MACSECF), + SECF(SECF_ETH2STP, RCC_AHB6SECSR, RCC_AHB6SECSR_ETH2STPSECF), + SECF(SECF_MCO1, RCC_SECCFGR, RCC_SECCFGR_MCO1SEC), + SECF(SECF_MCO2, RCC_SECCFGR, RCC_SECCFGR_MCO2SEC), +}; + +static const char * const adc12_src[] = { + "pll4_r", "ck_per", "pll3_q" +}; + +static const char * const dcmipp_src[] = { + "ck_axi", "pll2_q", "pll4_p", "ck_per", +}; + +static const char * const eth12_src[] = { + "pll4_p", "pll3_q" +}; + +static const char * const fdcan_src[] = { + "ck_hse", "pll3_q", "pll4_q", "pll4_r" +}; + +static const char * const fmc_src[] = { + "ck_axi", "pll3_r", "pll4_p", "ck_per" +}; + +static const char * const i2c12_src[] = { + "pclk1", "pll4_r", "ck_hsi", "ck_csi" +}; + +static const char * const i2c345_src[] = { + "pclk6", "pll4_r", "ck_hsi", "ck_csi" +}; + +static const char * const lptim1_src[] = { + "pclk1", "pll4_p", "pll3_q", "ck_lse", "ck_lsi", "ck_per" +}; + +static const char * const lptim23_src[] = { + "pclk3", "pll4_q", "ck_per", "ck_lse", "ck_lsi" +}; + +static const char * const lptim45_src[] = { + "pclk3", "pll4_p", "pll3_q", "ck_lse", "ck_lsi", "ck_per" +}; + +static const char * const mco1_src[] = { + "ck_hsi", "ck_hse", "ck_csi", "ck_lsi", "ck_lse" +}; + +static const char * const mco2_src[] = { + "ck_mpu", "ck_axi", "ck_mlahb", "pll4_p", "ck_hse", "ck_hsi" +}; + +static const char * const qspi_src[] = { + "ck_axi", "pll3_r", "pll4_p", "ck_per" +}; + +static const char * const rng1_src[] = { + "ck_csi", "pll4_r", "ck_lse", "ck_lsi" +}; + +static const char * const saes_src[] = { + "ck_axi", "ck_per", "pll4_r", "ck_lsi" +}; + +static const char * const sai1_src[] = { + "pll4_q", "pll3_q", "i2s_ckin", "ck_per", "pll3_r" +}; + +static const char * const sai2_src[] = { + "pll4_q", "pll3_q", "i2s_ckin", "ck_per", "spdif_ck_symb", "pll3_r" +}; + +static const char * const sdmmc12_src[] = { + "ck_axi", "pll3_r", "pll4_p", "ck_hsi" +}; + +static const char * const spdif_src[] = { + "pll4_p", "pll3_q", "ck_hsi" +}; + +static const char * const spi123_src[] = { + "pll4_p", "pll3_q", "i2s_ckin", "ck_per", "pll3_r" +}; + +static const char * const spi4_src[] = { + "pclk6", "pll4_q", "ck_hsi", "ck_csi", "ck_hse", "i2s_ckin" +}; + +static const char * const spi5_src[] = { + "pclk6", "pll4_q", "ck_hsi", "ck_csi", "ck_hse" +}; + +static const char * const stgen_src[] = { + "ck_hsi", "ck_hse" +}; + +static const char * const usart12_src[] = { + "pclk6", "pll3_q", "ck_hsi", "ck_csi", "pll4_q", "ck_hse" +}; + +static const char * const usart34578_src[] = { + "pclk1", "pll4_q", "ck_hsi", "ck_csi", "ck_hse" +}; + +static const char * const usart6_src[] = { + "pclk2", "pll4_q", "ck_hsi", "ck_csi", "ck_hse" +}; + +static const char * const usbo_src[] = { + "pll4_r", "ck_usbo_48m" +}; + +static const char * const usbphy_src[] = { + "ck_hse", "pll4_r", "clk-hse-div2" +}; + +/* Timer clocks */ +static struct clk_stm32_gate tim2_k = { + .gate_id = GATE_TIM2, + .hw.init = CLK_HW_INIT("tim2_k", "timg1_ck", &clk_stm32_gate_ops, CLK_SET_RATE_PARENT), +}; + +static struct clk_stm32_gate tim3_k = { + .gate_id = GATE_TIM3, + .hw.init = CLK_HW_INIT("tim3_k", "timg1_ck", &clk_stm32_gate_ops, CLK_SET_RATE_PARENT), +}; + +static struct clk_stm32_gate tim4_k = { + .gate_id = GATE_TIM4, + .hw.init = CLK_HW_INIT("tim4_k", "timg1_ck", &clk_stm32_gate_ops, CLK_SET_RATE_PARENT), +}; + +static struct clk_stm32_gate tim5_k = { + .gate_id = GATE_TIM5, + .hw.init = CLK_HW_INIT("tim5_k", "timg1_ck", &clk_stm32_gate_ops, CLK_SET_RATE_PARENT), +}; + +static struct clk_stm32_gate tim6_k = { + .gate_id = GATE_TIM6, + .hw.init = CLK_HW_INIT("tim6_k", "timg1_ck", &clk_stm32_gate_ops, CLK_SET_RATE_PARENT), +}; + +static struct clk_stm32_gate tim7_k = { + .gate_id = GATE_TIM7, + .hw.init = CLK_HW_INIT("tim7_k", "timg1_ck", &clk_stm32_gate_ops, CLK_SET_RATE_PARENT), +}; + +static struct clk_stm32_gate tim1_k = { + .gate_id = GATE_TIM1, + .hw.init = CLK_HW_INIT("tim1_k", "timg2_ck", &clk_stm32_gate_ops, CLK_SET_RATE_PARENT), +}; + +static struct clk_stm32_gate tim8_k = { + .gate_id = GATE_TIM8, + .hw.init = CLK_HW_INIT("tim8_k", "timg2_ck", &clk_stm32_gate_ops, CLK_SET_RATE_PARENT), +}; + +static struct clk_stm32_gate tim12_k = { + .gate_id = GATE_TIM12, + .hw.init = CLK_HW_INIT("tim12_k", "timg3_ck", &clk_stm32_gate_ops, CLK_SET_RATE_PARENT), +}; + +static struct clk_stm32_gate tim13_k = { + .gate_id = GATE_TIM13, + .hw.init = CLK_HW_INIT("tim13_k", "timg3_ck", &clk_stm32_gate_ops, CLK_SET_RATE_PARENT), +}; + +static struct clk_stm32_gate tim14_k = { + .gate_id = GATE_TIM14, + .hw.init = CLK_HW_INIT("tim14_k", "timg3_ck", &clk_stm32_gate_ops, CLK_SET_RATE_PARENT), +}; + +static struct clk_stm32_gate tim15_k = { + .gate_id = GATE_TIM15, + .hw.init = CLK_HW_INIT("tim15_k", "timg3_ck", &clk_stm32_gate_ops, CLK_SET_RATE_PARENT), +}; + +static struct clk_stm32_gate tim16_k = { + .gate_id = GATE_TIM16, + .hw.init = CLK_HW_INIT("tim16_k", "timg3_ck", &clk_stm32_gate_ops, CLK_SET_RATE_PARENT), +}; + +static struct clk_stm32_gate tim17_k = { + .gate_id = GATE_TIM17, + .hw.init = CLK_HW_INIT("tim17_k", "timg3_ck", &clk_stm32_gate_ops, CLK_SET_RATE_PARENT), +}; + +/* Peripheral clocks */ +static struct clk_stm32_gate sai1 = { + .gate_id = GATE_SAI1, + .hw.init = CLK_HW_INIT("sai1", "pclk2", &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate sai2 = { + .gate_id = GATE_SAI2, + .hw.init = CLK_HW_INIT("sai2", "pclk2", &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate syscfg = { + .gate_id = GATE_SYSCFG, + .hw.init = CLK_HW_INIT("syscfg", "pclk3", &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate vref = { + .gate_id = GATE_VREF, + .hw.init = CLK_HW_INIT("vref", "pclk3", &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate dts = { + .gate_id = GATE_DTS, + .hw.init = CLK_HW_INIT("dts", "pclk3", &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate pmbctrl = { + .gate_id = GATE_PMBCTRL, + .hw.init = CLK_HW_INIT("pmbctrl", "pclk3", &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate hdp = { + .gate_id = GATE_HDP, + .hw.init = CLK_HW_INIT("hdp", "pclk3", &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate iwdg2 = { + .gate_id = GATE_IWDG2APB, + .hw.init = CLK_HW_INIT("iwdg2", "pclk4", &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate stgenro = { + .gate_id = GATE_STGENRO, + .hw.init = CLK_HW_INIT("stgenro", "pclk4", &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate gpioa = { + .gate_id = GATE_GPIOA, + .hw.init = CLK_HW_INIT("gpioa", "pclk4", &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate gpiob = { + .gate_id = GATE_GPIOB, + .hw.init = CLK_HW_INIT("gpiob", "pclk4", &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate gpioc = { + .gate_id = GATE_GPIOC, + .hw.init = CLK_HW_INIT("gpioc", "pclk4", &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate gpiod = { + .gate_id = GATE_GPIOD, + .hw.init = CLK_HW_INIT("gpiod", "pclk4", &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate gpioe = { + .gate_id = GATE_GPIOE, + .hw.init = CLK_HW_INIT("gpioe", "pclk4", &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate gpiof = { + .gate_id = GATE_GPIOF, + .hw.init = CLK_HW_INIT("gpiof", "pclk4", &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate gpiog = { + .gate_id = GATE_GPIOG, + .hw.init = CLK_HW_INIT("gpiog", "pclk4", &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate gpioh = { + .gate_id = GATE_GPIOH, + .hw.init = CLK_HW_INIT("gpioh", "pclk4", &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate gpioi = { + .gate_id = GATE_GPIOI, + .hw.init = CLK_HW_INIT("gpioi", "pclk4", &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate tsc = { + .gate_id = GATE_TSC, + .hw.init = CLK_HW_INIT("tsc", "pclk4", &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ddrperfm = { + .gate_id = GATE_DDRPERFM, + .hw.init = CLK_HW_INIT("ddrperfm", "pclk4", &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate tzpc = { + .gate_id = GATE_TZC, + .hw.init = CLK_HW_INIT("tzpc", "pclk5", &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate iwdg1 = { + .gate_id = GATE_IWDG1APB, + .hw.init = CLK_HW_INIT("iwdg1", "pclk5", &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate bsec = { + .gate_id = GATE_BSEC, + .hw.init = CLK_HW_INIT("bsec", "pclk5", &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate dma1 = { + .gate_id = GATE_DMA1, + .hw.init = CLK_HW_INIT("dma1", "ck_mlahb", &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate dma2 = { + .gate_id = GATE_DMA2, + .hw.init = CLK_HW_INIT("dma2", "ck_mlahb", &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate dmamux1 = { + .gate_id = GATE_DMAMUX1, + .hw.init = CLK_HW_INIT("dmamux1", "ck_mlahb", &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate dma3 = { + .gate_id = GATE_DMA3, + .hw.init = CLK_HW_INIT("dma3", "ck_mlahb", &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate dmamux2 = { + .gate_id = GATE_DMAMUX2, + .hw.init = CLK_HW_INIT("dmamux2", "ck_mlahb", &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate adc1 = { + .gate_id = GATE_ADC1, + .hw.init = CLK_HW_INIT("adc1", "ck_mlahb", &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate adc2 = { + .gate_id = GATE_ADC2, + .hw.init = CLK_HW_INIT("adc2", "ck_mlahb", &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate pka = { + .gate_id = GATE_PKA, + .hw.init = CLK_HW_INIT("pka", "ck_axi", &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate cryp1 = { + .gate_id = GATE_CRYP1, + .hw.init = CLK_HW_INIT("cryp1", "ck_axi", &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate hash1 = { + .gate_id = GATE_HASH1, + .hw.init = CLK_HW_INIT("hash1", "ck_axi", &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate bkpsram = { + .gate_id = GATE_BKPSRAM, + .hw.init = CLK_HW_INIT("bkpsram", "ck_axi", &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate mdma = { + .gate_id = GATE_MDMA, + .hw.init = CLK_HW_INIT("mdma", "ck_axi", &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate eth1tx = { + .gate_id = GATE_ETH1TX, + .hw.init = CLK_HW_INIT("eth1tx", "ck_axi", &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate eth1rx = { + .gate_id = GATE_ETH1RX, + .hw.init = CLK_HW_INIT("eth1rx", "ck_axi", &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate eth1mac = { + .gate_id = GATE_ETH1MAC, + .hw.init = CLK_HW_INIT("eth1mac", "ck_axi", &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate eth2tx = { + .gate_id = GATE_ETH2TX, + .hw.init = CLK_HW_INIT("eth2tx", "ck_axi", &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate eth2rx = { + .gate_id = GATE_ETH2RX, + .hw.init = CLK_HW_INIT("eth2rx", "ck_axi", &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate eth2mac = { + .gate_id = GATE_ETH2MAC, + .hw.init = CLK_HW_INIT("eth2mac", "ck_axi", &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate crc1 = { + .gate_id = GATE_CRC1, + .hw.init = CLK_HW_INIT("crc1", "ck_axi", &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate usbh = { + .gate_id = GATE_USBH, + .hw.init = CLK_HW_INIT("usbh", "ck_axi", &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate eth1stp = { + .gate_id = GATE_ETH1STP, + .hw.init = CLK_HW_INIT("eth1stp", "ck_axi", &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate eth2stp = { + .gate_id = GATE_ETH2STP, + .hw.init = CLK_HW_INIT("eth2stp", "ck_axi", &clk_stm32_gate_ops, 0), +}; + +/* Kernel clocks */ +static struct clk_stm32_composite sdmmc1_k = { + .gate_id = GATE_SDMMC1, + .mux_id = MUX_SDMMC1, + .div_id = NO_STM32_DIV, + .hw.init = CLK_HW_INIT_PARENTS("sdmmc1_k", sdmmc12_src, &clk_stm32_composite_ops, + CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT), +}; + +static struct clk_stm32_composite sdmmc2_k = { + .gate_id = GATE_SDMMC2, + .mux_id = MUX_SDMMC2, + .div_id = NO_STM32_DIV, + .hw.init = CLK_HW_INIT_PARENTS("sdmmc2_k", sdmmc12_src, &clk_stm32_composite_ops, + CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT), +}; + +static struct clk_stm32_composite fmc_k = { + .gate_id = GATE_FMC, + .mux_id = MUX_FMC, + .div_id = NO_STM32_DIV, + .hw.init = CLK_HW_INIT_PARENTS("fmc_k", fmc_src, &clk_stm32_composite_ops, + CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT), +}; + +static struct clk_stm32_composite qspi_k = { + .gate_id = GATE_QSPI, + .mux_id = MUX_QSPI, + .div_id = NO_STM32_DIV, + .hw.init = CLK_HW_INIT_PARENTS("qspi_k", qspi_src, &clk_stm32_composite_ops, + CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT), +}; + +static struct clk_stm32_composite spi2_k = { + .gate_id = GATE_SPI2, + .mux_id = MUX_SPI23, + .div_id = NO_STM32_DIV, + .hw.init = CLK_HW_INIT_PARENTS("spi2_k", spi123_src, &clk_stm32_composite_ops, + CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT), +}; + +static struct clk_stm32_composite spi3_k = { + .gate_id = GATE_SPI3, + .mux_id = MUX_SPI23, + .div_id = NO_STM32_DIV, + .hw.init = CLK_HW_INIT_PARENTS("spi3_k", spi123_src, &clk_stm32_composite_ops, + CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT), +}; + +static struct clk_stm32_composite i2c1_k = { + .gate_id = GATE_I2C1, + .mux_id = MUX_I2C12, + .div_id = NO_STM32_DIV, + .hw.init = CLK_HW_INIT_PARENTS("i2c1_k", i2c12_src, &clk_stm32_composite_ops, + CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT), +}; + +static struct clk_stm32_composite i2c2_k = { + .gate_id = GATE_I2C2, + .mux_id = MUX_I2C12, + .div_id = NO_STM32_DIV, + .hw.init = CLK_HW_INIT_PARENTS("i2c2_k", i2c12_src, &clk_stm32_composite_ops, + CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT), +}; + +static struct clk_stm32_composite lptim4_k = { + .gate_id = GATE_LPTIM4, + .mux_id = MUX_LPTIM45, + .div_id = NO_STM32_DIV, + .hw.init = CLK_HW_INIT_PARENTS("lptim4_k", lptim45_src, &clk_stm32_composite_ops, + CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT), +}; + +static struct clk_stm32_composite lptim5_k = { + .gate_id = GATE_LPTIM5, + .mux_id = MUX_LPTIM45, + .div_id = NO_STM32_DIV, + .hw.init = CLK_HW_INIT_PARENTS("lptim5_k", lptim45_src, &clk_stm32_composite_ops, + CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT), +}; + +static struct clk_stm32_composite usart3_k = { + .gate_id = GATE_USART3, + .mux_id = MUX_UART35, + .div_id = NO_STM32_DIV, + .hw.init = CLK_HW_INIT_PARENTS("usart3_k", usart34578_src, &clk_stm32_composite_ops, + CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT), +}; + +static struct clk_stm32_composite uart5_k = { + .gate_id = GATE_UART5, + .mux_id = MUX_UART35, + .div_id = NO_STM32_DIV, + .hw.init = CLK_HW_INIT_PARENTS("uart5_k", usart34578_src, &clk_stm32_composite_ops, + CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT), +}; + +static struct clk_stm32_composite uart7_k = { + .gate_id = GATE_UART7, + .mux_id = MUX_UART78, + .div_id = NO_STM32_DIV, + .hw.init = CLK_HW_INIT_PARENTS("uart7_k", usart34578_src, &clk_stm32_composite_ops, + CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT), +}; + +static struct clk_stm32_composite uart8_k = { + .gate_id = GATE_UART8, + .mux_id = MUX_UART78, + .div_id = NO_STM32_DIV, + .hw.init = CLK_HW_INIT_PARENTS("uart8_k", usart34578_src, &clk_stm32_composite_ops, + CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT), +}; + +static struct clk_stm32_composite sai1_k = { + .gate_id = GATE_SAI1, + .mux_id = MUX_SAI1, + .div_id = NO_STM32_DIV, + .hw.init = CLK_HW_INIT_PARENTS("sai1_k", sai1_src, &clk_stm32_composite_ops, + CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT), +}; + +static struct clk_stm32_composite adfsdm_k = { + .gate_id = GATE_ADFSDM, + .mux_id = MUX_SAI1, + .div_id = NO_STM32_DIV, + .hw.init = CLK_HW_INIT_PARENTS("adfsdm_k", sai1_src, &clk_stm32_composite_ops, + CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT), +}; + +static struct clk_stm32_composite sai2_k = { + .gate_id = GATE_SAI2, + .mux_id = MUX_SAI2, + .div_id = NO_STM32_DIV, + .hw.init = CLK_HW_INIT_PARENTS("sai2_k", sai2_src, &clk_stm32_composite_ops, + CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT), +}; + +static struct clk_stm32_composite adc1_k = { + .gate_id = GATE_ADC1, + .mux_id = MUX_ADC1, + .div_id = NO_STM32_DIV, + .hw.init = CLK_HW_INIT_PARENTS("adc1_k", adc12_src, &clk_stm32_composite_ops, + CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT), +}; + +static struct clk_stm32_composite adc2_k = { + .gate_id = GATE_ADC2, + .mux_id = MUX_ADC2, + .div_id = NO_STM32_DIV, + .hw.init = CLK_HW_INIT_PARENTS("adc2_k", adc12_src, &clk_stm32_composite_ops, + CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT), +}; + +static struct clk_stm32_composite rng1_k = { + .gate_id = GATE_RNG1, + .mux_id = MUX_RNG1, + .div_id = NO_STM32_DIV, + .hw.init = CLK_HW_INIT_PARENTS("rng1_k", rng1_src, &clk_stm32_composite_ops, + CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT), +}; + +static struct clk_stm32_composite usbphy_k = { + .gate_id = GATE_USBPHY, + .mux_id = MUX_USBPHY, + .div_id = NO_STM32_DIV, + .hw.init = CLK_HW_INIT_PARENTS("usbphy_k", usbphy_src, &clk_stm32_composite_ops, + CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT), +}; + +static struct clk_stm32_composite stgen_k = { + .gate_id = GATE_STGENC, + .mux_id = MUX_STGEN, + .div_id = NO_STM32_DIV, + .hw.init = CLK_HW_INIT_PARENTS("stgen_k", stgen_src, &clk_stm32_composite_ops, + CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT), +}; + +static struct clk_stm32_composite spdif_k = { + .gate_id = GATE_SPDIF, + .mux_id = MUX_SPDIF, + .div_id = NO_STM32_DIV, + .hw.init = CLK_HW_INIT_PARENTS("spdif_k", spdif_src, &clk_stm32_composite_ops, + CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT), +}; + +static struct clk_stm32_composite spi1_k = { + .gate_id = GATE_SPI1, + .mux_id = MUX_SPI1, + .div_id = NO_STM32_DIV, + .hw.init = CLK_HW_INIT_PARENTS("spi1_k", spi123_src, &clk_stm32_composite_ops, + CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT), +}; + +static struct clk_stm32_composite spi4_k = { + .gate_id = GATE_SPI4, + .mux_id = MUX_SPI4, + .div_id = NO_STM32_DIV, + .hw.init = CLK_HW_INIT_PARENTS("spi4_k", spi4_src, &clk_stm32_composite_ops, + CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT), +}; + +static struct clk_stm32_composite spi5_k = { + .gate_id = GATE_SPI5, + .mux_id = MUX_SPI5, + .div_id = NO_STM32_DIV, + .hw.init = CLK_HW_INIT_PARENTS("spi5_k", spi5_src, &clk_stm32_composite_ops, + CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT), +}; + +static struct clk_stm32_composite i2c3_k = { + .gate_id = GATE_I2C3, + .mux_id = MUX_I2C3, + .div_id = NO_STM32_DIV, + .hw.init = CLK_HW_INIT_PARENTS("i2c3_k", i2c345_src, &clk_stm32_composite_ops, + CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT), +}; + +static struct clk_stm32_composite i2c4_k = { + .gate_id = GATE_I2C4, + .mux_id = MUX_I2C4, + .div_id = NO_STM32_DIV, + .hw.init = CLK_HW_INIT_PARENTS("i2c4_k", i2c345_src, &clk_stm32_composite_ops, + CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT), +}; + +static struct clk_stm32_composite i2c5_k = { + .gate_id = GATE_I2C5, + .mux_id = MUX_I2C5, + .div_id = NO_STM32_DIV, + .hw.init = CLK_HW_INIT_PARENTS("i2c5_k", i2c345_src, &clk_stm32_composite_ops, + CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT), +}; + +static struct clk_stm32_composite lptim1_k = { + .gate_id = GATE_LPTIM1, + .mux_id = MUX_LPTIM1, + .div_id = NO_STM32_DIV, + .hw.init = CLK_HW_INIT_PARENTS("lptim1_k", lptim1_src, &clk_stm32_composite_ops, + CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT), +}; + +static struct clk_stm32_composite lptim2_k = { + .gate_id = GATE_LPTIM2, + .mux_id = MUX_LPTIM2, + .div_id = NO_STM32_DIV, + .hw.init = CLK_HW_INIT_PARENTS("lptim2_k", lptim23_src, &clk_stm32_composite_ops, + CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT), +}; + +static struct clk_stm32_composite lptim3_k = { + .gate_id = GATE_LPTIM3, + .mux_id = MUX_LPTIM3, + .div_id = NO_STM32_DIV, + .hw.init = CLK_HW_INIT_PARENTS("lptim3_k", lptim23_src, &clk_stm32_composite_ops, + CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT), +}; + +static struct clk_stm32_composite usart1_k = { + .gate_id = GATE_USART1, + .mux_id = MUX_UART1, + .div_id = NO_STM32_DIV, + .hw.init = CLK_HW_INIT_PARENTS("usart1_k", usart12_src, &clk_stm32_composite_ops, + CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT), +}; + +static struct clk_stm32_composite usart2_k = { + .gate_id = GATE_USART2, + .mux_id = MUX_UART2, + .div_id = NO_STM32_DIV, + .hw.init = CLK_HW_INIT_PARENTS("usart2_k", usart12_src, &clk_stm32_composite_ops, + CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT), +}; + +static struct clk_stm32_composite uart4_k = { + .gate_id = GATE_UART4, + .mux_id = MUX_UART4, + .div_id = NO_STM32_DIV, + .hw.init = CLK_HW_INIT_PARENTS("uart4_k", usart34578_src, &clk_stm32_composite_ops, + CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT), +}; + +static struct clk_stm32_composite uart6_k = { + .gate_id = GATE_USART6, + .mux_id = MUX_UART6, + .div_id = NO_STM32_DIV, + .hw.init = CLK_HW_INIT_PARENTS("uart6_k", usart6_src, &clk_stm32_composite_ops, + CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT), +}; + +static struct clk_stm32_composite fdcan_k = { + .gate_id = GATE_FDCAN, + .mux_id = MUX_FDCAN, + .div_id = NO_STM32_DIV, + .hw.init = CLK_HW_INIT_PARENTS("fdcan_k", fdcan_src, &clk_stm32_composite_ops, + CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT), +}; + +static struct clk_stm32_composite dcmipp_k = { + .gate_id = GATE_DCMIPP, + .mux_id = MUX_DCMIPP, + .div_id = NO_STM32_DIV, + .hw.init = CLK_HW_INIT_PARENTS("dcmipp_k", dcmipp_src, &clk_stm32_composite_ops, + CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT), +}; + +static struct clk_stm32_composite usbo_k = { + .gate_id = GATE_USBO, + .mux_id = MUX_USBO, + .div_id = NO_STM32_DIV, + .hw.init = CLK_HW_INIT_PARENTS("usbo_k", usbo_src, &clk_stm32_composite_ops, + CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT), +}; + +static struct clk_stm32_composite saes_k = { + .gate_id = GATE_SAES, + .mux_id = MUX_SAES, + .div_id = NO_STM32_DIV, + .hw.init = CLK_HW_INIT_PARENTS("saes_k", saes_src, &clk_stm32_composite_ops, + CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT), +}; + +static struct clk_stm32_gate dfsdm_k = { + .gate_id = GATE_DFSDM, + .hw.init = CLK_HW_INIT("dfsdm_k", "ck_mlahb", &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ltdc_px = { + .gate_id = GATE_LTDC, + .hw.init = CLK_HW_INIT("ltdc_px", "pll4_q", &clk_stm32_gate_ops, CLK_SET_RATE_PARENT), +}; + +static struct clk_stm32_mux ck_ker_eth1 = { + .mux_id = MUX_ETH1, + .hw.init = CLK_HW_INIT_PARENTS("ck_ker_eth1", eth12_src, &clk_stm32_mux_ops, + CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT), +}; + +static struct clk_stm32_gate eth1ck_k = { + .gate_id = GATE_ETH1CK, + .hw.init = CLK_HW_INIT_HW("eth1ck_k", &ck_ker_eth1.hw, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_div eth1ptp_k = { + .div_id = DIV_ETH1PTP, + .hw.init = CLK_HW_INIT_HW("eth1ptp_k", &ck_ker_eth1.hw, &clk_stm32_divider_ops, + CLK_SET_RATE_NO_REPARENT), +}; + +static struct clk_stm32_mux ck_ker_eth2 = { + .mux_id = MUX_ETH2, + .hw.init = CLK_HW_INIT_PARENTS("ck_ker_eth2", eth12_src, &clk_stm32_mux_ops, + CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT), +}; + +static struct clk_stm32_gate eth2ck_k = { + .gate_id = GATE_ETH2CK, + .hw.init = CLK_HW_INIT_HW("eth2ck_k", &ck_ker_eth2.hw, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_div eth2ptp_k = { + .div_id = DIV_ETH2PTP, + .hw.init = CLK_HW_INIT_HW("eth2ptp_k", &ck_ker_eth2.hw, &clk_stm32_divider_ops, + CLK_SET_RATE_NO_REPARENT), +}; + +static struct clk_stm32_composite ck_mco1 = { + .gate_id = GATE_MCO1, + .mux_id = MUX_MCO1, + .div_id = DIV_MCO1, + .hw.init = CLK_HW_INIT_PARENTS("ck_mco1", mco1_src, &clk_stm32_composite_ops, + CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT | + CLK_IGNORE_UNUSED), +}; + +static struct clk_stm32_composite ck_mco2 = { + .gate_id = GATE_MCO2, + .mux_id = MUX_MCO2, + .div_id = DIV_MCO2, + .hw.init = CLK_HW_INIT_PARENTS("ck_mco2", mco2_src, &clk_stm32_composite_ops, + CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT | + CLK_IGNORE_UNUSED), +}; + +/* Debug clocks */ +static struct clk_stm32_gate ck_sys_dbg = { + .gate_id = GATE_DBGCK, + .hw.init = CLK_HW_INIT("ck_sys_dbg", "ck_axi", &clk_stm32_gate_ops, CLK_IS_CRITICAL), +}; + +static struct clk_stm32_composite ck_trace = { + .gate_id = GATE_TRACECK, + .mux_id = NO_STM32_MUX, + .div_id = DIV_TRACE, + .hw.init = CLK_HW_INIT("ck_trace", "ck_axi", &clk_stm32_composite_ops, CLK_IGNORE_UNUSED), +}; + +static const struct clock_config stm32mp13_clock_cfg[] = { + /* Timer clocks */ + STM32_GATE_CFG(TIM2_K, tim2_k, SECF_NONE), + STM32_GATE_CFG(TIM3_K, tim3_k, SECF_NONE), + STM32_GATE_CFG(TIM4_K, tim4_k, SECF_NONE), + STM32_GATE_CFG(TIM5_K, tim5_k, SECF_NONE), + STM32_GATE_CFG(TIM6_K, tim6_k, SECF_NONE), + STM32_GATE_CFG(TIM7_K, tim7_k, SECF_NONE), + STM32_GATE_CFG(TIM1_K, tim1_k, SECF_NONE), + STM32_GATE_CFG(TIM8_K, tim8_k, SECF_NONE), + STM32_GATE_CFG(TIM12_K, tim12_k, SECF_TIM12), + STM32_GATE_CFG(TIM13_K, tim13_k, SECF_TIM13), + STM32_GATE_CFG(TIM14_K, tim14_k, SECF_TIM14), + STM32_GATE_CFG(TIM15_K, tim15_k, SECF_TIM15), + STM32_GATE_CFG(TIM16_K, tim16_k, SECF_TIM16), + STM32_GATE_CFG(TIM17_K, tim17_k, SECF_TIM17), + + /* Peripheral clocks */ + STM32_GATE_CFG(SAI1, sai1, SECF_NONE), + STM32_GATE_CFG(SAI2, sai2, SECF_NONE), + STM32_GATE_CFG(SYSCFG, syscfg, SECF_NONE), + STM32_GATE_CFG(VREF, vref, SECF_VREF), + STM32_GATE_CFG(DTS, dts, SECF_NONE), + STM32_GATE_CFG(PMBCTRL, pmbctrl, SECF_NONE), + STM32_GATE_CFG(HDP, hdp, SECF_NONE), + STM32_GATE_CFG(IWDG2, iwdg2, SECF_NONE), + STM32_GATE_CFG(STGENRO, stgenro, SECF_STGENRO), + STM32_GATE_CFG(TZPC, tzpc, SECF_TZC), + STM32_GATE_CFG(IWDG1, iwdg1, SECF_IWDG1), + STM32_GATE_CFG(BSEC, bsec, SECF_BSEC), + STM32_GATE_CFG(DMA1, dma1, SECF_NONE), + STM32_GATE_CFG(DMA2, dma2, SECF_NONE), + STM32_GATE_CFG(DMAMUX1, dmamux1, SECF_NONE), + STM32_GATE_CFG(DMA3, dma3, SECF_DMA3), + STM32_GATE_CFG(DMAMUX2, dmamux2, SECF_DMAMUX2), + STM32_GATE_CFG(ADC1, adc1, SECF_ADC1), + STM32_GATE_CFG(ADC2, adc2, SECF_ADC2), + STM32_GATE_CFG(GPIOA, gpioa, SECF_NONE), + STM32_GATE_CFG(GPIOB, gpiob, SECF_NONE), + STM32_GATE_CFG(GPIOC, gpioc, SECF_NONE), + STM32_GATE_CFG(GPIOD, gpiod, SECF_NONE), + STM32_GATE_CFG(GPIOE, gpioe, SECF_NONE), + STM32_GATE_CFG(GPIOF, gpiof, SECF_NONE), + STM32_GATE_CFG(GPIOG, gpiog, SECF_NONE), + STM32_GATE_CFG(GPIOH, gpioh, SECF_NONE), + STM32_GATE_CFG(GPIOI, gpioi, SECF_NONE), + STM32_GATE_CFG(TSC, tsc, SECF_TZC), + STM32_GATE_CFG(PKA, pka, SECF_PKA), + STM32_GATE_CFG(CRYP1, cryp1, SECF_CRYP1), + STM32_GATE_CFG(HASH1, hash1, SECF_HASH1), + STM32_GATE_CFG(BKPSRAM, bkpsram, SECF_BKPSRAM), + STM32_GATE_CFG(MDMA, mdma, SECF_NONE), + STM32_GATE_CFG(ETH1TX, eth1tx, SECF_ETH1TX), + STM32_GATE_CFG(ETH1RX, eth1rx, SECF_ETH1RX), + STM32_GATE_CFG(ETH1MAC, eth1mac, SECF_ETH1MAC), + STM32_GATE_CFG(ETH2TX, eth2tx, SECF_ETH2TX), + STM32_GATE_CFG(ETH2RX, eth2rx, SECF_ETH2RX), + STM32_GATE_CFG(ETH2MAC, eth2mac, SECF_ETH2MAC), + STM32_GATE_CFG(CRC1, crc1, SECF_NONE), + STM32_GATE_CFG(USBH, usbh, SECF_NONE), + STM32_GATE_CFG(DDRPERFM, ddrperfm, SECF_NONE), + STM32_GATE_CFG(ETH1STP, eth1stp, SECF_ETH1STP), + STM32_GATE_CFG(ETH2STP, eth2stp, SECF_ETH2STP), + + /* Kernel clocks */ + STM32_COMPOSITE_CFG(SDMMC1_K, sdmmc1_k, SECF_SDMMC1), + STM32_COMPOSITE_CFG(SDMMC2_K, sdmmc2_k, SECF_SDMMC2), + STM32_COMPOSITE_CFG(FMC_K, fmc_k, SECF_FMC), + STM32_COMPOSITE_CFG(QSPI_K, qspi_k, SECF_QSPI), + STM32_COMPOSITE_CFG(SPI2_K, spi2_k, SECF_NONE), + STM32_COMPOSITE_CFG(SPI3_K, spi3_k, SECF_NONE), + STM32_COMPOSITE_CFG(I2C1_K, i2c1_k, SECF_NONE), + STM32_COMPOSITE_CFG(I2C2_K, i2c2_k, SECF_NONE), + STM32_COMPOSITE_CFG(LPTIM4_K, lptim4_k, SECF_NONE), + STM32_COMPOSITE_CFG(LPTIM5_K, lptim5_k, SECF_NONE), + STM32_COMPOSITE_CFG(USART3_K, usart3_k, SECF_NONE), + STM32_COMPOSITE_CFG(UART5_K, uart5_k, SECF_NONE), + STM32_COMPOSITE_CFG(UART7_K, uart7_k, SECF_NONE), + STM32_COMPOSITE_CFG(UART8_K, uart8_k, SECF_NONE), + STM32_COMPOSITE_CFG(SAI1_K, sai1_k, SECF_NONE), + STM32_COMPOSITE_CFG(SAI2_K, sai2_k, SECF_NONE), + STM32_COMPOSITE_CFG(ADFSDM_K, adfsdm_k, SECF_NONE), + STM32_COMPOSITE_CFG(ADC1_K, adc1_k, SECF_ADC1), + STM32_COMPOSITE_CFG(ADC2_K, adc2_k, SECF_ADC2), + STM32_COMPOSITE_CFG(RNG1_K, rng1_k, SECF_RNG1), + STM32_COMPOSITE_CFG(USBPHY_K, usbphy_k, SECF_USBPHY), + STM32_COMPOSITE_CFG(STGEN_K, stgen_k, SECF_STGENC), + STM32_COMPOSITE_CFG(SPDIF_K, spdif_k, SECF_NONE), + STM32_COMPOSITE_CFG(SPI1_K, spi1_k, SECF_NONE), + STM32_COMPOSITE_CFG(SPI4_K, spi4_k, SECF_SPI4), + STM32_COMPOSITE_CFG(SPI5_K, spi5_k, SECF_SPI5), + STM32_COMPOSITE_CFG(I2C3_K, i2c3_k, SECF_I2C3), + STM32_COMPOSITE_CFG(I2C4_K, i2c4_k, SECF_I2C4), + STM32_COMPOSITE_CFG(I2C5_K, i2c5_k, SECF_I2C5), + STM32_COMPOSITE_CFG(LPTIM1_K, lptim1_k, SECF_NONE), + STM32_COMPOSITE_CFG(LPTIM2_K, lptim2_k, SECF_LPTIM2), + STM32_COMPOSITE_CFG(LPTIM3_K, lptim3_k, SECF_LPTIM3), + STM32_COMPOSITE_CFG(USART1_K, usart1_k, SECF_USART1), + STM32_COMPOSITE_CFG(USART2_K, usart2_k, SECF_USART2), + STM32_COMPOSITE_CFG(UART4_K, uart4_k, SECF_NONE), + STM32_COMPOSITE_CFG(USART6_K, uart6_k, SECF_NONE), + STM32_COMPOSITE_CFG(FDCAN_K, fdcan_k, SECF_NONE), + STM32_COMPOSITE_CFG(DCMIPP_K, dcmipp_k, SECF_DCMIPP), + STM32_COMPOSITE_CFG(USBO_K, usbo_k, SECF_USBO), + STM32_COMPOSITE_CFG(SAES_K, saes_k, SECF_SAES), + STM32_GATE_CFG(DFSDM_K, dfsdm_k, SECF_NONE), + STM32_GATE_CFG(LTDC_PX, ltdc_px, SECF_NONE), + + STM32_MUX_CFG(NO_ID, ck_ker_eth1, SECF_ETH1CK), + STM32_GATE_CFG(ETH1CK_K, eth1ck_k, SECF_ETH1CK), + STM32_DIV_CFG(ETH1PTP_K, eth1ptp_k, SECF_ETH1CK), + + STM32_MUX_CFG(NO_ID, ck_ker_eth2, SECF_ETH2CK), + STM32_GATE_CFG(ETH2CK_K, eth2ck_k, SECF_ETH2CK), + STM32_DIV_CFG(ETH2PTP_K, eth2ptp_k, SECF_ETH2CK), + + STM32_GATE_CFG(CK_DBG, ck_sys_dbg, SECF_NONE), + STM32_COMPOSITE_CFG(CK_TRACE, ck_trace, SECF_NONE), + + STM32_COMPOSITE_CFG(CK_MCO1, ck_mco1, SECF_MCO1), + STM32_COMPOSITE_CFG(CK_MCO2, ck_mco2, SECF_MCO2), +}; + +static int stm32mp13_clock_is_provided_by_secure(void __iomem *base, + const struct clock_config *cfg) +{ + int sec_id = cfg->sec_id; + + if (sec_id != SECF_NONE) { + const struct clk_stm32_securiy *secf; + + secf = &stm32mp13_security[sec_id]; + + return !!(readl(base + secf->offset) & BIT(secf->bit_idx)); + } + + return 0; +} + +struct multi_mux { + struct clk_hw *hw1; + struct clk_hw *hw2; +}; + +static struct multi_mux *stm32_mp13_multi_mux[MUX_NB] = { + [MUX_SPI23] = &(struct multi_mux){ &spi2_k.hw, &spi3_k.hw }, + [MUX_I2C12] = &(struct multi_mux){ &i2c1_k.hw, &i2c2_k.hw }, + [MUX_LPTIM45] = &(struct multi_mux){ &lptim4_k.hw, &lptim5_k.hw }, + [MUX_UART35] = &(struct multi_mux){ &usart3_k.hw, &uart5_k.hw }, + [MUX_UART78] = &(struct multi_mux){ &uart7_k.hw, &uart8_k.hw }, + [MUX_SAI1] = &(struct multi_mux){ &sai1_k.hw, &adfsdm_k.hw }, +}; + +static struct clk_hw *stm32mp13_is_multi_mux(struct clk_hw *hw) +{ + struct clk_stm32_composite *composite = to_clk_stm32_composite(hw); + struct multi_mux *mmux = stm32_mp13_multi_mux[composite->mux_id]; + + if (mmux) { + if (!(mmux->hw1 == hw)) + return mmux->hw1; + else + return mmux->hw2; + } + + return NULL; +} + +static u16 stm32mp13_cpt_gate[GATE_NB]; + +static struct clk_stm32_clock_data stm32mp13_clock_data = { + .gate_cpt = stm32mp13_cpt_gate, + .gates = stm32mp13_gates, + .muxes = stm32mp13_muxes, + .dividers = stm32mp13_dividers, + .is_multi_mux = stm32mp13_is_multi_mux, +}; + +static const struct stm32_rcc_match_data stm32mp13_data = { + .tab_clocks = stm32mp13_clock_cfg, + .num_clocks = ARRAY_SIZE(stm32mp13_clock_cfg), + .clock_data = &stm32mp13_clock_data, + .check_security = &stm32mp13_clock_is_provided_by_secure, + .maxbinding = STM32MP1_LAST_CLK, + .clear_offset = RCC_CLR_OFFSET, +}; + +static const struct of_device_id stm32mp13_match_data[] = { + { + .compatible = "st,stm32mp13-rcc", + .data = &stm32mp13_data, + }, + { } +}; +MODULE_DEVICE_TABLE(of, stm32mp13_match_data); + +static int stm32mp1_rcc_init(struct device *dev) +{ + void __iomem *rcc_base; + int ret = -ENOMEM; + + rcc_base = of_iomap(dev_of_node(dev), 0); + if (!rcc_base) { + dev_err(dev, "%pOFn: unable to map resource", dev_of_node(dev)); + goto out; + } + + ret = stm32_rcc_init(dev, stm32mp13_match_data, rcc_base); +out: + if (ret) { + if (rcc_base) + iounmap(rcc_base); + + of_node_put(dev_of_node(dev)); + } + + return ret; +} + +static int get_clock_deps(struct device *dev) +{ + static const char * const clock_deps_name[] = { + "hsi", "hse", "csi", "lsi", "lse", + }; + size_t deps_size = sizeof(struct clk *) * ARRAY_SIZE(clock_deps_name); + struct clk **clk_deps; + int i; + + clk_deps = devm_kzalloc(dev, deps_size, GFP_KERNEL); + if (!clk_deps) + return -ENOMEM; + + for (i = 0; i < ARRAY_SIZE(clock_deps_name); i++) { + struct clk *clk = of_clk_get_by_name(dev_of_node(dev), + clock_deps_name[i]); + + if (IS_ERR(clk)) { + if (PTR_ERR(clk) != -EINVAL && PTR_ERR(clk) != -ENOENT) + return PTR_ERR(clk); + } else { + /* Device gets a reference count on the clock */ + clk_deps[i] = devm_clk_get(dev, __clk_get_name(clk)); + clk_put(clk); + } + } + + return 0; +} + +static int stm32mp1_rcc_clocks_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + int ret = get_clock_deps(dev); + + if (!ret) + ret = stm32mp1_rcc_init(dev); + + return ret; +} + +static int stm32mp1_rcc_clocks_remove(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *child, *np = dev_of_node(dev); + + for_each_available_child_of_node(np, child) + of_clk_del_provider(child); + + return 0; +} + +static struct platform_driver stm32mp13_rcc_clocks_driver = { + .driver = { + .name = "stm32mp13_rcc", + .of_match_table = stm32mp13_match_data, + }, + .probe = stm32mp1_rcc_clocks_probe, + .remove = stm32mp1_rcc_clocks_remove, +}; + +static int __init stm32mp13_clocks_init(void) +{ + return platform_driver_register(&stm32mp13_rcc_clocks_driver); +} +core_initcall(stm32mp13_clocks_init); diff --git a/drivers/clk/stm32/reset-stm32.c b/drivers/clk/stm32/reset-stm32.c new file mode 100644 index 0000000000000000000000000000000000000000..040870130e4b8058086bf011b49aaf5a81f5a320 --- /dev/null +++ b/drivers/clk/stm32/reset-stm32.c @@ -0,0 +1,122 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) STMicroelectronics 2022 - All Rights Reserved + * Author: Gabriel Fernandez for STMicroelectronics. + */ + +#include +#include +#include +#include +#include +#include + +#include "clk-stm32-core.h" + +#define STM32_RESET_ID_MASK GENMASK(15, 0) + +struct stm32_reset_data { + /* reset lock */ + spinlock_t lock; + struct reset_controller_dev rcdev; + void __iomem *membase; + u32 clear_offset; +}; + +static inline struct stm32_reset_data * +to_stm32_reset_data(struct reset_controller_dev *rcdev) +{ + return container_of(rcdev, struct stm32_reset_data, rcdev); +} + +static int stm32_reset_update(struct reset_controller_dev *rcdev, + unsigned long id, bool assert) +{ + struct stm32_reset_data *data = to_stm32_reset_data(rcdev); + int reg_width = sizeof(u32); + int bank = id / (reg_width * BITS_PER_BYTE); + int offset = id % (reg_width * BITS_PER_BYTE); + + if (data->clear_offset) { + void __iomem *addr; + + addr = data->membase + (bank * reg_width); + if (!assert) + addr += data->clear_offset; + + writel(BIT(offset), addr); + + } else { + unsigned long flags; + u32 reg; + + spin_lock_irqsave(&data->lock, flags); + + reg = readl(data->membase + (bank * reg_width)); + + if (assert) + reg |= BIT(offset); + else + reg &= ~BIT(offset); + + writel(reg, data->membase + (bank * reg_width)); + + spin_unlock_irqrestore(&data->lock, flags); + } + + return 0; +} + +static int stm32_reset_assert(struct reset_controller_dev *rcdev, + unsigned long id) +{ + return stm32_reset_update(rcdev, id, true); +} + +static int stm32_reset_deassert(struct reset_controller_dev *rcdev, + unsigned long id) +{ + return stm32_reset_update(rcdev, id, false); +} + +static int stm32_reset_status(struct reset_controller_dev *rcdev, + unsigned long id) +{ + struct stm32_reset_data *data = to_stm32_reset_data(rcdev); + int reg_width = sizeof(u32); + int bank = id / (reg_width * BITS_PER_BYTE); + int offset = id % (reg_width * BITS_PER_BYTE); + u32 reg; + + reg = readl(data->membase + (bank * reg_width)); + + return !!(reg & BIT(offset)); +} + +static const struct reset_control_ops stm32_reset_ops = { + .assert = stm32_reset_assert, + .deassert = stm32_reset_deassert, + .status = stm32_reset_status, +}; + +int stm32_rcc_reset_init(struct device *dev, const struct of_device_id *match, + void __iomem *base) +{ + const struct stm32_rcc_match_data *data = match->data; + struct stm32_reset_data *reset_data = NULL; + + data = match->data; + + reset_data = kzalloc(sizeof(*reset_data), GFP_KERNEL); + if (!reset_data) + return -ENOMEM; + + reset_data->membase = base; + reset_data->rcdev.owner = THIS_MODULE; + reset_data->rcdev.ops = &stm32_reset_ops; + reset_data->rcdev.of_node = dev_of_node(dev); + reset_data->rcdev.nr_resets = STM32_RESET_ID_MASK; + reset_data->clear_offset = data->clear_offset; + + return reset_controller_register(&reset_data->rcdev); +} diff --git a/drivers/clk/stm32/reset-stm32.h b/drivers/clk/stm32/reset-stm32.h new file mode 100644 index 0000000000000000000000000000000000000000..6eb6ea4b55ab953e300e8f149b43d3a0407d859c --- /dev/null +++ b/drivers/clk/stm32/reset-stm32.h @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) STMicroelectronics 2022 - All Rights Reserved + * Author: Gabriel Fernandez for STMicroelectronics. + */ + +int stm32_rcc_reset_init(struct device *dev, const struct of_device_id *match, + void __iomem *base); diff --git a/drivers/clk/stm32/stm32mp13_rcc.h b/drivers/clk/stm32/stm32mp13_rcc.h new file mode 100644 index 0000000000000000000000000000000000000000..a82512ae08f2f0652fd1cb41dafd10dd0ac2ede5 --- /dev/null +++ b/drivers/clk/stm32/stm32mp13_rcc.h @@ -0,0 +1,1748 @@ +/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */ +/* + * Copyright (C) 2020, STMicroelectronics - All Rights Reserved + * + * Configuration settings for the STM32MP13x CPU + */ + +#ifndef STM32MP13_RCC_H +#define STM32MP13_RCC_H +/* RCC registers */ +#define RCC_SECCFGR 0x0 +#define RCC_MP_SREQSETR 0x100 +#define RCC_MP_SREQCLRR 0x104 +#define RCC_MP_APRSTCR 0x108 +#define RCC_MP_APRSTSR 0x10c +#define RCC_PWRLPDLYCR 0x110 +#define RCC_MP_GRSTCSETR 0x114 +#define RCC_BR_RSTSCLRR 0x118 +#define RCC_MP_RSTSSETR 0x11c +#define RCC_MP_RSTSCLRR 0x120 +#define RCC_MP_IWDGFZSETR 0x124 +#define RCC_MP_IWDGFZCLRR 0x128 +#define RCC_MP_CIER 0x200 +#define RCC_MP_CIFR 0x204 +#define RCC_BDCR 0x400 +#define RCC_RDLSICR 0x404 +#define RCC_OCENSETR 0x420 +#define RCC_OCENCLRR 0x424 +#define RCC_OCRDYR 0x428 +#define RCC_HSICFGR 0x440 +#define RCC_CSICFGR 0x444 +#define RCC_MCO1CFGR 0x460 +#define RCC_MCO2CFGR 0x464 +#define RCC_DBGCFGR 0x468 +#define RCC_RCK12SELR 0x480 +#define RCC_RCK3SELR 0x484 +#define RCC_RCK4SELR 0x488 +#define RCC_PLL1CR 0x4a0 +#define RCC_PLL1CFGR1 0x4a4 +#define RCC_PLL1CFGR2 0x4a8 +#define RCC_PLL1FRACR 0x4ac +#define RCC_PLL1CSGR 0x4b0 +#define RCC_PLL2CR 0x4d0 +#define RCC_PLL2CFGR1 0x4d4 +#define RCC_PLL2CFGR2 0x4d8 +#define RCC_PLL2FRACR 0x4dc +#define RCC_PLL2CSGR 0x4e0 +#define RCC_PLL3CR 0x500 +#define RCC_PLL3CFGR1 0x504 +#define RCC_PLL3CFGR2 0x508 +#define RCC_PLL3FRACR 0x50c +#define RCC_PLL3CSGR 0x510 +#define RCC_PLL4CR 0x520 +#define RCC_PLL4CFGR1 0x524 +#define RCC_PLL4CFGR2 0x528 +#define RCC_PLL4FRACR 0x52c +#define RCC_PLL4CSGR 0x530 +#define RCC_MPCKSELR 0x540 +#define RCC_ASSCKSELR 0x544 +#define RCC_MSSCKSELR 0x548 +#define RCC_CPERCKSELR 0x54c +#define RCC_RTCDIVR 0x560 +#define RCC_MPCKDIVR 0x564 +#define RCC_AXIDIVR 0x568 +#define RCC_MLAHBDIVR 0x56c +#define RCC_APB1DIVR 0x570 +#define RCC_APB2DIVR 0x574 +#define RCC_APB3DIVR 0x578 +#define RCC_APB4DIVR 0x57c +#define RCC_APB5DIVR 0x580 +#define RCC_APB6DIVR 0x584 +#define RCC_TIMG1PRER 0x5a0 +#define RCC_TIMG2PRER 0x5a4 +#define RCC_TIMG3PRER 0x5a8 +#define RCC_DDRITFCR 0x5c0 +#define RCC_I2C12CKSELR 0x600 +#define RCC_I2C345CKSELR 0x604 +#define RCC_SPI2S1CKSELR 0x608 +#define RCC_SPI2S23CKSELR 0x60c +#define RCC_SPI45CKSELR 0x610 +#define RCC_UART12CKSELR 0x614 +#define RCC_UART35CKSELR 0x618 +#define RCC_UART4CKSELR 0x61c +#define RCC_UART6CKSELR 0x620 +#define RCC_UART78CKSELR 0x624 +#define RCC_LPTIM1CKSELR 0x628 +#define RCC_LPTIM23CKSELR 0x62c +#define RCC_LPTIM45CKSELR 0x630 +#define RCC_SAI1CKSELR 0x634 +#define RCC_SAI2CKSELR 0x638 +#define RCC_FDCANCKSELR 0x63c +#define RCC_SPDIFCKSELR 0x640 +#define RCC_ADC12CKSELR 0x644 +#define RCC_SDMMC12CKSELR 0x648 +#define RCC_ETH12CKSELR 0x64c +#define RCC_USBCKSELR 0x650 +#define RCC_QSPICKSELR 0x654 +#define RCC_FMCCKSELR 0x658 +#define RCC_RNG1CKSELR 0x65c +#define RCC_STGENCKSELR 0x660 +#define RCC_DCMIPPCKSELR 0x664 +#define RCC_SAESCKSELR 0x668 +#define RCC_APB1RSTSETR 0x6a0 +#define RCC_APB1RSTCLRR 0x6a4 +#define RCC_APB2RSTSETR 0x6a8 +#define RCC_APB2RSTCLRR 0x6ac +#define RCC_APB3RSTSETR 0x6b0 +#define RCC_APB3RSTCLRR 0x6b4 +#define RCC_APB4RSTSETR 0x6b8 +#define RCC_APB4RSTCLRR 0x6bc +#define RCC_APB5RSTSETR 0x6c0 +#define RCC_APB5RSTCLRR 0x6c4 +#define RCC_APB6RSTSETR 0x6c8 +#define RCC_APB6RSTCLRR 0x6cc +#define RCC_AHB2RSTSETR 0x6d0 +#define RCC_AHB2RSTCLRR 0x6d4 +#define RCC_AHB4RSTSETR 0x6e0 +#define RCC_AHB4RSTCLRR 0x6e4 +#define RCC_AHB5RSTSETR 0x6e8 +#define RCC_AHB5RSTCLRR 0x6ec +#define RCC_AHB6RSTSETR 0x6f0 +#define RCC_AHB6RSTCLRR 0x6f4 +#define RCC_MP_APB1ENSETR 0x700 +#define RCC_MP_APB1ENCLRR 0x704 +#define RCC_MP_APB2ENSETR 0x708 +#define RCC_MP_APB2ENCLRR 0x70c +#define RCC_MP_APB3ENSETR 0x710 +#define RCC_MP_APB3ENCLRR 0x714 +#define RCC_MP_S_APB3ENSETR 0x718 +#define RCC_MP_S_APB3ENCLRR 0x71c +#define RCC_MP_NS_APB3ENSETR 0x720 +#define RCC_MP_NS_APB3ENCLRR 0x724 +#define RCC_MP_APB4ENSETR 0x728 +#define RCC_MP_APB4ENCLRR 0x72c +#define RCC_MP_S_APB4ENSETR 0x730 +#define RCC_MP_S_APB4ENCLRR 0x734 +#define RCC_MP_NS_APB4ENSETR 0x738 +#define RCC_MP_NS_APB4ENCLRR 0x73c +#define RCC_MP_APB5ENSETR 0x740 +#define RCC_MP_APB5ENCLRR 0x744 +#define RCC_MP_APB6ENSETR 0x748 +#define RCC_MP_APB6ENCLRR 0x74c +#define RCC_MP_AHB2ENSETR 0x750 +#define RCC_MP_AHB2ENCLRR 0x754 +#define RCC_MP_AHB4ENSETR 0x760 +#define RCC_MP_AHB4ENCLRR 0x764 +#define RCC_MP_S_AHB4ENSETR 0x768 +#define RCC_MP_S_AHB4ENCLRR 0x76c +#define RCC_MP_NS_AHB4ENSETR 0x770 +#define RCC_MP_NS_AHB4ENCLRR 0x774 +#define RCC_MP_AHB5ENSETR 0x778 +#define RCC_MP_AHB5ENCLRR 0x77c +#define RCC_MP_AHB6ENSETR 0x780 +#define RCC_MP_AHB6ENCLRR 0x784 +#define RCC_MP_S_AHB6ENSETR 0x788 +#define RCC_MP_S_AHB6ENCLRR 0x78c +#define RCC_MP_NS_AHB6ENSETR 0x790 +#define RCC_MP_NS_AHB6ENCLRR 0x794 +#define RCC_MP_APB1LPENSETR 0x800 +#define RCC_MP_APB1LPENCLRR 0x804 +#define RCC_MP_APB2LPENSETR 0x808 +#define RCC_MP_APB2LPENCLRR 0x80c +#define RCC_MP_APB3LPENSETR 0x810 +#define RCC_MP_APB3LPENCLRR 0x814 +#define RCC_MP_S_APB3LPENSETR 0x818 +#define RCC_MP_S_APB3LPENCLRR 0x81c +#define RCC_MP_NS_APB3LPENSETR 0x820 +#define RCC_MP_NS_APB3LPENCLRR 0x824 +#define RCC_MP_APB4LPENSETR 0x828 +#define RCC_MP_APB4LPENCLRR 0x82c +#define RCC_MP_S_APB4LPENSETR 0x830 +#define RCC_MP_S_APB4LPENCLRR 0x834 +#define RCC_MP_NS_APB4LPENSETR 0x838 +#define RCC_MP_NS_APB4LPENCLRR 0x83c +#define RCC_MP_APB5LPENSETR 0x840 +#define RCC_MP_APB5LPENCLRR 0x844 +#define RCC_MP_APB6LPENSETR 0x848 +#define RCC_MP_APB6LPENCLRR 0x84c +#define RCC_MP_AHB2LPENSETR 0x850 +#define RCC_MP_AHB2LPENCLRR 0x854 +#define RCC_MP_AHB4LPENSETR 0x858 +#define RCC_MP_AHB4LPENCLRR 0x85c +#define RCC_MP_S_AHB4LPENSETR 0x868 +#define RCC_MP_S_AHB4LPENCLRR 0x86c +#define RCC_MP_NS_AHB4LPENSETR 0x870 +#define RCC_MP_NS_AHB4LPENCLRR 0x874 +#define RCC_MP_AHB5LPENSETR 0x878 +#define RCC_MP_AHB5LPENCLRR 0x87c +#define RCC_MP_AHB6LPENSETR 0x880 +#define RCC_MP_AHB6LPENCLRR 0x884 +#define RCC_MP_S_AHB6LPENSETR 0x888 +#define RCC_MP_S_AHB6LPENCLRR 0x88c +#define RCC_MP_NS_AHB6LPENSETR 0x890 +#define RCC_MP_NS_AHB6LPENCLRR 0x894 +#define RCC_MP_S_AXIMLPENSETR 0x898 +#define RCC_MP_S_AXIMLPENCLRR 0x89c +#define RCC_MP_NS_AXIMLPENSETR 0x8a0 +#define RCC_MP_NS_AXIMLPENCLRR 0x8a4 +#define RCC_MP_MLAHBLPENSETR 0x8a8 +#define RCC_MP_MLAHBLPENCLRR 0x8ac +#define RCC_APB3SECSR 0x8c0 +#define RCC_APB4SECSR 0x8c4 +#define RCC_APB5SECSR 0x8c8 +#define RCC_APB6SECSR 0x8cc +#define RCC_AHB2SECSR 0x8d0 +#define RCC_AHB4SECSR 0x8d4 +#define RCC_AHB5SECSR 0x8d8 +#define RCC_AHB6SECSR 0x8dc +#define RCC_VERR 0xff4 +#define RCC_IDR 0xff8 +#define RCC_SIDR 0xffc + +/* RCC_SECCFGR register fields */ +#define RCC_SECCFGR_HSISEC 0 +#define RCC_SECCFGR_CSISEC 1 +#define RCC_SECCFGR_HSESEC 2 +#define RCC_SECCFGR_LSISEC 3 +#define RCC_SECCFGR_LSESEC 4 +#define RCC_SECCFGR_PLL12SEC 8 +#define RCC_SECCFGR_PLL3SEC 9 +#define RCC_SECCFGR_PLL4SEC 10 +#define RCC_SECCFGR_MPUSEC 11 +#define RCC_SECCFGR_AXISEC 12 +#define RCC_SECCFGR_MLAHBSEC 13 +#define RCC_SECCFGR_APB3DIVSEC 16 +#define RCC_SECCFGR_APB4DIVSEC 17 +#define RCC_SECCFGR_APB5DIVSEC 18 +#define RCC_SECCFGR_APB6DIVSEC 19 +#define RCC_SECCFGR_TIMG3SEC 20 +#define RCC_SECCFGR_CPERSEC 21 +#define RCC_SECCFGR_MCO1SEC 22 +#define RCC_SECCFGR_MCO2SEC 23 +#define RCC_SECCFGR_STPSEC 24 +#define RCC_SECCFGR_RSTSEC 25 +#define RCC_SECCFGR_PWRSEC 31 + +/* RCC_MP_SREQSETR register fields */ +#define RCC_MP_SREQSETR_STPREQ_P0 BIT(0) + +/* RCC_MP_SREQCLRR register fields */ +#define RCC_MP_SREQCLRR_STPREQ_P0 BIT(0) + +/* RCC_MP_APRSTCR register fields */ +#define RCC_MP_APRSTCR_RDCTLEN BIT(0) +#define RCC_MP_APRSTCR_RSTTO_MASK GENMASK(14, 8) +#define RCC_MP_APRSTCR_RSTTO_SHIFT 8 + +/* RCC_MP_APRSTSR register fields */ +#define RCC_MP_APRSTSR_RSTTOV_MASK GENMASK(14, 8) +#define RCC_MP_APRSTSR_RSTTOV_SHIFT 8 + +/* RCC_PWRLPDLYCR register fields */ +#define RCC_PWRLPDLYCR_PWRLP_DLY_MASK GENMASK(21, 0) +#define RCC_PWRLPDLYCR_PWRLP_DLY_SHIFT 0 + +/* RCC_MP_GRSTCSETR register fields */ +#define RCC_MP_GRSTCSETR_MPSYSRST BIT(0) +#define RCC_MP_GRSTCSETR_MPUP0RST BIT(4) + +/* RCC_BR_RSTSCLRR register fields */ +#define RCC_BR_RSTSCLRR_PORRSTF BIT(0) +#define RCC_BR_RSTSCLRR_BORRSTF BIT(1) +#define RCC_BR_RSTSCLRR_PADRSTF BIT(2) +#define RCC_BR_RSTSCLRR_HCSSRSTF BIT(3) +#define RCC_BR_RSTSCLRR_VCORERSTF BIT(4) +#define RCC_BR_RSTSCLRR_VCPURSTF BIT(5) +#define RCC_BR_RSTSCLRR_MPSYSRSTF BIT(6) +#define RCC_BR_RSTSCLRR_IWDG1RSTF BIT(8) +#define RCC_BR_RSTSCLRR_IWDG2RSTF BIT(9) +#define RCC_BR_RSTSCLRR_MPUP0RSTF BIT(13) + +/* RCC_MP_RSTSSETR register fields */ +#define RCC_MP_RSTSSETR_PORRSTF BIT(0) +#define RCC_MP_RSTSSETR_BORRSTF BIT(1) +#define RCC_MP_RSTSSETR_PADRSTF BIT(2) +#define RCC_MP_RSTSSETR_HCSSRSTF BIT(3) +#define RCC_MP_RSTSSETR_VCORERSTF BIT(4) +#define RCC_MP_RSTSSETR_VCPURSTF BIT(5) +#define RCC_MP_RSTSSETR_MPSYSRSTF BIT(6) +#define RCC_MP_RSTSSETR_IWDG1RSTF BIT(8) +#define RCC_MP_RSTSSETR_IWDG2RSTF BIT(9) +#define RCC_MP_RSTSSETR_STP2RSTF BIT(10) +#define RCC_MP_RSTSSETR_STDBYRSTF BIT(11) +#define RCC_MP_RSTSSETR_CSTDBYRSTF BIT(12) +#define RCC_MP_RSTSSETR_MPUP0RSTF BIT(13) +#define RCC_MP_RSTSSETR_SPARE BIT(15) + +/* RCC_MP_RSTSCLRR register fields */ +#define RCC_MP_RSTSCLRR_PORRSTF BIT(0) +#define RCC_MP_RSTSCLRR_BORRSTF BIT(1) +#define RCC_MP_RSTSCLRR_PADRSTF BIT(2) +#define RCC_MP_RSTSCLRR_HCSSRSTF BIT(3) +#define RCC_MP_RSTSCLRR_VCORERSTF BIT(4) +#define RCC_MP_RSTSCLRR_VCPURSTF BIT(5) +#define RCC_MP_RSTSCLRR_MPSYSRSTF BIT(6) +#define RCC_MP_RSTSCLRR_IWDG1RSTF BIT(8) +#define RCC_MP_RSTSCLRR_IWDG2RSTF BIT(9) +#define RCC_MP_RSTSCLRR_STP2RSTF BIT(10) +#define RCC_MP_RSTSCLRR_STDBYRSTF BIT(11) +#define RCC_MP_RSTSCLRR_CSTDBYRSTF BIT(12) +#define RCC_MP_RSTSCLRR_MPUP0RSTF BIT(13) +#define RCC_MP_RSTSCLRR_SPARE BIT(15) + +/* RCC_MP_IWDGFZSETR register fields */ +#define RCC_MP_IWDGFZSETR_FZ_IWDG1 BIT(0) +#define RCC_MP_IWDGFZSETR_FZ_IWDG2 BIT(1) + +/* RCC_MP_IWDGFZCLRR register fields */ +#define RCC_MP_IWDGFZCLRR_FZ_IWDG1 BIT(0) +#define RCC_MP_IWDGFZCLRR_FZ_IWDG2 BIT(1) + +/* RCC_MP_CIER register fields */ +#define RCC_MP_CIER_LSIRDYIE BIT(0) +#define RCC_MP_CIER_LSERDYIE BIT(1) +#define RCC_MP_CIER_HSIRDYIE BIT(2) +#define RCC_MP_CIER_HSERDYIE BIT(3) +#define RCC_MP_CIER_CSIRDYIE BIT(4) +#define RCC_MP_CIER_PLL1DYIE BIT(8) +#define RCC_MP_CIER_PLL2DYIE BIT(9) +#define RCC_MP_CIER_PLL3DYIE BIT(10) +#define RCC_MP_CIER_PLL4DYIE BIT(11) +#define RCC_MP_CIER_LSECSSIE BIT(16) +#define RCC_MP_CIER_WKUPIE BIT(20) + +/* RCC_MP_CIFR register fields */ +#define RCC_MP_CIFR_LSIRDYF BIT(0) +#define RCC_MP_CIFR_LSERDYF BIT(1) +#define RCC_MP_CIFR_HSIRDYF BIT(2) +#define RCC_MP_CIFR_HSERDYF BIT(3) +#define RCC_MP_CIFR_CSIRDYF BIT(4) +#define RCC_MP_CIFR_PLL1DYF BIT(8) +#define RCC_MP_CIFR_PLL2DYF BIT(9) +#define RCC_MP_CIFR_PLL3DYF BIT(10) +#define RCC_MP_CIFR_PLL4DYF BIT(11) +#define RCC_MP_CIFR_LSECSSF BIT(16) +#define RCC_MP_CIFR_WKUPF BIT(20) + +/* RCC_BDCR register fields */ +#define RCC_BDCR_LSEON BIT(0) +#define RCC_BDCR_LSEBYP BIT(1) +#define RCC_BDCR_LSERDY BIT(2) +#define RCC_BDCR_DIGBYP BIT(3) +#define RCC_BDCR_LSEDRV_MASK GENMASK(5, 4) +#define RCC_BDCR_LSECSSON BIT(8) +#define RCC_BDCR_LSECSSD BIT(9) +#define RCC_BDCR_RTCSRC_MASK GENMASK(17, 16) +#define RCC_BDCR_RTCCKEN BIT(20) +#define RCC_BDCR_VSWRST BIT(31) +#define RCC_BDCR_LSEDRV_SHIFT 4 +#define RCC_BDCR_RTCSRC_SHIFT 16 + +/* RCC_RDLSICR register fields */ +#define RCC_RDLSICR_LSION BIT(0) +#define RCC_RDLSICR_LSIRDY BIT(1) +#define RCC_RDLSICR_MRD_MASK GENMASK(20, 16) +#define RCC_RDLSICR_EADLY_MASK GENMASK(26, 24) +#define RCC_RDLSICR_SPARE_MASK GENMASK(31, 27) +#define RCC_RDLSICR_MRD_SHIFT 16 +#define RCC_RDLSICR_EADLY_SHIFT 24 +#define RCC_RDLSICR_SPARE_SHIFT 27 + +/* RCC_OCENSETR register fields */ +#define RCC_OCENSETR_HSION BIT(0) +#define RCC_OCENSETR_HSIKERON BIT(1) +#define RCC_OCENSETR_CSION BIT(4) +#define RCC_OCENSETR_CSIKERON BIT(5) +#define RCC_OCENSETR_DIGBYP BIT(7) +#define RCC_OCENSETR_HSEON BIT(8) +#define RCC_OCENSETR_HSEKERON BIT(9) +#define RCC_OCENSETR_HSEBYP BIT(10) +#define RCC_OCENSETR_HSECSSON BIT(11) + +/* RCC_OCENCLRR register fields */ +#define RCC_OCENCLRR_HSION BIT(0) +#define RCC_OCENCLRR_HSIKERON BIT(1) +#define RCC_OCENCLRR_CSION BIT(4) +#define RCC_OCENCLRR_CSIKERON BIT(5) +#define RCC_OCENCLRR_DIGBYP BIT(7) +#define RCC_OCENCLRR_HSEON BIT(8) +#define RCC_OCENCLRR_HSEKERON BIT(9) +#define RCC_OCENCLRR_HSEBYP BIT(10) + +/* RCC_OCRDYR register fields */ +#define RCC_OCRDYR_HSIRDY BIT(0) +#define RCC_OCRDYR_HSIDIVRDY BIT(2) +#define RCC_OCRDYR_CSIRDY BIT(4) +#define RCC_OCRDYR_HSERDY BIT(8) +#define RCC_OCRDYR_MPUCKRDY BIT(23) +#define RCC_OCRDYR_AXICKRDY BIT(24) + +/* RCC_HSICFGR register fields */ +#define RCC_HSICFGR_HSIDIV_MASK GENMASK(1, 0) +#define RCC_HSICFGR_HSITRIM_MASK GENMASK(14, 8) +#define RCC_HSICFGR_HSICAL_MASK GENMASK(27, 16) +#define RCC_HSICFGR_HSIDIV_SHIFT 0 +#define RCC_HSICFGR_HSITRIM_SHIFT 8 +#define RCC_HSICFGR_HSICAL_SHIFT 16 + +/* RCC_CSICFGR register fields */ +#define RCC_CSICFGR_CSITRIM_MASK GENMASK(12, 8) +#define RCC_CSICFGR_CSICAL_MASK GENMASK(23, 16) +#define RCC_CSICFGR_CSITRIM_SHIFT 8 +#define RCC_CSICFGR_CSICAL_SHIFT 16 + +/* RCC_MCO1CFGR register fields */ +#define RCC_MCO1CFGR_MCO1SEL_MASK GENMASK(2, 0) +#define RCC_MCO1CFGR_MCO1DIV_MASK GENMASK(7, 4) +#define RCC_MCO1CFGR_MCO1ON BIT(12) +#define RCC_MCO1CFGR_MCO1SEL_SHIFT 0 +#define RCC_MCO1CFGR_MCO1DIV_SHIFT 4 + +/* RCC_MCO2CFGR register fields */ +#define RCC_MCO2CFGR_MCO2SEL_MASK GENMASK(2, 0) +#define RCC_MCO2CFGR_MCO2DIV_MASK GENMASK(7, 4) +#define RCC_MCO2CFGR_MCO2ON BIT(12) +#define RCC_MCO2CFGR_MCO2SEL_SHIFT 0 +#define RCC_MCO2CFGR_MCO2DIV_SHIFT 4 + +/* RCC_DBGCFGR register fields */ +#define RCC_DBGCFGR_TRACEDIV_MASK GENMASK(2, 0) +#define RCC_DBGCFGR_DBGCKEN BIT(8) +#define RCC_DBGCFGR_TRACECKEN BIT(9) +#define RCC_DBGCFGR_DBGRST BIT(12) +#define RCC_DBGCFGR_TRACEDIV_SHIFT 0 + +/* RCC_RCK12SELR register fields */ +#define RCC_RCK12SELR_PLL12SRC_MASK GENMASK(1, 0) +#define RCC_RCK12SELR_PLL12SRCRDY BIT(31) +#define RCC_RCK12SELR_PLL12SRC_SHIFT 0 + +/* RCC_RCK3SELR register fields */ +#define RCC_RCK3SELR_PLL3SRC_MASK GENMASK(1, 0) +#define RCC_RCK3SELR_PLL3SRCRDY BIT(31) +#define RCC_RCK3SELR_PLL3SRC_SHIFT 0 + +/* RCC_RCK4SELR register fields */ +#define RCC_RCK4SELR_PLL4SRC_MASK GENMASK(1, 0) +#define RCC_RCK4SELR_PLL4SRCRDY BIT(31) +#define RCC_RCK4SELR_PLL4SRC_SHIFT 0 + +/* RCC_PLL1CR register fields */ +#define RCC_PLL1CR_PLLON BIT(0) +#define RCC_PLL1CR_PLL1RDY BIT(1) +#define RCC_PLL1CR_SSCG_CTRL BIT(2) +#define RCC_PLL1CR_DIVPEN BIT(4) +#define RCC_PLL1CR_DIVQEN BIT(5) +#define RCC_PLL1CR_DIVREN BIT(6) + +/* RCC_PLL1CFGR1 register fields */ +#define RCC_PLL1CFGR1_DIVN_MASK GENMASK(8, 0) +#define RCC_PLL1CFGR1_DIVM1_MASK GENMASK(21, 16) +#define RCC_PLL1CFGR1_DIVN_SHIFT 0 +#define RCC_PLL1CFGR1_DIVM1_SHIFT 16 + +/* RCC_PLL1CFGR2 register fields */ +#define RCC_PLL1CFGR2_DIVP_MASK GENMASK(6, 0) +#define RCC_PLL1CFGR2_DIVQ_MASK GENMASK(14, 8) +#define RCC_PLL1CFGR2_DIVR_MASK GENMASK(22, 16) +#define RCC_PLL1CFGR2_DIVP_SHIFT 0 +#define RCC_PLL1CFGR2_DIVQ_SHIFT 8 +#define RCC_PLL1CFGR2_DIVR_SHIFT 16 + +/* RCC_PLL1FRACR register fields */ +#define RCC_PLL1FRACR_FRACV_MASK GENMASK(15, 3) +#define RCC_PLL1FRACR_FRACLE BIT(16) +#define RCC_PLL1FRACR_FRACV_SHIFT 3 + +/* RCC_PLL1CSGR register fields */ +#define RCC_PLL1CSGR_MOD_PER_MASK GENMASK(12, 0) +#define RCC_PLL1CSGR_TPDFN_DIS BIT(13) +#define RCC_PLL1CSGR_RPDFN_DIS BIT(14) +#define RCC_PLL1CSGR_SSCG_MODE BIT(15) +#define RCC_PLL1CSGR_INC_STEP_MASK GENMASK(30, 16) +#define RCC_PLL1CSGR_MOD_PER_SHIFT 0 +#define RCC_PLL1CSGR_INC_STEP_SHIFT 16 + +/* RCC_PLL2CR register fields */ +#define RCC_PLL2CR_PLLON BIT(0) +#define RCC_PLL2CR_PLL2RDY BIT(1) +#define RCC_PLL2CR_SSCG_CTRL BIT(2) +#define RCC_PLL2CR_DIVPEN BIT(4) +#define RCC_PLL2CR_DIVQEN BIT(5) +#define RCC_PLL2CR_DIVREN BIT(6) + +/* RCC_PLL2CFGR1 register fields */ +#define RCC_PLL2CFGR1_DIVN_MASK GENMASK(8, 0) +#define RCC_PLL2CFGR1_DIVM2_MASK GENMASK(21, 16) +#define RCC_PLL2CFGR1_DIVN_SHIFT 0 +#define RCC_PLL2CFGR1_DIVM2_SHIFT 16 + +/* RCC_PLL2CFGR2 register fields */ +#define RCC_PLL2CFGR2_DIVP_MASK GENMASK(6, 0) +#define RCC_PLL2CFGR2_DIVQ_MASK GENMASK(14, 8) +#define RCC_PLL2CFGR2_DIVR_MASK GENMASK(22, 16) +#define RCC_PLL2CFGR2_DIVP_SHIFT 0 +#define RCC_PLL2CFGR2_DIVQ_SHIFT 8 +#define RCC_PLL2CFGR2_DIVR_SHIFT 16 + +/* RCC_PLL2FRACR register fields */ +#define RCC_PLL2FRACR_FRACV_MASK GENMASK(15, 3) +#define RCC_PLL2FRACR_FRACLE BIT(16) +#define RCC_PLL2FRACR_FRACV_SHIFT 3 + +/* RCC_PLL2CSGR register fields */ +#define RCC_PLL2CSGR_MOD_PER_MASK GENMASK(12, 0) +#define RCC_PLL2CSGR_TPDFN_DIS BIT(13) +#define RCC_PLL2CSGR_RPDFN_DIS BIT(14) +#define RCC_PLL2CSGR_SSCG_MODE BIT(15) +#define RCC_PLL2CSGR_INC_STEP_MASK GENMASK(30, 16) +#define RCC_PLL2CSGR_MOD_PER_SHIFT 0 +#define RCC_PLL2CSGR_INC_STEP_SHIFT 16 + +/* RCC_PLL3CR register fields */ +#define RCC_PLL3CR_PLLON BIT(0) +#define RCC_PLL3CR_PLL3RDY BIT(1) +#define RCC_PLL3CR_SSCG_CTRL BIT(2) +#define RCC_PLL3CR_DIVPEN BIT(4) +#define RCC_PLL3CR_DIVQEN BIT(5) +#define RCC_PLL3CR_DIVREN BIT(6) + +/* RCC_PLL3CFGR1 register fields */ +#define RCC_PLL3CFGR1_DIVN_MASK GENMASK(8, 0) +#define RCC_PLL3CFGR1_DIVM3_MASK GENMASK(21, 16) +#define RCC_PLL3CFGR1_IFRGE_MASK GENMASK(25, 24) +#define RCC_PLL3CFGR1_DIVN_SHIFT 0 +#define RCC_PLL3CFGR1_DIVM3_SHIFT 16 +#define RCC_PLL3CFGR1_IFRGE_SHIFT 24 + +/* RCC_PLL3CFGR2 register fields */ +#define RCC_PLL3CFGR2_DIVP_MASK GENMASK(6, 0) +#define RCC_PLL3CFGR2_DIVQ_MASK GENMASK(14, 8) +#define RCC_PLL3CFGR2_DIVR_MASK GENMASK(22, 16) +#define RCC_PLL3CFGR2_DIVP_SHIFT 0 +#define RCC_PLL3CFGR2_DIVQ_SHIFT 8 +#define RCC_PLL3CFGR2_DIVR_SHIFT 16 + +/* RCC_PLL3FRACR register fields */ +#define RCC_PLL3FRACR_FRACV_MASK GENMASK(15, 3) +#define RCC_PLL3FRACR_FRACLE BIT(16) +#define RCC_PLL3FRACR_FRACV_SHIFT 3 + +/* RCC_PLL3CSGR register fields */ +#define RCC_PLL3CSGR_MOD_PER_MASK GENMASK(12, 0) +#define RCC_PLL3CSGR_TPDFN_DIS BIT(13) +#define RCC_PLL3CSGR_RPDFN_DIS BIT(14) +#define RCC_PLL3CSGR_SSCG_MODE BIT(15) +#define RCC_PLL3CSGR_INC_STEP_MASK GENMASK(30, 16) +#define RCC_PLL3CSGR_MOD_PER_SHIFT 0 +#define RCC_PLL3CSGR_INC_STEP_SHIFT 16 + +/* RCC_PLL4CR register fields */ +#define RCC_PLL4CR_PLLON BIT(0) +#define RCC_PLL4CR_PLL4RDY BIT(1) +#define RCC_PLL4CR_SSCG_CTRL BIT(2) +#define RCC_PLL4CR_DIVPEN BIT(4) +#define RCC_PLL4CR_DIVQEN BIT(5) +#define RCC_PLL4CR_DIVREN BIT(6) + +/* RCC_PLL4CFGR1 register fields */ +#define RCC_PLL4CFGR1_DIVN_MASK GENMASK(8, 0) +#define RCC_PLL4CFGR1_DIVM4_MASK GENMASK(21, 16) +#define RCC_PLL4CFGR1_IFRGE_MASK GENMASK(25, 24) +#define RCC_PLL4CFGR1_DIVN_SHIFT 0 +#define RCC_PLL4CFGR1_DIVM4_SHIFT 16 +#define RCC_PLL4CFGR1_IFRGE_SHIFT 24 + +/* RCC_PLL4CFGR2 register fields */ +#define RCC_PLL4CFGR2_DIVP_MASK GENMASK(6, 0) +#define RCC_PLL4CFGR2_DIVQ_MASK GENMASK(14, 8) +#define RCC_PLL4CFGR2_DIVR_MASK GENMASK(22, 16) +#define RCC_PLL4CFGR2_DIVP_SHIFT 0 +#define RCC_PLL4CFGR2_DIVQ_SHIFT 8 +#define RCC_PLL4CFGR2_DIVR_SHIFT 16 + +/* RCC_PLL4FRACR register fields */ +#define RCC_PLL4FRACR_FRACV_MASK GENMASK(15, 3) +#define RCC_PLL4FRACR_FRACLE BIT(16) +#define RCC_PLL4FRACR_FRACV_SHIFT 3 + +/* RCC_PLL4CSGR register fields */ +#define RCC_PLL4CSGR_MOD_PER_MASK GENMASK(12, 0) +#define RCC_PLL4CSGR_TPDFN_DIS BIT(13) +#define RCC_PLL4CSGR_RPDFN_DIS BIT(14) +#define RCC_PLL4CSGR_SSCG_MODE BIT(15) +#define RCC_PLL4CSGR_INC_STEP_MASK GENMASK(30, 16) +#define RCC_PLL4CSGR_MOD_PER_SHIFT 0 +#define RCC_PLL4CSGR_INC_STEP_SHIFT 16 + +/* RCC_MPCKSELR register fields */ +#define RCC_MPCKSELR_MPUSRC_MASK GENMASK(1, 0) +#define RCC_MPCKSELR_MPUSRCRDY BIT(31) +#define RCC_MPCKSELR_MPUSRC_SHIFT 0 + +/* RCC_ASSCKSELR register fields */ +#define RCC_ASSCKSELR_AXISSRC_MASK GENMASK(2, 0) +#define RCC_ASSCKSELR_AXISSRCRDY BIT(31) +#define RCC_ASSCKSELR_AXISSRC_SHIFT 0 + +/* RCC_MSSCKSELR register fields */ +#define RCC_MSSCKSELR_MLAHBSSRC_MASK GENMASK(1, 0) +#define RCC_MSSCKSELR_MLAHBSSRCRDY BIT(31) +#define RCC_MSSCKSELR_MLAHBSSRC_SHIFT 0 + +/* RCC_CPERCKSELR register fields */ +#define RCC_CPERCKSELR_CKPERSRC_MASK GENMASK(1, 0) +#define RCC_CPERCKSELR_CKPERSRC_SHIFT 0 + +/* RCC_RTCDIVR register fields */ +#define RCC_RTCDIVR_RTCDIV_MASK GENMASK(5, 0) +#define RCC_RTCDIVR_RTCDIV_SHIFT 0 + +/* RCC_MPCKDIVR register fields */ +#define RCC_MPCKDIVR_MPUDIV_MASK GENMASK(3, 0) +#define RCC_MPCKDIVR_MPUDIVRDY BIT(31) +#define RCC_MPCKDIVR_MPUDIV_SHIFT 0 + +/* RCC_AXIDIVR register fields */ +#define RCC_AXIDIVR_AXIDIV_MASK GENMASK(2, 0) +#define RCC_AXIDIVR_AXIDIVRDY BIT(31) +#define RCC_AXIDIVR_AXIDIV_SHIFT 0 + +/* RCC_MLAHBDIVR register fields */ +#define RCC_MLAHBDIVR_MLAHBDIV_MASK GENMASK(3, 0) +#define RCC_MLAHBDIVR_MLAHBDIVRDY BIT(31) +#define RCC_MLAHBDIVR_MLAHBDIV_SHIFT 0 + +/* RCC_APB1DIVR register fields */ +#define RCC_APB1DIVR_APB1DIV_MASK GENMASK(2, 0) +#define RCC_APB1DIVR_APB1DIVRDY BIT(31) +#define RCC_APB1DIVR_APB1DIV_SHIFT 0 + +/* RCC_APB2DIVR register fields */ +#define RCC_APB2DIVR_APB2DIV_MASK GENMASK(2, 0) +#define RCC_APB2DIVR_APB2DIVRDY BIT(31) +#define RCC_APB2DIVR_APB2DIV_SHIFT 0 + +/* RCC_APB3DIVR register fields */ +#define RCC_APB3DIVR_APB3DIV_MASK GENMASK(2, 0) +#define RCC_APB3DIVR_APB3DIVRDY BIT(31) +#define RCC_APB3DIVR_APB3DIV_SHIFT 0 + +/* RCC_APB4DIVR register fields */ +#define RCC_APB4DIVR_APB4DIV_MASK GENMASK(2, 0) +#define RCC_APB4DIVR_APB4DIVRDY BIT(31) +#define RCC_APB4DIVR_APB4DIV_SHIFT 0 + +/* RCC_APB5DIVR register fields */ +#define RCC_APB5DIVR_APB5DIV_MASK GENMASK(2, 0) +#define RCC_APB5DIVR_APB5DIVRDY BIT(31) +#define RCC_APB5DIVR_APB5DIV_SHIFT 0 + +/* RCC_APB6DIVR register fields */ +#define RCC_APB6DIVR_APB6DIV_MASK GENMASK(2, 0) +#define RCC_APB6DIVR_APB6DIVRDY BIT(31) +#define RCC_APB6DIVR_APB6DIV_SHIFT 0 + +/* RCC_TIMG1PRER register fields */ +#define RCC_TIMG1PRER_TIMG1PRE BIT(0) +#define RCC_TIMG1PRER_TIMG1PRERDY BIT(31) + +/* RCC_TIMG2PRER register fields */ +#define RCC_TIMG2PRER_TIMG2PRE BIT(0) +#define RCC_TIMG2PRER_TIMG2PRERDY BIT(31) + +/* RCC_TIMG3PRER register fields */ +#define RCC_TIMG3PRER_TIMG3PRE BIT(0) +#define RCC_TIMG3PRER_TIMG3PRERDY BIT(31) + +/* RCC_DDRITFCR register fields */ +#define RCC_DDRITFCR_DDRC1EN BIT(0) +#define RCC_DDRITFCR_DDRC1LPEN BIT(1) +#define RCC_DDRITFCR_DDRPHYCEN BIT(4) +#define RCC_DDRITFCR_DDRPHYCLPEN BIT(5) +#define RCC_DDRITFCR_DDRCAPBEN BIT(6) +#define RCC_DDRITFCR_DDRCAPBLPEN BIT(7) +#define RCC_DDRITFCR_AXIDCGEN BIT(8) +#define RCC_DDRITFCR_DDRPHYCAPBEN BIT(9) +#define RCC_DDRITFCR_DDRPHYCAPBLPEN BIT(10) +#define RCC_DDRITFCR_KERDCG_DLY_MASK GENMASK(13, 11) +#define RCC_DDRITFCR_DDRCAPBRST BIT(14) +#define RCC_DDRITFCR_DDRCAXIRST BIT(15) +#define RCC_DDRITFCR_DDRCORERST BIT(16) +#define RCC_DDRITFCR_DPHYAPBRST BIT(17) +#define RCC_DDRITFCR_DPHYRST BIT(18) +#define RCC_DDRITFCR_DPHYCTLRST BIT(19) +#define RCC_DDRITFCR_DDRCKMOD_MASK GENMASK(22, 20) +#define RCC_DDRITFCR_GSKPMOD BIT(23) +#define RCC_DDRITFCR_GSKPCTRL BIT(24) +#define RCC_DDRITFCR_DFILP_WIDTH_MASK GENMASK(27, 25) +#define RCC_DDRITFCR_GSKP_DUR_MASK GENMASK(31, 28) +#define RCC_DDRITFCR_KERDCG_DLY_SHIFT 11 +#define RCC_DDRITFCR_DDRCKMOD_SHIFT 20 +#define RCC_DDRITFCR_DFILP_WIDTH_SHIFT 25 +#define RCC_DDRITFCR_GSKP_DUR_SHIFT 28 + +/* RCC_I2C12CKSELR register fields */ +#define RCC_I2C12CKSELR_I2C12SRC_MASK GENMASK(2, 0) +#define RCC_I2C12CKSELR_I2C12SRC_SHIFT 0 + +/* RCC_I2C345CKSELR register fields */ +#define RCC_I2C345CKSELR_I2C3SRC_MASK GENMASK(2, 0) +#define RCC_I2C345CKSELR_I2C4SRC_MASK GENMASK(5, 3) +#define RCC_I2C345CKSELR_I2C5SRC_MASK GENMASK(8, 6) +#define RCC_I2C345CKSELR_I2C3SRC_SHIFT 0 +#define RCC_I2C345CKSELR_I2C4SRC_SHIFT 3 +#define RCC_I2C345CKSELR_I2C5SRC_SHIFT 6 + +/* RCC_SPI2S1CKSELR register fields */ +#define RCC_SPI2S1CKSELR_SPI1SRC_MASK GENMASK(2, 0) +#define RCC_SPI2S1CKSELR_SPI1SRC_SHIFT 0 + +/* RCC_SPI2S23CKSELR register fields */ +#define RCC_SPI2S23CKSELR_SPI23SRC_MASK GENMASK(2, 0) +#define RCC_SPI2S23CKSELR_SPI23SRC_SHIFT 0 + +/* RCC_SPI45CKSELR register fields */ +#define RCC_SPI45CKSELR_SPI4SRC_MASK GENMASK(2, 0) +#define RCC_SPI45CKSELR_SPI5SRC_MASK GENMASK(5, 3) +#define RCC_SPI45CKSELR_SPI4SRC_SHIFT 0 +#define RCC_SPI45CKSELR_SPI5SRC_SHIFT 3 + +/* RCC_UART12CKSELR register fields */ +#define RCC_UART12CKSELR_UART1SRC_MASK GENMASK(2, 0) +#define RCC_UART12CKSELR_UART2SRC_MASK GENMASK(5, 3) +#define RCC_UART12CKSELR_UART1SRC_SHIFT 0 +#define RCC_UART12CKSELR_UART2SRC_SHIFT 3 + +/* RCC_UART35CKSELR register fields */ +#define RCC_UART35CKSELR_UART35SRC_MASK GENMASK(2, 0) +#define RCC_UART35CKSELR_UART35SRC_SHIFT 0 + +/* RCC_UART4CKSELR register fields */ +#define RCC_UART4CKSELR_UART4SRC_MASK GENMASK(2, 0) +#define RCC_UART4CKSELR_UART4SRC_SHIFT 0 + +/* RCC_UART6CKSELR register fields */ +#define RCC_UART6CKSELR_UART6SRC_MASK GENMASK(2, 0) +#define RCC_UART6CKSELR_UART6SRC_SHIFT 0 + +/* RCC_UART78CKSELR register fields */ +#define RCC_UART78CKSELR_UART78SRC_MASK GENMASK(2, 0) +#define RCC_UART78CKSELR_UART78SRC_SHIFT 0 + +/* RCC_LPTIM1CKSELR register fields */ +#define RCC_LPTIM1CKSELR_LPTIM1SRC_MASK GENMASK(2, 0) +#define RCC_LPTIM1CKSELR_LPTIM1SRC_SHIFT 0 + +/* RCC_LPTIM23CKSELR register fields */ +#define RCC_LPTIM23CKSELR_LPTIM2SRC_MASK GENMASK(2, 0) +#define RCC_LPTIM23CKSELR_LPTIM3SRC_MASK GENMASK(5, 3) +#define RCC_LPTIM23CKSELR_LPTIM2SRC_SHIFT 0 +#define RCC_LPTIM23CKSELR_LPTIM3SRC_SHIFT 3 + +/* RCC_LPTIM45CKSELR register fields */ +#define RCC_LPTIM45CKSELR_LPTIM45SRC_MASK GENMASK(2, 0) +#define RCC_LPTIM45CKSELR_LPTIM45SRC_SHIFT 0 + +/* RCC_SAI1CKSELR register fields */ +#define RCC_SAI1CKSELR_SAI1SRC_MASK GENMASK(2, 0) +#define RCC_SAI1CKSELR_SAI1SRC_SHIFT 0 + +/* RCC_SAI2CKSELR register fields */ +#define RCC_SAI2CKSELR_SAI2SRC_MASK GENMASK(2, 0) +#define RCC_SAI2CKSELR_SAI2SRC_SHIFT 0 + +/* RCC_FDCANCKSELR register fields */ +#define RCC_FDCANCKSELR_FDCANSRC_MASK GENMASK(1, 0) +#define RCC_FDCANCKSELR_FDCANSRC_SHIFT 0 + +/* RCC_SPDIFCKSELR register fields */ +#define RCC_SPDIFCKSELR_SPDIFSRC_MASK GENMASK(1, 0) +#define RCC_SPDIFCKSELR_SPDIFSRC_SHIFT 0 + +/* RCC_ADC12CKSELR register fields */ +#define RCC_ADC12CKSELR_ADC1SRC_MASK GENMASK(1, 0) +#define RCC_ADC12CKSELR_ADC2SRC_MASK GENMASK(3, 2) +#define RCC_ADC12CKSELR_ADC1SRC_SHIFT 0 +#define RCC_ADC12CKSELR_ADC2SRC_SHIFT 2 + +/* RCC_SDMMC12CKSELR register fields */ +#define RCC_SDMMC12CKSELR_SDMMC1SRC_MASK GENMASK(2, 0) +#define RCC_SDMMC12CKSELR_SDMMC2SRC_MASK GENMASK(5, 3) +#define RCC_SDMMC12CKSELR_SDMMC1SRC_SHIFT 0 +#define RCC_SDMMC12CKSELR_SDMMC2SRC_SHIFT 3 + +/* RCC_ETH12CKSELR register fields */ +#define RCC_ETH12CKSELR_ETH1SRC_MASK GENMASK(1, 0) +#define RCC_ETH12CKSELR_ETH1PTPDIV_MASK GENMASK(7, 4) +#define RCC_ETH12CKSELR_ETH2SRC_MASK GENMASK(9, 8) +#define RCC_ETH12CKSELR_ETH2PTPDIV_MASK GENMASK(15, 12) +#define RCC_ETH12CKSELR_ETH1SRC_SHIFT 0 +#define RCC_ETH12CKSELR_ETH1PTPDIV_SHIFT 4 +#define RCC_ETH12CKSELR_ETH2SRC_SHIFT 8 +#define RCC_ETH12CKSELR_ETH2PTPDIV_SHIFT 12 + +/* RCC_USBCKSELR register fields */ +#define RCC_USBCKSELR_USBPHYSRC_MASK GENMASK(1, 0) +#define RCC_USBCKSELR_USBOSRC BIT(4) +#define RCC_USBCKSELR_USBPHYSRC_SHIFT 0 + +/* RCC_QSPICKSELR register fields */ +#define RCC_QSPICKSELR_QSPISRC_MASK GENMASK(1, 0) +#define RCC_QSPICKSELR_QSPISRC_SHIFT 0 + +/* RCC_FMCCKSELR register fields */ +#define RCC_FMCCKSELR_FMCSRC_MASK GENMASK(1, 0) +#define RCC_FMCCKSELR_FMCSRC_SHIFT 0 + +/* RCC_RNG1CKSELR register fields */ +#define RCC_RNG1CKSELR_RNG1SRC_MASK GENMASK(1, 0) +#define RCC_RNG1CKSELR_RNG1SRC_SHIFT 0 + +/* RCC_STGENCKSELR register fields */ +#define RCC_STGENCKSELR_STGENSRC_MASK GENMASK(1, 0) +#define RCC_STGENCKSELR_STGENSRC_SHIFT 0 + +/* RCC_DCMIPPCKSELR register fields */ +#define RCC_DCMIPPCKSELR_DCMIPPSRC_MASK GENMASK(1, 0) +#define RCC_DCMIPPCKSELR_DCMIPPSRC_SHIFT 0 + +/* RCC_SAESCKSELR register fields */ +#define RCC_SAESCKSELR_SAESSRC_MASK GENMASK(1, 0) +#define RCC_SAESCKSELR_SAESSRC_SHIFT 0 + +/* RCC_APB1RSTSETR register fields */ +#define RCC_APB1RSTSETR_TIM2RST BIT(0) +#define RCC_APB1RSTSETR_TIM3RST BIT(1) +#define RCC_APB1RSTSETR_TIM4RST BIT(2) +#define RCC_APB1RSTSETR_TIM5RST BIT(3) +#define RCC_APB1RSTSETR_TIM6RST BIT(4) +#define RCC_APB1RSTSETR_TIM7RST BIT(5) +#define RCC_APB1RSTSETR_LPTIM1RST BIT(9) +#define RCC_APB1RSTSETR_SPI2RST BIT(11) +#define RCC_APB1RSTSETR_SPI3RST BIT(12) +#define RCC_APB1RSTSETR_USART3RST BIT(15) +#define RCC_APB1RSTSETR_UART4RST BIT(16) +#define RCC_APB1RSTSETR_UART5RST BIT(17) +#define RCC_APB1RSTSETR_UART7RST BIT(18) +#define RCC_APB1RSTSETR_UART8RST BIT(19) +#define RCC_APB1RSTSETR_I2C1RST BIT(21) +#define RCC_APB1RSTSETR_I2C2RST BIT(22) +#define RCC_APB1RSTSETR_SPDIFRST BIT(26) + +/* RCC_APB1RSTCLRR register fields */ +#define RCC_APB1RSTCLRR_TIM2RST BIT(0) +#define RCC_APB1RSTCLRR_TIM3RST BIT(1) +#define RCC_APB1RSTCLRR_TIM4RST BIT(2) +#define RCC_APB1RSTCLRR_TIM5RST BIT(3) +#define RCC_APB1RSTCLRR_TIM6RST BIT(4) +#define RCC_APB1RSTCLRR_TIM7RST BIT(5) +#define RCC_APB1RSTCLRR_LPTIM1RST BIT(9) +#define RCC_APB1RSTCLRR_SPI2RST BIT(11) +#define RCC_APB1RSTCLRR_SPI3RST BIT(12) +#define RCC_APB1RSTCLRR_USART3RST BIT(15) +#define RCC_APB1RSTCLRR_UART4RST BIT(16) +#define RCC_APB1RSTCLRR_UART5RST BIT(17) +#define RCC_APB1RSTCLRR_UART7RST BIT(18) +#define RCC_APB1RSTCLRR_UART8RST BIT(19) +#define RCC_APB1RSTCLRR_I2C1RST BIT(21) +#define RCC_APB1RSTCLRR_I2C2RST BIT(22) +#define RCC_APB1RSTCLRR_SPDIFRST BIT(26) + +/* RCC_APB2RSTSETR register fields */ +#define RCC_APB2RSTSETR_TIM1RST BIT(0) +#define RCC_APB2RSTSETR_TIM8RST BIT(1) +#define RCC_APB2RSTSETR_SPI1RST BIT(8) +#define RCC_APB2RSTSETR_USART6RST BIT(13) +#define RCC_APB2RSTSETR_SAI1RST BIT(16) +#define RCC_APB2RSTSETR_SAI2RST BIT(17) +#define RCC_APB2RSTSETR_DFSDMRST BIT(20) +#define RCC_APB2RSTSETR_FDCANRST BIT(24) + +/* RCC_APB2RSTCLRR register fields */ +#define RCC_APB2RSTCLRR_TIM1RST BIT(0) +#define RCC_APB2RSTCLRR_TIM8RST BIT(1) +#define RCC_APB2RSTCLRR_SPI1RST BIT(8) +#define RCC_APB2RSTCLRR_USART6RST BIT(13) +#define RCC_APB2RSTCLRR_SAI1RST BIT(16) +#define RCC_APB2RSTCLRR_SAI2RST BIT(17) +#define RCC_APB2RSTCLRR_DFSDMRST BIT(20) +#define RCC_APB2RSTCLRR_FDCANRST BIT(24) + +/* RCC_APB3RSTSETR register fields */ +#define RCC_APB3RSTSETR_LPTIM2RST BIT(0) +#define RCC_APB3RSTSETR_LPTIM3RST BIT(1) +#define RCC_APB3RSTSETR_LPTIM4RST BIT(2) +#define RCC_APB3RSTSETR_LPTIM5RST BIT(3) +#define RCC_APB3RSTSETR_SYSCFGRST BIT(11) +#define RCC_APB3RSTSETR_VREFRST BIT(13) +#define RCC_APB3RSTSETR_DTSRST BIT(16) +#define RCC_APB3RSTSETR_PMBCTRLRST BIT(17) + +/* RCC_APB3RSTCLRR register fields */ +#define RCC_APB3RSTCLRR_LPTIM2RST BIT(0) +#define RCC_APB3RSTCLRR_LPTIM3RST BIT(1) +#define RCC_APB3RSTCLRR_LPTIM4RST BIT(2) +#define RCC_APB3RSTCLRR_LPTIM5RST BIT(3) +#define RCC_APB3RSTCLRR_SYSCFGRST BIT(11) +#define RCC_APB3RSTCLRR_VREFRST BIT(13) +#define RCC_APB3RSTCLRR_DTSRST BIT(16) +#define RCC_APB3RSTCLRR_PMBCTRLRST BIT(17) + +/* RCC_APB4RSTSETR register fields */ +#define RCC_APB4RSTSETR_LTDCRST BIT(0) +#define RCC_APB4RSTSETR_DCMIPPRST BIT(1) +#define RCC_APB4RSTSETR_DDRPERFMRST BIT(8) +#define RCC_APB4RSTSETR_USBPHYRST BIT(16) + +/* RCC_APB4RSTCLRR register fields */ +#define RCC_APB4RSTCLRR_LTDCRST BIT(0) +#define RCC_APB4RSTCLRR_DCMIPPRST BIT(1) +#define RCC_APB4RSTCLRR_DDRPERFMRST BIT(8) +#define RCC_APB4RSTCLRR_USBPHYRST BIT(16) + +/* RCC_APB5RSTSETR register fields */ +#define RCC_APB5RSTSETR_STGENRST BIT(20) + +/* RCC_APB5RSTCLRR register fields */ +#define RCC_APB5RSTCLRR_STGENRST BIT(20) + +/* RCC_APB6RSTSETR register fields */ +#define RCC_APB6RSTSETR_USART1RST BIT(0) +#define RCC_APB6RSTSETR_USART2RST BIT(1) +#define RCC_APB6RSTSETR_SPI4RST BIT(2) +#define RCC_APB6RSTSETR_SPI5RST BIT(3) +#define RCC_APB6RSTSETR_I2C3RST BIT(4) +#define RCC_APB6RSTSETR_I2C4RST BIT(5) +#define RCC_APB6RSTSETR_I2C5RST BIT(6) +#define RCC_APB6RSTSETR_TIM12RST BIT(7) +#define RCC_APB6RSTSETR_TIM13RST BIT(8) +#define RCC_APB6RSTSETR_TIM14RST BIT(9) +#define RCC_APB6RSTSETR_TIM15RST BIT(10) +#define RCC_APB6RSTSETR_TIM16RST BIT(11) +#define RCC_APB6RSTSETR_TIM17RST BIT(12) + +/* RCC_APB6RSTCLRR register fields */ +#define RCC_APB6RSTCLRR_USART1RST BIT(0) +#define RCC_APB6RSTCLRR_USART2RST BIT(1) +#define RCC_APB6RSTCLRR_SPI4RST BIT(2) +#define RCC_APB6RSTCLRR_SPI5RST BIT(3) +#define RCC_APB6RSTCLRR_I2C3RST BIT(4) +#define RCC_APB6RSTCLRR_I2C4RST BIT(5) +#define RCC_APB6RSTCLRR_I2C5RST BIT(6) +#define RCC_APB6RSTCLRR_TIM12RST BIT(7) +#define RCC_APB6RSTCLRR_TIM13RST BIT(8) +#define RCC_APB6RSTCLRR_TIM14RST BIT(9) +#define RCC_APB6RSTCLRR_TIM15RST BIT(10) +#define RCC_APB6RSTCLRR_TIM16RST BIT(11) +#define RCC_APB6RSTCLRR_TIM17RST BIT(12) + +/* RCC_AHB2RSTSETR register fields */ +#define RCC_AHB2RSTSETR_DMA1RST BIT(0) +#define RCC_AHB2RSTSETR_DMA2RST BIT(1) +#define RCC_AHB2RSTSETR_DMAMUX1RST BIT(2) +#define RCC_AHB2RSTSETR_DMA3RST BIT(3) +#define RCC_AHB2RSTSETR_DMAMUX2RST BIT(4) +#define RCC_AHB2RSTSETR_ADC1RST BIT(5) +#define RCC_AHB2RSTSETR_ADC2RST BIT(6) +#define RCC_AHB2RSTSETR_USBORST BIT(8) + +/* RCC_AHB2RSTCLRR register fields */ +#define RCC_AHB2RSTCLRR_DMA1RST BIT(0) +#define RCC_AHB2RSTCLRR_DMA2RST BIT(1) +#define RCC_AHB2RSTCLRR_DMAMUX1RST BIT(2) +#define RCC_AHB2RSTCLRR_DMA3RST BIT(3) +#define RCC_AHB2RSTCLRR_DMAMUX2RST BIT(4) +#define RCC_AHB2RSTCLRR_ADC1RST BIT(5) +#define RCC_AHB2RSTCLRR_ADC2RST BIT(6) +#define RCC_AHB2RSTCLRR_USBORST BIT(8) + +/* RCC_AHB4RSTSETR register fields */ +#define RCC_AHB4RSTSETR_GPIOARST BIT(0) +#define RCC_AHB4RSTSETR_GPIOBRST BIT(1) +#define RCC_AHB4RSTSETR_GPIOCRST BIT(2) +#define RCC_AHB4RSTSETR_GPIODRST BIT(3) +#define RCC_AHB4RSTSETR_GPIOERST BIT(4) +#define RCC_AHB4RSTSETR_GPIOFRST BIT(5) +#define RCC_AHB4RSTSETR_GPIOGRST BIT(6) +#define RCC_AHB4RSTSETR_GPIOHRST BIT(7) +#define RCC_AHB4RSTSETR_GPIOIRST BIT(8) +#define RCC_AHB4RSTSETR_TSCRST BIT(15) + +/* RCC_AHB4RSTCLRR register fields */ +#define RCC_AHB4RSTCLRR_GPIOARST BIT(0) +#define RCC_AHB4RSTCLRR_GPIOBRST BIT(1) +#define RCC_AHB4RSTCLRR_GPIOCRST BIT(2) +#define RCC_AHB4RSTCLRR_GPIODRST BIT(3) +#define RCC_AHB4RSTCLRR_GPIOERST BIT(4) +#define RCC_AHB4RSTCLRR_GPIOFRST BIT(5) +#define RCC_AHB4RSTCLRR_GPIOGRST BIT(6) +#define RCC_AHB4RSTCLRR_GPIOHRST BIT(7) +#define RCC_AHB4RSTCLRR_GPIOIRST BIT(8) +#define RCC_AHB4RSTCLRR_TSCRST BIT(15) + +/* RCC_AHB5RSTSETR register fields */ +#define RCC_AHB5RSTSETR_PKARST BIT(2) +#define RCC_AHB5RSTSETR_SAESRST BIT(3) +#define RCC_AHB5RSTSETR_CRYP1RST BIT(4) +#define RCC_AHB5RSTSETR_HASH1RST BIT(5) +#define RCC_AHB5RSTSETR_RNG1RST BIT(6) +#define RCC_AHB5RSTSETR_AXIMCRST BIT(16) + +/* RCC_AHB5RSTCLRR register fields */ +#define RCC_AHB5RSTCLRR_PKARST BIT(2) +#define RCC_AHB5RSTCLRR_SAESRST BIT(3) +#define RCC_AHB5RSTCLRR_CRYP1RST BIT(4) +#define RCC_AHB5RSTCLRR_HASH1RST BIT(5) +#define RCC_AHB5RSTCLRR_RNG1RST BIT(6) +#define RCC_AHB5RSTCLRR_AXIMCRST BIT(16) + +/* RCC_AHB6RSTSETR register fields */ +#define RCC_AHB6RSTSETR_MDMARST BIT(0) +#define RCC_AHB6RSTSETR_MCERST BIT(1) +#define RCC_AHB6RSTSETR_ETH1MACRST BIT(10) +#define RCC_AHB6RSTSETR_FMCRST BIT(12) +#define RCC_AHB6RSTSETR_QSPIRST BIT(14) +#define RCC_AHB6RSTSETR_SDMMC1RST BIT(16) +#define RCC_AHB6RSTSETR_SDMMC2RST BIT(17) +#define RCC_AHB6RSTSETR_CRC1RST BIT(20) +#define RCC_AHB6RSTSETR_USBHRST BIT(24) +#define RCC_AHB6RSTSETR_ETH2MACRST BIT(30) + +/* RCC_AHB6RSTCLRR register fields */ +#define RCC_AHB6RSTCLRR_MDMARST BIT(0) +#define RCC_AHB6RSTCLRR_MCERST BIT(1) +#define RCC_AHB6RSTCLRR_ETH1MACRST BIT(10) +#define RCC_AHB6RSTCLRR_FMCRST BIT(12) +#define RCC_AHB6RSTCLRR_QSPIRST BIT(14) +#define RCC_AHB6RSTCLRR_SDMMC1RST BIT(16) +#define RCC_AHB6RSTCLRR_SDMMC2RST BIT(17) +#define RCC_AHB6RSTCLRR_CRC1RST BIT(20) +#define RCC_AHB6RSTCLRR_USBHRST BIT(24) +#define RCC_AHB6RSTCLRR_ETH2MACRST BIT(30) + +/* RCC_MP_APB1ENSETR register fields */ +#define RCC_MP_APB1ENSETR_TIM2EN BIT(0) +#define RCC_MP_APB1ENSETR_TIM3EN BIT(1) +#define RCC_MP_APB1ENSETR_TIM4EN BIT(2) +#define RCC_MP_APB1ENSETR_TIM5EN BIT(3) +#define RCC_MP_APB1ENSETR_TIM6EN BIT(4) +#define RCC_MP_APB1ENSETR_TIM7EN BIT(5) +#define RCC_MP_APB1ENSETR_LPTIM1EN BIT(9) +#define RCC_MP_APB1ENSETR_SPI2EN BIT(11) +#define RCC_MP_APB1ENSETR_SPI3EN BIT(12) +#define RCC_MP_APB1ENSETR_USART3EN BIT(15) +#define RCC_MP_APB1ENSETR_UART4EN BIT(16) +#define RCC_MP_APB1ENSETR_UART5EN BIT(17) +#define RCC_MP_APB1ENSETR_UART7EN BIT(18) +#define RCC_MP_APB1ENSETR_UART8EN BIT(19) +#define RCC_MP_APB1ENSETR_I2C1EN BIT(21) +#define RCC_MP_APB1ENSETR_I2C2EN BIT(22) +#define RCC_MP_APB1ENSETR_SPDIFEN BIT(26) + +/* RCC_MP_APB1ENCLRR register fields */ +#define RCC_MP_APB1ENCLRR_TIM2EN BIT(0) +#define RCC_MP_APB1ENCLRR_TIM3EN BIT(1) +#define RCC_MP_APB1ENCLRR_TIM4EN BIT(2) +#define RCC_MP_APB1ENCLRR_TIM5EN BIT(3) +#define RCC_MP_APB1ENCLRR_TIM6EN BIT(4) +#define RCC_MP_APB1ENCLRR_TIM7EN BIT(5) +#define RCC_MP_APB1ENCLRR_LPTIM1EN BIT(9) +#define RCC_MP_APB1ENCLRR_SPI2EN BIT(11) +#define RCC_MP_APB1ENCLRR_SPI3EN BIT(12) +#define RCC_MP_APB1ENCLRR_USART3EN BIT(15) +#define RCC_MP_APB1ENCLRR_UART4EN BIT(16) +#define RCC_MP_APB1ENCLRR_UART5EN BIT(17) +#define RCC_MP_APB1ENCLRR_UART7EN BIT(18) +#define RCC_MP_APB1ENCLRR_UART8EN BIT(19) +#define RCC_MP_APB1ENCLRR_I2C1EN BIT(21) +#define RCC_MP_APB1ENCLRR_I2C2EN BIT(22) +#define RCC_MP_APB1ENCLRR_SPDIFEN BIT(26) + +/* RCC_MP_APB2ENSETR register fields */ +#define RCC_MP_APB2ENSETR_TIM1EN BIT(0) +#define RCC_MP_APB2ENSETR_TIM8EN BIT(1) +#define RCC_MP_APB2ENSETR_SPI1EN BIT(8) +#define RCC_MP_APB2ENSETR_USART6EN BIT(13) +#define RCC_MP_APB2ENSETR_SAI1EN BIT(16) +#define RCC_MP_APB2ENSETR_SAI2EN BIT(17) +#define RCC_MP_APB2ENSETR_DFSDMEN BIT(20) +#define RCC_MP_APB2ENSETR_ADFSDMEN BIT(21) +#define RCC_MP_APB2ENSETR_FDCANEN BIT(24) + +/* RCC_MP_APB2ENCLRR register fields */ +#define RCC_MP_APB2ENCLRR_TIM1EN BIT(0) +#define RCC_MP_APB2ENCLRR_TIM8EN BIT(1) +#define RCC_MP_APB2ENCLRR_SPI1EN BIT(8) +#define RCC_MP_APB2ENCLRR_USART6EN BIT(13) +#define RCC_MP_APB2ENCLRR_SAI1EN BIT(16) +#define RCC_MP_APB2ENCLRR_SAI2EN BIT(17) +#define RCC_MP_APB2ENCLRR_DFSDMEN BIT(20) +#define RCC_MP_APB2ENCLRR_ADFSDMEN BIT(21) +#define RCC_MP_APB2ENCLRR_FDCANEN BIT(24) + +/* RCC_MP_APB3ENSETR register fields */ +#define RCC_MP_APB3ENSETR_LPTIM2EN BIT(0) +#define RCC_MP_APB3ENSETR_LPTIM3EN BIT(1) +#define RCC_MP_APB3ENSETR_LPTIM4EN BIT(2) +#define RCC_MP_APB3ENSETR_LPTIM5EN BIT(3) +#define RCC_MP_APB3ENSETR_VREFEN BIT(13) +#define RCC_MP_APB3ENSETR_DTSEN BIT(16) +#define RCC_MP_APB3ENSETR_PMBCTRLEN BIT(17) +#define RCC_MP_APB3ENSETR_HDPEN BIT(20) + +/* RCC_MP_APB3ENCLRR register fields */ +#define RCC_MP_APB3ENCLRR_LPTIM2EN BIT(0) +#define RCC_MP_APB3ENCLRR_LPTIM3EN BIT(1) +#define RCC_MP_APB3ENCLRR_LPTIM4EN BIT(2) +#define RCC_MP_APB3ENCLRR_LPTIM5EN BIT(3) +#define RCC_MP_APB3ENCLRR_VREFEN BIT(13) +#define RCC_MP_APB3ENCLRR_DTSEN BIT(16) +#define RCC_MP_APB3ENCLRR_PMBCTRLEN BIT(17) +#define RCC_MP_APB3ENCLRR_HDPEN BIT(20) + +/* RCC_MP_S_APB3ENSETR register fields */ +#define RCC_MP_S_APB3ENSETR_SYSCFGEN BIT(0) + +/* RCC_MP_S_APB3ENCLRR register fields */ +#define RCC_MP_S_APB3ENCLRR_SYSCFGEN BIT(0) + +/* RCC_MP_NS_APB3ENSETR register fields */ +#define RCC_MP_NS_APB3ENSETR_SYSCFGEN BIT(0) + +/* RCC_MP_NS_APB3ENCLRR register fields */ +#define RCC_MP_NS_APB3ENCLRR_SYSCFGEN BIT(0) + +/* RCC_MP_APB4ENSETR register fields */ +#define RCC_MP_APB4ENSETR_DCMIPPEN BIT(1) +#define RCC_MP_APB4ENSETR_DDRPERFMEN BIT(8) +#define RCC_MP_APB4ENSETR_IWDG2APBEN BIT(15) +#define RCC_MP_APB4ENSETR_USBPHYEN BIT(16) +#define RCC_MP_APB4ENSETR_STGENROEN BIT(20) + +/* RCC_MP_APB4ENCLRR register fields */ +#define RCC_MP_APB4ENCLRR_DCMIPPEN BIT(1) +#define RCC_MP_APB4ENCLRR_DDRPERFMEN BIT(8) +#define RCC_MP_APB4ENCLRR_IWDG2APBEN BIT(15) +#define RCC_MP_APB4ENCLRR_USBPHYEN BIT(16) +#define RCC_MP_APB4ENCLRR_STGENROEN BIT(20) + +/* RCC_MP_S_APB4ENSETR register fields */ +#define RCC_MP_S_APB4ENSETR_LTDCEN BIT(0) + +/* RCC_MP_S_APB4ENCLRR register fields */ +#define RCC_MP_S_APB4ENCLRR_LTDCEN BIT(0) + +/* RCC_MP_NS_APB4ENSETR register fields */ +#define RCC_MP_NS_APB4ENSETR_LTDCEN BIT(0) + +/* RCC_MP_NS_APB4ENCLRR register fields */ +#define RCC_MP_NS_APB4ENCLRR_LTDCEN BIT(0) + +/* RCC_MP_APB5ENSETR register fields */ +#define RCC_MP_APB5ENSETR_RTCAPBEN BIT(8) +#define RCC_MP_APB5ENSETR_TZCEN BIT(11) +#define RCC_MP_APB5ENSETR_ETZPCEN BIT(13) +#define RCC_MP_APB5ENSETR_IWDG1APBEN BIT(15) +#define RCC_MP_APB5ENSETR_BSECEN BIT(16) +#define RCC_MP_APB5ENSETR_STGENCEN BIT(20) + +/* RCC_MP_APB5ENCLRR register fields */ +#define RCC_MP_APB5ENCLRR_RTCAPBEN BIT(8) +#define RCC_MP_APB5ENCLRR_TZCEN BIT(11) +#define RCC_MP_APB5ENCLRR_ETZPCEN BIT(13) +#define RCC_MP_APB5ENCLRR_IWDG1APBEN BIT(15) +#define RCC_MP_APB5ENCLRR_BSECEN BIT(16) +#define RCC_MP_APB5ENCLRR_STGENCEN BIT(20) + +/* RCC_MP_APB6ENSETR register fields */ +#define RCC_MP_APB6ENSETR_USART1EN BIT(0) +#define RCC_MP_APB6ENSETR_USART2EN BIT(1) +#define RCC_MP_APB6ENSETR_SPI4EN BIT(2) +#define RCC_MP_APB6ENSETR_SPI5EN BIT(3) +#define RCC_MP_APB6ENSETR_I2C3EN BIT(4) +#define RCC_MP_APB6ENSETR_I2C4EN BIT(5) +#define RCC_MP_APB6ENSETR_I2C5EN BIT(6) +#define RCC_MP_APB6ENSETR_TIM12EN BIT(7) +#define RCC_MP_APB6ENSETR_TIM13EN BIT(8) +#define RCC_MP_APB6ENSETR_TIM14EN BIT(9) +#define RCC_MP_APB6ENSETR_TIM15EN BIT(10) +#define RCC_MP_APB6ENSETR_TIM16EN BIT(11) +#define RCC_MP_APB6ENSETR_TIM17EN BIT(12) + +/* RCC_MP_APB6ENCLRR register fields */ +#define RCC_MP_APB6ENCLRR_USART1EN BIT(0) +#define RCC_MP_APB6ENCLRR_USART2EN BIT(1) +#define RCC_MP_APB6ENCLRR_SPI4EN BIT(2) +#define RCC_MP_APB6ENCLRR_SPI5EN BIT(3) +#define RCC_MP_APB6ENCLRR_I2C3EN BIT(4) +#define RCC_MP_APB6ENCLRR_I2C4EN BIT(5) +#define RCC_MP_APB6ENCLRR_I2C5EN BIT(6) +#define RCC_MP_APB6ENCLRR_TIM12EN BIT(7) +#define RCC_MP_APB6ENCLRR_TIM13EN BIT(8) +#define RCC_MP_APB6ENCLRR_TIM14EN BIT(9) +#define RCC_MP_APB6ENCLRR_TIM15EN BIT(10) +#define RCC_MP_APB6ENCLRR_TIM16EN BIT(11) +#define RCC_MP_APB6ENCLRR_TIM17EN BIT(12) + +/* RCC_MP_AHB2ENSETR register fields */ +#define RCC_MP_AHB2ENSETR_DMA1EN BIT(0) +#define RCC_MP_AHB2ENSETR_DMA2EN BIT(1) +#define RCC_MP_AHB2ENSETR_DMAMUX1EN BIT(2) +#define RCC_MP_AHB2ENSETR_DMA3EN BIT(3) +#define RCC_MP_AHB2ENSETR_DMAMUX2EN BIT(4) +#define RCC_MP_AHB2ENSETR_ADC1EN BIT(5) +#define RCC_MP_AHB2ENSETR_ADC2EN BIT(6) +#define RCC_MP_AHB2ENSETR_USBOEN BIT(8) + +/* RCC_MP_AHB2ENCLRR register fields */ +#define RCC_MP_AHB2ENCLRR_DMA1EN BIT(0) +#define RCC_MP_AHB2ENCLRR_DMA2EN BIT(1) +#define RCC_MP_AHB2ENCLRR_DMAMUX1EN BIT(2) +#define RCC_MP_AHB2ENCLRR_DMA3EN BIT(3) +#define RCC_MP_AHB2ENCLRR_DMAMUX2EN BIT(4) +#define RCC_MP_AHB2ENCLRR_ADC1EN BIT(5) +#define RCC_MP_AHB2ENCLRR_ADC2EN BIT(6) +#define RCC_MP_AHB2ENCLRR_USBOEN BIT(8) + +/* RCC_MP_AHB4ENSETR register fields */ +#define RCC_MP_AHB4ENSETR_TSCEN BIT(15) + +/* RCC_MP_AHB4ENCLRR register fields */ +#define RCC_MP_AHB4ENCLRR_TSCEN BIT(15) + +/* RCC_MP_S_AHB4ENSETR register fields */ +#define RCC_MP_S_AHB4ENSETR_GPIOAEN BIT(0) +#define RCC_MP_S_AHB4ENSETR_GPIOBEN BIT(1) +#define RCC_MP_S_AHB4ENSETR_GPIOCEN BIT(2) +#define RCC_MP_S_AHB4ENSETR_GPIODEN BIT(3) +#define RCC_MP_S_AHB4ENSETR_GPIOEEN BIT(4) +#define RCC_MP_S_AHB4ENSETR_GPIOFEN BIT(5) +#define RCC_MP_S_AHB4ENSETR_GPIOGEN BIT(6) +#define RCC_MP_S_AHB4ENSETR_GPIOHEN BIT(7) +#define RCC_MP_S_AHB4ENSETR_GPIOIEN BIT(8) + +/* RCC_MP_S_AHB4ENCLRR register fields */ +#define RCC_MP_S_AHB4ENCLRR_GPIOAEN BIT(0) +#define RCC_MP_S_AHB4ENCLRR_GPIOBEN BIT(1) +#define RCC_MP_S_AHB4ENCLRR_GPIOCEN BIT(2) +#define RCC_MP_S_AHB4ENCLRR_GPIODEN BIT(3) +#define RCC_MP_S_AHB4ENCLRR_GPIOEEN BIT(4) +#define RCC_MP_S_AHB4ENCLRR_GPIOFEN BIT(5) +#define RCC_MP_S_AHB4ENCLRR_GPIOGEN BIT(6) +#define RCC_MP_S_AHB4ENCLRR_GPIOHEN BIT(7) +#define RCC_MP_S_AHB4ENCLRR_GPIOIEN BIT(8) + +/* RCC_MP_NS_AHB4ENSETR register fields */ +#define RCC_MP_NS_AHB4ENSETR_GPIOAEN BIT(0) +#define RCC_MP_NS_AHB4ENSETR_GPIOBEN BIT(1) +#define RCC_MP_NS_AHB4ENSETR_GPIOCEN BIT(2) +#define RCC_MP_NS_AHB4ENSETR_GPIODEN BIT(3) +#define RCC_MP_NS_AHB4ENSETR_GPIOEEN BIT(4) +#define RCC_MP_NS_AHB4ENSETR_GPIOFEN BIT(5) +#define RCC_MP_NS_AHB4ENSETR_GPIOGEN BIT(6) +#define RCC_MP_NS_AHB4ENSETR_GPIOHEN BIT(7) +#define RCC_MP_NS_AHB4ENSETR_GPIOIEN BIT(8) + +/* RCC_MP_NS_AHB4ENCLRR register fields */ +#define RCC_MP_NS_AHB4ENCLRR_GPIOAEN BIT(0) +#define RCC_MP_NS_AHB4ENCLRR_GPIOBEN BIT(1) +#define RCC_MP_NS_AHB4ENCLRR_GPIOCEN BIT(2) +#define RCC_MP_NS_AHB4ENCLRR_GPIODEN BIT(3) +#define RCC_MP_NS_AHB4ENCLRR_GPIOEEN BIT(4) +#define RCC_MP_NS_AHB4ENCLRR_GPIOFEN BIT(5) +#define RCC_MP_NS_AHB4ENCLRR_GPIOGEN BIT(6) +#define RCC_MP_NS_AHB4ENCLRR_GPIOHEN BIT(7) +#define RCC_MP_NS_AHB4ENCLRR_GPIOIEN BIT(8) + +/* RCC_MP_AHB5ENSETR register fields */ +#define RCC_MP_AHB5ENSETR_PKAEN BIT(2) +#define RCC_MP_AHB5ENSETR_SAESEN BIT(3) +#define RCC_MP_AHB5ENSETR_CRYP1EN BIT(4) +#define RCC_MP_AHB5ENSETR_HASH1EN BIT(5) +#define RCC_MP_AHB5ENSETR_RNG1EN BIT(6) +#define RCC_MP_AHB5ENSETR_BKPSRAMEN BIT(8) +#define RCC_MP_AHB5ENSETR_AXIMCEN BIT(16) + +/* RCC_MP_AHB5ENCLRR register fields */ +#define RCC_MP_AHB5ENCLRR_PKAEN BIT(2) +#define RCC_MP_AHB5ENCLRR_SAESEN BIT(3) +#define RCC_MP_AHB5ENCLRR_CRYP1EN BIT(4) +#define RCC_MP_AHB5ENCLRR_HASH1EN BIT(5) +#define RCC_MP_AHB5ENCLRR_RNG1EN BIT(6) +#define RCC_MP_AHB5ENCLRR_BKPSRAMEN BIT(8) +#define RCC_MP_AHB5ENCLRR_AXIMCEN BIT(16) + +/* RCC_MP_AHB6ENSETR register fields */ +#define RCC_MP_AHB6ENSETR_MCEEN BIT(1) +#define RCC_MP_AHB6ENSETR_ETH1CKEN BIT(7) +#define RCC_MP_AHB6ENSETR_ETH1TXEN BIT(8) +#define RCC_MP_AHB6ENSETR_ETH1RXEN BIT(9) +#define RCC_MP_AHB6ENSETR_ETH1MACEN BIT(10) +#define RCC_MP_AHB6ENSETR_FMCEN BIT(12) +#define RCC_MP_AHB6ENSETR_QSPIEN BIT(14) +#define RCC_MP_AHB6ENSETR_SDMMC1EN BIT(16) +#define RCC_MP_AHB6ENSETR_SDMMC2EN BIT(17) +#define RCC_MP_AHB6ENSETR_CRC1EN BIT(20) +#define RCC_MP_AHB6ENSETR_USBHEN BIT(24) +#define RCC_MP_AHB6ENSETR_ETH2CKEN BIT(27) +#define RCC_MP_AHB6ENSETR_ETH2TXEN BIT(28) +#define RCC_MP_AHB6ENSETR_ETH2RXEN BIT(29) +#define RCC_MP_AHB6ENSETR_ETH2MACEN BIT(30) + +/* RCC_MP_AHB6ENCLRR register fields */ +#define RCC_MP_AHB6ENCLRR_MCEEN BIT(1) +#define RCC_MP_AHB6ENCLRR_ETH1CKEN BIT(7) +#define RCC_MP_AHB6ENCLRR_ETH1TXEN BIT(8) +#define RCC_MP_AHB6ENCLRR_ETH1RXEN BIT(9) +#define RCC_MP_AHB6ENCLRR_ETH1MACEN BIT(10) +#define RCC_MP_AHB6ENCLRR_FMCEN BIT(12) +#define RCC_MP_AHB6ENCLRR_QSPIEN BIT(14) +#define RCC_MP_AHB6ENCLRR_SDMMC1EN BIT(16) +#define RCC_MP_AHB6ENCLRR_SDMMC2EN BIT(17) +#define RCC_MP_AHB6ENCLRR_CRC1EN BIT(20) +#define RCC_MP_AHB6ENCLRR_USBHEN BIT(24) +#define RCC_MP_AHB6ENCLRR_ETH2CKEN BIT(27) +#define RCC_MP_AHB6ENCLRR_ETH2TXEN BIT(28) +#define RCC_MP_AHB6ENCLRR_ETH2RXEN BIT(29) +#define RCC_MP_AHB6ENCLRR_ETH2MACEN BIT(30) + +/* RCC_MP_S_AHB6ENSETR register fields */ +#define RCC_MP_S_AHB6ENSETR_MDMAEN BIT(0) + +/* RCC_MP_S_AHB6ENCLRR register fields */ +#define RCC_MP_S_AHB6ENCLRR_MDMAEN BIT(0) + +/* RCC_MP_NS_AHB6ENSETR register fields */ +#define RCC_MP_NS_AHB6ENSETR_MDMAEN BIT(0) + +/* RCC_MP_NS_AHB6ENCLRR register fields */ +#define RCC_MP_NS_AHB6ENCLRR_MDMAEN BIT(0) + +/* RCC_MP_APB1LPENSETR register fields */ +#define RCC_MP_APB1LPENSETR_TIM2LPEN BIT(0) +#define RCC_MP_APB1LPENSETR_TIM3LPEN BIT(1) +#define RCC_MP_APB1LPENSETR_TIM4LPEN BIT(2) +#define RCC_MP_APB1LPENSETR_TIM5LPEN BIT(3) +#define RCC_MP_APB1LPENSETR_TIM6LPEN BIT(4) +#define RCC_MP_APB1LPENSETR_TIM7LPEN BIT(5) +#define RCC_MP_APB1LPENSETR_LPTIM1LPEN BIT(9) +#define RCC_MP_APB1LPENSETR_SPI2LPEN BIT(11) +#define RCC_MP_APB1LPENSETR_SPI3LPEN BIT(12) +#define RCC_MP_APB1LPENSETR_USART3LPEN BIT(15) +#define RCC_MP_APB1LPENSETR_UART4LPEN BIT(16) +#define RCC_MP_APB1LPENSETR_UART5LPEN BIT(17) +#define RCC_MP_APB1LPENSETR_UART7LPEN BIT(18) +#define RCC_MP_APB1LPENSETR_UART8LPEN BIT(19) +#define RCC_MP_APB1LPENSETR_I2C1LPEN BIT(21) +#define RCC_MP_APB1LPENSETR_I2C2LPEN BIT(22) +#define RCC_MP_APB1LPENSETR_SPDIFLPEN BIT(26) + +/* RCC_MP_APB1LPENCLRR register fields */ +#define RCC_MP_APB1LPENCLRR_TIM2LPEN BIT(0) +#define RCC_MP_APB1LPENCLRR_TIM3LPEN BIT(1) +#define RCC_MP_APB1LPENCLRR_TIM4LPEN BIT(2) +#define RCC_MP_APB1LPENCLRR_TIM5LPEN BIT(3) +#define RCC_MP_APB1LPENCLRR_TIM6LPEN BIT(4) +#define RCC_MP_APB1LPENCLRR_TIM7LPEN BIT(5) +#define RCC_MP_APB1LPENCLRR_LPTIM1LPEN BIT(9) +#define RCC_MP_APB1LPENCLRR_SPI2LPEN BIT(11) +#define RCC_MP_APB1LPENCLRR_SPI3LPEN BIT(12) +#define RCC_MP_APB1LPENCLRR_USART3LPEN BIT(15) +#define RCC_MP_APB1LPENCLRR_UART4LPEN BIT(16) +#define RCC_MP_APB1LPENCLRR_UART5LPEN BIT(17) +#define RCC_MP_APB1LPENCLRR_UART7LPEN BIT(18) +#define RCC_MP_APB1LPENCLRR_UART8LPEN BIT(19) +#define RCC_MP_APB1LPENCLRR_I2C1LPEN BIT(21) +#define RCC_MP_APB1LPENCLRR_I2C2LPEN BIT(22) +#define RCC_MP_APB1LPENCLRR_SPDIFLPEN BIT(26) + +/* RCC_MP_APB2LPENSETR register fields */ +#define RCC_MP_APB2LPENSETR_TIM1LPEN BIT(0) +#define RCC_MP_APB2LPENSETR_TIM8LPEN BIT(1) +#define RCC_MP_APB2LPENSETR_SPI1LPEN BIT(8) +#define RCC_MP_APB2LPENSETR_USART6LPEN BIT(13) +#define RCC_MP_APB2LPENSETR_SAI1LPEN BIT(16) +#define RCC_MP_APB2LPENSETR_SAI2LPEN BIT(17) +#define RCC_MP_APB2LPENSETR_DFSDMLPEN BIT(20) +#define RCC_MP_APB2LPENSETR_ADFSDMLPEN BIT(21) +#define RCC_MP_APB2LPENSETR_FDCANLPEN BIT(24) + +/* RCC_MP_APB2LPENCLRR register fields */ +#define RCC_MP_APB2LPENCLRR_TIM1LPEN BIT(0) +#define RCC_MP_APB2LPENCLRR_TIM8LPEN BIT(1) +#define RCC_MP_APB2LPENCLRR_SPI1LPEN BIT(8) +#define RCC_MP_APB2LPENCLRR_USART6LPEN BIT(13) +#define RCC_MP_APB2LPENCLRR_SAI1LPEN BIT(16) +#define RCC_MP_APB2LPENCLRR_SAI2LPEN BIT(17) +#define RCC_MP_APB2LPENCLRR_DFSDMLPEN BIT(20) +#define RCC_MP_APB2LPENCLRR_ADFSDMLPEN BIT(21) +#define RCC_MP_APB2LPENCLRR_FDCANLPEN BIT(24) + +/* RCC_MP_APB3LPENSETR register fields */ +#define RCC_MP_APB3LPENSETR_LPTIM2LPEN BIT(0) +#define RCC_MP_APB3LPENSETR_LPTIM3LPEN BIT(1) +#define RCC_MP_APB3LPENSETR_LPTIM4LPEN BIT(2) +#define RCC_MP_APB3LPENSETR_LPTIM5LPEN BIT(3) +#define RCC_MP_APB3LPENSETR_VREFLPEN BIT(13) +#define RCC_MP_APB3LPENSETR_DTSLPEN BIT(16) +#define RCC_MP_APB3LPENSETR_PMBCTRLLPEN BIT(17) + +/* RCC_MP_APB3LPENCLRR register fields */ +#define RCC_MP_APB3LPENCLRR_LPTIM2LPEN BIT(0) +#define RCC_MP_APB3LPENCLRR_LPTIM3LPEN BIT(1) +#define RCC_MP_APB3LPENCLRR_LPTIM4LPEN BIT(2) +#define RCC_MP_APB3LPENCLRR_LPTIM5LPEN BIT(3) +#define RCC_MP_APB3LPENCLRR_VREFLPEN BIT(13) +#define RCC_MP_APB3LPENCLRR_DTSLPEN BIT(16) +#define RCC_MP_APB3LPENCLRR_PMBCTRLLPEN BIT(17) + +/* RCC_MP_S_APB3LPENSETR register fields */ +#define RCC_MP_S_APB3LPENSETR_SYSCFGLPEN BIT(0) + +/* RCC_MP_S_APB3LPENCLRR register fields */ +#define RCC_MP_S_APB3LPENCLRR_SYSCFGLPEN BIT(0) + +/* RCC_MP_NS_APB3LPENSETR register fields */ +#define RCC_MP_NS_APB3LPENSETR_SYSCFGLPEN BIT(0) + +/* RCC_MP_NS_APB3LPENCLRR register fields */ +#define RCC_MP_NS_APB3LPENCLRR_SYSCFGLPEN BIT(0) + +/* RCC_MP_APB4LPENSETR register fields */ +#define RCC_MP_APB4LPENSETR_DCMIPPLPEN BIT(1) +#define RCC_MP_APB4LPENSETR_DDRPERFMLPEN BIT(8) +#define RCC_MP_APB4LPENSETR_IWDG2APBLPEN BIT(15) +#define RCC_MP_APB4LPENSETR_USBPHYLPEN BIT(16) +#define RCC_MP_APB4LPENSETR_STGENROLPEN BIT(20) +#define RCC_MP_APB4LPENSETR_STGENROSTPEN BIT(21) + +/* RCC_MP_APB4LPENCLRR register fields */ +#define RCC_MP_APB4LPENCLRR_DCMIPPLPEN BIT(1) +#define RCC_MP_APB4LPENCLRR_DDRPERFMLPEN BIT(8) +#define RCC_MP_APB4LPENCLRR_IWDG2APBLPEN BIT(15) +#define RCC_MP_APB4LPENCLRR_USBPHYLPEN BIT(16) +#define RCC_MP_APB4LPENCLRR_STGENROLPEN BIT(20) +#define RCC_MP_APB4LPENCLRR_STGENROSTPEN BIT(21) + +/* RCC_MP_S_APB4LPENSETR register fields */ +#define RCC_MP_S_APB4LPENSETR_LTDCLPEN BIT(0) + +/* RCC_MP_S_APB4LPENCLRR register fields */ +#define RCC_MP_S_APB4LPENCLRR_LTDCLPEN BIT(0) + +/* RCC_MP_NS_APB4LPENSETR register fields */ +#define RCC_MP_NS_APB4LPENSETR_LTDCLPEN BIT(0) + +/* RCC_MP_NS_APB4LPENCLRR register fields */ +#define RCC_MP_NS_APB4LPENCLRR_LTDCLPEN BIT(0) + +/* RCC_MP_APB5LPENSETR register fields */ +#define RCC_MP_APB5LPENSETR_RTCAPBLPEN BIT(8) +#define RCC_MP_APB5LPENSETR_TZCLPEN BIT(11) +#define RCC_MP_APB5LPENSETR_ETZPCLPEN BIT(13) +#define RCC_MP_APB5LPENSETR_IWDG1APBLPEN BIT(15) +#define RCC_MP_APB5LPENSETR_BSECLPEN BIT(16) +#define RCC_MP_APB5LPENSETR_STGENCLPEN BIT(20) +#define RCC_MP_APB5LPENSETR_STGENCSTPEN BIT(21) + +/* RCC_MP_APB5LPENCLRR register fields */ +#define RCC_MP_APB5LPENCLRR_RTCAPBLPEN BIT(8) +#define RCC_MP_APB5LPENCLRR_TZCLPEN BIT(11) +#define RCC_MP_APB5LPENCLRR_ETZPCLPEN BIT(13) +#define RCC_MP_APB5LPENCLRR_IWDG1APBLPEN BIT(15) +#define RCC_MP_APB5LPENCLRR_BSECLPEN BIT(16) +#define RCC_MP_APB5LPENCLRR_STGENCLPEN BIT(20) +#define RCC_MP_APB5LPENCLRR_STGENCSTPEN BIT(21) + +/* RCC_MP_APB6LPENSETR register fields */ +#define RCC_MP_APB6LPENSETR_USART1LPEN BIT(0) +#define RCC_MP_APB6LPENSETR_USART2LPEN BIT(1) +#define RCC_MP_APB6LPENSETR_SPI4LPEN BIT(2) +#define RCC_MP_APB6LPENSETR_SPI5LPEN BIT(3) +#define RCC_MP_APB6LPENSETR_I2C3LPEN BIT(4) +#define RCC_MP_APB6LPENSETR_I2C4LPEN BIT(5) +#define RCC_MP_APB6LPENSETR_I2C5LPEN BIT(6) +#define RCC_MP_APB6LPENSETR_TIM12LPEN BIT(7) +#define RCC_MP_APB6LPENSETR_TIM13LPEN BIT(8) +#define RCC_MP_APB6LPENSETR_TIM14LPEN BIT(9) +#define RCC_MP_APB6LPENSETR_TIM15LPEN BIT(10) +#define RCC_MP_APB6LPENSETR_TIM16LPEN BIT(11) +#define RCC_MP_APB6LPENSETR_TIM17LPEN BIT(12) + +/* RCC_MP_APB6LPENCLRR register fields */ +#define RCC_MP_APB6LPENCLRR_USART1LPEN BIT(0) +#define RCC_MP_APB6LPENCLRR_USART2LPEN BIT(1) +#define RCC_MP_APB6LPENCLRR_SPI4LPEN BIT(2) +#define RCC_MP_APB6LPENCLRR_SPI5LPEN BIT(3) +#define RCC_MP_APB6LPENCLRR_I2C3LPEN BIT(4) +#define RCC_MP_APB6LPENCLRR_I2C4LPEN BIT(5) +#define RCC_MP_APB6LPENCLRR_I2C5LPEN BIT(6) +#define RCC_MP_APB6LPENCLRR_TIM12LPEN BIT(7) +#define RCC_MP_APB6LPENCLRR_TIM13LPEN BIT(8) +#define RCC_MP_APB6LPENCLRR_TIM14LPEN BIT(9) +#define RCC_MP_APB6LPENCLRR_TIM15LPEN BIT(10) +#define RCC_MP_APB6LPENCLRR_TIM16LPEN BIT(11) +#define RCC_MP_APB6LPENCLRR_TIM17LPEN BIT(12) + +/* RCC_MP_AHB2LPENSETR register fields */ +#define RCC_MP_AHB2LPENSETR_DMA1LPEN BIT(0) +#define RCC_MP_AHB2LPENSETR_DMA2LPEN BIT(1) +#define RCC_MP_AHB2LPENSETR_DMAMUX1LPEN BIT(2) +#define RCC_MP_AHB2LPENSETR_DMA3LPEN BIT(3) +#define RCC_MP_AHB2LPENSETR_DMAMUX2LPEN BIT(4) +#define RCC_MP_AHB2LPENSETR_ADC1LPEN BIT(5) +#define RCC_MP_AHB2LPENSETR_ADC2LPEN BIT(6) +#define RCC_MP_AHB2LPENSETR_USBOLPEN BIT(8) + +/* RCC_MP_AHB2LPENCLRR register fields */ +#define RCC_MP_AHB2LPENCLRR_DMA1LPEN BIT(0) +#define RCC_MP_AHB2LPENCLRR_DMA2LPEN BIT(1) +#define RCC_MP_AHB2LPENCLRR_DMAMUX1LPEN BIT(2) +#define RCC_MP_AHB2LPENCLRR_DMA3LPEN BIT(3) +#define RCC_MP_AHB2LPENCLRR_DMAMUX2LPEN BIT(4) +#define RCC_MP_AHB2LPENCLRR_ADC1LPEN BIT(5) +#define RCC_MP_AHB2LPENCLRR_ADC2LPEN BIT(6) +#define RCC_MP_AHB2LPENCLRR_USBOLPEN BIT(8) + +/* RCC_MP_AHB4LPENSETR register fields */ +#define RCC_MP_AHB4LPENSETR_TSCLPEN BIT(15) + +/* RCC_MP_AHB4LPENCLRR register fields */ +#define RCC_MP_AHB4LPENCLRR_TSCLPEN BIT(15) + +/* RCC_MP_S_AHB4LPENSETR register fields */ +#define RCC_MP_S_AHB4LPENSETR_GPIOALPEN BIT(0) +#define RCC_MP_S_AHB4LPENSETR_GPIOBLPEN BIT(1) +#define RCC_MP_S_AHB4LPENSETR_GPIOCLPEN BIT(2) +#define RCC_MP_S_AHB4LPENSETR_GPIODLPEN BIT(3) +#define RCC_MP_S_AHB4LPENSETR_GPIOELPEN BIT(4) +#define RCC_MP_S_AHB4LPENSETR_GPIOFLPEN BIT(5) +#define RCC_MP_S_AHB4LPENSETR_GPIOGLPEN BIT(6) +#define RCC_MP_S_AHB4LPENSETR_GPIOHLPEN BIT(7) +#define RCC_MP_S_AHB4LPENSETR_GPIOILPEN BIT(8) + +/* RCC_MP_S_AHB4LPENCLRR register fields */ +#define RCC_MP_S_AHB4LPENCLRR_GPIOALPEN BIT(0) +#define RCC_MP_S_AHB4LPENCLRR_GPIOBLPEN BIT(1) +#define RCC_MP_S_AHB4LPENCLRR_GPIOCLPEN BIT(2) +#define RCC_MP_S_AHB4LPENCLRR_GPIODLPEN BIT(3) +#define RCC_MP_S_AHB4LPENCLRR_GPIOELPEN BIT(4) +#define RCC_MP_S_AHB4LPENCLRR_GPIOFLPEN BIT(5) +#define RCC_MP_S_AHB4LPENCLRR_GPIOGLPEN BIT(6) +#define RCC_MP_S_AHB4LPENCLRR_GPIOHLPEN BIT(7) +#define RCC_MP_S_AHB4LPENCLRR_GPIOILPEN BIT(8) + +/* RCC_MP_NS_AHB4LPENSETR register fields */ +#define RCC_MP_NS_AHB4LPENSETR_GPIOALPEN BIT(0) +#define RCC_MP_NS_AHB4LPENSETR_GPIOBLPEN BIT(1) +#define RCC_MP_NS_AHB4LPENSETR_GPIOCLPEN BIT(2) +#define RCC_MP_NS_AHB4LPENSETR_GPIODLPEN BIT(3) +#define RCC_MP_NS_AHB4LPENSETR_GPIOELPEN BIT(4) +#define RCC_MP_NS_AHB4LPENSETR_GPIOFLPEN BIT(5) +#define RCC_MP_NS_AHB4LPENSETR_GPIOGLPEN BIT(6) +#define RCC_MP_NS_AHB4LPENSETR_GPIOHLPEN BIT(7) +#define RCC_MP_NS_AHB4LPENSETR_GPIOILPEN BIT(8) + +/* RCC_MP_NS_AHB4LPENCLRR register fields */ +#define RCC_MP_NS_AHB4LPENCLRR_GPIOALPEN BIT(0) +#define RCC_MP_NS_AHB4LPENCLRR_GPIOBLPEN BIT(1) +#define RCC_MP_NS_AHB4LPENCLRR_GPIOCLPEN BIT(2) +#define RCC_MP_NS_AHB4LPENCLRR_GPIODLPEN BIT(3) +#define RCC_MP_NS_AHB4LPENCLRR_GPIOELPEN BIT(4) +#define RCC_MP_NS_AHB4LPENCLRR_GPIOFLPEN BIT(5) +#define RCC_MP_NS_AHB4LPENCLRR_GPIOGLPEN BIT(6) +#define RCC_MP_NS_AHB4LPENCLRR_GPIOHLPEN BIT(7) +#define RCC_MP_NS_AHB4LPENCLRR_GPIOILPEN BIT(8) + +/* RCC_MP_AHB5LPENSETR register fields */ +#define RCC_MP_AHB5LPENSETR_PKALPEN BIT(2) +#define RCC_MP_AHB5LPENSETR_SAESLPEN BIT(3) +#define RCC_MP_AHB5LPENSETR_CRYP1LPEN BIT(4) +#define RCC_MP_AHB5LPENSETR_HASH1LPEN BIT(5) +#define RCC_MP_AHB5LPENSETR_RNG1LPEN BIT(6) +#define RCC_MP_AHB5LPENSETR_BKPSRAMLPEN BIT(8) + +/* RCC_MP_AHB5LPENCLRR register fields */ +#define RCC_MP_AHB5LPENCLRR_PKALPEN BIT(2) +#define RCC_MP_AHB5LPENCLRR_SAESLPEN BIT(3) +#define RCC_MP_AHB5LPENCLRR_CRYP1LPEN BIT(4) +#define RCC_MP_AHB5LPENCLRR_HASH1LPEN BIT(5) +#define RCC_MP_AHB5LPENCLRR_RNG1LPEN BIT(6) +#define RCC_MP_AHB5LPENCLRR_BKPSRAMLPEN BIT(8) + +/* RCC_MP_AHB6LPENSETR register fields */ +#define RCC_MP_AHB6LPENSETR_MCELPEN BIT(1) +#define RCC_MP_AHB6LPENSETR_ETH1CKLPEN BIT(7) +#define RCC_MP_AHB6LPENSETR_ETH1TXLPEN BIT(8) +#define RCC_MP_AHB6LPENSETR_ETH1RXLPEN BIT(9) +#define RCC_MP_AHB6LPENSETR_ETH1MACLPEN BIT(10) +#define RCC_MP_AHB6LPENSETR_ETH1STPEN BIT(11) +#define RCC_MP_AHB6LPENSETR_FMCLPEN BIT(12) +#define RCC_MP_AHB6LPENSETR_QSPILPEN BIT(14) +#define RCC_MP_AHB6LPENSETR_SDMMC1LPEN BIT(16) +#define RCC_MP_AHB6LPENSETR_SDMMC2LPEN BIT(17) +#define RCC_MP_AHB6LPENSETR_CRC1LPEN BIT(20) +#define RCC_MP_AHB6LPENSETR_USBHLPEN BIT(24) +#define RCC_MP_AHB6LPENSETR_ETH2CKLPEN BIT(27) +#define RCC_MP_AHB6LPENSETR_ETH2TXLPEN BIT(28) +#define RCC_MP_AHB6LPENSETR_ETH2RXLPEN BIT(29) +#define RCC_MP_AHB6LPENSETR_ETH2MACLPEN BIT(30) +#define RCC_MP_AHB6LPENSETR_ETH2STPEN BIT(31) + +/* RCC_MP_AHB6LPENCLRR register fields */ +#define RCC_MP_AHB6LPENCLRR_MCELPEN BIT(1) +#define RCC_MP_AHB6LPENCLRR_ETH1CKLPEN BIT(7) +#define RCC_MP_AHB6LPENCLRR_ETH1TXLPEN BIT(8) +#define RCC_MP_AHB6LPENCLRR_ETH1RXLPEN BIT(9) +#define RCC_MP_AHB6LPENCLRR_ETH1MACLPEN BIT(10) +#define RCC_MP_AHB6LPENCLRR_ETH1STPEN BIT(11) +#define RCC_MP_AHB6LPENCLRR_FMCLPEN BIT(12) +#define RCC_MP_AHB6LPENCLRR_QSPILPEN BIT(14) +#define RCC_MP_AHB6LPENCLRR_SDMMC1LPEN BIT(16) +#define RCC_MP_AHB6LPENCLRR_SDMMC2LPEN BIT(17) +#define RCC_MP_AHB6LPENCLRR_CRC1LPEN BIT(20) +#define RCC_MP_AHB6LPENCLRR_USBHLPEN BIT(24) +#define RCC_MP_AHB6LPENCLRR_ETH2CKLPEN BIT(27) +#define RCC_MP_AHB6LPENCLRR_ETH2TXLPEN BIT(28) +#define RCC_MP_AHB6LPENCLRR_ETH2RXLPEN BIT(29) +#define RCC_MP_AHB6LPENCLRR_ETH2MACLPEN BIT(30) +#define RCC_MP_AHB6LPENCLRR_ETH2STPEN BIT(31) + +/* RCC_MP_S_AHB6LPENSETR register fields */ +#define RCC_MP_S_AHB6LPENSETR_MDMALPEN BIT(0) + +/* RCC_MP_S_AHB6LPENCLRR register fields */ +#define RCC_MP_S_AHB6LPENCLRR_MDMALPEN BIT(0) + +/* RCC_MP_NS_AHB6LPENSETR register fields */ +#define RCC_MP_NS_AHB6LPENSETR_MDMALPEN BIT(0) + +/* RCC_MP_NS_AHB6LPENCLRR register fields */ +#define RCC_MP_NS_AHB6LPENCLRR_MDMALPEN BIT(0) + +/* RCC_MP_S_AXIMLPENSETR register fields */ +#define RCC_MP_S_AXIMLPENSETR_SYSRAMLPEN BIT(0) + +/* RCC_MP_S_AXIMLPENCLRR register fields */ +#define RCC_MP_S_AXIMLPENCLRR_SYSRAMLPEN BIT(0) + +/* RCC_MP_NS_AXIMLPENSETR register fields */ +#define RCC_MP_NS_AXIMLPENSETR_SYSRAMLPEN BIT(0) + +/* RCC_MP_NS_AXIMLPENCLRR register fields */ +#define RCC_MP_NS_AXIMLPENCLRR_SYSRAMLPEN BIT(0) + +/* RCC_MP_MLAHBLPENSETR register fields */ +#define RCC_MP_MLAHBLPENSETR_SRAM1LPEN BIT(0) +#define RCC_MP_MLAHBLPENSETR_SRAM2LPEN BIT(1) +#define RCC_MP_MLAHBLPENSETR_SRAM3LPEN BIT(2) + +/* RCC_MP_MLAHBLPENCLRR register fields */ +#define RCC_MP_MLAHBLPENCLRR_SRAM1LPEN BIT(0) +#define RCC_MP_MLAHBLPENCLRR_SRAM2LPEN BIT(1) +#define RCC_MP_MLAHBLPENCLRR_SRAM3LPEN BIT(2) + +/* RCC_APB3SECSR register fields */ +#define RCC_APB3SECSR_LPTIM2SECF 0 +#define RCC_APB3SECSR_LPTIM3SECF 1 +#define RCC_APB3SECSR_VREFSECF 13 + +/* RCC_APB4SECSR register fields */ +#define RCC_APB4SECSR_DCMIPPSECF 1 +#define RCC_APB4SECSR_USBPHYSECF 16 + +/* RCC_APB5SECSR register fields */ +#define RCC_APB5SECSR_RTCSECF 8 +#define RCC_APB5SECSR_TZCSECF 11 +#define RCC_APB5SECSR_ETZPCSECF 13 +#define RCC_APB5SECSR_IWDG1SECF 15 +#define RCC_APB5SECSR_BSECSECF 16 +#define RCC_APB5SECSR_STGENCSECF_MASK GENMASK(21, 20) +#define RCC_APB5SECSR_STGENCSECF 20 +#define RCC_APB5SECSR_STGENROSECF 21 + +/* RCC_APB6SECSR register fields */ +#define RCC_APB6SECSR_USART1SECF 0 +#define RCC_APB6SECSR_USART2SECF 1 +#define RCC_APB6SECSR_SPI4SECF 2 +#define RCC_APB6SECSR_SPI5SECF 3 +#define RCC_APB6SECSR_I2C3SECF 4 +#define RCC_APB6SECSR_I2C4SECF 5 +#define RCC_APB6SECSR_I2C5SECF 6 +#define RCC_APB6SECSR_TIM12SECF 7 +#define RCC_APB6SECSR_TIM13SECF 8 +#define RCC_APB6SECSR_TIM14SECF 9 +#define RCC_APB6SECSR_TIM15SECF 10 +#define RCC_APB6SECSR_TIM16SECF 11 +#define RCC_APB6SECSR_TIM17SECF 12 + +/* RCC_AHB2SECSR register fields */ +#define RCC_AHB2SECSR_DMA3SECF 3 +#define RCC_AHB2SECSR_DMAMUX2SECF 4 +#define RCC_AHB2SECSR_ADC1SECF 5 +#define RCC_AHB2SECSR_ADC2SECF 6 +#define RCC_AHB2SECSR_USBOSECF 8 + +/* RCC_AHB4SECSR register fields */ +#define RCC_AHB4SECSR_TSCSECF 15 + +/* RCC_AHB5SECSR register fields */ +#define RCC_AHB5SECSR_PKASECF 2 +#define RCC_AHB5SECSR_SAESSECF 3 +#define RCC_AHB5SECSR_CRYP1SECF 4 +#define RCC_AHB5SECSR_HASH1SECF 5 +#define RCC_AHB5SECSR_RNG1SECF 6 +#define RCC_AHB5SECSR_BKPSRAMSECF 8 + +/* RCC_AHB6SECSR register fields */ +#define RCC_AHB6SECSR_MCESECF 1 +#define RCC_AHB6SECSR_FMCSECF 12 +#define RCC_AHB6SECSR_QSPISECF 14 +#define RCC_AHB6SECSR_SDMMC1SECF 16 +#define RCC_AHB6SECSR_SDMMC2SECF 17 + +#define RCC_AHB6SECSR_ETH1SECF_MASK GENMASK(11, 7) +#define RCC_AHB6SECSR_ETH2SECF_MASK GENMASK(31, 27) +#define RCC_AHB6SECSR_ETH1SECF_SHIFT 7 +#define RCC_AHB6SECSR_ETH2SECF_SHIFT 27 + +#define RCC_AHB6SECSR_ETH1CKSECF 7 +#define RCC_AHB6SECSR_ETH1TXSECF 8 +#define RCC_AHB6SECSR_ETH1RXSECF 9 +#define RCC_AHB6SECSR_ETH1MACSECF 10 +#define RCC_AHB6SECSR_ETH1STPSECF 11 + +#define RCC_AHB6SECSR_ETH2CKSECF 27 +#define RCC_AHB6SECSR_ETH2TXSECF 28 +#define RCC_AHB6SECSR_ETH2RXSECF 29 +#define RCC_AHB6SECSR_ETH2MACSECF 30 +#define RCC_AHB6SECSR_ETH2STPSECF 31 + +/* RCC_VERR register fields */ +#define RCC_VERR_MINREV_MASK GENMASK(3, 0) +#define RCC_VERR_MAJREV_MASK GENMASK(7, 4) +#define RCC_VERR_MINREV_SHIFT 0 +#define RCC_VERR_MAJREV_SHIFT 4 + +/* RCC_IDR register fields */ +#define RCC_IDR_ID_MASK GENMASK(31, 0) +#define RCC_IDR_ID_SHIFT 0 + +/* RCC_SIDR register fields */ +#define RCC_SIDR_SID_MASK GENMASK(31, 0) +#define RCC_SIDR_SID_SHIFT 0 + +#endif /* STM32MP13_RCC_H */ + diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c b/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c index 712e103382d8057a2ae080f063ae91d59527f7ed..29a8c710ae068133aa70bd4ae3bcce63b23c0368 100644 --- a/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c +++ b/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c @@ -98,6 +98,8 @@ static SUNXI_CCU_GATE(r_apb1_ir_clk, "r-apb1-ir", "r-apb1", 0x1cc, BIT(0), 0); static SUNXI_CCU_GATE(r_apb1_w1_clk, "r-apb1-w1", "r-apb1", 0x1ec, BIT(0), 0); +static SUNXI_CCU_GATE(r_apb1_rtc_clk, "r-apb1-rtc", "r-apb1", + 0x20c, BIT(0), CLK_IGNORE_UNUSED); /* Information of IR(RX) mod clock is gathered from BSP source code */ static const char * const r_mod0_default_parents[] = { "osc32k", "osc24M" }; @@ -147,6 +149,7 @@ static struct ccu_common *sun50i_h616_r_ccu_clks[] = { &r_apb2_i2c_clk.common, &r_apb2_rsb_clk.common, &r_apb1_ir_clk.common, + &r_apb1_rtc_clk.common, &ir_clk.common, }; @@ -164,6 +167,7 @@ static struct clk_hw_onecell_data sun50i_h6_r_hw_clks = { [CLK_R_APB2_RSB] = &r_apb2_rsb_clk.common.hw, [CLK_R_APB1_IR] = &r_apb1_ir_clk.common.hw, [CLK_R_APB1_W1] = &r_apb1_w1_clk.common.hw, + [CLK_R_APB1_RTC] = &r_apb1_rtc_clk.common.hw, [CLK_IR] = &ir_clk.common.hw, [CLK_W1] = &w1_clk.common.hw, }, @@ -179,6 +183,7 @@ static struct clk_hw_onecell_data sun50i_h616_r_hw_clks = { [CLK_R_APB2_I2C] = &r_apb2_i2c_clk.common.hw, [CLK_R_APB2_RSB] = &r_apb2_rsb_clk.common.hw, [CLK_R_APB1_IR] = &r_apb1_ir_clk.common.hw, + [CLK_R_APB1_RTC] = &r_apb1_rtc_clk.common.hw, [CLK_IR] = &ir_clk.common.hw, }, .num = CLK_NUMBER, diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.h b/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.h index 7e290b840803564b62e5743fb314fe38179fe4cd..10e9b66afc6a9ae0bb50a9f90198fc933dbdc7d4 100644 --- a/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.h +++ b/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.h @@ -14,6 +14,6 @@ #define CLK_R_APB2 3 -#define CLK_NUMBER (CLK_R_APB2_RSB + 1) +#define CLK_NUMBER (CLK_R_APB1_RTC + 1) #endif /* _CCU_SUN50I_H6_R_H */ diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h616.c b/drivers/clk/sunxi-ng/ccu-sun50i-h616.c index 49a2474cf3146d6f7146510122fded28d23bf7d2..21e918582aa564119fdc562a11fd78fd5eeb72d2 100644 --- a/drivers/clk/sunxi-ng/ccu-sun50i-h616.c +++ b/drivers/clk/sunxi-ng/ccu-sun50i-h616.c @@ -704,6 +704,13 @@ static CLK_FIXED_FACTOR_HWS(pll_periph0_2x_clk, "pll-periph0-2x", pll_periph0_parents, 1, 2, 0); +static const struct clk_hw *pll_periph0_2x_hws[] = { + &pll_periph0_2x_clk.hw +}; + +static CLK_FIXED_FACTOR_HWS(pll_system_32k_clk, "pll-system-32k", + pll_periph0_2x_hws, 36621, 1, 0); + static const struct clk_hw *pll_periph1_parents[] = { &pll_periph1_clk.common.hw }; @@ -852,6 +859,7 @@ static struct clk_hw_onecell_data sun50i_h616_hw_clks = { [CLK_PLL_DDR1] = &pll_ddr1_clk.common.hw, [CLK_PLL_PERIPH0] = &pll_periph0_clk.common.hw, [CLK_PLL_PERIPH0_2X] = &pll_periph0_2x_clk.hw, + [CLK_PLL_SYSTEM_32K] = &pll_system_32k_clk.hw, [CLK_PLL_PERIPH1] = &pll_periph1_clk.common.hw, [CLK_PLL_PERIPH1_2X] = &pll_periph1_2x_clk.hw, [CLK_PLL_GPU] = &pll_gpu_clk.common.hw, diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h616.h b/drivers/clk/sunxi-ng/ccu-sun50i-h616.h index dd671b413f22446255c83ab6242bcf886549ddfc..fdd2f4d5103f4c7f564e1fcdae232b9be6617026 100644 --- a/drivers/clk/sunxi-ng/ccu-sun50i-h616.h +++ b/drivers/clk/sunxi-ng/ccu-sun50i-h616.h @@ -51,6 +51,6 @@ #define CLK_BUS_DRAM 56 -#define CLK_NUMBER (CLK_BUS_HDCP + 1) +#define CLK_NUMBER (CLK_PLL_SYSTEM_32K + 1) #endif /* _CCU_SUN50I_H616_H_ */ diff --git a/drivers/clk/tegra/clk-bpmp.c b/drivers/clk/tegra/clk-bpmp.c index 6ecf18f71c329fa24608d103d07d7fde7a59db06..3748a39dae7cb442c5a29527f317a7605f83bdea 100644 --- a/drivers/clk/tegra/clk-bpmp.c +++ b/drivers/clk/tegra/clk-bpmp.c @@ -164,15 +164,18 @@ static unsigned long tegra_bpmp_clk_recalc_rate(struct clk_hw *hw, return response.rate; } -static long tegra_bpmp_clk_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) +static int tegra_bpmp_clk_determine_rate(struct clk_hw *hw, + struct clk_rate_request *rate_req) { struct tegra_bpmp_clk *clk = to_tegra_bpmp_clk(hw); struct cmd_clk_round_rate_response response; struct cmd_clk_round_rate_request request; struct tegra_bpmp_clk_message msg; + unsigned long rate; int err; + rate = min(max(rate_req->rate, rate_req->min_rate), rate_req->max_rate); + memset(&request, 0, sizeof(request)); request.rate = min_t(u64, rate, S64_MAX); @@ -188,7 +191,9 @@ static long tegra_bpmp_clk_round_rate(struct clk_hw *hw, unsigned long rate, if (err < 0) return err; - return response.rate; + rate_req->rate = (unsigned long)response.rate; + + return 0; } static int tegra_bpmp_clk_set_parent(struct clk_hw *hw, u8 index) @@ -290,7 +295,7 @@ static const struct clk_ops tegra_bpmp_clk_rate_ops = { .unprepare = tegra_bpmp_clk_unprepare, .is_prepared = tegra_bpmp_clk_is_prepared, .recalc_rate = tegra_bpmp_clk_recalc_rate, - .round_rate = tegra_bpmp_clk_round_rate, + .determine_rate = tegra_bpmp_clk_determine_rate, .set_rate = tegra_bpmp_clk_set_rate, }; @@ -299,7 +304,7 @@ static const struct clk_ops tegra_bpmp_clk_mux_rate_ops = { .unprepare = tegra_bpmp_clk_unprepare, .is_prepared = tegra_bpmp_clk_is_prepared, .recalc_rate = tegra_bpmp_clk_recalc_rate, - .round_rate = tegra_bpmp_clk_round_rate, + .determine_rate = tegra_bpmp_clk_determine_rate, .set_parent = tegra_bpmp_clk_set_parent, .get_parent = tegra_bpmp_clk_get_parent, .set_rate = tegra_bpmp_clk_set_rate, @@ -448,15 +453,29 @@ static int tegra_bpmp_probe_clocks(struct tegra_bpmp *bpmp, return count; } +static unsigned int +tegra_bpmp_clk_id_to_index(const struct tegra_bpmp_clk_info *clocks, + unsigned int num_clocks, unsigned int id) +{ + unsigned int i; + + for (i = 0; i < num_clocks; i++) + if (clocks[i].id == id) + return i; + + return UINT_MAX; +} + static const struct tegra_bpmp_clk_info * tegra_bpmp_clk_find(const struct tegra_bpmp_clk_info *clocks, unsigned int num_clocks, unsigned int id) { unsigned int i; - for (i = 0; i < num_clocks; i++) - if (clocks[i].id == id) - return &clocks[i]; + i = tegra_bpmp_clk_id_to_index(clocks, num_clocks, id); + + if (i < num_clocks) + return &clocks[i]; return NULL; } @@ -539,31 +558,57 @@ tegra_bpmp_clk_register(struct tegra_bpmp *bpmp, return clk; } +static void tegra_bpmp_register_clocks_one(struct tegra_bpmp *bpmp, + struct tegra_bpmp_clk_info *infos, + unsigned int i, + unsigned int count) +{ + unsigned int j; + struct tegra_bpmp_clk_info *info; + struct tegra_bpmp_clk *clk; + + if (bpmp->clocks[i]) { + /* already registered */ + return; + } + + info = &infos[i]; + for (j = 0; j < info->num_parents; ++j) { + unsigned int p_id = info->parents[j]; + unsigned int p_i = tegra_bpmp_clk_id_to_index(infos, count, + p_id); + if (p_i < count) + tegra_bpmp_register_clocks_one(bpmp, infos, p_i, count); + } + + clk = tegra_bpmp_clk_register(bpmp, info, infos, count); + if (IS_ERR(clk)) { + dev_err(bpmp->dev, + "failed to register clock %u (%s): %ld\n", + info->id, info->name, PTR_ERR(clk)); + /* intentionally store the error pointer to + * bpmp->clocks[i] to avoid re-attempting the + * registration later + */ + } + + bpmp->clocks[i] = clk; +} + static int tegra_bpmp_register_clocks(struct tegra_bpmp *bpmp, struct tegra_bpmp_clk_info *infos, unsigned int count) { - struct tegra_bpmp_clk *clk; unsigned int i; bpmp->num_clocks = count; - bpmp->clocks = devm_kcalloc(bpmp->dev, count, sizeof(clk), GFP_KERNEL); + bpmp->clocks = devm_kcalloc(bpmp->dev, count, sizeof(struct tegra_bpmp_clk), GFP_KERNEL); if (!bpmp->clocks) return -ENOMEM; for (i = 0; i < count; i++) { - struct tegra_bpmp_clk_info *info = &infos[i]; - - clk = tegra_bpmp_clk_register(bpmp, info, infos, count); - if (IS_ERR(clk)) { - dev_err(bpmp->dev, - "failed to register clock %u (%s): %ld\n", - info->id, info->name, PTR_ERR(clk)); - continue; - } - - bpmp->clocks[i] = clk; + tegra_bpmp_register_clocks_one(bpmp, infos, i, count); } return 0; diff --git a/drivers/clk/tegra/clk-dfll.c b/drivers/clk/tegra/clk-dfll.c index 6144447f86c6323ab3880c1d076854d19b200f0d..41433927b55c58428e33fcbcb21a01d439166281 100644 --- a/drivers/clk/tegra/clk-dfll.c +++ b/drivers/clk/tegra/clk-dfll.c @@ -271,6 +271,7 @@ struct tegra_dfll { struct clk *ref_clk; struct clk *i2c_clk; struct clk *dfll_clk; + struct reset_control *dfll_rst; struct reset_control *dvco_rst; unsigned long ref_rate; unsigned long i2c_clk_rate; @@ -666,7 +667,7 @@ static int dfll_force_output(struct tegra_dfll *td, unsigned int out_sel) } /** - * dfll_load_lut - load the voltage lookup table + * dfll_load_i2c_lut - load the voltage lookup table * @td: struct tegra_dfll * * * Load the voltage-to-PMIC register value lookup table into the DFLL @@ -897,7 +898,7 @@ static void dfll_set_frequency_request(struct tegra_dfll *td, } /** - * tegra_dfll_request_rate - set the next rate for the DFLL to tune to + * dfll_request_rate - set the next rate for the DFLL to tune to * @td: DFLL instance * @rate: clock rate to target * @@ -1005,7 +1006,7 @@ static void dfll_set_open_loop_config(struct tegra_dfll *td) } /** - * tegra_dfll_lock - switch from open-loop to closed-loop mode + * dfll_lock - switch from open-loop to closed-loop mode * @td: DFLL instance * * Switch from OPEN_LOOP state to CLOSED_LOOP state. Returns 0 upon success, @@ -1046,7 +1047,7 @@ static int dfll_lock(struct tegra_dfll *td) } /** - * tegra_dfll_unlock - switch from closed-loop to open-loop mode + * dfll_unlock - switch from closed-loop to open-loop mode * @td: DFLL instance * * Switch from CLOSED_LOOP state to OPEN_LOOP state. Returns 0 upon success, @@ -1464,6 +1465,7 @@ static int dfll_init(struct tegra_dfll *td) return -EINVAL; } + reset_control_deassert(td->dfll_rst); reset_control_deassert(td->dvco_rst); ret = clk_prepare(td->ref_clk); @@ -1509,6 +1511,7 @@ di_err1: clk_unprepare(td->ref_clk); reset_control_assert(td->dvco_rst); + reset_control_assert(td->dfll_rst); return ret; } @@ -1530,6 +1533,7 @@ int tegra_dfll_suspend(struct device *dev) } reset_control_assert(td->dvco_rst); + reset_control_assert(td->dfll_rst); return 0; } @@ -1548,6 +1552,7 @@ int tegra_dfll_resume(struct device *dev) { struct tegra_dfll *td = dev_get_drvdata(dev); + reset_control_deassert(td->dfll_rst); reset_control_deassert(td->dvco_rst); pm_runtime_get_sync(td->dev); @@ -1951,6 +1956,12 @@ int tegra_dfll_register(struct platform_device *pdev, td->soc = soc; + td->dfll_rst = devm_reset_control_get_optional(td->dev, "dfll"); + if (IS_ERR(td->dfll_rst)) { + dev_err(td->dev, "couldn't get dfll reset\n"); + return PTR_ERR(td->dfll_rst); + } + td->dvco_rst = devm_reset_control_get(td->dev, "dvco"); if (IS_ERR(td->dvco_rst)) { dev_err(td->dev, "couldn't get dvco reset\n"); @@ -2087,6 +2098,7 @@ struct tegra_dfll_soc_data *tegra_dfll_unregister(struct platform_device *pdev) clk_unprepare(td->i2c_clk); reset_control_assert(td->dvco_rst); + reset_control_assert(td->dfll_rst); return td->soc; } diff --git a/drivers/clk/ti/clkctrl.c b/drivers/clk/ti/clkctrl.c index 064066e9e85b738d36209bef01c7161f7e447446..617360e20d86f5adbe2fb8e86791557d609d4e6f 100644 --- a/drivers/clk/ti/clkctrl.c +++ b/drivers/clk/ti/clkctrl.c @@ -232,8 +232,7 @@ static struct clk_hw *_ti_omap4_clkctrl_xlate(struct of_phandle_args *clkspec, void *data) { struct omap_clkctrl_provider *provider = data; - struct omap_clkctrl_clk *entry; - bool found = false; + struct omap_clkctrl_clk *entry = NULL, *iter; if (clkspec->args_count != 2) return ERR_PTR(-EINVAL); @@ -241,15 +240,15 @@ static struct clk_hw *_ti_omap4_clkctrl_xlate(struct of_phandle_args *clkspec, pr_debug("%s: looking for %x:%x\n", __func__, clkspec->args[0], clkspec->args[1]); - list_for_each_entry(entry, &provider->clocks, node) { - if (entry->reg_offset == clkspec->args[0] && - entry->bit_offset == clkspec->args[1]) { - found = true; + list_for_each_entry(iter, &provider->clocks, node) { + if (iter->reg_offset == clkspec->args[0] && + iter->bit_offset == clkspec->args[1]) { + entry = iter; break; } } - if (!found) + if (!entry) return ERR_PTR(-EINVAL); return entry->clk; diff --git a/drivers/clk/ti/composite.c b/drivers/clk/ti/composite.c index 8d60319be3683c8e9c86052d4590474eaa095c6c..779b9900f636d7c6daa9ddec4a0fc4453d6ae5b2 100644 --- a/drivers/clk/ti/composite.c +++ b/drivers/clk/ti/composite.c @@ -255,7 +255,7 @@ int __init ti_clk_add_component(struct device_node *node, struct clk_hw *hw, return -EINVAL; } - parent_names = kzalloc((sizeof(char *) * num_parents), GFP_KERNEL); + parent_names = kcalloc(num_parents, sizeof(char *), GFP_KERNEL); if (!parent_names) return -ENOMEM; diff --git a/drivers/clk/ux500/clk-prcmu.c b/drivers/clk/ux500/clk-prcmu.c index 937b6bb82b303ce89cfd9b1ba92360144cb71b20..4deb37f19a7ce331d039fd4c0463265457b48b22 100644 --- a/drivers/clk/ux500/clk-prcmu.c +++ b/drivers/clk/ux500/clk-prcmu.c @@ -14,27 +14,28 @@ #include "clk.h" #define to_clk_prcmu(_hw) container_of(_hw, struct clk_prcmu, hw) +#define to_clk_prcmu_clkout(_hw) container_of(_hw, struct clk_prcmu_clkout, hw) struct clk_prcmu { struct clk_hw hw; u8 cg_sel; - int is_prepared; - int is_enabled; int opp_requested; }; +struct clk_prcmu_clkout { + struct clk_hw hw; + u8 clkout_id; + u8 source; + u8 divider; +}; + /* PRCMU clock operations. */ static int clk_prcmu_prepare(struct clk_hw *hw) { - int ret; struct clk_prcmu *clk = to_clk_prcmu(hw); - ret = prcmu_request_clock(clk->cg_sel, true); - if (!ret) - clk->is_prepared = 1; - - return ret; + return prcmu_request_clock(clk->cg_sel, true); } static void clk_prcmu_unprepare(struct clk_hw *hw) @@ -42,34 +43,7 @@ static void clk_prcmu_unprepare(struct clk_hw *hw) struct clk_prcmu *clk = to_clk_prcmu(hw); if (prcmu_request_clock(clk->cg_sel, false)) pr_err("clk_prcmu: %s failed to disable %s.\n", __func__, - clk_hw_get_name(hw)); - else - clk->is_prepared = 0; -} - -static int clk_prcmu_is_prepared(struct clk_hw *hw) -{ - struct clk_prcmu *clk = to_clk_prcmu(hw); - return clk->is_prepared; -} - -static int clk_prcmu_enable(struct clk_hw *hw) -{ - struct clk_prcmu *clk = to_clk_prcmu(hw); - clk->is_enabled = 1; - return 0; -} - -static void clk_prcmu_disable(struct clk_hw *hw) -{ - struct clk_prcmu *clk = to_clk_prcmu(hw); - clk->is_enabled = 0; -} - -static int clk_prcmu_is_enabled(struct clk_hw *hw) -{ - struct clk_prcmu *clk = to_clk_prcmu(hw); - return clk->is_enabled; + clk_hw_get_name(hw)); } static unsigned long clk_prcmu_recalc_rate(struct clk_hw *hw, @@ -118,7 +92,6 @@ static int clk_prcmu_opp_prepare(struct clk_hw *hw) return err; } - clk->is_prepared = 1; return 0; } @@ -137,8 +110,6 @@ static void clk_prcmu_opp_unprepare(struct clk_hw *hw) (char *)clk_hw_get_name(hw)); clk->opp_requested = 0; } - - clk->is_prepared = 0; } static int clk_prcmu_opp_volt_prepare(struct clk_hw *hw) @@ -163,7 +134,6 @@ static int clk_prcmu_opp_volt_prepare(struct clk_hw *hw) return err; } - clk->is_prepared = 1; return 0; } @@ -181,17 +151,11 @@ static void clk_prcmu_opp_volt_unprepare(struct clk_hw *hw) prcmu_request_ape_opp_100_voltage(false); clk->opp_requested = 0; } - - clk->is_prepared = 0; } static const struct clk_ops clk_prcmu_scalable_ops = { .prepare = clk_prcmu_prepare, .unprepare = clk_prcmu_unprepare, - .is_prepared = clk_prcmu_is_prepared, - .enable = clk_prcmu_enable, - .disable = clk_prcmu_disable, - .is_enabled = clk_prcmu_is_enabled, .recalc_rate = clk_prcmu_recalc_rate, .round_rate = clk_prcmu_round_rate, .set_rate = clk_prcmu_set_rate, @@ -200,57 +164,43 @@ static const struct clk_ops clk_prcmu_scalable_ops = { static const struct clk_ops clk_prcmu_gate_ops = { .prepare = clk_prcmu_prepare, .unprepare = clk_prcmu_unprepare, - .is_prepared = clk_prcmu_is_prepared, - .enable = clk_prcmu_enable, - .disable = clk_prcmu_disable, - .is_enabled = clk_prcmu_is_enabled, .recalc_rate = clk_prcmu_recalc_rate, }; static const struct clk_ops clk_prcmu_scalable_rate_ops = { - .is_enabled = clk_prcmu_is_enabled, .recalc_rate = clk_prcmu_recalc_rate, .round_rate = clk_prcmu_round_rate, .set_rate = clk_prcmu_set_rate, }; static const struct clk_ops clk_prcmu_rate_ops = { - .is_enabled = clk_prcmu_is_enabled, .recalc_rate = clk_prcmu_recalc_rate, }; static const struct clk_ops clk_prcmu_opp_gate_ops = { .prepare = clk_prcmu_opp_prepare, .unprepare = clk_prcmu_opp_unprepare, - .is_prepared = clk_prcmu_is_prepared, - .enable = clk_prcmu_enable, - .disable = clk_prcmu_disable, - .is_enabled = clk_prcmu_is_enabled, .recalc_rate = clk_prcmu_recalc_rate, }; static const struct clk_ops clk_prcmu_opp_volt_scalable_ops = { .prepare = clk_prcmu_opp_volt_prepare, .unprepare = clk_prcmu_opp_volt_unprepare, - .is_prepared = clk_prcmu_is_prepared, - .enable = clk_prcmu_enable, - .disable = clk_prcmu_disable, - .is_enabled = clk_prcmu_is_enabled, .recalc_rate = clk_prcmu_recalc_rate, .round_rate = clk_prcmu_round_rate, .set_rate = clk_prcmu_set_rate, }; -static struct clk *clk_reg_prcmu(const char *name, - const char *parent_name, - u8 cg_sel, - unsigned long rate, - unsigned long flags, - const struct clk_ops *clk_prcmu_ops) +static struct clk_hw *clk_reg_prcmu(const char *name, + const char *parent_name, + u8 cg_sel, + unsigned long rate, + unsigned long flags, + const struct clk_ops *clk_prcmu_ops) { struct clk_prcmu *clk; struct clk_init_data clk_prcmu_init; - struct clk *clk_reg; + int ret; if (!name) { pr_err("clk_prcmu: %s invalid arguments passed\n", __func__); @@ -262,8 +212,6 @@ static struct clk *clk_reg_prcmu(const char *name, return ERR_PTR(-ENOMEM); clk->cg_sel = cg_sel; - clk->is_prepared = 1; - clk->is_enabled = 1; clk->opp_requested = 0; /* "rate" can be used for changing the initial frequency */ if (rate) @@ -276,11 +224,11 @@ static struct clk *clk_reg_prcmu(const char *name, clk_prcmu_init.num_parents = (parent_name ? 1 : 0); clk->hw.init = &clk_prcmu_init; - clk_reg = clk_register(NULL, &clk->hw); - if (IS_ERR_OR_NULL(clk_reg)) + ret = clk_hw_register(NULL, &clk->hw); + if (ret) goto free_clk; - return clk_reg; + return &clk->hw; free_clk: kfree(clk); @@ -288,59 +236,165 @@ free_clk: return ERR_PTR(-ENOMEM); } -struct clk *clk_reg_prcmu_scalable(const char *name, - const char *parent_name, - u8 cg_sel, - unsigned long rate, - unsigned long flags) +struct clk_hw *clk_reg_prcmu_scalable(const char *name, + const char *parent_name, + u8 cg_sel, + unsigned long rate, + unsigned long flags) { return clk_reg_prcmu(name, parent_name, cg_sel, rate, flags, &clk_prcmu_scalable_ops); } -struct clk *clk_reg_prcmu_gate(const char *name, - const char *parent_name, - u8 cg_sel, - unsigned long flags) +struct clk_hw *clk_reg_prcmu_gate(const char *name, + const char *parent_name, + u8 cg_sel, + unsigned long flags) { return clk_reg_prcmu(name, parent_name, cg_sel, 0, flags, &clk_prcmu_gate_ops); } -struct clk *clk_reg_prcmu_scalable_rate(const char *name, - const char *parent_name, - u8 cg_sel, - unsigned long rate, - unsigned long flags) +struct clk_hw *clk_reg_prcmu_scalable_rate(const char *name, + const char *parent_name, + u8 cg_sel, + unsigned long rate, + unsigned long flags) { return clk_reg_prcmu(name, parent_name, cg_sel, rate, flags, &clk_prcmu_scalable_rate_ops); } -struct clk *clk_reg_prcmu_rate(const char *name, - const char *parent_name, - u8 cg_sel, - unsigned long flags) +struct clk_hw *clk_reg_prcmu_rate(const char *name, + const char *parent_name, + u8 cg_sel, + unsigned long flags) { return clk_reg_prcmu(name, parent_name, cg_sel, 0, flags, &clk_prcmu_rate_ops); } -struct clk *clk_reg_prcmu_opp_gate(const char *name, - const char *parent_name, - u8 cg_sel, - unsigned long flags) +struct clk_hw *clk_reg_prcmu_opp_gate(const char *name, + const char *parent_name, + u8 cg_sel, + unsigned long flags) { return clk_reg_prcmu(name, parent_name, cg_sel, 0, flags, &clk_prcmu_opp_gate_ops); } -struct clk *clk_reg_prcmu_opp_volt_scalable(const char *name, - const char *parent_name, - u8 cg_sel, - unsigned long rate, - unsigned long flags) +struct clk_hw *clk_reg_prcmu_opp_volt_scalable(const char *name, + const char *parent_name, + u8 cg_sel, + unsigned long rate, + unsigned long flags) { return clk_reg_prcmu(name, parent_name, cg_sel, rate, flags, &clk_prcmu_opp_volt_scalable_ops); } + +/* The clkout (external) clock is special and need special ops */ + +static int clk_prcmu_clkout_prepare(struct clk_hw *hw) +{ + struct clk_prcmu_clkout *clk = to_clk_prcmu_clkout(hw); + + return prcmu_config_clkout(clk->clkout_id, clk->source, clk->divider); +} + +static void clk_prcmu_clkout_unprepare(struct clk_hw *hw) +{ + struct clk_prcmu_clkout *clk = to_clk_prcmu_clkout(hw); + int ret; + + /* The clkout clock is disabled by dividing by 0 */ + ret = prcmu_config_clkout(clk->clkout_id, clk->source, 0); + if (ret) + pr_err("clk_prcmu: %s failed to disable %s\n", __func__, + clk_hw_get_name(hw)); +} + +static unsigned long clk_prcmu_clkout_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct clk_prcmu_clkout *clk = to_clk_prcmu_clkout(hw); + + return (parent_rate / clk->divider); +} + +static u8 clk_prcmu_clkout_get_parent(struct clk_hw *hw) +{ + struct clk_prcmu_clkout *clk = to_clk_prcmu_clkout(hw); + + return clk->source; +} + +static int clk_prcmu_clkout_set_parent(struct clk_hw *hw, u8 index) +{ + struct clk_prcmu_clkout *clk = to_clk_prcmu_clkout(hw); + + clk->source = index; + /* Make sure the change reaches the hardware immediately */ + if (clk_hw_is_prepared(hw)) + return clk_prcmu_clkout_prepare(hw); + return 0; +} + +static const struct clk_ops clk_prcmu_clkout_ops = { + .prepare = clk_prcmu_clkout_prepare, + .unprepare = clk_prcmu_clkout_unprepare, + .recalc_rate = clk_prcmu_clkout_recalc_rate, + .get_parent = clk_prcmu_clkout_get_parent, + .set_parent = clk_prcmu_clkout_set_parent, +}; + +struct clk_hw *clk_reg_prcmu_clkout(const char *name, + const char * const *parent_names, + int num_parents, + u8 source, u8 divider) + +{ + struct clk_prcmu_clkout *clk; + struct clk_init_data clk_prcmu_clkout_init; + u8 clkout_id; + int ret; + + if (!name) { + pr_err("clk_prcmu_clkout: %s invalid arguments passed\n", __func__); + return ERR_PTR(-EINVAL); + } + + if (!strcmp(name, "clkout1")) + clkout_id = 0; + else if (!strcmp(name, "clkout2")) + clkout_id = 1; + else { + pr_err("clk_prcmu_clkout: %s bad clock name\n", __func__); + return ERR_PTR(-EINVAL); + } + + clk = kzalloc(sizeof(*clk), GFP_KERNEL); + if (!clk) + return ERR_PTR(-ENOMEM); + + clk->clkout_id = clkout_id; + clk->source = source; + clk->divider = divider; + + clk_prcmu_clkout_init.name = name; + clk_prcmu_clkout_init.ops = &clk_prcmu_clkout_ops; + clk_prcmu_clkout_init.flags = CLK_GET_RATE_NOCACHE; + clk_prcmu_clkout_init.parent_names = parent_names; + clk_prcmu_clkout_init.num_parents = num_parents; + clk->hw.init = &clk_prcmu_clkout_init; + + ret = clk_hw_register(NULL, &clk->hw); + if (ret) + goto free_clkout; + + return &clk->hw; +free_clkout: + kfree(clk); + pr_err("clk_prcmu_clkout: %s failed to register clk\n", __func__); + return ERR_PTR(-ENOMEM); +} diff --git a/drivers/clk/ux500/clk.h b/drivers/clk/ux500/clk.h index 40cd9fc95b8b3472bb5fcf6878096617414fcc15..91003cf8003cdad4088d84c5b9b80c69d532b2db 100644 --- a/drivers/clk/ux500/clk.h +++ b/drivers/clk/ux500/clk.h @@ -13,6 +13,7 @@ #include struct clk; +struct clk_hw; struct clk *clk_reg_prcc_pclk(const char *name, const char *parent_name, @@ -26,38 +27,43 @@ struct clk *clk_reg_prcc_kclk(const char *name, u32 cg_sel, unsigned long flags); -struct clk *clk_reg_prcmu_scalable(const char *name, - const char *parent_name, - u8 cg_sel, - unsigned long rate, - unsigned long flags); - -struct clk *clk_reg_prcmu_gate(const char *name, - const char *parent_name, - u8 cg_sel, - unsigned long flags); - -struct clk *clk_reg_prcmu_scalable_rate(const char *name, - const char *parent_name, - u8 cg_sel, - unsigned long rate, - unsigned long flags); - -struct clk *clk_reg_prcmu_rate(const char *name, - const char *parent_name, - u8 cg_sel, - unsigned long flags); - -struct clk *clk_reg_prcmu_opp_gate(const char *name, - const char *parent_name, - u8 cg_sel, - unsigned long flags); - -struct clk *clk_reg_prcmu_opp_volt_scalable(const char *name, - const char *parent_name, - u8 cg_sel, - unsigned long rate, - unsigned long flags); +struct clk_hw *clk_reg_prcmu_scalable(const char *name, + const char *parent_name, + u8 cg_sel, + unsigned long rate, + unsigned long flags); + +struct clk_hw *clk_reg_prcmu_gate(const char *name, + const char *parent_name, + u8 cg_sel, + unsigned long flags); + +struct clk_hw *clk_reg_prcmu_scalable_rate(const char *name, + const char *parent_name, + u8 cg_sel, + unsigned long rate, + unsigned long flags); + +struct clk_hw *clk_reg_prcmu_rate(const char *name, + const char *parent_name, + u8 cg_sel, + unsigned long flags); + +struct clk_hw *clk_reg_prcmu_opp_gate(const char *name, + const char *parent_name, + u8 cg_sel, + unsigned long flags); + +struct clk_hw *clk_reg_prcmu_opp_volt_scalable(const char *name, + const char *parent_name, + u8 cg_sel, + unsigned long rate, + unsigned long flags); + +struct clk_hw *clk_reg_prcmu_clkout(const char *name, + const char * const *parent_names, + int num_parents, + u8 source, u8 divider); struct clk *clk_reg_sysctrl_gate(struct device *dev, const char *name, diff --git a/drivers/clk/ux500/reset-prcc.c b/drivers/clk/ux500/reset-prcc.c index fcd5d042806a689789dcbc20e4bfaaedac19e191..f7e48941fbc70640871ade934f6bf93ef338770b 100644 --- a/drivers/clk/ux500/reset-prcc.c +++ b/drivers/clk/ux500/reset-prcc.c @@ -58,7 +58,7 @@ static void __iomem *u8500_prcc_reset_base(struct u8500_prcc_reset *ur, prcc_num = id / PRCC_PERIPHS_PER_CLUSTER; index = prcc_num_to_index(prcc_num); - if (index > ARRAY_SIZE(ur->base)) + if (index >= ARRAY_SIZE(ur->base)) return NULL; return ur->base[index]; diff --git a/drivers/clk/ux500/u8500_of_clk.c b/drivers/clk/ux500/u8500_of_clk.c index e86ed2eec3fd3f0f3332cf0bcf73e8bc56bd305c..8e2f6c65db2a7c7a92752c14fe0a3bb3340f247c 100644 --- a/drivers/clk/ux500/u8500_of_clk.c +++ b/drivers/clk/ux500/u8500_of_clk.c @@ -15,9 +15,9 @@ #include "prcc.h" #include "reset-prcc.h" -static struct clk *prcmu_clk[PRCMU_NUM_CLKS]; static struct clk *prcc_pclk[(PRCC_NUM_PERIPH_CLUSTERS + 1) * PRCC_PERIPHS_PER_CLUSTER]; static struct clk *prcc_kclk[(PRCC_NUM_PERIPH_CLUSTERS + 1) * PRCC_PERIPHS_PER_CLUSTER]; +static struct clk_hw *clkout_clk[2]; #define PRCC_SHOW(clk, base, bit) \ clk[(base * PRCC_PERIPHS_PER_CLUSTER) + bit] @@ -46,6 +46,82 @@ static struct clk *ux500_twocell_get(struct of_phandle_args *clkspec, return PRCC_SHOW(clk_data, base, bit); } +static struct clk_hw_onecell_data u8500_prcmu_hw_clks = { + .hws = { + /* + * This assignment makes sure the dynamic array + * gets the right size. + */ + [PRCMU_NUM_CLKS] = NULL, + }, + .num = PRCMU_NUM_CLKS, +}; + +/* Essentially names for the first PRCMU_CLKSRC_* defines */ +static const char * const u8500_clkout_parents[] = { + "clk38m_to_clkgen", + "aclk", + /* Just called "sysclk" in documentation */ + "ab8500_sysclk", + "lcdclk", + "sdmmcclk", + "tvclk", + "timclk", + /* CLK009 is not implemented, add it if you need it */ + "clk009", +}; + +static struct clk_hw *ux500_clkout_get(struct of_phandle_args *clkspec, + void *data) +{ + u32 id, source, divider; + struct clk_hw *clkout; + + if (clkspec->args_count != 3) + return ERR_PTR(-EINVAL); + + id = clkspec->args[0]; + source = clkspec->args[1]; + divider = clkspec->args[2]; + + if (id > 1) { + pr_err("%s: invalid clkout ID %d\n", __func__, id); + return ERR_PTR(-EINVAL); + } + + if (clkout_clk[id]) { + pr_info("%s: clkout%d already registered, not reconfiguring\n", + __func__, id + 1); + return clkout_clk[id]; + } + + if (source > 7) { + pr_err("%s: invalid source ID %d\n", __func__, source); + return ERR_PTR(-EINVAL); + } + + if (divider == 0 || divider > 63) { + pr_err("%s: invalid divider %d\n", __func__, divider); + return ERR_PTR(-EINVAL); + } + + pr_debug("registering clkout%d with source %d and divider %d\n", + id + 1, source, divider); + + clkout = clk_reg_prcmu_clkout(id ? "clkout2" : "clkout1", + u8500_clkout_parents, + ARRAY_SIZE(u8500_clkout_parents), + source, divider); + if (IS_ERR(clkout)) { + pr_err("failed to register clkout%d\n", id + 1); + return ERR_CAST(clkout); + } + + clkout_clk[id] = clkout; + + return clkout; +} + static void u8500_clk_init(struct device_node *np) { struct prcmu_fw_version *fw_version; @@ -77,19 +153,29 @@ static void u8500_clk_init(struct device_node *np) } /* Clock sources */ - clk = clk_reg_prcmu_gate("soc0_pll", NULL, PRCMU_PLLSOC0, - CLK_IGNORE_UNUSED); - prcmu_clk[PRCMU_PLLSOC0] = clk; + u8500_prcmu_hw_clks.hws[PRCMU_PLLSOC0] = + clk_reg_prcmu_gate("soc0_pll", NULL, PRCMU_PLLSOC0, + CLK_IGNORE_UNUSED); - clk = clk_reg_prcmu_gate("soc1_pll", NULL, PRCMU_PLLSOC1, - CLK_IGNORE_UNUSED); - prcmu_clk[PRCMU_PLLSOC1] = clk; + u8500_prcmu_hw_clks.hws[PRCMU_PLLSOC1] = + clk_reg_prcmu_gate("soc1_pll", NULL, PRCMU_PLLSOC1, + CLK_IGNORE_UNUSED); - clk = clk_reg_prcmu_gate("ddr_pll", NULL, PRCMU_PLLDDR, - CLK_IGNORE_UNUSED); - prcmu_clk[PRCMU_PLLDDR] = clk; + u8500_prcmu_hw_clks.hws[PRCMU_PLLDDR] = + clk_reg_prcmu_gate("ddr_pll", NULL, PRCMU_PLLDDR, + CLK_IGNORE_UNUSED); - /* FIXME: Add sys, ulp and int clocks here. */ + /* + * Read-only clocks that only return their current rate, only used + * as parents to other clocks and not visible in the device tree. + * clk38m_to_clkgen is the same as the SYSCLK, i.e. the root clock. + */ + clk_reg_prcmu_rate("clk38m_to_clkgen", NULL, PRCMU_SYSCLK, + CLK_IGNORE_UNUSED); + clk_reg_prcmu_rate("aclk", NULL, PRCMU_ACLK, + CLK_IGNORE_UNUSED); + + /* TODO: add CLK009 if needed */ rtc_clk = clk_register_fixed_rate(NULL, "rtc32k", "NULL", CLK_IGNORE_UNUSED, @@ -113,146 +199,106 @@ static void u8500_clk_init(struct device_node *np) } if (sgaclk_parent) - clk = clk_reg_prcmu_gate("sgclk", sgaclk_parent, - PRCMU_SGACLK, 0); + u8500_prcmu_hw_clks.hws[PRCMU_SGACLK] = + clk_reg_prcmu_gate("sgclk", sgaclk_parent, + PRCMU_SGACLK, 0); else - clk = clk_reg_prcmu_gate("sgclk", NULL, PRCMU_SGACLK, 0); - prcmu_clk[PRCMU_SGACLK] = clk; - - clk = clk_reg_prcmu_gate("uartclk", NULL, PRCMU_UARTCLK, 0); - prcmu_clk[PRCMU_UARTCLK] = clk; - - clk = clk_reg_prcmu_gate("msp02clk", NULL, PRCMU_MSP02CLK, 0); - prcmu_clk[PRCMU_MSP02CLK] = clk; - - clk = clk_reg_prcmu_gate("msp1clk", NULL, PRCMU_MSP1CLK, 0); - prcmu_clk[PRCMU_MSP1CLK] = clk; - - clk = clk_reg_prcmu_gate("i2cclk", NULL, PRCMU_I2CCLK, 0); - prcmu_clk[PRCMU_I2CCLK] = clk; - - clk = clk_reg_prcmu_gate("slimclk", NULL, PRCMU_SLIMCLK, 0); - prcmu_clk[PRCMU_SLIMCLK] = clk; - - clk = clk_reg_prcmu_gate("per1clk", NULL, PRCMU_PER1CLK, 0); - prcmu_clk[PRCMU_PER1CLK] = clk; - - clk = clk_reg_prcmu_gate("per2clk", NULL, PRCMU_PER2CLK, 0); - prcmu_clk[PRCMU_PER2CLK] = clk; - - clk = clk_reg_prcmu_gate("per3clk", NULL, PRCMU_PER3CLK, 0); - prcmu_clk[PRCMU_PER3CLK] = clk; - - clk = clk_reg_prcmu_gate("per5clk", NULL, PRCMU_PER5CLK, 0); - prcmu_clk[PRCMU_PER5CLK] = clk; - - clk = clk_reg_prcmu_gate("per6clk", NULL, PRCMU_PER6CLK, 0); - prcmu_clk[PRCMU_PER6CLK] = clk; - - clk = clk_reg_prcmu_gate("per7clk", NULL, PRCMU_PER7CLK, 0); - prcmu_clk[PRCMU_PER7CLK] = clk; - - clk = clk_reg_prcmu_scalable("lcdclk", NULL, PRCMU_LCDCLK, 0, - CLK_SET_RATE_GATE); - prcmu_clk[PRCMU_LCDCLK] = clk; - - clk = clk_reg_prcmu_opp_gate("bmlclk", NULL, PRCMU_BMLCLK, 0); - prcmu_clk[PRCMU_BMLCLK] = clk; - - clk = clk_reg_prcmu_scalable("hsitxclk", NULL, PRCMU_HSITXCLK, 0, - CLK_SET_RATE_GATE); - prcmu_clk[PRCMU_HSITXCLK] = clk; - - clk = clk_reg_prcmu_scalable("hsirxclk", NULL, PRCMU_HSIRXCLK, 0, - CLK_SET_RATE_GATE); - prcmu_clk[PRCMU_HSIRXCLK] = clk; - - clk = clk_reg_prcmu_scalable("hdmiclk", NULL, PRCMU_HDMICLK, 0, - CLK_SET_RATE_GATE); - prcmu_clk[PRCMU_HDMICLK] = clk; - - clk = clk_reg_prcmu_gate("apeatclk", NULL, PRCMU_APEATCLK, 0); - prcmu_clk[PRCMU_APEATCLK] = clk; - - clk = clk_reg_prcmu_scalable("apetraceclk", NULL, PRCMU_APETRACECLK, 0, - CLK_SET_RATE_GATE); - prcmu_clk[PRCMU_APETRACECLK] = clk; - - clk = clk_reg_prcmu_gate("mcdeclk", NULL, PRCMU_MCDECLK, 0); - prcmu_clk[PRCMU_MCDECLK] = clk; - - clk = clk_reg_prcmu_opp_gate("ipi2cclk", NULL, PRCMU_IPI2CCLK, 0); - prcmu_clk[PRCMU_IPI2CCLK] = clk; - - clk = clk_reg_prcmu_gate("dsialtclk", NULL, PRCMU_DSIALTCLK, 0); - prcmu_clk[PRCMU_DSIALTCLK] = clk; - - clk = clk_reg_prcmu_gate("dmaclk", NULL, PRCMU_DMACLK, 0); - prcmu_clk[PRCMU_DMACLK] = clk; - - clk = clk_reg_prcmu_gate("b2r2clk", NULL, PRCMU_B2R2CLK, 0); - prcmu_clk[PRCMU_B2R2CLK] = clk; - - clk = clk_reg_prcmu_scalable("tvclk", NULL, PRCMU_TVCLK, 0, - CLK_SET_RATE_GATE); - prcmu_clk[PRCMU_TVCLK] = clk; - - clk = clk_reg_prcmu_gate("sspclk", NULL, PRCMU_SSPCLK, 0); - prcmu_clk[PRCMU_SSPCLK] = clk; - - clk = clk_reg_prcmu_gate("rngclk", NULL, PRCMU_RNGCLK, 0); - prcmu_clk[PRCMU_RNGCLK] = clk; - - clk = clk_reg_prcmu_gate("uiccclk", NULL, PRCMU_UICCCLK, 0); - prcmu_clk[PRCMU_UICCCLK] = clk; - - clk = clk_reg_prcmu_gate("timclk", NULL, PRCMU_TIMCLK, 0); - prcmu_clk[PRCMU_TIMCLK] = clk; - - clk = clk_reg_prcmu_gate("ab8500_sysclk", NULL, PRCMU_SYSCLK, 0); - prcmu_clk[PRCMU_SYSCLK] = clk; - - clk = clk_reg_prcmu_opp_volt_scalable("sdmmcclk", NULL, PRCMU_SDMMCCLK, - 100000000, CLK_SET_RATE_GATE); - prcmu_clk[PRCMU_SDMMCCLK] = clk; - - clk = clk_reg_prcmu_scalable("dsi_pll", "hdmiclk", - PRCMU_PLLDSI, 0, CLK_SET_RATE_GATE); - prcmu_clk[PRCMU_PLLDSI] = clk; - - clk = clk_reg_prcmu_scalable("dsi0clk", "dsi_pll", - PRCMU_DSI0CLK, 0, CLK_SET_RATE_GATE); - prcmu_clk[PRCMU_DSI0CLK] = clk; - - clk = clk_reg_prcmu_scalable("dsi1clk", "dsi_pll", - PRCMU_DSI1CLK, 0, CLK_SET_RATE_GATE); - prcmu_clk[PRCMU_DSI1CLK] = clk; - - clk = clk_reg_prcmu_scalable("dsi0escclk", "tvclk", - PRCMU_DSI0ESCCLK, 0, CLK_SET_RATE_GATE); - prcmu_clk[PRCMU_DSI0ESCCLK] = clk; - - clk = clk_reg_prcmu_scalable("dsi1escclk", "tvclk", - PRCMU_DSI1ESCCLK, 0, CLK_SET_RATE_GATE); - prcmu_clk[PRCMU_DSI1ESCCLK] = clk; - - clk = clk_reg_prcmu_scalable("dsi2escclk", "tvclk", - PRCMU_DSI2ESCCLK, 0, CLK_SET_RATE_GATE); - prcmu_clk[PRCMU_DSI2ESCCLK] = clk; - - clk = clk_reg_prcmu_scalable_rate("armss", NULL, - PRCMU_ARMSS, 0, CLK_IGNORE_UNUSED); - prcmu_clk[PRCMU_ARMSS] = clk; + u8500_prcmu_hw_clks.hws[PRCMU_SGACLK] = + clk_reg_prcmu_gate("sgclk", NULL, PRCMU_SGACLK, 0); + + u8500_prcmu_hw_clks.hws[PRCMU_UARTCLK] = + clk_reg_prcmu_gate("uartclk", NULL, PRCMU_UARTCLK, 0); + u8500_prcmu_hw_clks.hws[PRCMU_MSP02CLK] = + clk_reg_prcmu_gate("msp02clk", NULL, PRCMU_MSP02CLK, 0); + u8500_prcmu_hw_clks.hws[PRCMU_MSP1CLK] = + clk_reg_prcmu_gate("msp1clk", NULL, PRCMU_MSP1CLK, 0); + u8500_prcmu_hw_clks.hws[PRCMU_I2CCLK] = + clk_reg_prcmu_gate("i2cclk", NULL, PRCMU_I2CCLK, 0); + u8500_prcmu_hw_clks.hws[PRCMU_SLIMCLK] = + clk_reg_prcmu_gate("slimclk", NULL, PRCMU_SLIMCLK, 0); + u8500_prcmu_hw_clks.hws[PRCMU_PER1CLK] = + clk_reg_prcmu_gate("per1clk", NULL, PRCMU_PER1CLK, 0); + u8500_prcmu_hw_clks.hws[PRCMU_PER2CLK] = + clk_reg_prcmu_gate("per2clk", NULL, PRCMU_PER2CLK, 0); + u8500_prcmu_hw_clks.hws[PRCMU_PER3CLK] = + clk_reg_prcmu_gate("per3clk", NULL, PRCMU_PER3CLK, 0); + u8500_prcmu_hw_clks.hws[PRCMU_PER5CLK] = + clk_reg_prcmu_gate("per5clk", NULL, PRCMU_PER5CLK, 0); + u8500_prcmu_hw_clks.hws[PRCMU_PER6CLK] = + clk_reg_prcmu_gate("per6clk", NULL, PRCMU_PER6CLK, 0); + u8500_prcmu_hw_clks.hws[PRCMU_PER7CLK] = + clk_reg_prcmu_gate("per7clk", NULL, PRCMU_PER7CLK, 0); + u8500_prcmu_hw_clks.hws[PRCMU_LCDCLK] = + clk_reg_prcmu_scalable("lcdclk", NULL, PRCMU_LCDCLK, 0, + CLK_SET_RATE_GATE); + u8500_prcmu_hw_clks.hws[PRCMU_BMLCLK] = + clk_reg_prcmu_opp_gate("bmlclk", NULL, PRCMU_BMLCLK, 0); + u8500_prcmu_hw_clks.hws[PRCMU_HSITXCLK] = + clk_reg_prcmu_scalable("hsitxclk", NULL, PRCMU_HSITXCLK, 0, + CLK_SET_RATE_GATE); + u8500_prcmu_hw_clks.hws[PRCMU_HSIRXCLK] = + clk_reg_prcmu_scalable("hsirxclk", NULL, PRCMU_HSIRXCLK, 0, + CLK_SET_RATE_GATE); + u8500_prcmu_hw_clks.hws[PRCMU_HDMICLK] = + clk_reg_prcmu_scalable("hdmiclk", NULL, PRCMU_HDMICLK, 0, + CLK_SET_RATE_GATE); + u8500_prcmu_hw_clks.hws[PRCMU_APEATCLK] = + clk_reg_prcmu_gate("apeatclk", NULL, PRCMU_APEATCLK, 0); + u8500_prcmu_hw_clks.hws[PRCMU_APETRACECLK] = + clk_reg_prcmu_scalable("apetraceclk", NULL, PRCMU_APETRACECLK, 0, + CLK_SET_RATE_GATE); + u8500_prcmu_hw_clks.hws[PRCMU_MCDECLK] = + clk_reg_prcmu_gate("mcdeclk", NULL, PRCMU_MCDECLK, 0); + u8500_prcmu_hw_clks.hws[PRCMU_IPI2CCLK] = + clk_reg_prcmu_opp_gate("ipi2cclk", NULL, PRCMU_IPI2CCLK, 0); + u8500_prcmu_hw_clks.hws[PRCMU_DSIALTCLK] = + clk_reg_prcmu_gate("dsialtclk", NULL, PRCMU_DSIALTCLK, 0); + u8500_prcmu_hw_clks.hws[PRCMU_DMACLK] = + clk_reg_prcmu_gate("dmaclk", NULL, PRCMU_DMACLK, 0); + u8500_prcmu_hw_clks.hws[PRCMU_B2R2CLK] = + clk_reg_prcmu_gate("b2r2clk", NULL, PRCMU_B2R2CLK, 0); + u8500_prcmu_hw_clks.hws[PRCMU_TVCLK] = + clk_reg_prcmu_scalable("tvclk", NULL, PRCMU_TVCLK, 0, + CLK_SET_RATE_GATE); + u8500_prcmu_hw_clks.hws[PRCMU_SSPCLK] = + clk_reg_prcmu_gate("sspclk", NULL, PRCMU_SSPCLK, 0); + u8500_prcmu_hw_clks.hws[PRCMU_RNGCLK] = + clk_reg_prcmu_gate("rngclk", NULL, PRCMU_RNGCLK, 0); + u8500_prcmu_hw_clks.hws[PRCMU_UICCCLK] = + clk_reg_prcmu_gate("uiccclk", NULL, PRCMU_UICCCLK, 0); + u8500_prcmu_hw_clks.hws[PRCMU_TIMCLK] = + clk_reg_prcmu_gate("timclk", NULL, PRCMU_TIMCLK, 0); + u8500_prcmu_hw_clks.hws[PRCMU_SYSCLK] = + clk_reg_prcmu_gate("ab8500_sysclk", NULL, PRCMU_SYSCLK, 0); + u8500_prcmu_hw_clks.hws[PRCMU_SDMMCCLK] = + clk_reg_prcmu_opp_volt_scalable("sdmmcclk", NULL, + PRCMU_SDMMCCLK, 100000000, + CLK_SET_RATE_GATE); + u8500_prcmu_hw_clks.hws[PRCMU_PLLDSI] = + clk_reg_prcmu_scalable("dsi_pll", "hdmiclk", + PRCMU_PLLDSI, 0, CLK_SET_RATE_GATE); + u8500_prcmu_hw_clks.hws[PRCMU_DSI0CLK] = + clk_reg_prcmu_scalable("dsi0clk", "dsi_pll", + PRCMU_DSI0CLK, 0, CLK_SET_RATE_GATE); + u8500_prcmu_hw_clks.hws[PRCMU_DSI1CLK] = + clk_reg_prcmu_scalable("dsi1clk", "dsi_pll", + PRCMU_DSI1CLK, 0, CLK_SET_RATE_GATE); + u8500_prcmu_hw_clks.hws[PRCMU_DSI0ESCCLK] = + clk_reg_prcmu_scalable("dsi0escclk", "tvclk", + PRCMU_DSI0ESCCLK, 0, CLK_SET_RATE_GATE); + u8500_prcmu_hw_clks.hws[PRCMU_DSI1ESCCLK] = + clk_reg_prcmu_scalable("dsi1escclk", "tvclk", + PRCMU_DSI1ESCCLK, 0, CLK_SET_RATE_GATE); + u8500_prcmu_hw_clks.hws[PRCMU_DSI2ESCCLK] = + clk_reg_prcmu_scalable("dsi2escclk", "tvclk", + PRCMU_DSI2ESCCLK, 0, CLK_SET_RATE_GATE); + u8500_prcmu_hw_clks.hws[PRCMU_ARMSS] = + clk_reg_prcmu_scalable_rate("armss", NULL, + PRCMU_ARMSS, 0, CLK_IGNORE_UNUSED); twd_clk = clk_register_fixed_factor(NULL, "smp_twd", "armss", CLK_IGNORE_UNUSED, 1, 2); - /* - * FIXME: Add special handled PRCMU clocks here: - * 1. clkout0yuv, use PRCMU as parent + need regulator + pinctrl. - * 2. ab9540_clkout1yuv, see clkout0yuv - */ - /* PRCC P-clocks */ clk = clk_reg_prcc_pclk("p1_pclk0", "per1clk", bases[CLKRST1_INDEX], BIT(0), 0); @@ -546,13 +592,13 @@ static void u8500_clk_init(struct device_node *np) PRCC_KCLK_STORE(clk, 6, 0); for_each_child_of_node(np, child) { - static struct clk_onecell_data clk_data; + if (of_node_name_eq(child, "prcmu-clock")) + of_clk_add_hw_provider(child, of_clk_hw_onecell_get, + &u8500_prcmu_hw_clks); + + if (of_node_name_eq(child, "clkout-clock")) + of_clk_add_hw_provider(child, ux500_clkout_get, NULL); - if (of_node_name_eq(child, "prcmu-clock")) { - clk_data.clks = prcmu_clk; - clk_data.clk_num = ARRAY_SIZE(prcmu_clk); - of_clk_add_provider(child, of_clk_src_onecell_get, &clk_data); - } if (of_node_name_eq(child, "prcc-periph-clock")) of_clk_add_provider(child, ux500_twocell_get, prcc_pclk); diff --git a/drivers/cpufreq/cppc_cpufreq.c b/drivers/cpufreq/cppc_cpufreq.c index d092c9bb4ba39c40e848a2994cd0855c0fc8afb7..24eaf0ec344d55027beda78e77a7436db7dc4b95 100644 --- a/drivers/cpufreq/cppc_cpufreq.c +++ b/drivers/cpufreq/cppc_cpufreq.c @@ -61,6 +61,8 @@ static struct cppc_workaround_oem_info wa_info[] = { } }; +static struct cpufreq_driver cppc_cpufreq_driver; + #ifdef CONFIG_ACPI_CPPC_CPUFREQ_FIE /* Frequency invariance support */ @@ -75,7 +77,6 @@ struct cppc_freq_invariance { static DEFINE_PER_CPU(struct cppc_freq_invariance, cppc_freq_inv); static struct kthread_worker *kworker_fie; -static struct cpufreq_driver cppc_cpufreq_driver; static unsigned int hisi_cppc_cpufreq_get_rate(unsigned int cpu); static int cppc_perf_from_fbctrs(struct cppc_cpudata *cpu_data, struct cppc_perf_fb_ctrs *fb_ctrs_t0, @@ -440,6 +441,14 @@ static unsigned int cppc_cpufreq_get_transition_delay_us(unsigned int cpu) } return cppc_get_transition_latency(cpu) / NSEC_PER_USEC; } +#else +static unsigned int cppc_cpufreq_get_transition_delay_us(unsigned int cpu) +{ + return cppc_get_transition_latency(cpu) / NSEC_PER_USEC; +} +#endif + +#if defined(CONFIG_ARM64) && defined(CONFIG_ENERGY_MODEL) static DEFINE_PER_CPU(unsigned int, efficiency_class); static void cppc_cpufreq_register_em(struct cpufreq_policy *policy); @@ -620,21 +629,12 @@ static void cppc_cpufreq_register_em(struct cpufreq_policy *policy) } #else - -static unsigned int cppc_cpufreq_get_transition_delay_us(unsigned int cpu) -{ - return cppc_get_transition_latency(cpu) / NSEC_PER_USEC; -} static int populate_efficiency_class(void) { return 0; } -static void cppc_cpufreq_register_em(struct cpufreq_policy *policy) -{ -} #endif - static struct cppc_cpudata *cppc_cpufreq_get_cpu_data(unsigned int cpu) { struct cppc_cpudata *cpu_data; diff --git a/drivers/cpufreq/mediatek-cpufreq.c b/drivers/cpufreq/mediatek-cpufreq.c index 866163883b48dd6dab42bb231e3b93be47c9d19d..37a1eb20f5ba6dff4634bcf52172b74b2687d3b5 100644 --- a/drivers/cpufreq/mediatek-cpufreq.c +++ b/drivers/cpufreq/mediatek-cpufreq.c @@ -8,18 +8,22 @@ #include #include #include +#include #include #include +#include #include #include #include -#include -#include -#define MIN_VOLT_SHIFT (100000) -#define MAX_VOLT_SHIFT (200000) -#define MAX_VOLT_LIMIT (1150000) -#define VOLT_TOL (10000) +struct mtk_cpufreq_platform_data { + int min_volt_shift; + int max_volt_shift; + int proc_max_volt; + int sram_min_volt; + int sram_max_volt; + bool ccifreq_supported; +}; /* * The struct mtk_cpu_dvfs_info holds necessary information for doing CPU DVFS @@ -35,6 +39,7 @@ struct mtk_cpu_dvfs_info { struct cpumask cpus; struct device *cpu_dev; + struct device *cci_dev; struct regulator *proc_reg; struct regulator *sram_reg; struct clk *cpu_clk; @@ -42,8 +47,20 @@ struct mtk_cpu_dvfs_info { struct list_head list_head; int intermediate_voltage; bool need_voltage_tracking; + int vproc_on_boot; + int pre_vproc; + /* Avoid race condition for regulators between notify and policy */ + struct mutex reg_lock; + struct notifier_block opp_nb; + unsigned int opp_cpu; + unsigned long current_freq; + const struct mtk_cpufreq_platform_data *soc_data; + int vtrack_max; + bool ccifreq_bound; }; +static struct platform_device *cpufreq_pdev; + static LIST_HEAD(dvfs_info_list); static struct mtk_cpu_dvfs_info *mtk_cpu_dvfs_info_lookup(int cpu) @@ -61,142 +78,123 @@ static struct mtk_cpu_dvfs_info *mtk_cpu_dvfs_info_lookup(int cpu) static int mtk_cpufreq_voltage_tracking(struct mtk_cpu_dvfs_info *info, int new_vproc) { + const struct mtk_cpufreq_platform_data *soc_data = info->soc_data; struct regulator *proc_reg = info->proc_reg; struct regulator *sram_reg = info->sram_reg; - int old_vproc, old_vsram, new_vsram, vsram, vproc, ret; - - old_vproc = regulator_get_voltage(proc_reg); - if (old_vproc < 0) { - pr_err("%s: invalid Vproc value: %d\n", __func__, old_vproc); - return old_vproc; - } - /* Vsram should not exceed the maximum allowed voltage of SoC. */ - new_vsram = min(new_vproc + MIN_VOLT_SHIFT, MAX_VOLT_LIMIT); - - if (old_vproc < new_vproc) { - /* - * When scaling up voltages, Vsram and Vproc scale up step - * by step. At each step, set Vsram to (Vproc + 200mV) first, - * then set Vproc to (Vsram - 100mV). - * Keep doing it until Vsram and Vproc hit target voltages. - */ - do { - old_vsram = regulator_get_voltage(sram_reg); - if (old_vsram < 0) { - pr_err("%s: invalid Vsram value: %d\n", - __func__, old_vsram); - return old_vsram; - } - old_vproc = regulator_get_voltage(proc_reg); - if (old_vproc < 0) { - pr_err("%s: invalid Vproc value: %d\n", - __func__, old_vproc); - return old_vproc; - } - - vsram = min(new_vsram, old_vproc + MAX_VOLT_SHIFT); + int pre_vproc, pre_vsram, new_vsram, vsram, vproc, ret; + int retry = info->vtrack_max; + + pre_vproc = regulator_get_voltage(proc_reg); + if (pre_vproc < 0) { + dev_err(info->cpu_dev, + "invalid Vproc value: %d\n", pre_vproc); + return pre_vproc; + } - if (vsram + VOLT_TOL >= MAX_VOLT_LIMIT) { - vsram = MAX_VOLT_LIMIT; + pre_vsram = regulator_get_voltage(sram_reg); + if (pre_vsram < 0) { + dev_err(info->cpu_dev, "invalid Vsram value: %d\n", pre_vsram); + return pre_vsram; + } - /* - * If the target Vsram hits the maximum voltage, - * try to set the exact voltage value first. - */ - ret = regulator_set_voltage(sram_reg, vsram, - vsram); - if (ret) - ret = regulator_set_voltage(sram_reg, - vsram - VOLT_TOL, - vsram); + new_vsram = clamp(new_vproc + soc_data->min_volt_shift, + soc_data->sram_min_volt, soc_data->sram_max_volt); - vproc = new_vproc; - } else { - ret = regulator_set_voltage(sram_reg, vsram, - vsram + VOLT_TOL); + do { + if (pre_vproc <= new_vproc) { + vsram = clamp(pre_vproc + soc_data->max_volt_shift, + soc_data->sram_min_volt, new_vsram); + ret = regulator_set_voltage(sram_reg, vsram, + soc_data->sram_max_volt); - vproc = vsram - MIN_VOLT_SHIFT; - } if (ret) return ret; + if (vsram == soc_data->sram_max_volt || + new_vsram == soc_data->sram_min_volt) + vproc = new_vproc; + else + vproc = vsram - soc_data->min_volt_shift; + ret = regulator_set_voltage(proc_reg, vproc, - vproc + VOLT_TOL); + soc_data->proc_max_volt); if (ret) { - regulator_set_voltage(sram_reg, old_vsram, - old_vsram); + regulator_set_voltage(sram_reg, pre_vsram, + soc_data->sram_max_volt); return ret; } - } while (vproc < new_vproc || vsram < new_vsram); - } else if (old_vproc > new_vproc) { - /* - * When scaling down voltages, Vsram and Vproc scale down step - * by step. At each step, set Vproc to (Vsram - 200mV) first, - * then set Vproc to (Vproc + 100mV). - * Keep doing it until Vsram and Vproc hit target voltages. - */ - do { - old_vproc = regulator_get_voltage(proc_reg); - if (old_vproc < 0) { - pr_err("%s: invalid Vproc value: %d\n", - __func__, old_vproc); - return old_vproc; - } - old_vsram = regulator_get_voltage(sram_reg); - if (old_vsram < 0) { - pr_err("%s: invalid Vsram value: %d\n", - __func__, old_vsram); - return old_vsram; - } - - vproc = max(new_vproc, old_vsram - MAX_VOLT_SHIFT); + } else if (pre_vproc > new_vproc) { + vproc = max(new_vproc, + pre_vsram - soc_data->max_volt_shift); ret = regulator_set_voltage(proc_reg, vproc, - vproc + VOLT_TOL); + soc_data->proc_max_volt); if (ret) return ret; if (vproc == new_vproc) vsram = new_vsram; else - vsram = max(new_vsram, vproc + MIN_VOLT_SHIFT); - - if (vsram + VOLT_TOL >= MAX_VOLT_LIMIT) { - vsram = MAX_VOLT_LIMIT; - - /* - * If the target Vsram hits the maximum voltage, - * try to set the exact voltage value first. - */ - ret = regulator_set_voltage(sram_reg, vsram, - vsram); - if (ret) - ret = regulator_set_voltage(sram_reg, - vsram - VOLT_TOL, - vsram); - } else { - ret = regulator_set_voltage(sram_reg, vsram, - vsram + VOLT_TOL); - } + vsram = max(new_vsram, + vproc + soc_data->min_volt_shift); + ret = regulator_set_voltage(sram_reg, vsram, + soc_data->sram_max_volt); if (ret) { - regulator_set_voltage(proc_reg, old_vproc, - old_vproc); + regulator_set_voltage(proc_reg, pre_vproc, + soc_data->proc_max_volt); return ret; } - } while (vproc > new_vproc + VOLT_TOL || - vsram > new_vsram + VOLT_TOL); - } + } + + pre_vproc = vproc; + pre_vsram = vsram; + + if (--retry < 0) { + dev_err(info->cpu_dev, + "over loop count, failed to set voltage\n"); + return -EINVAL; + } + } while (vproc != new_vproc || vsram != new_vsram); return 0; } static int mtk_cpufreq_set_voltage(struct mtk_cpu_dvfs_info *info, int vproc) { + const struct mtk_cpufreq_platform_data *soc_data = info->soc_data; + int ret; + if (info->need_voltage_tracking) - return mtk_cpufreq_voltage_tracking(info, vproc); + ret = mtk_cpufreq_voltage_tracking(info, vproc); else - return regulator_set_voltage(info->proc_reg, vproc, - vproc + VOLT_TOL); + ret = regulator_set_voltage(info->proc_reg, vproc, + soc_data->proc_max_volt); + if (!ret) + info->pre_vproc = vproc; + + return ret; +} + +static bool is_ccifreq_ready(struct mtk_cpu_dvfs_info *info) +{ + struct device_link *sup_link; + + if (info->ccifreq_bound) + return true; + + sup_link = device_link_add(info->cpu_dev, info->cci_dev, + DL_FLAG_AUTOREMOVE_CONSUMER); + if (!sup_link) { + dev_err(info->cpu_dev, "cpu%d: sup_link is NULL\n", info->opp_cpu); + return false; + } + + if (sup_link->supplier->links.status != DL_DEV_DRIVER_BOUND) + return false; + + info->ccifreq_bound = true; + + return true; } static int mtk_cpufreq_set_target(struct cpufreq_policy *policy, @@ -208,219 +206,367 @@ static int mtk_cpufreq_set_target(struct cpufreq_policy *policy, struct mtk_cpu_dvfs_info *info = policy->driver_data; struct device *cpu_dev = info->cpu_dev; struct dev_pm_opp *opp; - long freq_hz, old_freq_hz; - int vproc, old_vproc, inter_vproc, target_vproc, ret; + long freq_hz, pre_freq_hz; + int vproc, pre_vproc, inter_vproc, target_vproc, ret; inter_vproc = info->intermediate_voltage; - old_freq_hz = clk_get_rate(cpu_clk); - old_vproc = regulator_get_voltage(info->proc_reg); - if (old_vproc < 0) { - pr_err("%s: invalid Vproc value: %d\n", __func__, old_vproc); - return old_vproc; + pre_freq_hz = clk_get_rate(cpu_clk); + + mutex_lock(&info->reg_lock); + + if (unlikely(info->pre_vproc <= 0)) + pre_vproc = regulator_get_voltage(info->proc_reg); + else + pre_vproc = info->pre_vproc; + + if (pre_vproc < 0) { + dev_err(cpu_dev, "invalid Vproc value: %d\n", pre_vproc); + ret = pre_vproc; + goto out; } freq_hz = freq_table[index].frequency * 1000; opp = dev_pm_opp_find_freq_ceil(cpu_dev, &freq_hz); if (IS_ERR(opp)) { - pr_err("cpu%d: failed to find OPP for %ld\n", - policy->cpu, freq_hz); - return PTR_ERR(opp); + dev_err(cpu_dev, "cpu%d: failed to find OPP for %ld\n", + policy->cpu, freq_hz); + ret = PTR_ERR(opp); + goto out; } vproc = dev_pm_opp_get_voltage(opp); dev_pm_opp_put(opp); + /* + * If MediaTek cci is supported but is not ready, we will use the value + * of max(target cpu voltage, booting voltage) to prevent high freqeuncy + * low voltage crash. + */ + if (info->soc_data->ccifreq_supported && !is_ccifreq_ready(info)) + vproc = max(vproc, info->vproc_on_boot); + /* * If the new voltage or the intermediate voltage is higher than the * current voltage, scale up voltage first. */ - target_vproc = (inter_vproc > vproc) ? inter_vproc : vproc; - if (old_vproc < target_vproc) { + target_vproc = max(inter_vproc, vproc); + if (pre_vproc <= target_vproc) { ret = mtk_cpufreq_set_voltage(info, target_vproc); if (ret) { - pr_err("cpu%d: failed to scale up voltage!\n", - policy->cpu); - mtk_cpufreq_set_voltage(info, old_vproc); - return ret; + dev_err(cpu_dev, + "cpu%d: failed to scale up voltage!\n", policy->cpu); + mtk_cpufreq_set_voltage(info, pre_vproc); + goto out; } } /* Reparent the CPU clock to intermediate clock. */ ret = clk_set_parent(cpu_clk, info->inter_clk); if (ret) { - pr_err("cpu%d: failed to re-parent cpu clock!\n", - policy->cpu); - mtk_cpufreq_set_voltage(info, old_vproc); - WARN_ON(1); - return ret; + dev_err(cpu_dev, + "cpu%d: failed to re-parent cpu clock!\n", policy->cpu); + mtk_cpufreq_set_voltage(info, pre_vproc); + goto out; } /* Set the original PLL to target rate. */ ret = clk_set_rate(armpll, freq_hz); if (ret) { - pr_err("cpu%d: failed to scale cpu clock rate!\n", - policy->cpu); + dev_err(cpu_dev, + "cpu%d: failed to scale cpu clock rate!\n", policy->cpu); clk_set_parent(cpu_clk, armpll); - mtk_cpufreq_set_voltage(info, old_vproc); - return ret; + mtk_cpufreq_set_voltage(info, pre_vproc); + goto out; } /* Set parent of CPU clock back to the original PLL. */ ret = clk_set_parent(cpu_clk, armpll); if (ret) { - pr_err("cpu%d: failed to re-parent cpu clock!\n", - policy->cpu); + dev_err(cpu_dev, + "cpu%d: failed to re-parent cpu clock!\n", policy->cpu); mtk_cpufreq_set_voltage(info, inter_vproc); - WARN_ON(1); - return ret; + goto out; } /* * If the new voltage is lower than the intermediate voltage or the * original voltage, scale down to the new voltage. */ - if (vproc < inter_vproc || vproc < old_vproc) { + if (vproc < inter_vproc || vproc < pre_vproc) { ret = mtk_cpufreq_set_voltage(info, vproc); if (ret) { - pr_err("cpu%d: failed to scale down voltage!\n", - policy->cpu); + dev_err(cpu_dev, + "cpu%d: failed to scale down voltage!\n", policy->cpu); clk_set_parent(cpu_clk, info->inter_clk); - clk_set_rate(armpll, old_freq_hz); + clk_set_rate(armpll, pre_freq_hz); clk_set_parent(cpu_clk, armpll); - return ret; + goto out; } } - return 0; + info->current_freq = freq_hz; + +out: + mutex_unlock(&info->reg_lock); + + return ret; } #define DYNAMIC_POWER "dynamic-power-coefficient" +static int mtk_cpufreq_opp_notifier(struct notifier_block *nb, + unsigned long event, void *data) +{ + struct dev_pm_opp *opp = data; + struct dev_pm_opp *new_opp; + struct mtk_cpu_dvfs_info *info; + unsigned long freq, volt; + struct cpufreq_policy *policy; + int ret = 0; + + info = container_of(nb, struct mtk_cpu_dvfs_info, opp_nb); + + if (event == OPP_EVENT_ADJUST_VOLTAGE) { + freq = dev_pm_opp_get_freq(opp); + + mutex_lock(&info->reg_lock); + if (info->current_freq == freq) { + volt = dev_pm_opp_get_voltage(opp); + ret = mtk_cpufreq_set_voltage(info, volt); + if (ret) + dev_err(info->cpu_dev, + "failed to scale voltage: %d\n", ret); + } + mutex_unlock(&info->reg_lock); + } else if (event == OPP_EVENT_DISABLE) { + freq = dev_pm_opp_get_freq(opp); + + /* case of current opp item is disabled */ + if (info->current_freq == freq) { + freq = 1; + new_opp = dev_pm_opp_find_freq_ceil(info->cpu_dev, + &freq); + if (IS_ERR(new_opp)) { + dev_err(info->cpu_dev, + "all opp items are disabled\n"); + ret = PTR_ERR(new_opp); + return notifier_from_errno(ret); + } + + dev_pm_opp_put(new_opp); + policy = cpufreq_cpu_get(info->opp_cpu); + if (policy) { + cpufreq_driver_target(policy, freq / 1000, + CPUFREQ_RELATION_L); + cpufreq_cpu_put(policy); + } + } + } + + return notifier_from_errno(ret); +} + +static struct device *of_get_cci(struct device *cpu_dev) +{ + struct device_node *np; + struct platform_device *pdev; + + np = of_parse_phandle(cpu_dev->of_node, "mediatek,cci", 0); + if (IS_ERR_OR_NULL(np)) + return NULL; + + pdev = of_find_device_by_node(np); + of_node_put(np); + if (IS_ERR_OR_NULL(pdev)) + return NULL; + + return &pdev->dev; +} + static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu) { struct device *cpu_dev; - struct regulator *proc_reg = ERR_PTR(-ENODEV); - struct regulator *sram_reg = ERR_PTR(-ENODEV); - struct clk *cpu_clk = ERR_PTR(-ENODEV); - struct clk *inter_clk = ERR_PTR(-ENODEV); struct dev_pm_opp *opp; unsigned long rate; int ret; cpu_dev = get_cpu_device(cpu); if (!cpu_dev) { - pr_err("failed to get cpu%d device\n", cpu); + dev_err(cpu_dev, "failed to get cpu%d device\n", cpu); return -ENODEV; } + info->cpu_dev = cpu_dev; - cpu_clk = clk_get(cpu_dev, "cpu"); - if (IS_ERR(cpu_clk)) { - if (PTR_ERR(cpu_clk) == -EPROBE_DEFER) - pr_warn("cpu clk for cpu%d not ready, retry.\n", cpu); - else - pr_err("failed to get cpu clk for cpu%d\n", cpu); - - ret = PTR_ERR(cpu_clk); - return ret; + info->ccifreq_bound = false; + if (info->soc_data->ccifreq_supported) { + info->cci_dev = of_get_cci(info->cpu_dev); + if (IS_ERR_OR_NULL(info->cci_dev)) { + ret = PTR_ERR(info->cci_dev); + dev_err(cpu_dev, "cpu%d: failed to get cci device\n", cpu); + return -ENODEV; + } } - inter_clk = clk_get(cpu_dev, "intermediate"); - if (IS_ERR(inter_clk)) { - if (PTR_ERR(inter_clk) == -EPROBE_DEFER) - pr_warn("intermediate clk for cpu%d not ready, retry.\n", - cpu); - else - pr_err("failed to get intermediate clk for cpu%d\n", - cpu); + info->cpu_clk = clk_get(cpu_dev, "cpu"); + if (IS_ERR(info->cpu_clk)) { + ret = PTR_ERR(info->cpu_clk); + return dev_err_probe(cpu_dev, ret, + "cpu%d: failed to get cpu clk\n", cpu); + } - ret = PTR_ERR(inter_clk); + info->inter_clk = clk_get(cpu_dev, "intermediate"); + if (IS_ERR(info->inter_clk)) { + ret = PTR_ERR(info->inter_clk); + dev_err_probe(cpu_dev, ret, + "cpu%d: failed to get intermediate clk\n", cpu); goto out_free_resources; } - proc_reg = regulator_get_optional(cpu_dev, "proc"); - if (IS_ERR(proc_reg)) { - if (PTR_ERR(proc_reg) == -EPROBE_DEFER) - pr_warn("proc regulator for cpu%d not ready, retry.\n", - cpu); - else - pr_err("failed to get proc regulator for cpu%d\n", - cpu); + info->proc_reg = regulator_get_optional(cpu_dev, "proc"); + if (IS_ERR(info->proc_reg)) { + ret = PTR_ERR(info->proc_reg); + dev_err_probe(cpu_dev, ret, + "cpu%d: failed to get proc regulator\n", cpu); + goto out_free_resources; + } - ret = PTR_ERR(proc_reg); + ret = regulator_enable(info->proc_reg); + if (ret) { + dev_warn(cpu_dev, "cpu%d: failed to enable vproc\n", cpu); goto out_free_resources; } /* Both presence and absence of sram regulator are valid cases. */ - sram_reg = regulator_get_exclusive(cpu_dev, "sram"); + info->sram_reg = regulator_get_optional(cpu_dev, "sram"); + if (IS_ERR(info->sram_reg)) + info->sram_reg = NULL; + else { + ret = regulator_enable(info->sram_reg); + if (ret) { + dev_warn(cpu_dev, "cpu%d: failed to enable vsram\n", cpu); + goto out_free_resources; + } + } /* Get OPP-sharing information from "operating-points-v2" bindings */ ret = dev_pm_opp_of_get_sharing_cpus(cpu_dev, &info->cpus); if (ret) { - pr_err("failed to get OPP-sharing information for cpu%d\n", - cpu); + dev_err(cpu_dev, + "cpu%d: failed to get OPP-sharing information\n", cpu); goto out_free_resources; } ret = dev_pm_opp_of_cpumask_add_table(&info->cpus); if (ret) { - pr_warn("no OPP table for cpu%d\n", cpu); + dev_warn(cpu_dev, "cpu%d: no OPP table\n", cpu); goto out_free_resources; } + ret = clk_prepare_enable(info->cpu_clk); + if (ret) + goto out_free_opp_table; + + ret = clk_prepare_enable(info->inter_clk); + if (ret) + goto out_disable_mux_clock; + + if (info->soc_data->ccifreq_supported) { + info->vproc_on_boot = regulator_get_voltage(info->proc_reg); + if (info->vproc_on_boot < 0) { + dev_err(info->cpu_dev, + "invalid Vproc value: %d\n", info->vproc_on_boot); + goto out_disable_inter_clock; + } + } + /* Search a safe voltage for intermediate frequency. */ - rate = clk_get_rate(inter_clk); + rate = clk_get_rate(info->inter_clk); opp = dev_pm_opp_find_freq_ceil(cpu_dev, &rate); if (IS_ERR(opp)) { - pr_err("failed to get intermediate opp for cpu%d\n", cpu); + dev_err(cpu_dev, "cpu%d: failed to get intermediate opp\n", cpu); ret = PTR_ERR(opp); - goto out_free_opp_table; + goto out_disable_inter_clock; } info->intermediate_voltage = dev_pm_opp_get_voltage(opp); dev_pm_opp_put(opp); - info->cpu_dev = cpu_dev; - info->proc_reg = proc_reg; - info->sram_reg = IS_ERR(sram_reg) ? NULL : sram_reg; - info->cpu_clk = cpu_clk; - info->inter_clk = inter_clk; + mutex_init(&info->reg_lock); + info->current_freq = clk_get_rate(info->cpu_clk); + + info->opp_cpu = cpu; + info->opp_nb.notifier_call = mtk_cpufreq_opp_notifier; + ret = dev_pm_opp_register_notifier(cpu_dev, &info->opp_nb); + if (ret) { + dev_err(cpu_dev, "cpu%d: failed to register opp notifier\n", cpu); + goto out_disable_inter_clock; + } /* * If SRAM regulator is present, software "voltage tracking" is needed * for this CPU power domain. */ - info->need_voltage_tracking = !IS_ERR(sram_reg); + info->need_voltage_tracking = (info->sram_reg != NULL); + + /* + * We assume min voltage is 0 and tracking target voltage using + * min_volt_shift for each iteration. + * The vtrack_max is 3 times of expeted iteration count. + */ + info->vtrack_max = 3 * DIV_ROUND_UP(max(info->soc_data->sram_max_volt, + info->soc_data->proc_max_volt), + info->soc_data->min_volt_shift); return 0; +out_disable_inter_clock: + clk_disable_unprepare(info->inter_clk); + +out_disable_mux_clock: + clk_disable_unprepare(info->cpu_clk); + out_free_opp_table: dev_pm_opp_of_cpumask_remove_table(&info->cpus); out_free_resources: - if (!IS_ERR(proc_reg)) - regulator_put(proc_reg); - if (!IS_ERR(sram_reg)) - regulator_put(sram_reg); - if (!IS_ERR(cpu_clk)) - clk_put(cpu_clk); - if (!IS_ERR(inter_clk)) - clk_put(inter_clk); + if (regulator_is_enabled(info->proc_reg)) + regulator_disable(info->proc_reg); + if (info->sram_reg && regulator_is_enabled(info->sram_reg)) + regulator_disable(info->sram_reg); + + if (!IS_ERR(info->proc_reg)) + regulator_put(info->proc_reg); + if (!IS_ERR(info->sram_reg)) + regulator_put(info->sram_reg); + if (!IS_ERR(info->cpu_clk)) + clk_put(info->cpu_clk); + if (!IS_ERR(info->inter_clk)) + clk_put(info->inter_clk); return ret; } static void mtk_cpu_dvfs_info_release(struct mtk_cpu_dvfs_info *info) { - if (!IS_ERR(info->proc_reg)) + if (!IS_ERR(info->proc_reg)) { + regulator_disable(info->proc_reg); regulator_put(info->proc_reg); - if (!IS_ERR(info->sram_reg)) + } + if (!IS_ERR(info->sram_reg)) { + regulator_disable(info->sram_reg); regulator_put(info->sram_reg); - if (!IS_ERR(info->cpu_clk)) + } + if (!IS_ERR(info->cpu_clk)) { + clk_disable_unprepare(info->cpu_clk); clk_put(info->cpu_clk); - if (!IS_ERR(info->inter_clk)) + } + if (!IS_ERR(info->inter_clk)) { + clk_disable_unprepare(info->inter_clk); clk_put(info->inter_clk); + } dev_pm_opp_of_cpumask_remove_table(&info->cpus); + dev_pm_opp_unregister_notifier(info->cpu_dev, &info->opp_nb); } static int mtk_cpufreq_init(struct cpufreq_policy *policy) @@ -432,14 +578,15 @@ static int mtk_cpufreq_init(struct cpufreq_policy *policy) info = mtk_cpu_dvfs_info_lookup(policy->cpu); if (!info) { pr_err("dvfs info for cpu%d is not initialized.\n", - policy->cpu); + policy->cpu); return -EINVAL; } ret = dev_pm_opp_init_cpufreq_table(info->cpu_dev, &freq_table); if (ret) { - pr_err("failed to init cpufreq table for cpu%d: %d\n", - policy->cpu, ret); + dev_err(info->cpu_dev, + "failed to init cpufreq table for cpu%d: %d\n", + policy->cpu, ret); return ret; } @@ -476,9 +623,17 @@ static struct cpufreq_driver mtk_cpufreq_driver = { static int mtk_cpufreq_probe(struct platform_device *pdev) { + const struct mtk_cpufreq_platform_data *data; struct mtk_cpu_dvfs_info *info, *tmp; int cpu, ret; + data = dev_get_platdata(&pdev->dev); + if (!data) { + dev_err(&pdev->dev, + "failed to get mtk cpufreq platform data\n"); + return -ENODEV; + } + for_each_possible_cpu(cpu) { info = mtk_cpu_dvfs_info_lookup(cpu); if (info) @@ -490,6 +645,7 @@ static int mtk_cpufreq_probe(struct platform_device *pdev) goto release_dvfs_info_list; } + info->soc_data = data; ret = mtk_cpu_dvfs_info_init(info, cpu); if (ret) { dev_err(&pdev->dev, @@ -525,20 +681,47 @@ static struct platform_driver mtk_cpufreq_platdrv = { .probe = mtk_cpufreq_probe, }; +static const struct mtk_cpufreq_platform_data mt2701_platform_data = { + .min_volt_shift = 100000, + .max_volt_shift = 200000, + .proc_max_volt = 1150000, + .sram_min_volt = 0, + .sram_max_volt = 1150000, + .ccifreq_supported = false, +}; + +static const struct mtk_cpufreq_platform_data mt8183_platform_data = { + .min_volt_shift = 100000, + .max_volt_shift = 200000, + .proc_max_volt = 1150000, + .sram_min_volt = 0, + .sram_max_volt = 1150000, + .ccifreq_supported = true, +}; + +static const struct mtk_cpufreq_platform_data mt8186_platform_data = { + .min_volt_shift = 100000, + .max_volt_shift = 250000, + .proc_max_volt = 1118750, + .sram_min_volt = 850000, + .sram_max_volt = 1118750, + .ccifreq_supported = true, +}; + /* List of machines supported by this driver */ static const struct of_device_id mtk_cpufreq_machines[] __initconst = { - { .compatible = "mediatek,mt2701", }, - { .compatible = "mediatek,mt2712", }, - { .compatible = "mediatek,mt7622", }, - { .compatible = "mediatek,mt7623", }, - { .compatible = "mediatek,mt8167", }, - { .compatible = "mediatek,mt817x", }, - { .compatible = "mediatek,mt8173", }, - { .compatible = "mediatek,mt8176", }, - { .compatible = "mediatek,mt8183", }, - { .compatible = "mediatek,mt8365", }, - { .compatible = "mediatek,mt8516", }, - + { .compatible = "mediatek,mt2701", .data = &mt2701_platform_data }, + { .compatible = "mediatek,mt2712", .data = &mt2701_platform_data }, + { .compatible = "mediatek,mt7622", .data = &mt2701_platform_data }, + { .compatible = "mediatek,mt7623", .data = &mt2701_platform_data }, + { .compatible = "mediatek,mt8167", .data = &mt2701_platform_data }, + { .compatible = "mediatek,mt817x", .data = &mt2701_platform_data }, + { .compatible = "mediatek,mt8173", .data = &mt2701_platform_data }, + { .compatible = "mediatek,mt8176", .data = &mt2701_platform_data }, + { .compatible = "mediatek,mt8183", .data = &mt8183_platform_data }, + { .compatible = "mediatek,mt8186", .data = &mt8186_platform_data }, + { .compatible = "mediatek,mt8365", .data = &mt2701_platform_data }, + { .compatible = "mediatek,mt8516", .data = &mt2701_platform_data }, { } }; MODULE_DEVICE_TABLE(of, mtk_cpufreq_machines); @@ -547,7 +730,7 @@ static int __init mtk_cpufreq_driver_init(void) { struct device_node *np; const struct of_device_id *match; - struct platform_device *pdev; + const struct mtk_cpufreq_platform_data *data; int err; np = of_find_node_by_path("/"); @@ -560,6 +743,7 @@ static int __init mtk_cpufreq_driver_init(void) pr_debug("Machine is not compatible with mtk-cpufreq\n"); return -ENODEV; } + data = match->data; err = platform_driver_register(&mtk_cpufreq_platdrv); if (err) @@ -571,16 +755,24 @@ static int __init mtk_cpufreq_driver_init(void) * and the device registration codes are put here to handle defer * probing. */ - pdev = platform_device_register_simple("mtk-cpufreq", -1, NULL, 0); - if (IS_ERR(pdev)) { + cpufreq_pdev = platform_device_register_data(NULL, "mtk-cpufreq", -1, + data, sizeof(*data)); + if (IS_ERR(cpufreq_pdev)) { pr_err("failed to register mtk-cpufreq platform device\n"); platform_driver_unregister(&mtk_cpufreq_platdrv); - return PTR_ERR(pdev); + return PTR_ERR(cpufreq_pdev); } return 0; } -device_initcall(mtk_cpufreq_driver_init); +module_init(mtk_cpufreq_driver_init) + +static void __exit mtk_cpufreq_driver_exit(void) +{ + platform_device_unregister(cpufreq_pdev); + platform_driver_unregister(&mtk_cpufreq_platdrv); +} +module_exit(mtk_cpufreq_driver_exit) MODULE_DESCRIPTION("MediaTek CPUFreq driver"); MODULE_AUTHOR("Pi-Cheng Chen "); diff --git a/drivers/cpufreq/tegra194-cpufreq.c b/drivers/cpufreq/tegra194-cpufreq.c index ac381db25dbe2a1e64106ecd0fd20a67c18f9581..2a6a98764a8ca6977cbc630899cc331b9b680b8f 100644 --- a/drivers/cpufreq/tegra194-cpufreq.c +++ b/drivers/cpufreq/tegra194-cpufreq.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved + * Copyright (c) 2020 - 2022, NVIDIA CORPORATION. All rights reserved */ #include @@ -24,6 +24,17 @@ #define CPUFREQ_TBL_STEP_HZ (50 * KHZ * KHZ) #define MAX_CNT ~0U +#define NDIV_MASK 0x1FF + +#define CORE_OFFSET(cpu) (cpu * 8) +#define CMU_CLKS_BASE 0x2000 +#define SCRATCH_FREQ_CORE_REG(data, cpu) (data->regs + CMU_CLKS_BASE + CORE_OFFSET(cpu)) + +#define MMCRAB_CLUSTER_BASE(cl) (0x30000 + (cl * 0x10000)) +#define CLUSTER_ACTMON_BASE(data, cl) \ + (data->regs + (MMCRAB_CLUSTER_BASE(cl) + data->soc->actmon_cntr_base)) +#define CORE_ACTMON_CNTR_REG(data, cl, cpu) (CLUSTER_ACTMON_BASE(data, cl) + CORE_OFFSET(cpu)) + /* cpufreq transisition latency */ #define TEGRA_CPUFREQ_TRANSITION_LATENCY (300 * 1000) /* unit in nanoseconds */ @@ -35,12 +46,6 @@ enum cluster { MAX_CLUSTERS, }; -struct tegra194_cpufreq_data { - void __iomem *regs; - size_t num_clusters; - struct cpufreq_frequency_table **tables; -}; - struct tegra_cpu_ctr { u32 cpu; u32 coreclk_cnt, last_coreclk_cnt; @@ -52,13 +57,127 @@ struct read_counters_work { struct tegra_cpu_ctr c; }; +struct tegra_cpufreq_ops { + void (*read_counters)(struct tegra_cpu_ctr *c); + void (*set_cpu_ndiv)(struct cpufreq_policy *policy, u64 ndiv); + void (*get_cpu_cluster_id)(u32 cpu, u32 *cpuid, u32 *clusterid); + int (*get_cpu_ndiv)(u32 cpu, u32 cpuid, u32 clusterid, u64 *ndiv); +}; + +struct tegra_cpufreq_soc { + struct tegra_cpufreq_ops *ops; + int maxcpus_per_cluster; + phys_addr_t actmon_cntr_base; +}; + +struct tegra194_cpufreq_data { + void __iomem *regs; + size_t num_clusters; + struct cpufreq_frequency_table **tables; + const struct tegra_cpufreq_soc *soc; +}; + static struct workqueue_struct *read_counters_wq; -static void get_cpu_cluster(void *cluster) +static void tegra_get_cpu_mpidr(void *mpidr) +{ + *((u64 *)mpidr) = read_cpuid_mpidr() & MPIDR_HWID_BITMASK; +} + +static void tegra234_get_cpu_cluster_id(u32 cpu, u32 *cpuid, u32 *clusterid) +{ + u64 mpidr; + + smp_call_function_single(cpu, tegra_get_cpu_mpidr, &mpidr, true); + + if (cpuid) + *cpuid = MPIDR_AFFINITY_LEVEL(mpidr, 1); + if (clusterid) + *clusterid = MPIDR_AFFINITY_LEVEL(mpidr, 2); +} + +static int tegra234_get_cpu_ndiv(u32 cpu, u32 cpuid, u32 clusterid, u64 *ndiv) { - u64 mpidr = read_cpuid_mpidr() & MPIDR_HWID_BITMASK; + struct tegra194_cpufreq_data *data = cpufreq_get_driver_data(); + void __iomem *freq_core_reg; + u64 mpidr_id; + + /* use physical id to get address of per core frequency register */ + mpidr_id = (clusterid * data->soc->maxcpus_per_cluster) + cpuid; + freq_core_reg = SCRATCH_FREQ_CORE_REG(data, mpidr_id); + + *ndiv = readl(freq_core_reg) & NDIV_MASK; + + return 0; +} - *((uint32_t *)cluster) = MPIDR_AFFINITY_LEVEL(mpidr, 1); +static void tegra234_set_cpu_ndiv(struct cpufreq_policy *policy, u64 ndiv) +{ + struct tegra194_cpufreq_data *data = cpufreq_get_driver_data(); + void __iomem *freq_core_reg; + u32 cpu, cpuid, clusterid; + u64 mpidr_id; + + for_each_cpu_and(cpu, policy->cpus, cpu_online_mask) { + data->soc->ops->get_cpu_cluster_id(cpu, &cpuid, &clusterid); + + /* use physical id to get address of per core frequency register */ + mpidr_id = (clusterid * data->soc->maxcpus_per_cluster) + cpuid; + freq_core_reg = SCRATCH_FREQ_CORE_REG(data, mpidr_id); + + writel(ndiv, freq_core_reg); + } +} + +/* + * This register provides access to two counter values with a single + * 64-bit read. The counter values are used to determine the average + * actual frequency a core has run at over a period of time. + * [63:32] PLLP counter: Counts at fixed frequency (408 MHz) + * [31:0] Core clock counter: Counts on every core clock cycle + */ +static void tegra234_read_counters(struct tegra_cpu_ctr *c) +{ + struct tegra194_cpufreq_data *data = cpufreq_get_driver_data(); + void __iomem *actmon_reg; + u32 cpuid, clusterid; + u64 val; + + data->soc->ops->get_cpu_cluster_id(c->cpu, &cpuid, &clusterid); + actmon_reg = CORE_ACTMON_CNTR_REG(data, clusterid, cpuid); + + val = readq(actmon_reg); + c->last_refclk_cnt = upper_32_bits(val); + c->last_coreclk_cnt = lower_32_bits(val); + udelay(US_DELAY); + val = readq(actmon_reg); + c->refclk_cnt = upper_32_bits(val); + c->coreclk_cnt = lower_32_bits(val); +} + +static struct tegra_cpufreq_ops tegra234_cpufreq_ops = { + .read_counters = tegra234_read_counters, + .get_cpu_cluster_id = tegra234_get_cpu_cluster_id, + .get_cpu_ndiv = tegra234_get_cpu_ndiv, + .set_cpu_ndiv = tegra234_set_cpu_ndiv, +}; + +const struct tegra_cpufreq_soc tegra234_cpufreq_soc = { + .ops = &tegra234_cpufreq_ops, + .actmon_cntr_base = 0x9000, + .maxcpus_per_cluster = 4, +}; + +static void tegra194_get_cpu_cluster_id(u32 cpu, u32 *cpuid, u32 *clusterid) +{ + u64 mpidr; + + smp_call_function_single(cpu, tegra_get_cpu_mpidr, &mpidr, true); + + if (cpuid) + *cpuid = MPIDR_AFFINITY_LEVEL(mpidr, 0); + if (clusterid) + *clusterid = MPIDR_AFFINITY_LEVEL(mpidr, 1); } /* @@ -85,11 +204,24 @@ static inline u32 map_ndiv_to_freq(struct mrq_cpu_ndiv_limits_response return nltbl->ref_clk_hz / KHZ * ndiv / (nltbl->pdiv * nltbl->mdiv); } +static void tegra194_read_counters(struct tegra_cpu_ctr *c) +{ + u64 val; + + val = read_freq_feedback(); + c->last_refclk_cnt = lower_32_bits(val); + c->last_coreclk_cnt = upper_32_bits(val); + udelay(US_DELAY); + val = read_freq_feedback(); + c->refclk_cnt = lower_32_bits(val); + c->coreclk_cnt = upper_32_bits(val); +} + static void tegra_read_counters(struct work_struct *work) { + struct tegra194_cpufreq_data *data = cpufreq_get_driver_data(); struct read_counters_work *read_counters_work; struct tegra_cpu_ctr *c; - u64 val; /* * ref_clk_counter(32 bit counter) runs on constant clk, @@ -107,13 +239,7 @@ static void tegra_read_counters(struct work_struct *work) work); c = &read_counters_work->c; - val = read_freq_feedback(); - c->last_refclk_cnt = lower_32_bits(val); - c->last_coreclk_cnt = upper_32_bits(val); - udelay(US_DELAY); - val = read_freq_feedback(); - c->refclk_cnt = lower_32_bits(val); - c->coreclk_cnt = upper_32_bits(val); + data->soc->ops->read_counters(c); } /* @@ -177,7 +303,7 @@ static unsigned int tegra194_calculate_speed(u32 cpu) return (rate_mhz * KHZ); /* in KHz */ } -static void get_cpu_ndiv(void *ndiv) +static void tegra194_get_cpu_ndiv_sysreg(void *ndiv) { u64 ndiv_val; @@ -186,30 +312,43 @@ static void get_cpu_ndiv(void *ndiv) *(u64 *)ndiv = ndiv_val; } -static void set_cpu_ndiv(void *data) +static int tegra194_get_cpu_ndiv(u32 cpu, u32 cpuid, u32 clusterid, u64 *ndiv) +{ + int ret; + + ret = smp_call_function_single(cpu, tegra194_get_cpu_ndiv_sysreg, &ndiv, true); + + return ret; +} + +static void tegra194_set_cpu_ndiv_sysreg(void *data) { - struct cpufreq_frequency_table *tbl = data; - u64 ndiv_val = (u64)tbl->driver_data; + u64 ndiv_val = *(u64 *)data; asm volatile("msr s3_0_c15_c0_4, %0" : : "r" (ndiv_val)); } +static void tegra194_set_cpu_ndiv(struct cpufreq_policy *policy, u64 ndiv) +{ + on_each_cpu_mask(policy->cpus, tegra194_set_cpu_ndiv_sysreg, &ndiv, true); +} + static unsigned int tegra194_get_speed(u32 cpu) { struct tegra194_cpufreq_data *data = cpufreq_get_driver_data(); struct cpufreq_frequency_table *pos; + u32 cpuid, clusterid; unsigned int rate; u64 ndiv; int ret; - u32 cl; - smp_call_function_single(cpu, get_cpu_cluster, &cl, true); + data->soc->ops->get_cpu_cluster_id(cpu, &cpuid, &clusterid); /* reconstruct actual cpu freq using counters */ rate = tegra194_calculate_speed(cpu); /* get last written ndiv value */ - ret = smp_call_function_single(cpu, get_cpu_ndiv, &ndiv, true); + ret = data->soc->ops->get_cpu_ndiv(cpu, cpuid, clusterid, &ndiv); if (WARN_ON_ONCE(ret)) return rate; @@ -219,7 +358,7 @@ static unsigned int tegra194_get_speed(u32 cpu) * to the last written ndiv value from freq_table. This is * done to return consistent value. */ - cpufreq_for_each_valid_entry(pos, data->tables[cl]) { + cpufreq_for_each_valid_entry(pos, data->tables[clusterid]) { if (pos->driver_data != ndiv) continue; @@ -237,19 +376,22 @@ static unsigned int tegra194_get_speed(u32 cpu) static int tegra194_cpufreq_init(struct cpufreq_policy *policy) { struct tegra194_cpufreq_data *data = cpufreq_get_driver_data(); - u32 cpu; - u32 cl; + int maxcpus_per_cluster = data->soc->maxcpus_per_cluster; + u32 start_cpu, cpu; + u32 clusterid; - smp_call_function_single(policy->cpu, get_cpu_cluster, &cl, true); + data->soc->ops->get_cpu_cluster_id(policy->cpu, NULL, &clusterid); - if (cl >= data->num_clusters || !data->tables[cl]) + if (clusterid >= data->num_clusters || !data->tables[clusterid]) return -EINVAL; + start_cpu = rounddown(policy->cpu, maxcpus_per_cluster); /* set same policy for all cpus in a cluster */ - for (cpu = (cl * 2); cpu < ((cl + 1) * 2); cpu++) - cpumask_set_cpu(cpu, policy->cpus); - - policy->freq_table = data->tables[cl]; + for (cpu = start_cpu; cpu < (start_cpu + maxcpus_per_cluster); cpu++) { + if (cpu_possible(cpu)) + cpumask_set_cpu(cpu, policy->cpus); + } + policy->freq_table = data->tables[clusterid]; policy->cpuinfo.transition_latency = TEGRA_CPUFREQ_TRANSITION_LATENCY; return 0; @@ -259,13 +401,14 @@ static int tegra194_cpufreq_set_target(struct cpufreq_policy *policy, unsigned int index) { struct cpufreq_frequency_table *tbl = policy->freq_table + index; + struct tegra194_cpufreq_data *data = cpufreq_get_driver_data(); /* * Each core writes frequency in per core register. Then both cores * in a cluster run at same frequency which is the maximum frequency * request out of the values requested by both cores in that cluster. */ - on_each_cpu_mask(policy->cpus, set_cpu_ndiv, tbl, true); + data->soc->ops->set_cpu_ndiv(policy, (u64)tbl->driver_data); return 0; } @@ -280,6 +423,18 @@ static struct cpufreq_driver tegra194_cpufreq_driver = { .attr = cpufreq_generic_attr, }; +static struct tegra_cpufreq_ops tegra194_cpufreq_ops = { + .read_counters = tegra194_read_counters, + .get_cpu_cluster_id = tegra194_get_cpu_cluster_id, + .get_cpu_ndiv = tegra194_get_cpu_ndiv, + .set_cpu_ndiv = tegra194_set_cpu_ndiv, +}; + +const struct tegra_cpufreq_soc tegra194_cpufreq_soc = { + .ops = &tegra194_cpufreq_ops, + .maxcpus_per_cluster = 2, +}; + static void tegra194_cpufreq_free_resources(void) { destroy_workqueue(read_counters_wq); @@ -359,6 +514,7 @@ init_freq_table(struct platform_device *pdev, struct tegra_bpmp *bpmp, static int tegra194_cpufreq_probe(struct platform_device *pdev) { + const struct tegra_cpufreq_soc *soc; struct tegra194_cpufreq_data *data; struct tegra_bpmp *bpmp; int err, i; @@ -367,12 +523,28 @@ static int tegra194_cpufreq_probe(struct platform_device *pdev) if (!data) return -ENOMEM; + soc = of_device_get_match_data(&pdev->dev); + + if (soc->ops && soc->maxcpus_per_cluster) { + data->soc = soc; + } else { + dev_err(&pdev->dev, "soc data missing\n"); + return -EINVAL; + } + data->num_clusters = MAX_CLUSTERS; data->tables = devm_kcalloc(&pdev->dev, data->num_clusters, sizeof(*data->tables), GFP_KERNEL); if (!data->tables) return -ENOMEM; + if (soc->actmon_cntr_base) { + /* mmio registers are used for frequency request and re-construction */ + data->regs = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(data->regs)) + return PTR_ERR(data->regs); + } + platform_set_drvdata(pdev, data); bpmp = tegra_bpmp_get(&pdev->dev); @@ -416,10 +588,10 @@ static int tegra194_cpufreq_remove(struct platform_device *pdev) } static const struct of_device_id tegra194_cpufreq_of_match[] = { - { .compatible = "nvidia,tegra194-ccplex", }, + { .compatible = "nvidia,tegra194-ccplex", .data = &tegra194_cpufreq_soc }, + { .compatible = "nvidia,tegra234-ccplex-cluster", .data = &tegra234_cpufreq_soc }, { /* sentinel */ } }; -MODULE_DEVICE_TABLE(of, tegra194_cpufreq_of_match); static struct platform_driver tegra194_ccplex_driver = { .driver = { diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index 7b2d138bc83e05f9b1a4f38c18c4ed57b05f354a..ee99c02c84e81e516b5e986519790ac044472650 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -216,9 +216,9 @@ config CRYPTO_AES_S390 config CRYPTO_CHACHA_S390 tristate "ChaCha20 stream cipher" depends on S390 - select CRYPTO_ALGAPI select CRYPTO_SKCIPHER - select CRYPTO_CHACHA20 + select CRYPTO_LIB_CHACHA_GENERIC + select CRYPTO_ARCH_HAVE_LIB_CHACHA help This is the s390 SIMD implementation of the ChaCha20 stream cipher (RFC 7539). diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile index 0a4fff23d272ef1152a824d0ac6f6a0502ba66c6..f81703a86b98e0acd47c8b65dc1f147a1ca91624 100644 --- a/drivers/crypto/Makefile +++ b/drivers/crypto/Makefile @@ -3,6 +3,7 @@ obj-$(CONFIG_CRYPTO_DEV_ALLWINNER) += allwinner/ obj-$(CONFIG_CRYPTO_DEV_ATMEL_AES) += atmel-aes.o obj-$(CONFIG_CRYPTO_DEV_ATMEL_SHA) += atmel-sha.o obj-$(CONFIG_CRYPTO_DEV_ATMEL_TDES) += atmel-tdes.o +# __init ordering requires atmel-i2c being before atmel-ecc and atmel-sha204a. obj-$(CONFIG_CRYPTO_DEV_ATMEL_I2C) += atmel-i2c.o obj-$(CONFIG_CRYPTO_DEV_ATMEL_ECC) += atmel-ecc.o obj-$(CONFIG_CRYPTO_DEV_ATMEL_SHA204A) += atmel-sha204a.o diff --git a/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-cipher.c b/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-cipher.c index dec79fa3ebafb83951901b07044ee1f994639c93..10fe9f73a5fb45097b8ae1537fd1879fe8e772db 100644 --- a/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-cipher.c +++ b/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-cipher.c @@ -20,7 +20,6 @@ static int noinline_for_stack sun4i_ss_opti_poll(struct skcipher_request *areq) unsigned int ivsize = crypto_skcipher_ivsize(tfm); struct sun4i_cipher_req_ctx *ctx = skcipher_request_ctx(areq); u32 mode = ctx->mode; - void *backup_iv = NULL; /* when activating SS, the default FIFO space is SS_RX_DEFAULT(32) */ u32 rx_cnt = SS_RX_DEFAULT; u32 tx_cnt = 0; @@ -48,10 +47,8 @@ static int noinline_for_stack sun4i_ss_opti_poll(struct skcipher_request *areq) } if (areq->iv && ivsize > 0 && mode & SS_DECRYPTION) { - backup_iv = kzalloc(ivsize, GFP_KERNEL); - if (!backup_iv) - return -ENOMEM; - scatterwalk_map_and_copy(backup_iv, areq->src, areq->cryptlen - ivsize, ivsize, 0); + scatterwalk_map_and_copy(ctx->backup_iv, areq->src, + areq->cryptlen - ivsize, ivsize, 0); } if (IS_ENABLED(CONFIG_CRYPTO_DEV_SUN4I_SS_DEBUG)) { @@ -134,8 +131,8 @@ static int noinline_for_stack sun4i_ss_opti_poll(struct skcipher_request *areq) if (areq->iv) { if (mode & SS_DECRYPTION) { - memcpy(areq->iv, backup_iv, ivsize); - kfree_sensitive(backup_iv); + memcpy(areq->iv, ctx->backup_iv, ivsize); + memzero_explicit(ctx->backup_iv, ivsize); } else { scatterwalk_map_and_copy(areq->iv, areq->dst, areq->cryptlen - ivsize, ivsize, 0); @@ -199,7 +196,6 @@ static int sun4i_ss_cipher_poll(struct skcipher_request *areq) unsigned int ileft = areq->cryptlen; unsigned int oleft = areq->cryptlen; unsigned int todo; - void *backup_iv = NULL; struct sg_mapping_iter mi, mo; unsigned long pi = 0, po = 0; /* progress for in and out */ bool miter_err; @@ -244,10 +240,8 @@ static int sun4i_ss_cipher_poll(struct skcipher_request *areq) return sun4i_ss_cipher_poll_fallback(areq); if (areq->iv && ivsize > 0 && mode & SS_DECRYPTION) { - backup_iv = kzalloc(ivsize, GFP_KERNEL); - if (!backup_iv) - return -ENOMEM; - scatterwalk_map_and_copy(backup_iv, areq->src, areq->cryptlen - ivsize, ivsize, 0); + scatterwalk_map_and_copy(ctx->backup_iv, areq->src, + areq->cryptlen - ivsize, ivsize, 0); } if (IS_ENABLED(CONFIG_CRYPTO_DEV_SUN4I_SS_DEBUG)) { @@ -384,8 +378,8 @@ static int sun4i_ss_cipher_poll(struct skcipher_request *areq) } if (areq->iv) { if (mode & SS_DECRYPTION) { - memcpy(areq->iv, backup_iv, ivsize); - kfree_sensitive(backup_iv); + memcpy(areq->iv, ctx->backup_iv, ivsize); + memzero_explicit(ctx->backup_iv, ivsize); } else { scatterwalk_map_and_copy(areq->iv, areq->dst, areq->cryptlen - ivsize, ivsize, 0); diff --git a/drivers/crypto/allwinner/sun4i-ss/sun4i-ss.h b/drivers/crypto/allwinner/sun4i-ss/sun4i-ss.h index 0fee6f4e2d90dc700ce393ae7df24bd67d759ae2..ba59c7a488252224d364b02ccb9c38176b473784 100644 --- a/drivers/crypto/allwinner/sun4i-ss/sun4i-ss.h +++ b/drivers/crypto/allwinner/sun4i-ss/sun4i-ss.h @@ -183,6 +183,7 @@ struct sun4i_tfm_ctx { struct sun4i_cipher_req_ctx { u32 mode; + u8 backup_iv[AES_BLOCK_SIZE]; struct skcipher_request fallback_req; // keep at the end }; diff --git a/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-cipher.c b/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-cipher.c index 35e3cadccac2bf1a647c3eb73485206ba6ad5074..74b4e910a38d7bd790bf95dc817502d62d3cf947 100644 --- a/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-cipher.c +++ b/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-cipher.c @@ -25,26 +25,62 @@ static int sun8i_ce_cipher_need_fallback(struct skcipher_request *areq) { struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(areq); struct scatterlist *sg; + struct skcipher_alg *alg = crypto_skcipher_alg(tfm); + struct sun8i_ce_alg_template *algt; + unsigned int todo, len; + + algt = container_of(alg, struct sun8i_ce_alg_template, alg.skcipher); + + if (sg_nents_for_len(areq->src, areq->cryptlen) > MAX_SG || + sg_nents_for_len(areq->dst, areq->cryptlen) > MAX_SG) { + algt->stat_fb_maxsg++; + return true; + } - if (sg_nents(areq->src) > MAX_SG || sg_nents(areq->dst) > MAX_SG) + if (areq->cryptlen < crypto_skcipher_ivsize(tfm)) { + algt->stat_fb_leniv++; return true; + } - if (areq->cryptlen < crypto_skcipher_ivsize(tfm)) + if (areq->cryptlen == 0) { + algt->stat_fb_len0++; return true; + } - if (areq->cryptlen == 0 || areq->cryptlen % 16) + if (areq->cryptlen % 16) { + algt->stat_fb_mod16++; return true; + } + len = areq->cryptlen; sg = areq->src; while (sg) { - if (sg->length % 4 || !IS_ALIGNED(sg->offset, sizeof(u32))) + if (!IS_ALIGNED(sg->offset, sizeof(u32))) { + algt->stat_fb_srcali++; + return true; + } + todo = min(len, sg->length); + if (todo % 4) { + algt->stat_fb_srclen++; return true; + } + len -= todo; sg = sg_next(sg); } + + len = areq->cryptlen; sg = areq->dst; while (sg) { - if (sg->length % 4 || !IS_ALIGNED(sg->offset, sizeof(u32))) + if (!IS_ALIGNED(sg->offset, sizeof(u32))) { + algt->stat_fb_dstali++; + return true; + } + todo = min(len, sg->length); + if (todo % 4) { + algt->stat_fb_dstlen++; return true; + } + len -= todo; sg = sg_next(sg); } return false; @@ -94,6 +130,8 @@ static int sun8i_ce_cipher_prepare(struct crypto_engine *engine, void *async_req int nr_sgs = 0; int nr_sgd = 0; int err = 0; + int ns = sg_nents_for_len(areq->src, areq->cryptlen); + int nd = sg_nents_for_len(areq->dst, areq->cryptlen); algt = container_of(alg, struct sun8i_ce_alg_template, alg.skcipher); @@ -152,23 +190,13 @@ static int sun8i_ce_cipher_prepare(struct crypto_engine *engine, void *async_req ivsize = crypto_skcipher_ivsize(tfm); if (areq->iv && crypto_skcipher_ivsize(tfm) > 0) { rctx->ivlen = ivsize; - rctx->bounce_iv = kzalloc(ivsize, GFP_KERNEL | GFP_DMA); - if (!rctx->bounce_iv) { - err = -ENOMEM; - goto theend_key; - } if (rctx->op_dir & CE_DECRYPTION) { - rctx->backup_iv = kzalloc(ivsize, GFP_KERNEL); - if (!rctx->backup_iv) { - err = -ENOMEM; - goto theend_key; - } offset = areq->cryptlen - ivsize; - scatterwalk_map_and_copy(rctx->backup_iv, areq->src, + scatterwalk_map_and_copy(chan->backup_iv, areq->src, offset, ivsize, 0); } - memcpy(rctx->bounce_iv, areq->iv, ivsize); - rctx->addr_iv = dma_map_single(ce->dev, rctx->bounce_iv, rctx->ivlen, + memcpy(chan->bounce_iv, areq->iv, ivsize); + rctx->addr_iv = dma_map_single(ce->dev, chan->bounce_iv, rctx->ivlen, DMA_TO_DEVICE); if (dma_mapping_error(ce->dev, rctx->addr_iv)) { dev_err(ce->dev, "Cannot DMA MAP IV\n"); @@ -179,8 +207,7 @@ static int sun8i_ce_cipher_prepare(struct crypto_engine *engine, void *async_req } if (areq->src == areq->dst) { - nr_sgs = dma_map_sg(ce->dev, areq->src, sg_nents(areq->src), - DMA_BIDIRECTIONAL); + nr_sgs = dma_map_sg(ce->dev, areq->src, ns, DMA_BIDIRECTIONAL); if (nr_sgs <= 0 || nr_sgs > MAX_SG) { dev_err(ce->dev, "Invalid sg number %d\n", nr_sgs); err = -EINVAL; @@ -188,15 +215,13 @@ static int sun8i_ce_cipher_prepare(struct crypto_engine *engine, void *async_req } nr_sgd = nr_sgs; } else { - nr_sgs = dma_map_sg(ce->dev, areq->src, sg_nents(areq->src), - DMA_TO_DEVICE); + nr_sgs = dma_map_sg(ce->dev, areq->src, ns, DMA_TO_DEVICE); if (nr_sgs <= 0 || nr_sgs > MAX_SG) { dev_err(ce->dev, "Invalid sg number %d\n", nr_sgs); err = -EINVAL; goto theend_iv; } - nr_sgd = dma_map_sg(ce->dev, areq->dst, sg_nents(areq->dst), - DMA_FROM_DEVICE); + nr_sgd = dma_map_sg(ce->dev, areq->dst, nd, DMA_FROM_DEVICE); if (nr_sgd <= 0 || nr_sgd > MAX_SG) { dev_err(ce->dev, "Invalid sg number %d\n", nr_sgd); err = -EINVAL; @@ -241,14 +266,11 @@ static int sun8i_ce_cipher_prepare(struct crypto_engine *engine, void *async_req theend_sgs: if (areq->src == areq->dst) { - dma_unmap_sg(ce->dev, areq->src, sg_nents(areq->src), - DMA_BIDIRECTIONAL); + dma_unmap_sg(ce->dev, areq->src, ns, DMA_BIDIRECTIONAL); } else { if (nr_sgs > 0) - dma_unmap_sg(ce->dev, areq->src, sg_nents(areq->src), - DMA_TO_DEVICE); - dma_unmap_sg(ce->dev, areq->dst, sg_nents(areq->dst), - DMA_FROM_DEVICE); + dma_unmap_sg(ce->dev, areq->src, ns, DMA_TO_DEVICE); + dma_unmap_sg(ce->dev, areq->dst, nd, DMA_FROM_DEVICE); } theend_iv: @@ -257,16 +279,15 @@ theend_iv: dma_unmap_single(ce->dev, rctx->addr_iv, rctx->ivlen, DMA_TO_DEVICE); offset = areq->cryptlen - ivsize; if (rctx->op_dir & CE_DECRYPTION) { - memcpy(areq->iv, rctx->backup_iv, ivsize); - kfree_sensitive(rctx->backup_iv); + memcpy(areq->iv, chan->backup_iv, ivsize); + memzero_explicit(chan->backup_iv, ivsize); } else { scatterwalk_map_and_copy(areq->iv, areq->dst, offset, ivsize, 0); } - kfree(rctx->bounce_iv); + memzero_explicit(chan->bounce_iv, ivsize); } -theend_key: dma_unmap_single(ce->dev, rctx->addr_key, op->keylen, DMA_TO_DEVICE); theend: @@ -322,13 +343,13 @@ static int sun8i_ce_cipher_unprepare(struct crypto_engine *engine, void *async_r dma_unmap_single(ce->dev, rctx->addr_iv, rctx->ivlen, DMA_TO_DEVICE); offset = areq->cryptlen - ivsize; if (rctx->op_dir & CE_DECRYPTION) { - memcpy(areq->iv, rctx->backup_iv, ivsize); - kfree_sensitive(rctx->backup_iv); + memcpy(areq->iv, chan->backup_iv, ivsize); + memzero_explicit(chan->backup_iv, ivsize); } else { scatterwalk_map_and_copy(areq->iv, areq->dst, offset, ivsize, 0); } - kfree(rctx->bounce_iv); + memzero_explicit(chan->bounce_iv, ivsize); } dma_unmap_single(ce->dev, rctx->addr_key, op->keylen, DMA_TO_DEVICE); @@ -398,10 +419,9 @@ int sun8i_ce_cipher_init(struct crypto_tfm *tfm) sktfm->reqsize = sizeof(struct sun8i_cipher_req_ctx) + crypto_skcipher_reqsize(op->fallback_tfm); - - dev_info(op->ce->dev, "Fallback for %s is %s\n", - crypto_tfm_alg_driver_name(&sktfm->base), - crypto_tfm_alg_driver_name(crypto_skcipher_tfm(op->fallback_tfm))); + memcpy(algt->fbname, + crypto_tfm_alg_driver_name(crypto_skcipher_tfm(op->fallback_tfm)), + CRYPTO_MAX_ALG_NAME); op->enginectx.op.do_one_request = sun8i_ce_cipher_run; op->enginectx.op.prepare_request = sun8i_ce_cipher_prepare; diff --git a/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-core.c b/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-core.c index d8623c7e0d1d68c2a6bacd41d86c4336f794d18d..9f659469983544c96883c9af51bf7c205272a3cb 100644 --- a/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-core.c +++ b/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-core.c @@ -283,7 +283,7 @@ static struct sun8i_ce_alg_template ce_algs[] = { .cra_priority = 400, .cra_blocksize = AES_BLOCK_SIZE, .cra_flags = CRYPTO_ALG_TYPE_SKCIPHER | - CRYPTO_ALG_ASYNC | CRYPTO_ALG_ALLOCATES_MEMORY | + CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK, .cra_ctxsize = sizeof(struct sun8i_cipher_tfm_ctx), .cra_module = THIS_MODULE, @@ -310,7 +310,7 @@ static struct sun8i_ce_alg_template ce_algs[] = { .cra_priority = 400, .cra_blocksize = AES_BLOCK_SIZE, .cra_flags = CRYPTO_ALG_TYPE_SKCIPHER | - CRYPTO_ALG_ASYNC | CRYPTO_ALG_ALLOCATES_MEMORY | + CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK, .cra_ctxsize = sizeof(struct sun8i_cipher_tfm_ctx), .cra_module = THIS_MODULE, @@ -336,7 +336,7 @@ static struct sun8i_ce_alg_template ce_algs[] = { .cra_priority = 400, .cra_blocksize = DES3_EDE_BLOCK_SIZE, .cra_flags = CRYPTO_ALG_TYPE_SKCIPHER | - CRYPTO_ALG_ASYNC | CRYPTO_ALG_ALLOCATES_MEMORY | + CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK, .cra_ctxsize = sizeof(struct sun8i_cipher_tfm_ctx), .cra_module = THIS_MODULE, @@ -363,7 +363,7 @@ static struct sun8i_ce_alg_template ce_algs[] = { .cra_priority = 400, .cra_blocksize = DES3_EDE_BLOCK_SIZE, .cra_flags = CRYPTO_ALG_TYPE_SKCIPHER | - CRYPTO_ALG_ASYNC | CRYPTO_ALG_ALLOCATES_MEMORY | + CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK, .cra_ctxsize = sizeof(struct sun8i_cipher_tfm_ctx), .cra_module = THIS_MODULE, @@ -595,19 +595,47 @@ static int sun8i_ce_debugfs_show(struct seq_file *seq, void *v) continue; switch (ce_algs[i].type) { case CRYPTO_ALG_TYPE_SKCIPHER: - seq_printf(seq, "%s %s %lu %lu\n", + seq_printf(seq, "%s %s reqs=%lu fallback=%lu\n", ce_algs[i].alg.skcipher.base.cra_driver_name, ce_algs[i].alg.skcipher.base.cra_name, ce_algs[i].stat_req, ce_algs[i].stat_fb); + seq_printf(seq, "\tLast fallback is: %s\n", + ce_algs[i].fbname); + seq_printf(seq, "\tFallback due to 0 length: %lu\n", + ce_algs[i].stat_fb_len0); + seq_printf(seq, "\tFallback due to length !mod16: %lu\n", + ce_algs[i].stat_fb_mod16); + seq_printf(seq, "\tFallback due to length < IV: %lu\n", + ce_algs[i].stat_fb_leniv); + seq_printf(seq, "\tFallback due to source alignment: %lu\n", + ce_algs[i].stat_fb_srcali); + seq_printf(seq, "\tFallback due to dest alignment: %lu\n", + ce_algs[i].stat_fb_dstali); + seq_printf(seq, "\tFallback due to source length: %lu\n", + ce_algs[i].stat_fb_srclen); + seq_printf(seq, "\tFallback due to dest length: %lu\n", + ce_algs[i].stat_fb_dstlen); + seq_printf(seq, "\tFallback due to SG numbers: %lu\n", + ce_algs[i].stat_fb_maxsg); break; case CRYPTO_ALG_TYPE_AHASH: - seq_printf(seq, "%s %s %lu %lu\n", + seq_printf(seq, "%s %s reqs=%lu fallback=%lu\n", ce_algs[i].alg.hash.halg.base.cra_driver_name, ce_algs[i].alg.hash.halg.base.cra_name, ce_algs[i].stat_req, ce_algs[i].stat_fb); + seq_printf(seq, "\tLast fallback is: %s\n", + ce_algs[i].fbname); + seq_printf(seq, "\tFallback due to 0 length: %lu\n", + ce_algs[i].stat_fb_len0); + seq_printf(seq, "\tFallback due to length: %lu\n", + ce_algs[i].stat_fb_srclen); + seq_printf(seq, "\tFallback due to alignment: %lu\n", + ce_algs[i].stat_fb_srcali); + seq_printf(seq, "\tFallback due to SG numbers: %lu\n", + ce_algs[i].stat_fb_maxsg); break; case CRYPTO_ALG_TYPE_RNG: - seq_printf(seq, "%s %s %lu %lu\n", + seq_printf(seq, "%s %s reqs=%lu bytes=%lu\n", ce_algs[i].alg.rng.base.cra_driver_name, ce_algs[i].alg.rng.base.cra_name, ce_algs[i].stat_req, ce_algs[i].stat_bytes); @@ -673,6 +701,18 @@ static int sun8i_ce_allocate_chanlist(struct sun8i_ce_dev *ce) err = -ENOMEM; goto error_engine; } + ce->chanlist[i].bounce_iv = devm_kmalloc(ce->dev, AES_BLOCK_SIZE, + GFP_KERNEL | GFP_DMA); + if (!ce->chanlist[i].bounce_iv) { + err = -ENOMEM; + goto error_engine; + } + ce->chanlist[i].backup_iv = devm_kmalloc(ce->dev, AES_BLOCK_SIZE, + GFP_KERNEL); + if (!ce->chanlist[i].backup_iv) { + err = -ENOMEM; + goto error_engine; + } } return 0; error_engine: diff --git a/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-hash.c b/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-hash.c index 859b7522faaac5f6665a8d05dfcf96985fda8236..8b5b9b9d04c34217698755df18c77de43d5088de 100644 --- a/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-hash.c +++ b/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-hash.c @@ -50,9 +50,9 @@ int sun8i_ce_hash_crainit(struct crypto_tfm *tfm) sizeof(struct sun8i_ce_hash_reqctx) + crypto_ahash_reqsize(op->fallback_tfm)); - dev_info(op->ce->dev, "Fallback for %s is %s\n", - crypto_tfm_alg_driver_name(tfm), - crypto_tfm_alg_driver_name(&op->fallback_tfm->base)); + memcpy(algt->fbname, crypto_tfm_alg_driver_name(&op->fallback_tfm->base), + CRYPTO_MAX_ALG_NAME); + err = pm_runtime_get_sync(op->ce->dev); if (err < 0) goto error_pm; @@ -199,17 +199,32 @@ static int sun8i_ce_hash_digest_fb(struct ahash_request *areq) static bool sun8i_ce_hash_need_fallback(struct ahash_request *areq) { + struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); + struct ahash_alg *alg = __crypto_ahash_alg(tfm->base.__crt_alg); + struct sun8i_ce_alg_template *algt; struct scatterlist *sg; - if (areq->nbytes == 0) + algt = container_of(alg, struct sun8i_ce_alg_template, alg.hash); + + if (areq->nbytes == 0) { + algt->stat_fb_len0++; return true; + } /* we need to reserve one SG for padding one */ - if (sg_nents(areq->src) > MAX_SG - 1) + if (sg_nents_for_len(areq->src, areq->nbytes) > MAX_SG - 1) { + algt->stat_fb_maxsg++; return true; + } sg = areq->src; while (sg) { - if (sg->length % 4 || !IS_ALIGNED(sg->offset, sizeof(u32))) + if (sg->length % 4) { + algt->stat_fb_srclen++; return true; + } + if (!IS_ALIGNED(sg->offset, sizeof(u32))) { + algt->stat_fb_srcali++; + return true; + } sg = sg_next(sg); } return false; @@ -229,7 +244,7 @@ int sun8i_ce_hash_digest(struct ahash_request *areq) if (sun8i_ce_hash_need_fallback(areq)) return sun8i_ce_hash_digest_fb(areq); - nr_sgs = sg_nents(areq->src); + nr_sgs = sg_nents_for_len(areq->src, areq->nbytes); if (nr_sgs > MAX_SG - 1) return sun8i_ce_hash_digest_fb(areq); @@ -248,6 +263,64 @@ int sun8i_ce_hash_digest(struct ahash_request *areq) return crypto_transfer_hash_request_to_engine(engine, areq); } +static u64 hash_pad(__le32 *buf, unsigned int bufsize, u64 padi, u64 byte_count, bool le, int bs) +{ + u64 fill, min_fill, j, k; + __be64 *bebits; + __le64 *lebits; + + j = padi; + buf[j++] = cpu_to_le32(0x80); + + if (bs == 64) { + fill = 64 - (byte_count % 64); + min_fill = 2 * sizeof(u32) + sizeof(u32); + } else { + fill = 128 - (byte_count % 128); + min_fill = 4 * sizeof(u32) + sizeof(u32); + } + + if (fill < min_fill) + fill += bs; + + k = j; + j += (fill - min_fill) / sizeof(u32); + if (j * 4 > bufsize) { + pr_err("%s OVERFLOW %llu\n", __func__, j); + return 0; + } + for (; k < j; k++) + buf[k] = 0; + + if (le) { + /* MD5 */ + lebits = (__le64 *)&buf[j]; + *lebits = cpu_to_le64(byte_count << 3); + j += 2; + } else { + if (bs == 64) { + /* sha1 sha224 sha256 */ + bebits = (__be64 *)&buf[j]; + *bebits = cpu_to_be64(byte_count << 3); + j += 2; + } else { + /* sha384 sha512*/ + bebits = (__be64 *)&buf[j]; + *bebits = cpu_to_be64(byte_count >> 61); + j += 2; + bebits = (__be64 *)&buf[j]; + *bebits = cpu_to_be64(byte_count << 3); + j += 2; + } + } + if (j * 4 > bufsize) { + pr_err("%s OVERFLOW %llu\n", __func__, j); + return 0; + } + + return j; +} + int sun8i_ce_hash_run(struct crypto_engine *engine, void *breq) { struct ahash_request *areq = container_of(breq, struct ahash_request, base); @@ -266,14 +339,11 @@ int sun8i_ce_hash_run(struct crypto_engine *engine, void *breq) __le32 *bf; void *buf = NULL; int j, i, todo; - int nbw = 0; - u64 fill, min_fill; - __be64 *bebits; - __le64 *lebits; void *result = NULL; u64 bs; int digestsize; dma_addr_t addr_res, addr_pad; + int ns = sg_nents_for_len(areq->src, areq->nbytes); algt = container_of(alg, struct sun8i_ce_alg_template, alg.hash); ce = algt->ce; @@ -318,7 +388,7 @@ int sun8i_ce_hash_run(struct crypto_engine *engine, void *breq) cet->t_sym_ctl = 0; cet->t_asym_ctl = 0; - nr_sgs = dma_map_sg(ce->dev, areq->src, sg_nents(areq->src), DMA_TO_DEVICE); + nr_sgs = dma_map_sg(ce->dev, areq->src, ns, DMA_TO_DEVICE); if (nr_sgs <= 0 || nr_sgs > MAX_SG) { dev_err(ce->dev, "Invalid sg number %d\n", nr_sgs); err = -EINVAL; @@ -348,44 +418,25 @@ int sun8i_ce_hash_run(struct crypto_engine *engine, void *breq) byte_count = areq->nbytes; j = 0; - bf[j++] = cpu_to_le32(0x80); - - if (bs == 64) { - fill = 64 - (byte_count % 64); - min_fill = 2 * sizeof(u32) + (nbw ? 0 : sizeof(u32)); - } else { - fill = 128 - (byte_count % 128); - min_fill = 4 * sizeof(u32) + (nbw ? 0 : sizeof(u32)); - } - - if (fill < min_fill) - fill += bs; - - j += (fill - min_fill) / sizeof(u32); switch (algt->ce_algo_id) { case CE_ID_HASH_MD5: - lebits = (__le64 *)&bf[j]; - *lebits = cpu_to_le64(byte_count << 3); - j += 2; + j = hash_pad(bf, 2 * bs, j, byte_count, true, bs); break; case CE_ID_HASH_SHA1: case CE_ID_HASH_SHA224: case CE_ID_HASH_SHA256: - bebits = (__be64 *)&bf[j]; - *bebits = cpu_to_be64(byte_count << 3); - j += 2; + j = hash_pad(bf, 2 * bs, j, byte_count, false, bs); break; case CE_ID_HASH_SHA384: case CE_ID_HASH_SHA512: - bebits = (__be64 *)&bf[j]; - *bebits = cpu_to_be64(byte_count >> 61); - j += 2; - bebits = (__be64 *)&bf[j]; - *bebits = cpu_to_be64(byte_count << 3); - j += 2; + j = hash_pad(bf, 2 * bs, j, byte_count, false, bs); break; } + if (!j) { + err = -EINVAL; + goto theend; + } addr_pad = dma_map_single(ce->dev, buf, j * 4, DMA_TO_DEVICE); cet->t_src[i].addr = cpu_to_le32(addr_pad); @@ -406,8 +457,7 @@ int sun8i_ce_hash_run(struct crypto_engine *engine, void *breq) err = sun8i_ce_run_task(ce, flow, crypto_tfm_alg_name(areq->base.tfm)); dma_unmap_single(ce->dev, addr_pad, j * 4, DMA_TO_DEVICE); - dma_unmap_sg(ce->dev, areq->src, sg_nents(areq->src), - DMA_TO_DEVICE); + dma_unmap_sg(ce->dev, areq->src, ns, DMA_TO_DEVICE); dma_unmap_single(ce->dev, addr_res, digestsize, DMA_FROM_DEVICE); diff --git a/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-prng.c b/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-prng.c index b3a9bbfb8831f3f1704528b84f504d971558de9f..b3cc43ea6c8a69db03844222696bdb738ab3eb87 100644 --- a/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-prng.c +++ b/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-prng.c @@ -108,11 +108,9 @@ int sun8i_ce_prng_generate(struct crypto_rng *tfm, const u8 *src, goto err_dst; } - err = pm_runtime_get_sync(ce->dev); - if (err < 0) { - pm_runtime_put_noidle(ce->dev); + err = pm_runtime_resume_and_get(ce->dev); + if (err < 0) goto err_pm; - } mutex_lock(&ce->rnglock); chan = &ce->chanlist[flow]; diff --git a/drivers/crypto/allwinner/sun8i-ce/sun8i-ce.h b/drivers/crypto/allwinner/sun8i-ce/sun8i-ce.h index 624a5926f21f19642c004e958fb4b214dbdf8c9d..8177aaba443498463a5c7e9c40a4916b6bef1c06 100644 --- a/drivers/crypto/allwinner/sun8i-ce/sun8i-ce.h +++ b/drivers/crypto/allwinner/sun8i-ce/sun8i-ce.h @@ -186,6 +186,8 @@ struct ce_task { * @status: set to 1 by interrupt if task is done * @t_phy: Physical address of task * @tl: pointer to the current ce_task for this flow + * @backup_iv: buffer which contain the next IV to store + * @bounce_iv: buffer which contain the IV * @stat_req: number of request done by this flow */ struct sun8i_ce_flow { @@ -195,6 +197,8 @@ struct sun8i_ce_flow { dma_addr_t t_phy; int timeout; struct ce_task *tl; + void *backup_iv; + void *bounce_iv; #ifdef CONFIG_CRYPTO_DEV_SUN8I_CE_DEBUG unsigned long stat_req; #endif @@ -241,8 +245,6 @@ struct sun8i_ce_dev { * struct sun8i_cipher_req_ctx - context for a skcipher request * @op_dir: direction (encrypt vs decrypt) for this request * @flow: the flow to use for this request - * @backup_iv: buffer which contain the next IV to store - * @bounce_iv: buffer which contain the IV * @ivlen: size of bounce_iv * @nr_sgs: The number of source SG (as given by dma_map_sg()) * @nr_sgd: The number of destination SG (as given by dma_map_sg()) @@ -253,8 +255,6 @@ struct sun8i_ce_dev { struct sun8i_cipher_req_ctx { u32 op_dir; int flow; - void *backup_iv; - void *bounce_iv; unsigned int ivlen; int nr_sgs; int nr_sgd; @@ -333,11 +333,18 @@ struct sun8i_ce_alg_template { struct ahash_alg hash; struct rng_alg rng; } alg; -#ifdef CONFIG_CRYPTO_DEV_SUN8I_CE_DEBUG unsigned long stat_req; unsigned long stat_fb; unsigned long stat_bytes; -#endif + unsigned long stat_fb_maxsg; + unsigned long stat_fb_leniv; + unsigned long stat_fb_len0; + unsigned long stat_fb_mod16; + unsigned long stat_fb_srcali; + unsigned long stat_fb_srclen; + unsigned long stat_fb_dstali; + unsigned long stat_fb_dstlen; + char fbname[CRYPTO_MAX_ALG_NAME]; }; int sun8i_ce_enqueue(struct crypto_async_request *areq, u32 type); diff --git a/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-cipher.c b/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-cipher.c index 554e400d41cad612f45f3864a7621757593254ef..5bb950182026f03deb572ab8eda48dd025f5d1cb 100644 --- a/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-cipher.c +++ b/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-cipher.c @@ -22,34 +22,53 @@ static bool sun8i_ss_need_fallback(struct skcipher_request *areq) { + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(areq); + struct skcipher_alg *alg = crypto_skcipher_alg(tfm); + struct sun8i_ss_alg_template *algt = container_of(alg, struct sun8i_ss_alg_template, alg.skcipher); struct scatterlist *in_sg = areq->src; struct scatterlist *out_sg = areq->dst; struct scatterlist *sg; + unsigned int todo, len; - if (areq->cryptlen == 0 || areq->cryptlen % 16) + if (areq->cryptlen == 0 || areq->cryptlen % 16) { + algt->stat_fb_len++; return true; + } - if (sg_nents(areq->src) > 8 || sg_nents(areq->dst) > 8) + if (sg_nents_for_len(areq->src, areq->cryptlen) > 8 || + sg_nents_for_len(areq->dst, areq->cryptlen) > 8) { + algt->stat_fb_sgnum++; return true; + } + len = areq->cryptlen; sg = areq->src; while (sg) { - if ((sg->length % 16) != 0) - return true; - if ((sg_dma_len(sg) % 16) != 0) + todo = min(len, sg->length); + if ((todo % 16) != 0) { + algt->stat_fb_sglen++; return true; - if (!IS_ALIGNED(sg->offset, 16)) + } + if (!IS_ALIGNED(sg->offset, 16)) { + algt->stat_fb_align++; return true; + } + len -= todo; sg = sg_next(sg); } + len = areq->cryptlen; sg = areq->dst; while (sg) { - if ((sg->length % 16) != 0) - return true; - if ((sg_dma_len(sg) % 16) != 0) + todo = min(len, sg->length); + if ((todo % 16) != 0) { + algt->stat_fb_sglen++; return true; - if (!IS_ALIGNED(sg->offset, 16)) + } + if (!IS_ALIGNED(sg->offset, 16)) { + algt->stat_fb_align++; return true; + } + len -= todo; sg = sg_next(sg); } @@ -93,6 +112,68 @@ static int sun8i_ss_cipher_fallback(struct skcipher_request *areq) return err; } +static int sun8i_ss_setup_ivs(struct skcipher_request *areq) +{ + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(areq); + struct sun8i_cipher_tfm_ctx *op = crypto_skcipher_ctx(tfm); + struct sun8i_ss_dev *ss = op->ss; + struct sun8i_cipher_req_ctx *rctx = skcipher_request_ctx(areq); + struct scatterlist *sg = areq->src; + unsigned int todo, offset; + unsigned int len = areq->cryptlen; + unsigned int ivsize = crypto_skcipher_ivsize(tfm); + struct sun8i_ss_flow *sf = &ss->flows[rctx->flow]; + int i = 0; + u32 a; + int err; + + rctx->ivlen = ivsize; + if (rctx->op_dir & SS_DECRYPTION) { + offset = areq->cryptlen - ivsize; + scatterwalk_map_and_copy(sf->biv, areq->src, offset, + ivsize, 0); + } + + /* we need to copy all IVs from source in case DMA is bi-directionnal */ + while (sg && len) { + if (sg_dma_len(sg) == 0) { + sg = sg_next(sg); + continue; + } + if (i == 0) + memcpy(sf->iv[0], areq->iv, ivsize); + a = dma_map_single(ss->dev, sf->iv[i], ivsize, DMA_TO_DEVICE); + if (dma_mapping_error(ss->dev, a)) { + memzero_explicit(sf->iv[i], ivsize); + dev_err(ss->dev, "Cannot DMA MAP IV\n"); + err = -EFAULT; + goto dma_iv_error; + } + rctx->p_iv[i] = a; + /* we need to setup all others IVs only in the decrypt way */ + if (rctx->op_dir & SS_ENCRYPTION) + return 0; + todo = min(len, sg_dma_len(sg)); + len -= todo; + i++; + if (i < MAX_SG) { + offset = sg->length - ivsize; + scatterwalk_map_and_copy(sf->iv[i], sg, offset, ivsize, 0); + } + rctx->niv = i; + sg = sg_next(sg); + } + + return 0; +dma_iv_error: + i--; + while (i >= 0) { + dma_unmap_single(ss->dev, rctx->p_iv[i], ivsize, DMA_TO_DEVICE); + memzero_explicit(sf->iv[i], ivsize); + } + return err; +} + static int sun8i_ss_cipher(struct skcipher_request *areq) { struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(areq); @@ -101,12 +182,14 @@ static int sun8i_ss_cipher(struct skcipher_request *areq) struct sun8i_cipher_req_ctx *rctx = skcipher_request_ctx(areq); struct skcipher_alg *alg = crypto_skcipher_alg(tfm); struct sun8i_ss_alg_template *algt; + struct sun8i_ss_flow *sf = &ss->flows[rctx->flow]; struct scatterlist *sg; unsigned int todo, len, offset, ivsize; - void *backup_iv = NULL; int nr_sgs = 0; int nr_sgd = 0; int err = 0; + int nsgs = sg_nents_for_len(areq->src, areq->cryptlen); + int nsgd = sg_nents_for_len(areq->dst, areq->cryptlen); int i; algt = container_of(alg, struct sun8i_ss_alg_template, alg.skcipher); @@ -134,34 +217,12 @@ static int sun8i_ss_cipher(struct skcipher_request *areq) ivsize = crypto_skcipher_ivsize(tfm); if (areq->iv && crypto_skcipher_ivsize(tfm) > 0) { - rctx->ivlen = ivsize; - rctx->biv = kzalloc(ivsize, GFP_KERNEL | GFP_DMA); - if (!rctx->biv) { - err = -ENOMEM; + err = sun8i_ss_setup_ivs(areq); + if (err) goto theend_key; - } - if (rctx->op_dir & SS_DECRYPTION) { - backup_iv = kzalloc(ivsize, GFP_KERNEL); - if (!backup_iv) { - err = -ENOMEM; - goto theend_key; - } - offset = areq->cryptlen - ivsize; - scatterwalk_map_and_copy(backup_iv, areq->src, offset, - ivsize, 0); - } - memcpy(rctx->biv, areq->iv, ivsize); - rctx->p_iv = dma_map_single(ss->dev, rctx->biv, rctx->ivlen, - DMA_TO_DEVICE); - if (dma_mapping_error(ss->dev, rctx->p_iv)) { - dev_err(ss->dev, "Cannot DMA MAP IV\n"); - err = -ENOMEM; - goto theend_iv; - } } if (areq->src == areq->dst) { - nr_sgs = dma_map_sg(ss->dev, areq->src, sg_nents(areq->src), - DMA_BIDIRECTIONAL); + nr_sgs = dma_map_sg(ss->dev, areq->src, nsgs, DMA_BIDIRECTIONAL); if (nr_sgs <= 0 || nr_sgs > 8) { dev_err(ss->dev, "Invalid sg number %d\n", nr_sgs); err = -EINVAL; @@ -169,15 +230,13 @@ static int sun8i_ss_cipher(struct skcipher_request *areq) } nr_sgd = nr_sgs; } else { - nr_sgs = dma_map_sg(ss->dev, areq->src, sg_nents(areq->src), - DMA_TO_DEVICE); + nr_sgs = dma_map_sg(ss->dev, areq->src, nsgs, DMA_TO_DEVICE); if (nr_sgs <= 0 || nr_sgs > 8) { dev_err(ss->dev, "Invalid sg number %d\n", nr_sgs); err = -EINVAL; goto theend_iv; } - nr_sgd = dma_map_sg(ss->dev, areq->dst, sg_nents(areq->dst), - DMA_FROM_DEVICE); + nr_sgd = dma_map_sg(ss->dev, areq->dst, nsgd, DMA_FROM_DEVICE); if (nr_sgd <= 0 || nr_sgd > 8) { dev_err(ss->dev, "Invalid sg number %d\n", nr_sgd); err = -EINVAL; @@ -233,31 +292,26 @@ sgd_next: theend_sgs: if (areq->src == areq->dst) { - dma_unmap_sg(ss->dev, areq->src, sg_nents(areq->src), - DMA_BIDIRECTIONAL); + dma_unmap_sg(ss->dev, areq->src, nsgs, DMA_BIDIRECTIONAL); } else { - dma_unmap_sg(ss->dev, areq->src, sg_nents(areq->src), - DMA_TO_DEVICE); - dma_unmap_sg(ss->dev, areq->dst, sg_nents(areq->dst), - DMA_FROM_DEVICE); + dma_unmap_sg(ss->dev, areq->src, nsgs, DMA_TO_DEVICE); + dma_unmap_sg(ss->dev, areq->dst, nsgd, DMA_FROM_DEVICE); } theend_iv: - if (rctx->p_iv) - dma_unmap_single(ss->dev, rctx->p_iv, rctx->ivlen, - DMA_TO_DEVICE); - if (areq->iv && ivsize > 0) { - if (rctx->biv) { - offset = areq->cryptlen - ivsize; - if (rctx->op_dir & SS_DECRYPTION) { - memcpy(areq->iv, backup_iv, ivsize); - kfree_sensitive(backup_iv); - } else { - scatterwalk_map_and_copy(areq->iv, areq->dst, offset, - ivsize, 0); - } - kfree(rctx->biv); + for (i = 0; i < rctx->niv; i++) { + dma_unmap_single(ss->dev, rctx->p_iv[i], ivsize, DMA_TO_DEVICE); + memzero_explicit(sf->iv[i], ivsize); + } + + offset = areq->cryptlen - ivsize; + if (rctx->op_dir & SS_DECRYPTION) { + memcpy(areq->iv, sf->biv, ivsize); + memzero_explicit(sf->biv, ivsize); + } else { + scatterwalk_map_and_copy(areq->iv, areq->dst, offset, + ivsize, 0); } } @@ -349,9 +403,9 @@ int sun8i_ss_cipher_init(struct crypto_tfm *tfm) crypto_skcipher_reqsize(op->fallback_tfm); - dev_info(op->ss->dev, "Fallback for %s is %s\n", - crypto_tfm_alg_driver_name(&sktfm->base), - crypto_tfm_alg_driver_name(crypto_skcipher_tfm(op->fallback_tfm))); + memcpy(algt->fbname, + crypto_tfm_alg_driver_name(crypto_skcipher_tfm(op->fallback_tfm)), + CRYPTO_MAX_ALG_NAME); op->enginectx.op.do_one_request = sun8i_ss_handle_cipher_request; op->enginectx.op.prepare_request = NULL; diff --git a/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-core.c b/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-core.c index 319fe3279a7162e5bc5811822878fe87a9543129..98593a0cff6943a2fdf8fd0433422301f54b1b32 100644 --- a/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-core.c +++ b/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-core.c @@ -66,6 +66,7 @@ int sun8i_ss_run_task(struct sun8i_ss_dev *ss, struct sun8i_cipher_req_ctx *rctx const char *name) { int flow = rctx->flow; + unsigned int ivlen = rctx->ivlen; u32 v = SS_START; int i; @@ -104,15 +105,14 @@ int sun8i_ss_run_task(struct sun8i_ss_dev *ss, struct sun8i_cipher_req_ctx *rctx mutex_lock(&ss->mlock); writel(rctx->p_key, ss->base + SS_KEY_ADR_REG); - if (i == 0) { - if (rctx->p_iv) - writel(rctx->p_iv, ss->base + SS_IV_ADR_REG); - } else { - if (rctx->biv) { - if (rctx->op_dir == SS_ENCRYPTION) - writel(rctx->t_dst[i - 1].addr + rctx->t_dst[i - 1].len * 4 - rctx->ivlen, ss->base + SS_IV_ADR_REG); + if (ivlen) { + if (rctx->op_dir == SS_ENCRYPTION) { + if (i == 0) + writel(rctx->p_iv[0], ss->base + SS_IV_ADR_REG); else - writel(rctx->t_src[i - 1].addr + rctx->t_src[i - 1].len * 4 - rctx->ivlen, ss->base + SS_IV_ADR_REG); + writel(rctx->t_dst[i - 1].addr + rctx->t_dst[i - 1].len * 4 - ivlen, ss->base + SS_IV_ADR_REG); + } else { + writel(rctx->p_iv[i], ss->base + SS_IV_ADR_REG); } } @@ -409,6 +409,37 @@ static struct sun8i_ss_alg_template ss_algs[] = { } } }, +{ .type = CRYPTO_ALG_TYPE_AHASH, + .ss_algo_id = SS_ID_HASH_SHA1, + .alg.hash = { + .init = sun8i_ss_hash_init, + .update = sun8i_ss_hash_update, + .final = sun8i_ss_hash_final, + .finup = sun8i_ss_hash_finup, + .digest = sun8i_ss_hash_digest, + .export = sun8i_ss_hash_export, + .import = sun8i_ss_hash_import, + .setkey = sun8i_ss_hmac_setkey, + .halg = { + .digestsize = SHA1_DIGEST_SIZE, + .statesize = sizeof(struct sha1_state), + .base = { + .cra_name = "hmac(sha1)", + .cra_driver_name = "hmac-sha1-sun8i-ss", + .cra_priority = 300, + .cra_alignmask = 3, + .cra_flags = CRYPTO_ALG_TYPE_AHASH | + CRYPTO_ALG_ASYNC | + CRYPTO_ALG_NEED_FALLBACK, + .cra_blocksize = SHA1_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct sun8i_ss_hash_tfm_ctx), + .cra_module = THIS_MODULE, + .cra_init = sun8i_ss_hash_crainit, + .cra_exit = sun8i_ss_hash_craexit, + } + } + } +}, #endif }; @@ -430,6 +461,17 @@ static int sun8i_ss_debugfs_show(struct seq_file *seq, void *v) ss_algs[i].alg.skcipher.base.cra_driver_name, ss_algs[i].alg.skcipher.base.cra_name, ss_algs[i].stat_req, ss_algs[i].stat_fb); + + seq_printf(seq, "\tLast fallback is: %s\n", + ss_algs[i].fbname); + seq_printf(seq, "\tFallback due to length: %lu\n", + ss_algs[i].stat_fb_len); + seq_printf(seq, "\tFallback due to SG length: %lu\n", + ss_algs[i].stat_fb_sglen); + seq_printf(seq, "\tFallback due to alignment: %lu\n", + ss_algs[i].stat_fb_align); + seq_printf(seq, "\tFallback due to SG numbers: %lu\n", + ss_algs[i].stat_fb_sgnum); break; case CRYPTO_ALG_TYPE_RNG: seq_printf(seq, "%s %s reqs=%lu tsize=%lu\n", @@ -442,6 +484,16 @@ static int sun8i_ss_debugfs_show(struct seq_file *seq, void *v) ss_algs[i].alg.hash.halg.base.cra_driver_name, ss_algs[i].alg.hash.halg.base.cra_name, ss_algs[i].stat_req, ss_algs[i].stat_fb); + seq_printf(seq, "\tLast fallback is: %s\n", + ss_algs[i].fbname); + seq_printf(seq, "\tFallback due to length: %lu\n", + ss_algs[i].stat_fb_len); + seq_printf(seq, "\tFallback due to SG length: %lu\n", + ss_algs[i].stat_fb_sglen); + seq_printf(seq, "\tFallback due to alignment: %lu\n", + ss_algs[i].stat_fb_align); + seq_printf(seq, "\tFallback due to SG numbers: %lu\n", + ss_algs[i].stat_fb_sgnum); break; } } @@ -464,7 +516,7 @@ static void sun8i_ss_free_flows(struct sun8i_ss_dev *ss, int i) */ static int allocate_flows(struct sun8i_ss_dev *ss) { - int i, err; + int i, j, err; ss->flows = devm_kcalloc(ss->dev, MAXFLOW, sizeof(struct sun8i_ss_flow), GFP_KERNEL); @@ -474,6 +526,28 @@ static int allocate_flows(struct sun8i_ss_dev *ss) for (i = 0; i < MAXFLOW; i++) { init_completion(&ss->flows[i].complete); + ss->flows[i].biv = devm_kmalloc(ss->dev, AES_BLOCK_SIZE, + GFP_KERNEL | GFP_DMA); + if (!ss->flows[i].biv) + goto error_engine; + + for (j = 0; j < MAX_SG; j++) { + ss->flows[i].iv[j] = devm_kmalloc(ss->dev, AES_BLOCK_SIZE, + GFP_KERNEL | GFP_DMA); + if (!ss->flows[i].iv[j]) + goto error_engine; + } + + /* the padding could be up to two block. */ + ss->flows[i].pad = devm_kmalloc(ss->dev, MAX_PAD_SIZE, + GFP_KERNEL | GFP_DMA); + if (!ss->flows[i].pad) + goto error_engine; + ss->flows[i].result = devm_kmalloc(ss->dev, SHA256_DIGEST_SIZE, + GFP_KERNEL | GFP_DMA); + if (!ss->flows[i].result) + goto error_engine; + ss->flows[i].engine = crypto_engine_alloc_init(ss->dev, true); if (!ss->flows[i].engine) { dev_err(ss->dev, "Cannot allocate engine\n"); diff --git a/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-hash.c b/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-hash.c index 1a71ed49d2333c09a88d04ab618f1a6dd86891be..ac417a6b39e5fd2912e38dbb1f573e25ff5e0a36 100644 --- a/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-hash.c +++ b/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-hash.c @@ -14,11 +14,99 @@ #include #include #include +#include +#include #include #include #include #include "sun8i-ss.h" +static int sun8i_ss_hashkey(struct sun8i_ss_hash_tfm_ctx *tfmctx, const u8 *key, + unsigned int keylen) +{ + struct crypto_shash *xtfm; + struct shash_desc *sdesc; + size_t len; + int ret = 0; + + xtfm = crypto_alloc_shash("sha1", 0, CRYPTO_ALG_NEED_FALLBACK); + if (!xtfm) + return -ENOMEM; + + len = sizeof(*sdesc) + crypto_shash_descsize(xtfm); + sdesc = kmalloc(len, GFP_KERNEL); + if (!sdesc) { + ret = -ENOMEM; + goto err_hashkey_sdesc; + } + sdesc->tfm = xtfm; + + ret = crypto_shash_init(sdesc); + if (ret) { + dev_err(tfmctx->ss->dev, "shash init error ret=%d\n", ret); + goto err_hashkey; + } + ret = crypto_shash_finup(sdesc, key, keylen, tfmctx->key); + if (ret) + dev_err(tfmctx->ss->dev, "shash finup error\n"); +err_hashkey: + kfree(sdesc); +err_hashkey_sdesc: + crypto_free_shash(xtfm); + return ret; +} + +int sun8i_ss_hmac_setkey(struct crypto_ahash *ahash, const u8 *key, + unsigned int keylen) +{ + struct sun8i_ss_hash_tfm_ctx *tfmctx = crypto_ahash_ctx(ahash); + struct ahash_alg *alg = __crypto_ahash_alg(ahash->base.__crt_alg); + struct sun8i_ss_alg_template *algt; + int digestsize, i; + int bs = crypto_ahash_blocksize(ahash); + int ret; + + algt = container_of(alg, struct sun8i_ss_alg_template, alg.hash); + digestsize = algt->alg.hash.halg.digestsize; + + if (keylen > bs) { + ret = sun8i_ss_hashkey(tfmctx, key, keylen); + if (ret) + return ret; + tfmctx->keylen = digestsize; + } else { + tfmctx->keylen = keylen; + memcpy(tfmctx->key, key, keylen); + } + + tfmctx->ipad = kzalloc(bs, GFP_KERNEL | GFP_DMA); + if (!tfmctx->ipad) + return -ENOMEM; + tfmctx->opad = kzalloc(bs, GFP_KERNEL | GFP_DMA); + if (!tfmctx->opad) { + ret = -ENOMEM; + goto err_opad; + } + + memset(tfmctx->key + tfmctx->keylen, 0, bs - tfmctx->keylen); + memcpy(tfmctx->ipad, tfmctx->key, tfmctx->keylen); + memcpy(tfmctx->opad, tfmctx->key, tfmctx->keylen); + for (i = 0; i < bs; i++) { + tfmctx->ipad[i] ^= HMAC_IPAD_VALUE; + tfmctx->opad[i] ^= HMAC_OPAD_VALUE; + } + + ret = crypto_ahash_setkey(tfmctx->fallback_tfm, key, keylen); + if (!ret) + return 0; + + memzero_explicit(tfmctx->key, keylen); + kfree_sensitive(tfmctx->opad); +err_opad: + kfree_sensitive(tfmctx->ipad); + return ret; +} + int sun8i_ss_hash_crainit(struct crypto_tfm *tfm) { struct sun8i_ss_hash_tfm_ctx *op = crypto_tfm_ctx(tfm); @@ -50,9 +138,8 @@ int sun8i_ss_hash_crainit(struct crypto_tfm *tfm) sizeof(struct sun8i_ss_hash_reqctx) + crypto_ahash_reqsize(op->fallback_tfm)); - dev_info(op->ss->dev, "Fallback for %s is %s\n", - crypto_tfm_alg_driver_name(tfm), - crypto_tfm_alg_driver_name(&op->fallback_tfm->base)); + memcpy(algt->fbname, crypto_tfm_alg_driver_name(&op->fallback_tfm->base), CRYPTO_MAX_ALG_NAME); + err = pm_runtime_get_sync(op->ss->dev); if (err < 0) goto error_pm; @@ -67,6 +154,9 @@ void sun8i_ss_hash_craexit(struct crypto_tfm *tfm) { struct sun8i_ss_hash_tfm_ctx *tfmctx = crypto_tfm_ctx(tfm); + kfree_sensitive(tfmctx->ipad); + kfree_sensitive(tfmctx->opad); + crypto_free_ahash(tfmctx->fallback_tfm); pm_runtime_put_sync_suspend(tfmctx->ss->dev); } @@ -258,23 +348,48 @@ static int sun8i_ss_run_hash_task(struct sun8i_ss_dev *ss, static bool sun8i_ss_hash_need_fallback(struct ahash_request *areq) { + struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); + struct ahash_alg *alg = __crypto_ahash_alg(tfm->base.__crt_alg); + struct sun8i_ss_alg_template *algt; struct scatterlist *sg; - if (areq->nbytes == 0) + algt = container_of(alg, struct sun8i_ss_alg_template, alg.hash); + + if (areq->nbytes == 0) { + algt->stat_fb_len++; + return true; + } + + if (areq->nbytes >= MAX_PAD_SIZE - 64) { + algt->stat_fb_len++; return true; + } + /* we need to reserve one SG for the padding one */ - if (sg_nents(areq->src) > MAX_SG - 1) + if (sg_nents(areq->src) > MAX_SG - 1) { + algt->stat_fb_sgnum++; return true; + } + sg = areq->src; while (sg) { /* SS can operate hash only on full block size * since SS support only MD5,sha1,sha224 and sha256, blocksize * is always 64 - * TODO: handle request if last SG is not len%64 - * but this will need to copy data on a new SG of size=64 */ - if (sg->length % 64 || !IS_ALIGNED(sg->offset, sizeof(u32))) + /* Only the last block could be bounced to the pad buffer */ + if (sg->length % 64 && sg_next(sg)) { + algt->stat_fb_sglen++; + return true; + } + if (!IS_ALIGNED(sg->offset, sizeof(u32))) { + algt->stat_fb_align++; + return true; + } + if (sg->length % 4) { + algt->stat_fb_sglen++; return true; + } sg = sg_next(sg); } return false; @@ -288,21 +403,11 @@ int sun8i_ss_hash_digest(struct ahash_request *areq) struct sun8i_ss_alg_template *algt; struct sun8i_ss_dev *ss; struct crypto_engine *engine; - struct scatterlist *sg; - int nr_sgs, e, i; + int e; if (sun8i_ss_hash_need_fallback(areq)) return sun8i_ss_hash_digest_fb(areq); - nr_sgs = sg_nents(areq->src); - if (nr_sgs > MAX_SG - 1) - return sun8i_ss_hash_digest_fb(areq); - - for_each_sg(areq->src, sg, nr_sgs, i) { - if (sg->length % 4 || !IS_ALIGNED(sg->offset, sizeof(u32))) - return sun8i_ss_hash_digest_fb(areq); - } - algt = container_of(alg, struct sun8i_ss_alg_template, alg.hash); ss = algt->ss; @@ -313,6 +418,64 @@ int sun8i_ss_hash_digest(struct ahash_request *areq) return crypto_transfer_hash_request_to_engine(engine, areq); } +static u64 hash_pad(__le32 *buf, unsigned int bufsize, u64 padi, u64 byte_count, bool le, int bs) +{ + u64 fill, min_fill, j, k; + __be64 *bebits; + __le64 *lebits; + + j = padi; + buf[j++] = cpu_to_le32(0x80); + + if (bs == 64) { + fill = 64 - (byte_count % 64); + min_fill = 2 * sizeof(u32) + sizeof(u32); + } else { + fill = 128 - (byte_count % 128); + min_fill = 4 * sizeof(u32) + sizeof(u32); + } + + if (fill < min_fill) + fill += bs; + + k = j; + j += (fill - min_fill) / sizeof(u32); + if (j * 4 > bufsize) { + pr_err("%s OVERFLOW %llu\n", __func__, j); + return 0; + } + for (; k < j; k++) + buf[k] = 0; + + if (le) { + /* MD5 */ + lebits = (__le64 *)&buf[j]; + *lebits = cpu_to_le64(byte_count << 3); + j += 2; + } else { + if (bs == 64) { + /* sha1 sha224 sha256 */ + bebits = (__be64 *)&buf[j]; + *bebits = cpu_to_be64(byte_count << 3); + j += 2; + } else { + /* sha384 sha512*/ + bebits = (__be64 *)&buf[j]; + *bebits = cpu_to_be64(byte_count >> 61); + j += 2; + bebits = (__be64 *)&buf[j]; + *bebits = cpu_to_be64(byte_count << 3); + j += 2; + } + } + if (j * 4 > bufsize) { + pr_err("%s OVERFLOW %llu\n", __func__, j); + return 0; + } + + return j; +} + /* sun8i_ss_hash_run - run an ahash request * Send the data of the request to the SS along with an extra SG with padding */ @@ -320,20 +483,26 @@ int sun8i_ss_hash_run(struct crypto_engine *engine, void *breq) { struct ahash_request *areq = container_of(breq, struct ahash_request, base); struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); + struct sun8i_ss_hash_tfm_ctx *tfmctx = crypto_ahash_ctx(tfm); struct ahash_alg *alg = __crypto_ahash_alg(tfm->base.__crt_alg); struct sun8i_ss_hash_reqctx *rctx = ahash_request_ctx(areq); struct sun8i_ss_alg_template *algt; struct sun8i_ss_dev *ss; struct scatterlist *sg; + int bs = crypto_ahash_blocksize(tfm); int nr_sgs, err, digestsize; unsigned int len; - u64 fill, min_fill, byte_count; + u64 byte_count; void *pad, *result; - int j, i, todo; - __be64 *bebits; - __le64 *lebits; - dma_addr_t addr_res, addr_pad; + int j, i, k, todo; + dma_addr_t addr_res, addr_pad, addr_xpad; __le32 *bf; + /* HMAC step: + * 0: normal hashing + * 1: IPAD + * 2: OPAD + */ + int hmac = 0; algt = container_of(alg, struct sun8i_ss_alg_template, alg.hash); ss = algt->ss; @@ -342,18 +511,10 @@ int sun8i_ss_hash_run(struct crypto_engine *engine, void *breq) if (digestsize == SHA224_DIGEST_SIZE) digestsize = SHA256_DIGEST_SIZE; - /* the padding could be up to two block. */ - pad = kzalloc(algt->alg.hash.halg.base.cra_blocksize * 2, GFP_KERNEL | GFP_DMA); - if (!pad) - return -ENOMEM; + result = ss->flows[rctx->flow].result; + pad = ss->flows[rctx->flow].pad; bf = (__le32 *)pad; - result = kzalloc(digestsize, GFP_KERNEL | GFP_DMA); - if (!result) { - kfree(pad); - return -ENOMEM; - } - for (i = 0; i < MAX_SG; i++) { rctx->t_dst[i].addr = 0; rctx->t_dst[i].len = 0; @@ -376,17 +537,33 @@ int sun8i_ss_hash_run(struct crypto_engine *engine, void *breq) if (dma_mapping_error(ss->dev, addr_res)) { dev_err(ss->dev, "DMA map dest\n"); err = -EINVAL; - goto theend; + goto err_dma_result; } + j = 0; len = areq->nbytes; - for_each_sg(areq->src, sg, nr_sgs, i) { - rctx->t_src[i].addr = sg_dma_address(sg); + sg = areq->src; + i = 0; + while (len > 0 && sg) { + if (sg_dma_len(sg) == 0) { + sg = sg_next(sg); + continue; + } todo = min(len, sg_dma_len(sg)); - rctx->t_src[i].len = todo / 4; - len -= todo; - rctx->t_dst[i].addr = addr_res; - rctx->t_dst[i].len = digestsize / 4; + /* only the last SG could be with a size not modulo64 */ + if (todo % 64 == 0) { + rctx->t_src[i].addr = sg_dma_address(sg); + rctx->t_src[i].len = todo / 4; + rctx->t_dst[i].addr = addr_res; + rctx->t_dst[i].len = digestsize / 4; + len -= todo; + } else { + scatterwalk_map_and_copy(bf, sg, 0, todo, 0); + j += todo / 4; + len -= todo; + } + sg = sg_next(sg); + i++; } if (len > 0) { dev_err(ss->dev, "remaining len %d\n", len); @@ -394,55 +571,135 @@ int sun8i_ss_hash_run(struct crypto_engine *engine, void *breq) goto theend; } + if (j > 0) + i--; + +retry: byte_count = areq->nbytes; - j = 0; - bf[j++] = cpu_to_le32(0x80); + if (tfmctx->keylen && hmac == 0) { + hmac = 1; + /* shift all SG one slot up, to free slot 0 for IPAD */ + for (k = 6; k >= 0; k--) { + rctx->t_src[k + 1].addr = rctx->t_src[k].addr; + rctx->t_src[k + 1].len = rctx->t_src[k].len; + rctx->t_dst[k + 1].addr = rctx->t_dst[k].addr; + rctx->t_dst[k + 1].len = rctx->t_dst[k].len; + } + addr_xpad = dma_map_single(ss->dev, tfmctx->ipad, bs, DMA_TO_DEVICE); + if (dma_mapping_error(ss->dev, addr_xpad)) { + dev_err(ss->dev, "Fail to create DMA mapping of ipad\n"); + goto err_dma_xpad; + } + rctx->t_src[0].addr = addr_xpad; + rctx->t_src[0].len = bs / 4; + rctx->t_dst[0].addr = addr_res; + rctx->t_dst[0].len = digestsize / 4; + i++; + byte_count = areq->nbytes + bs; + } + if (tfmctx->keylen && hmac == 2) { + for (i = 0; i < MAX_SG; i++) { + rctx->t_src[i].addr = 0; + rctx->t_src[i].len = 0; + rctx->t_dst[i].addr = 0; + rctx->t_dst[i].len = 0; + } - fill = 64 - (byte_count % 64); - min_fill = 3 * sizeof(u32); + addr_res = dma_map_single(ss->dev, result, digestsize, DMA_FROM_DEVICE); + if (dma_mapping_error(ss->dev, addr_res)) { + dev_err(ss->dev, "Fail to create DMA mapping of result\n"); + err = -EINVAL; + goto err_dma_result; + } + addr_xpad = dma_map_single(ss->dev, tfmctx->opad, bs, DMA_TO_DEVICE); + if (dma_mapping_error(ss->dev, addr_xpad)) { + dev_err(ss->dev, "Fail to create DMA mapping of opad\n"); + goto err_dma_xpad; + } + rctx->t_src[0].addr = addr_xpad; + rctx->t_src[0].len = bs / 4; - if (fill < min_fill) - fill += 64; + memcpy(bf, result, digestsize); + j = digestsize / 4; + i = 1; + byte_count = digestsize + bs; - j += (fill - min_fill) / sizeof(u32); + rctx->t_dst[0].addr = addr_res; + rctx->t_dst[0].len = digestsize / 4; + } switch (algt->ss_algo_id) { case SS_ID_HASH_MD5: - lebits = (__le64 *)&bf[j]; - *lebits = cpu_to_le64(byte_count << 3); - j += 2; + j = hash_pad(bf, 4096, j, byte_count, true, bs); break; case SS_ID_HASH_SHA1: case SS_ID_HASH_SHA224: case SS_ID_HASH_SHA256: - bebits = (__be64 *)&bf[j]; - *bebits = cpu_to_be64(byte_count << 3); - j += 2; + j = hash_pad(bf, 4096, j, byte_count, false, bs); break; } + if (!j) { + err = -EINVAL; + goto theend; + } addr_pad = dma_map_single(ss->dev, pad, j * 4, DMA_TO_DEVICE); - rctx->t_src[i].addr = addr_pad; - rctx->t_src[i].len = j; - rctx->t_dst[i].addr = addr_res; - rctx->t_dst[i].len = digestsize / 4; if (dma_mapping_error(ss->dev, addr_pad)) { dev_err(ss->dev, "DMA error on padding SG\n"); err = -EINVAL; - goto theend; + goto err_dma_pad; } + rctx->t_src[i].addr = addr_pad; + rctx->t_src[i].len = j; + rctx->t_dst[i].addr = addr_res; + rctx->t_dst[i].len = digestsize / 4; err = sun8i_ss_run_hash_task(ss, rctx, crypto_tfm_alg_name(areq->base.tfm)); + /* + * mini helper for checking dma map/unmap + * flow start for hmac = 0 (and HMAC = 1) + * HMAC = 0 + * MAP src + * MAP res + * + * retry: + * if hmac then hmac = 1 + * MAP xpad (ipad) + * if hmac == 2 + * MAP res + * MAP xpad (opad) + * MAP pad + * ACTION! + * UNMAP pad + * if hmac + * UNMAP xpad + * UNMAP res + * if hmac < 2 + * UNMAP SRC + * + * if hmac = 1 then hmac = 2 goto retry + */ + dma_unmap_single(ss->dev, addr_pad, j * 4, DMA_TO_DEVICE); - dma_unmap_sg(ss->dev, areq->src, sg_nents(areq->src), - DMA_TO_DEVICE); + +err_dma_pad: + if (hmac > 0) + dma_unmap_single(ss->dev, addr_xpad, bs, DMA_TO_DEVICE); +err_dma_xpad: dma_unmap_single(ss->dev, addr_res, digestsize, DMA_FROM_DEVICE); +err_dma_result: + if (hmac < 2) + dma_unmap_sg(ss->dev, areq->src, sg_nents(areq->src), + DMA_TO_DEVICE); + if (hmac == 1 && !err) { + hmac = 2; + goto retry; + } - memcpy(areq->result, result, algt->alg.hash.halg.digestsize); + if (!err) + memcpy(areq->result, result, algt->alg.hash.halg.digestsize); theend: - kfree(pad); - kfree(result); local_bh_disable(); crypto_finalize_hash_request(engine, breq, err); local_bh_enable(); diff --git a/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-prng.c b/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-prng.c index 246a6782674c35311709eedd38fe85a6156af5e7..dd677e9ed06f77659768781b974d82d42e2745e4 100644 --- a/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-prng.c +++ b/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-prng.c @@ -112,11 +112,9 @@ int sun8i_ss_prng_generate(struct crypto_rng *tfm, const u8 *src, goto err_iv; } - err = pm_runtime_get_sync(ss->dev); - if (err < 0) { - pm_runtime_put_noidle(ss->dev); + err = pm_runtime_resume_and_get(ss->dev); + if (err < 0) goto err_pm; - } err = 0; mutex_lock(&ss->mlock); diff --git a/drivers/crypto/allwinner/sun8i-ss/sun8i-ss.h b/drivers/crypto/allwinner/sun8i-ss/sun8i-ss.h index 28188685b910087feb0a3579e3b7c1f32e438b79..df6f08f6092f136ef053e52ba6943e397462a93b 100644 --- a/drivers/crypto/allwinner/sun8i-ss/sun8i-ss.h +++ b/drivers/crypto/allwinner/sun8i-ss/sun8i-ss.h @@ -82,6 +82,8 @@ #define PRNG_DATA_SIZE (160 / 8) #define PRNG_SEED_SIZE DIV_ROUND_UP(175, 8) +#define MAX_PAD_SIZE 4096 + /* * struct ss_clock - Describe clocks used by sun8i-ss * @name: Name of clock needed by this variant @@ -121,11 +123,19 @@ struct sginfo { * @complete: completion for the current task on this flow * @status: set to 1 by interrupt if task is done * @stat_req: number of request done by this flow + * @iv: list of IV to use for each step + * @biv: buffer which contain the backuped IV + * @pad: padding buffer for hash operations + * @result: buffer for storing the result of hash operations */ struct sun8i_ss_flow { struct crypto_engine *engine; struct completion complete; int status; + u8 *iv[MAX_SG]; + u8 *biv; + void *pad; + void *result; #ifdef CONFIG_CRYPTO_DEV_SUN8I_SS_DEBUG unsigned long stat_req; #endif @@ -164,28 +174,28 @@ struct sun8i_ss_dev { * @t_src: list of mapped SGs with their size * @t_dst: list of mapped SGs with their size * @p_key: DMA address of the key - * @p_iv: DMA address of the IV + * @p_iv: DMA address of the IVs + * @niv: Number of IVs DMA mapped * @method: current algorithm for this request * @op_mode: op_mode for this request * @op_dir: direction (encrypt vs decrypt) for this request * @flow: the flow to use for this request - * @ivlen: size of biv + * @ivlen: size of IVs * @keylen: keylen for this request - * @biv: buffer which contain the IV * @fallback_req: request struct for invoking the fallback skcipher TFM */ struct sun8i_cipher_req_ctx { struct sginfo t_src[MAX_SG]; struct sginfo t_dst[MAX_SG]; u32 p_key; - u32 p_iv; + u32 p_iv[MAX_SG]; + int niv; u32 method; u32 op_mode; u32 op_dir; int flow; unsigned int ivlen; unsigned int keylen; - void *biv; struct skcipher_request fallback_req; // keep at the end }; @@ -229,6 +239,10 @@ struct sun8i_ss_hash_tfm_ctx { struct crypto_engine_ctx enginectx; struct crypto_ahash *fallback_tfm; struct sun8i_ss_dev *ss; + u8 *ipad; + u8 *opad; + u8 key[SHA256_BLOCK_SIZE]; + int keylen; }; /* @@ -269,11 +283,14 @@ struct sun8i_ss_alg_template { struct rng_alg rng; struct ahash_alg hash; } alg; -#ifdef CONFIG_CRYPTO_DEV_SUN8I_SS_DEBUG unsigned long stat_req; unsigned long stat_fb; unsigned long stat_bytes; -#endif + unsigned long stat_fb_len; + unsigned long stat_fb_sglen; + unsigned long stat_fb_align; + unsigned long stat_fb_sgnum; + char fbname[CRYPTO_MAX_ALG_NAME]; }; int sun8i_ss_enqueue(struct crypto_async_request *areq, u32 type); @@ -306,3 +323,5 @@ int sun8i_ss_hash_update(struct ahash_request *areq); int sun8i_ss_hash_finup(struct ahash_request *areq); int sun8i_ss_hash_digest(struct ahash_request *areq); int sun8i_ss_hash_run(struct crypto_engine *engine, void *breq); +int sun8i_ss_hmac_setkey(struct crypto_ahash *ahash, const u8 *key, + unsigned int keylen); diff --git a/drivers/crypto/atmel-ecc.c b/drivers/crypto/atmel-ecc.c index 333fbefbbccbd94fda92eba0b6c5e666fd7e10ba..59a57279e77bfc4609de022f6d4d07747a5c0935 100644 --- a/drivers/crypto/atmel-ecc.c +++ b/drivers/crypto/atmel-ecc.c @@ -398,7 +398,7 @@ static int __init atmel_ecc_init(void) static void __exit atmel_ecc_exit(void) { - flush_scheduled_work(); + atmel_i2c_flush_queue(); i2c_del_driver(&atmel_ecc_driver); } diff --git a/drivers/crypto/atmel-i2c.c b/drivers/crypto/atmel-i2c.c index 6fd3e969211d7aa7d14fc14fb94b18610d093b62..81ce09bedda8f4348ba25ca8a676a92f83d2c96b 100644 --- a/drivers/crypto/atmel-i2c.c +++ b/drivers/crypto/atmel-i2c.c @@ -263,6 +263,8 @@ static void atmel_i2c_work_handler(struct work_struct *work) work_data->cbk(work_data, work_data->areq, status); } +static struct workqueue_struct *atmel_wq; + void atmel_i2c_enqueue(struct atmel_i2c_work_data *work_data, void (*cbk)(struct atmel_i2c_work_data *work_data, void *areq, int status), @@ -272,10 +274,16 @@ void atmel_i2c_enqueue(struct atmel_i2c_work_data *work_data, work_data->areq = areq; INIT_WORK(&work_data->work, atmel_i2c_work_handler); - schedule_work(&work_data->work); + queue_work(atmel_wq, &work_data->work); } EXPORT_SYMBOL(atmel_i2c_enqueue); +void atmel_i2c_flush_queue(void) +{ + flush_workqueue(atmel_wq); +} +EXPORT_SYMBOL(atmel_i2c_flush_queue); + static inline size_t atmel_i2c_wake_token_sz(u32 bus_clk_rate) { u32 no_of_bits = DIV_ROUND_UP(TWLO_USEC * bus_clk_rate, USEC_PER_SEC); @@ -364,14 +372,24 @@ int atmel_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) i2c_set_clientdata(client, i2c_priv); - ret = device_sanity_check(client); - if (ret) - return ret; - - return 0; + return device_sanity_check(client); } EXPORT_SYMBOL(atmel_i2c_probe); +static int __init atmel_i2c_init(void) +{ + atmel_wq = alloc_workqueue("atmel_wq", 0, 0); + return atmel_wq ? 0 : -ENOMEM; +} + +static void __exit atmel_i2c_exit(void) +{ + destroy_workqueue(atmel_wq); +} + +module_init(atmel_i2c_init); +module_exit(atmel_i2c_exit); + MODULE_AUTHOR("Tudor Ambarus "); MODULE_DESCRIPTION("Microchip / Atmel ECC (I2C) driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/crypto/atmel-i2c.h b/drivers/crypto/atmel-i2c.h index 63b97b104f16f580db069a788335dc2f706f5b85..48929efe2a5bf20112c1e0cc2ec178b7fb1ad107 100644 --- a/drivers/crypto/atmel-i2c.h +++ b/drivers/crypto/atmel-i2c.h @@ -173,6 +173,7 @@ void atmel_i2c_enqueue(struct atmel_i2c_work_data *work_data, void (*cbk)(struct atmel_i2c_work_data *work_data, void *areq, int status), void *areq); +void atmel_i2c_flush_queue(void); int atmel_i2c_send_receive(struct i2c_client *client, struct atmel_i2c_cmd *cmd); diff --git a/drivers/crypto/atmel-sha204a.c b/drivers/crypto/atmel-sha204a.c index c96c14e7dab1c0ae89fd026bb733155cf761659c..e4087bdd24759960b21aa3b102edb2b49849578a 100644 --- a/drivers/crypto/atmel-sha204a.c +++ b/drivers/crypto/atmel-sha204a.c @@ -121,23 +121,24 @@ static int atmel_sha204a_remove(struct i2c_client *client) struct atmel_i2c_client_priv *i2c_priv = i2c_get_clientdata(client); if (atomic_read(&i2c_priv->tfm_count)) { - dev_err(&client->dev, "Device is busy\n"); - return -EBUSY; + dev_emerg(&client->dev, "Device is busy, will remove it anyhow\n"); + return 0; } - if (i2c_priv->hwrng.priv) - kfree((void *)i2c_priv->hwrng.priv); + kfree((void *)i2c_priv->hwrng.priv); return 0; } static const struct of_device_id atmel_sha204a_dt_ids[] = { + { .compatible = "atmel,atsha204", }, { .compatible = "atmel,atsha204a", }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, atmel_sha204a_dt_ids); static const struct i2c_device_id atmel_sha204a_id[] = { + { "atsha204", 0 }, { "atsha204a", 0 }, { /* sentinel */ } }; @@ -159,7 +160,7 @@ static int __init atmel_sha204a_init(void) static void __exit atmel_sha204a_exit(void) { - flush_scheduled_work(); + atmel_i2c_flush_queue(); i2c_del_driver(&atmel_sha204a_driver); } diff --git a/drivers/crypto/caam/Kconfig b/drivers/crypto/caam/Kconfig index ea9f8b1ae981cf86046a6cbac6af9e51c845d075..ec6a9e6ad4d237195a658da3e265c3c5cf9b1e1e 100644 --- a/drivers/crypto/caam/Kconfig +++ b/drivers/crypto/caam/Kconfig @@ -151,6 +151,14 @@ config CRYPTO_DEV_FSL_CAAM_RNG_API Selecting this will register the SEC4 hardware rng to the hw_random API for supplying the kernel entropy pool. +config CRYPTO_DEV_FSL_CAAM_PRNG_API + bool "Register Pseudo random number generation implementation with Crypto API" + default y + select CRYPTO_RNG + help + Selecting this will register the SEC hardware prng to + the Crypto API. + config CRYPTO_DEV_FSL_CAAM_BLOB_GEN bool diff --git a/drivers/crypto/caam/Makefile b/drivers/crypto/caam/Makefile index 25f7ae5a4642e738a6594954e0709a635716055d..acf1b197eb84ba7d540e08fad2ce5b634f4d4e65 100644 --- a/drivers/crypto/caam/Makefile +++ b/drivers/crypto/caam/Makefile @@ -20,6 +20,7 @@ caam_jr-$(CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API) += caamalg.o caam_jr-$(CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API_QI) += caamalg_qi.o caam_jr-$(CONFIG_CRYPTO_DEV_FSL_CAAM_AHASH_API) += caamhash.o caam_jr-$(CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_API) += caamrng.o +caam_jr-$(CONFIG_CRYPTO_DEV_FSL_CAAM_PRNG_API) += caamprng.o caam_jr-$(CONFIG_CRYPTO_DEV_FSL_CAAM_PKC_API) += caampkc.o pkc_desc.o caam_jr-$(CONFIG_CRYPTO_DEV_FSL_CAAM_BLOB_GEN) += blob_gen.o diff --git a/drivers/crypto/caam/caamprng.c b/drivers/crypto/caam/caamprng.c new file mode 100644 index 0000000000000000000000000000000000000000..4839e66300a23bfaed0e0e516591a2a3c158e61a --- /dev/null +++ b/drivers/crypto/caam/caamprng.c @@ -0,0 +1,235 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Driver to expose SEC4 PRNG via crypto RNG API + * + * Copyright 2022 NXP + * + */ + +#include +#include +#include "compat.h" +#include "regs.h" +#include "intern.h" +#include "desc_constr.h" +#include "jr.h" +#include "error.h" + +/* + * Length of used descriptors, see caam_init_desc() + */ +#define CAAM_PRNG_MAX_DESC_LEN (CAAM_CMD_SZ + \ + CAAM_CMD_SZ + \ + CAAM_CMD_SZ + CAAM_PTR_SZ_MAX) + +/* prng per-device context */ +struct caam_prng_ctx { + int err; + struct completion done; +}; + +struct caam_prng_alg { + struct rng_alg rng; + bool registered; +}; + +static void caam_prng_done(struct device *jrdev, u32 *desc, u32 err, + void *context) +{ + struct caam_prng_ctx *jctx = context; + + jctx->err = err ? caam_jr_strstatus(jrdev, err) : 0; + + complete(&jctx->done); +} + +static u32 *caam_init_reseed_desc(u32 *desc) +{ + init_job_desc(desc, 0); /* + 1 cmd_sz */ + /* Generate random bytes: + 1 cmd_sz */ + append_operation(desc, OP_TYPE_CLASS1_ALG | OP_ALG_ALGSEL_RNG | + OP_ALG_AS_FINALIZE); + + print_hex_dump_debug("prng reseed desc@: ", DUMP_PREFIX_ADDRESS, + 16, 4, desc, desc_bytes(desc), 1); + + return desc; +} + +static u32 *caam_init_prng_desc(u32 *desc, dma_addr_t dst_dma, u32 len) +{ + init_job_desc(desc, 0); /* + 1 cmd_sz */ + /* Generate random bytes: + 1 cmd_sz */ + append_operation(desc, OP_ALG_ALGSEL_RNG | OP_TYPE_CLASS1_ALG); + /* Store bytes: + 1 cmd_sz + caam_ptr_sz */ + append_fifo_store(desc, dst_dma, + len, FIFOST_TYPE_RNGSTORE); + + print_hex_dump_debug("prng job desc@: ", DUMP_PREFIX_ADDRESS, + 16, 4, desc, desc_bytes(desc), 1); + + return desc; +} + +static int caam_prng_generate(struct crypto_rng *tfm, + const u8 *src, unsigned int slen, + u8 *dst, unsigned int dlen) +{ + struct caam_prng_ctx ctx; + struct device *jrdev; + dma_addr_t dst_dma; + u32 *desc; + u8 *buf; + int ret; + + buf = kzalloc(dlen, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + jrdev = caam_jr_alloc(); + ret = PTR_ERR_OR_ZERO(jrdev); + if (ret) { + pr_err("Job Ring Device allocation failed\n"); + kfree(buf); + return ret; + } + + desc = kzalloc(CAAM_PRNG_MAX_DESC_LEN, GFP_KERNEL | GFP_DMA); + if (!desc) { + ret = -ENOMEM; + goto out1; + } + + dst_dma = dma_map_single(jrdev, buf, dlen, DMA_FROM_DEVICE); + if (dma_mapping_error(jrdev, dst_dma)) { + dev_err(jrdev, "Failed to map destination buffer memory\n"); + ret = -ENOMEM; + goto out; + } + + init_completion(&ctx.done); + ret = caam_jr_enqueue(jrdev, + caam_init_prng_desc(desc, dst_dma, dlen), + caam_prng_done, &ctx); + + if (ret == -EINPROGRESS) { + wait_for_completion(&ctx.done); + ret = ctx.err; + } + + dma_unmap_single(jrdev, dst_dma, dlen, DMA_FROM_DEVICE); + + if (!ret) + memcpy(dst, buf, dlen); +out: + kfree(desc); +out1: + caam_jr_free(jrdev); + kfree(buf); + return ret; +} + +static void caam_prng_exit(struct crypto_tfm *tfm) {} + +static int caam_prng_init(struct crypto_tfm *tfm) +{ + return 0; +} + +static int caam_prng_seed(struct crypto_rng *tfm, + const u8 *seed, unsigned int slen) +{ + struct caam_prng_ctx ctx; + struct device *jrdev; + u32 *desc; + int ret; + + if (slen) { + pr_err("Seed length should be zero\n"); + return -EINVAL; + } + + jrdev = caam_jr_alloc(); + ret = PTR_ERR_OR_ZERO(jrdev); + if (ret) { + pr_err("Job Ring Device allocation failed\n"); + return ret; + } + + desc = kzalloc(CAAM_PRNG_MAX_DESC_LEN, GFP_KERNEL | GFP_DMA); + if (!desc) { + caam_jr_free(jrdev); + return -ENOMEM; + } + + init_completion(&ctx.done); + ret = caam_jr_enqueue(jrdev, + caam_init_reseed_desc(desc), + caam_prng_done, &ctx); + + if (ret == -EINPROGRESS) { + wait_for_completion(&ctx.done); + ret = ctx.err; + } + + kfree(desc); + caam_jr_free(jrdev); + return ret; +} + +static struct caam_prng_alg caam_prng_alg = { + .rng = { + .generate = caam_prng_generate, + .seed = caam_prng_seed, + .seedsize = 0, + .base = { + .cra_name = "stdrng", + .cra_driver_name = "prng-caam", + .cra_priority = 500, + .cra_ctxsize = sizeof(struct caam_prng_ctx), + .cra_module = THIS_MODULE, + .cra_init = caam_prng_init, + .cra_exit = caam_prng_exit, + }, + } +}; + +void caam_prng_unregister(void *data) +{ + if (caam_prng_alg.registered) + crypto_unregister_rng(&caam_prng_alg.rng); +} + +int caam_prng_register(struct device *ctrldev) +{ + struct caam_drv_private *priv = dev_get_drvdata(ctrldev); + u32 rng_inst; + int ret = 0; + + /* Check for available RNG blocks before registration */ + if (priv->era < 10) + rng_inst = (rd_reg32(&priv->jr[0]->perfmon.cha_num_ls) & + CHA_ID_LS_RNG_MASK) >> CHA_ID_LS_RNG_SHIFT; + else + rng_inst = rd_reg32(&priv->jr[0]->vreg.rng) & CHA_VER_NUM_MASK; + + if (!rng_inst) { + dev_dbg(ctrldev, "RNG block is not available... skipping registering algorithm\n"); + return ret; + } + + ret = crypto_register_rng(&caam_prng_alg.rng); + if (ret) { + dev_err(ctrldev, + "couldn't register rng crypto alg: %d\n", + ret); + return ret; + } + + caam_prng_alg.registered = true; + + dev_info(ctrldev, + "rng crypto API alg registered %s\n", caam_prng_alg.rng.base.cra_driver_name); + + return 0; +} diff --git a/drivers/crypto/caam/ctrl.c b/drivers/crypto/caam/ctrl.c index 38c4d88a9d03d7fe0f0285fffc538cf30833dbdd..32253a064d0fec27eead334e0e57a5d466edf495 100644 --- a/drivers/crypto/caam/ctrl.c +++ b/drivers/crypto/caam/ctrl.c @@ -609,6 +609,13 @@ static bool check_version(struct fsl_mc_version *mc_version, u32 major, } #endif +static bool needs_entropy_delay_adjustment(void) +{ + if (of_machine_is_compatible("fsl,imx6sx")) + return true; + return false; +} + /* Probe routine for CAAM top (controller) level */ static int caam_probe(struct platform_device *pdev) { @@ -868,6 +875,8 @@ static int caam_probe(struct platform_device *pdev) * Also, if a handle was instantiated, do not change * the TRNG parameters. */ + if (needs_entropy_delay_adjustment()) + ent_delay = 12000; if (!(ctrlpriv->rng4_sh_init || inst_handles)) { dev_info(dev, "Entropy delay = %u\n", @@ -884,6 +893,15 @@ static int caam_probe(struct platform_device *pdev) */ ret = instantiate_rng(dev, inst_handles, gen_sk); + /* + * Entropy delay is determined via TRNG characterization. + * TRNG characterization is run across different voltages + * and temperatures. + * If worst case value for ent_dly is identified, + * the loop can be skipped for that platform. + */ + if (needs_entropy_delay_adjustment()) + break; if (ret == -EAGAIN) /* * if here, the loop will rerun, diff --git a/drivers/crypto/caam/intern.h b/drivers/crypto/caam/intern.h index e92210e2ab76339f370504477dea57d0770d5960..572cf66c887a055b72d145ead8ece8c923abc461 100644 --- a/drivers/crypto/caam/intern.h +++ b/drivers/crypto/caam/intern.h @@ -186,6 +186,21 @@ static inline void caam_rng_exit(struct device *dev) {} #endif /* CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_API */ +#ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_PRNG_API + +int caam_prng_register(struct device *dev); +void caam_prng_unregister(void *data); + +#else + +static inline int caam_prng_register(struct device *dev) +{ + return 0; +} + +static inline void caam_prng_unregister(void *data) {} +#endif /* CONFIG_CRYPTO_DEV_FSL_CAAM_PRNG_API */ + #ifdef CONFIG_CAAM_QI int caam_qi_algapi_init(struct device *dev); diff --git a/drivers/crypto/caam/jr.c b/drivers/crypto/caam/jr.c index 7f2b1101f5677db69c5e18e8976f8f965e728481..724fdec18bf9782083bd7ce7215844dc15a07398 100644 --- a/drivers/crypto/caam/jr.c +++ b/drivers/crypto/caam/jr.c @@ -39,6 +39,7 @@ static void register_algs(struct caam_drv_private_jr *jrpriv, caam_algapi_hash_init(dev); caam_pkc_init(dev); jrpriv->hwrng = !caam_rng_init(dev); + caam_prng_register(dev); caam_qi_algapi_init(dev); algs_unlock: @@ -53,7 +54,7 @@ static void unregister_algs(void) goto algs_unlock; caam_qi_algapi_exit(); - + caam_prng_unregister(NULL); caam_pkc_exit(); caam_algapi_hash_exit(); caam_algapi_exit(); diff --git a/drivers/crypto/cavium/nitrox/nitrox_main.c b/drivers/crypto/cavium/nitrox/nitrox_main.c index 6c61817996a3338b5a193557f7ffd5cb06fd3bb6..432a61aca0c5fae3994e9428e2916e659b738e36 100644 --- a/drivers/crypto/cavium/nitrox/nitrox_main.c +++ b/drivers/crypto/cavium/nitrox/nitrox_main.c @@ -269,15 +269,17 @@ static void nitrox_remove_from_devlist(struct nitrox_device *ndev) struct nitrox_device *nitrox_get_first_device(void) { - struct nitrox_device *ndev; + struct nitrox_device *ndev = NULL, *iter; mutex_lock(&devlist_lock); - list_for_each_entry(ndev, &ndevlist, list) { - if (nitrox_ready(ndev)) + list_for_each_entry(iter, &ndevlist, list) { + if (nitrox_ready(iter)) { + ndev = iter; break; + } } mutex_unlock(&devlist_lock); - if (&ndev->list == &ndevlist) + if (!ndev) return NULL; refcount_inc(&ndev->refcnt); diff --git a/drivers/crypto/ccp/psp-dev.c b/drivers/crypto/ccp/psp-dev.c index ae7b4459991448a662fe63a3094d770840517081..c9c741ac84421929715691f567fccd90fe77a2e4 100644 --- a/drivers/crypto/ccp/psp-dev.c +++ b/drivers/crypto/ccp/psp-dev.c @@ -70,17 +70,23 @@ static unsigned int psp_get_capability(struct psp_device *psp) */ if (val == 0xffffffff) { dev_notice(psp->dev, "psp: unable to access the device: you might be running a broken BIOS.\n"); - return 0; + return -ENODEV; } + psp->capability = val; + + /* Detect if TSME and SME are both enabled */ + if (psp->capability & PSP_CAPABILITY_PSP_SECURITY_REPORTING && + psp->capability & (PSP_SECURITY_TSME_STATUS << PSP_CAPABILITY_PSP_SECURITY_OFFSET) && + cc_platform_has(CC_ATTR_HOST_MEM_ENCRYPT)) + dev_notice(psp->dev, "psp: Both TSME and SME are active, SME is unnecessary when TSME is active.\n"); - return val; + return 0; } -static int psp_check_sev_support(struct psp_device *psp, - unsigned int capability) +static int psp_check_sev_support(struct psp_device *psp) { /* Check if device supports SEV feature */ - if (!(capability & 1)) { + if (!(psp->capability & PSP_CAPABILITY_SEV)) { dev_dbg(psp->dev, "psp does not support SEV\n"); return -ENODEV; } @@ -88,11 +94,10 @@ static int psp_check_sev_support(struct psp_device *psp, return 0; } -static int psp_check_tee_support(struct psp_device *psp, - unsigned int capability) +static int psp_check_tee_support(struct psp_device *psp) { /* Check if device supports TEE feature */ - if (!(capability & 2)) { + if (!(psp->capability & PSP_CAPABILITY_TEE)) { dev_dbg(psp->dev, "psp does not support TEE\n"); return -ENODEV; } @@ -100,30 +105,17 @@ static int psp_check_tee_support(struct psp_device *psp, return 0; } -static int psp_check_support(struct psp_device *psp, - unsigned int capability) -{ - int sev_support = psp_check_sev_support(psp, capability); - int tee_support = psp_check_tee_support(psp, capability); - - /* Return error if device neither supports SEV nor TEE */ - if (sev_support && tee_support) - return -ENODEV; - - return 0; -} - -static int psp_init(struct psp_device *psp, unsigned int capability) +static int psp_init(struct psp_device *psp) { int ret; - if (!psp_check_sev_support(psp, capability)) { + if (!psp_check_sev_support(psp)) { ret = sev_dev_init(psp); if (ret) return ret; } - if (!psp_check_tee_support(psp, capability)) { + if (!psp_check_tee_support(psp)) { ret = tee_dev_init(psp); if (ret) return ret; @@ -136,7 +128,6 @@ int psp_dev_init(struct sp_device *sp) { struct device *dev = sp->dev; struct psp_device *psp; - unsigned int capability; int ret; ret = -ENOMEM; @@ -155,11 +146,7 @@ int psp_dev_init(struct sp_device *sp) psp->io_regs = sp->io_map; - capability = psp_get_capability(psp); - if (!capability) - goto e_disable; - - ret = psp_check_support(psp, capability); + ret = psp_get_capability(psp); if (ret) goto e_disable; @@ -174,7 +161,7 @@ int psp_dev_init(struct sp_device *sp) goto e_err; } - ret = psp_init(psp, capability); + ret = psp_init(psp); if (ret) goto e_irq; diff --git a/drivers/crypto/ccp/psp-dev.h b/drivers/crypto/ccp/psp-dev.h index ef38e4135d810ff44f4006af8858be16c7aa8e47..d528eb04c3ef674ce3bf466b0441d8e2629906aa 100644 --- a/drivers/crypto/ccp/psp-dev.h +++ b/drivers/crypto/ccp/psp-dev.h @@ -45,6 +45,8 @@ struct psp_device { void *sev_data; void *tee_data; + + unsigned int capability; }; void psp_set_sev_irq_handler(struct psp_device *psp, psp_irq_handler_t handler, @@ -57,4 +59,24 @@ void psp_clear_tee_irq_handler(struct psp_device *psp); struct psp_device *psp_get_master_device(void); +#define PSP_CAPABILITY_SEV BIT(0) +#define PSP_CAPABILITY_TEE BIT(1) +#define PSP_CAPABILITY_PSP_SECURITY_REPORTING BIT(7) + +#define PSP_CAPABILITY_PSP_SECURITY_OFFSET 8 +/* + * The PSP doesn't directly store these bits in the capability register + * but instead copies them from the results of query command. + * + * The offsets from the query command are below, and shifted when used. + */ +#define PSP_SECURITY_FUSED_PART BIT(0) +#define PSP_SECURITY_DEBUG_LOCK_ON BIT(2) +#define PSP_SECURITY_TSME_STATUS BIT(5) +#define PSP_SECURITY_ANTI_ROLLBACK_STATUS BIT(7) +#define PSP_SECURITY_RPMC_PRODUCTION_ENABLED BIT(8) +#define PSP_SECURITY_RPMC_SPIROM_AVAILABLE BIT(9) +#define PSP_SECURITY_HSP_TPM_AVAILABLE BIT(10) +#define PSP_SECURITY_ROM_ARMOR_ENFORCED BIT(11) + #endif /* __PSP_DEV_H */ diff --git a/drivers/crypto/ccp/sev-dev.c b/drivers/crypto/ccp/sev-dev.c index 6ab93dfd478a99f8c36cdf640990986d9d7f774d..799b476fc3e8210bc70db064188feecf2009b3f1 100644 --- a/drivers/crypto/ccp/sev-dev.c +++ b/drivers/crypto/ccp/sev-dev.c @@ -23,6 +23,7 @@ #include #include #include +#include #include @@ -170,6 +171,31 @@ static void *sev_fw_alloc(unsigned long len) return page_address(page); } +static struct file *open_file_as_root(const char *filename, int flags, umode_t mode) +{ + struct file *fp; + struct path root; + struct cred *cred; + const struct cred *old_cred; + + task_lock(&init_task); + get_fs_root(init_task.fs, &root); + task_unlock(&init_task); + + cred = prepare_creds(); + if (!cred) + return ERR_PTR(-ENOMEM); + cred->fsuid = GLOBAL_ROOT_UID; + old_cred = override_creds(cred); + + fp = file_open_root(&root, filename, flags, mode); + path_put(&root); + + revert_creds(old_cred); + + return fp; +} + static int sev_read_init_ex_file(void) { struct sev_device *sev = psp_master->sev_data; @@ -181,7 +207,7 @@ static int sev_read_init_ex_file(void) if (!sev_init_ex_buffer) return -EOPNOTSUPP; - fp = filp_open(init_ex_path, O_RDONLY, 0); + fp = open_file_as_root(init_ex_path, O_RDONLY, 0); if (IS_ERR(fp)) { int ret = PTR_ERR(fp); @@ -217,7 +243,7 @@ static void sev_write_init_ex_file(void) if (!sev_init_ex_buffer) return; - fp = filp_open(init_ex_path, O_CREAT | O_WRONLY, 0600); + fp = open_file_as_root(init_ex_path, O_CREAT | O_WRONLY, 0600); if (IS_ERR(fp)) { dev_err(sev->dev, "SEV: could not open file for write, error %ld\n", @@ -435,7 +461,7 @@ static int __sev_platform_init_locked(int *error) * initialization function should succeed by replacing the state * with a reset state. */ - dev_dbg(sev->dev, "SEV: retrying INIT command"); + dev_err(sev->dev, "SEV: retrying INIT command because of SECURE_DATA_INVALID error. Retrying once to reset PSP SEV state."); rc = init_function(&psp_ret); } if (error) diff --git a/drivers/crypto/ccp/sp-pci.c b/drivers/crypto/ccp/sp-pci.c index 88c672ad27e445776184b4e88c8ef8517f3a4a6b..b5970ae54d0ea20cf8cb4f36144e11151e2de7e6 100644 --- a/drivers/crypto/ccp/sp-pci.c +++ b/drivers/crypto/ccp/sp-pci.c @@ -32,6 +32,67 @@ struct sp_pci { }; static struct sp_device *sp_dev_master; +#define attribute_show(name, def) \ +static ssize_t name##_show(struct device *d, struct device_attribute *attr, \ + char *buf) \ +{ \ + struct sp_device *sp = dev_get_drvdata(d); \ + struct psp_device *psp = sp->psp_data; \ + int bit = PSP_SECURITY_##def << PSP_CAPABILITY_PSP_SECURITY_OFFSET; \ + return sysfs_emit(buf, "%d\n", (psp->capability & bit) > 0); \ +} + +attribute_show(fused_part, FUSED_PART) +static DEVICE_ATTR_RO(fused_part); +attribute_show(debug_lock_on, DEBUG_LOCK_ON) +static DEVICE_ATTR_RO(debug_lock_on); +attribute_show(tsme_status, TSME_STATUS) +static DEVICE_ATTR_RO(tsme_status); +attribute_show(anti_rollback_status, ANTI_ROLLBACK_STATUS) +static DEVICE_ATTR_RO(anti_rollback_status); +attribute_show(rpmc_production_enabled, RPMC_PRODUCTION_ENABLED) +static DEVICE_ATTR_RO(rpmc_production_enabled); +attribute_show(rpmc_spirom_available, RPMC_SPIROM_AVAILABLE) +static DEVICE_ATTR_RO(rpmc_spirom_available); +attribute_show(hsp_tpm_available, HSP_TPM_AVAILABLE) +static DEVICE_ATTR_RO(hsp_tpm_available); +attribute_show(rom_armor_enforced, ROM_ARMOR_ENFORCED) +static DEVICE_ATTR_RO(rom_armor_enforced); + +static struct attribute *psp_attrs[] = { + &dev_attr_fused_part.attr, + &dev_attr_debug_lock_on.attr, + &dev_attr_tsme_status.attr, + &dev_attr_anti_rollback_status.attr, + &dev_attr_rpmc_production_enabled.attr, + &dev_attr_rpmc_spirom_available.attr, + &dev_attr_hsp_tpm_available.attr, + &dev_attr_rom_armor_enforced.attr, + NULL +}; + +static umode_t psp_security_is_visible(struct kobject *kobj, struct attribute *attr, int idx) +{ + struct device *dev = kobj_to_dev(kobj); + struct sp_device *sp = dev_get_drvdata(dev); + struct psp_device *psp = sp->psp_data; + + if (psp && (psp->capability & PSP_CAPABILITY_PSP_SECURITY_REPORTING)) + return 0444; + + return 0; +} + +static struct attribute_group psp_attr_group = { + .attrs = psp_attrs, + .is_visible = psp_security_is_visible, +}; + +static const struct attribute_group *psp_groups[] = { + &psp_attr_group, + NULL, +}; + static int sp_get_msix_irqs(struct sp_device *sp) { struct sp_pci *sp_pci = sp->dev_specific; @@ -391,6 +452,7 @@ static struct pci_driver sp_pci_driver = { .remove = sp_pci_remove, .shutdown = sp_pci_shutdown, .driver.pm = &sp_pci_pm_ops, + .dev_groups = psp_groups, }; int sp_pci_init(void) diff --git a/drivers/crypto/ccree/cc_buffer_mgr.c b/drivers/crypto/ccree/cc_buffer_mgr.c index 11e0278c8631d2e0b2ea5f0e406b02074218a658..6140e492732265b0af70b6b00c53c6dd7e82d774 100644 --- a/drivers/crypto/ccree/cc_buffer_mgr.c +++ b/drivers/crypto/ccree/cc_buffer_mgr.c @@ -356,12 +356,14 @@ void cc_unmap_cipher_request(struct device *dev, void *ctx, req_ctx->mlli_params.mlli_dma_addr); } - dma_unmap_sg(dev, src, req_ctx->in_nents, DMA_BIDIRECTIONAL); - dev_dbg(dev, "Unmapped req->src=%pK\n", sg_virt(src)); - if (src != dst) { - dma_unmap_sg(dev, dst, req_ctx->out_nents, DMA_BIDIRECTIONAL); + dma_unmap_sg(dev, src, req_ctx->in_nents, DMA_TO_DEVICE); + dma_unmap_sg(dev, dst, req_ctx->out_nents, DMA_FROM_DEVICE); dev_dbg(dev, "Unmapped req->dst=%pK\n", sg_virt(dst)); + dev_dbg(dev, "Unmapped req->src=%pK\n", sg_virt(src)); + } else { + dma_unmap_sg(dev, src, req_ctx->in_nents, DMA_BIDIRECTIONAL); + dev_dbg(dev, "Unmapped req->src=%pK\n", sg_virt(src)); } } @@ -377,6 +379,7 @@ int cc_map_cipher_request(struct cc_drvdata *drvdata, void *ctx, u32 dummy = 0; int rc = 0; u32 mapped_nents = 0; + int src_direction = (src != dst ? DMA_TO_DEVICE : DMA_BIDIRECTIONAL); req_ctx->dma_buf_type = CC_DMA_BUF_DLLI; mlli_params->curr_pool = NULL; @@ -399,7 +402,7 @@ int cc_map_cipher_request(struct cc_drvdata *drvdata, void *ctx, } /* Map the src SGL */ - rc = cc_map_sg(dev, src, nbytes, DMA_BIDIRECTIONAL, &req_ctx->in_nents, + rc = cc_map_sg(dev, src, nbytes, src_direction, &req_ctx->in_nents, LLI_MAX_NUM_OF_DATA_ENTRIES, &dummy, &mapped_nents); if (rc) goto cipher_exit; @@ -416,7 +419,7 @@ int cc_map_cipher_request(struct cc_drvdata *drvdata, void *ctx, } } else { /* Map the dst sg */ - rc = cc_map_sg(dev, dst, nbytes, DMA_BIDIRECTIONAL, + rc = cc_map_sg(dev, dst, nbytes, DMA_FROM_DEVICE, &req_ctx->out_nents, LLI_MAX_NUM_OF_DATA_ENTRIES, &dummy, &mapped_nents); if (rc) @@ -456,6 +459,7 @@ void cc_unmap_aead_request(struct device *dev, struct aead_request *req) struct aead_req_ctx *areq_ctx = aead_request_ctx(req); unsigned int hw_iv_size = areq_ctx->hw_iv_size; struct cc_drvdata *drvdata = dev_get_drvdata(dev); + int src_direction = (req->src != req->dst ? DMA_TO_DEVICE : DMA_BIDIRECTIONAL); if (areq_ctx->mac_buf_dma_addr) { dma_unmap_single(dev, areq_ctx->mac_buf_dma_addr, @@ -514,13 +518,11 @@ void cc_unmap_aead_request(struct device *dev, struct aead_request *req) sg_virt(req->src), areq_ctx->src.nents, areq_ctx->assoc.nents, areq_ctx->assoclen, req->cryptlen); - dma_unmap_sg(dev, req->src, areq_ctx->src.mapped_nents, - DMA_BIDIRECTIONAL); + dma_unmap_sg(dev, req->src, areq_ctx->src.mapped_nents, src_direction); if (req->src != req->dst) { dev_dbg(dev, "Unmapping dst sgl: req->dst=%pK\n", sg_virt(req->dst)); - dma_unmap_sg(dev, req->dst, areq_ctx->dst.mapped_nents, - DMA_BIDIRECTIONAL); + dma_unmap_sg(dev, req->dst, areq_ctx->dst.mapped_nents, DMA_FROM_DEVICE); } if (drvdata->coherent && areq_ctx->gen_ctx.op_type == DRV_CRYPTO_DIRECTION_DECRYPT && @@ -843,7 +845,7 @@ static int cc_aead_chain_data(struct cc_drvdata *drvdata, else size_for_map -= authsize; - rc = cc_map_sg(dev, req->dst, size_for_map, DMA_BIDIRECTIONAL, + rc = cc_map_sg(dev, req->dst, size_for_map, DMA_FROM_DEVICE, &areq_ctx->dst.mapped_nents, LLI_MAX_NUM_OF_DATA_ENTRIES, &dst_last_bytes, &dst_mapped_nents); @@ -1056,7 +1058,8 @@ int cc_map_aead_request(struct cc_drvdata *drvdata, struct aead_request *req) size_to_map += authsize; } - rc = cc_map_sg(dev, req->src, size_to_map, DMA_BIDIRECTIONAL, + rc = cc_map_sg(dev, req->src, size_to_map, + (req->src != req->dst ? DMA_TO_DEVICE : DMA_BIDIRECTIONAL), &areq_ctx->src.mapped_nents, (LLI_MAX_NUM_OF_ASSOC_DATA_ENTRIES + LLI_MAX_NUM_OF_DATA_ENTRIES), diff --git a/drivers/crypto/ccree/cc_driver.c b/drivers/crypto/ccree/cc_driver.c index 790fa9058a36d02382e7239f33805ecfbe887165..7d1bee86d58108fa8409d86d5740eda1eb3f324a 100644 --- a/drivers/crypto/ccree/cc_driver.c +++ b/drivers/crypto/ccree/cc_driver.c @@ -529,24 +529,26 @@ static int init_cc_resources(struct platform_device *plat_dev) goto post_req_mgr_err; } - /* Allocate crypto algs */ - rc = cc_cipher_alloc(new_drvdata); + /* hash must be allocated first due to use of send_request_init() + * and dependency of AEAD on it + */ + rc = cc_hash_alloc(new_drvdata); if (rc) { - dev_err(dev, "cc_cipher_alloc failed\n"); + dev_err(dev, "cc_hash_alloc failed\n"); goto post_buf_mgr_err; } - /* hash must be allocated before aead since hash exports APIs */ - rc = cc_hash_alloc(new_drvdata); + /* Allocate crypto algs */ + rc = cc_cipher_alloc(new_drvdata); if (rc) { - dev_err(dev, "cc_hash_alloc failed\n"); - goto post_cipher_err; + dev_err(dev, "cc_cipher_alloc failed\n"); + goto post_hash_err; } rc = cc_aead_alloc(new_drvdata); if (rc) { dev_err(dev, "cc_aead_alloc failed\n"); - goto post_hash_err; + goto post_cipher_err; } /* If we got here and FIPS mode is enabled @@ -558,10 +560,10 @@ static int init_cc_resources(struct platform_device *plat_dev) pm_runtime_put(dev); return 0; -post_hash_err: - cc_hash_free(new_drvdata); post_cipher_err: cc_cipher_free(new_drvdata); +post_hash_err: + cc_hash_free(new_drvdata); post_buf_mgr_err: cc_buffer_mgr_fini(new_drvdata); post_req_mgr_err: @@ -593,8 +595,8 @@ static void cleanup_cc_resources(struct platform_device *plat_dev) (struct cc_drvdata *)platform_get_drvdata(plat_dev); cc_aead_free(drvdata); - cc_hash_free(drvdata); cc_cipher_free(drvdata); + cc_hash_free(drvdata); cc_buffer_mgr_fini(drvdata); cc_req_mgr_fini(drvdata); cc_fips_fini(drvdata); diff --git a/drivers/crypto/hisilicon/Kconfig b/drivers/crypto/hisilicon/Kconfig index e572f9982d4ef4bbd2e0c177170d31e60436440d..27e1fa91206390d62f4b65a52d75980f5001b279 100644 --- a/drivers/crypto/hisilicon/Kconfig +++ b/drivers/crypto/hisilicon/Kconfig @@ -26,6 +26,7 @@ config CRYPTO_DEV_HISI_SEC2 select CRYPTO_SHA1 select CRYPTO_SHA256 select CRYPTO_SHA512 + select CRYPTO_SM4 depends on PCI && PCI_MSI depends on UACCE || UACCE=n depends on ARM64 || (COMPILE_TEST && 64BIT) diff --git a/drivers/crypto/hisilicon/hpre/hpre_main.c b/drivers/crypto/hisilicon/hpre/hpre_main.c index 36ab30e9e6549b2472e1f12c1eab2d1ad2547686..9d529df0eab9b1a7cc3349d33a289738dc7f2eac 100644 --- a/drivers/crypto/hisilicon/hpre/hpre_main.c +++ b/drivers/crypto/hisilicon/hpre/hpre_main.c @@ -36,6 +36,12 @@ #define HPRE_DATA_WUSER_CFG 0x301040 #define HPRE_INT_MASK 0x301400 #define HPRE_INT_STATUS 0x301800 +#define HPRE_HAC_INT_MSK 0x301400 +#define HPRE_HAC_RAS_CE_ENB 0x301410 +#define HPRE_HAC_RAS_NFE_ENB 0x301414 +#define HPRE_HAC_RAS_FE_ENB 0x301418 +#define HPRE_HAC_INT_SET 0x301500 +#define HPRE_RNG_TIMEOUT_NUM 0x301A34 #define HPRE_CORE_INT_ENABLE 0 #define HPRE_CORE_INT_DISABLE GENMASK(21, 0) #define HPRE_RDCHN_INI_ST 0x301a00 @@ -107,6 +113,15 @@ #define HPRE_SQE_MASK_OFFSET 8 #define HPRE_SQE_MASK_LEN 24 +#define HPRE_DFX_BASE 0x301000 +#define HPRE_DFX_COMMON1 0x301400 +#define HPRE_DFX_COMMON2 0x301A00 +#define HPRE_DFX_CORE 0x302000 +#define HPRE_DFX_BASE_LEN 0x55 +#define HPRE_DFX_COMMON1_LEN 0x41 +#define HPRE_DFX_COMMON2_LEN 0xE +#define HPRE_DFX_CORE_LEN 0x43 + static const char hpre_name[] = "hisi_hpre"; static struct dentry *hpre_debugfs_root; static const struct pci_device_id hpre_dev_ids[] = { @@ -192,28 +207,32 @@ static const u64 hpre_cluster_offsets[] = { }; static const struct debugfs_reg32 hpre_cluster_dfx_regs[] = { - {"CORES_EN_STATUS ", HPRE_CORE_EN_OFFSET}, - {"CORES_INI_CFG ", HPRE_CORE_INI_CFG_OFFSET}, - {"CORES_INI_STATUS ", HPRE_CORE_INI_STATUS_OFFSET}, - {"CORES_HTBT_WARN ", HPRE_CORE_HTBT_WARN_OFFSET}, - {"CORES_IS_SCHD ", HPRE_CORE_IS_SCHD_OFFSET}, + {"CORES_EN_STATUS ", HPRE_CORE_EN_OFFSET}, + {"CORES_INI_CFG ", HPRE_CORE_INI_CFG_OFFSET}, + {"CORES_INI_STATUS ", HPRE_CORE_INI_STATUS_OFFSET}, + {"CORES_HTBT_WARN ", HPRE_CORE_HTBT_WARN_OFFSET}, + {"CORES_IS_SCHD ", HPRE_CORE_IS_SCHD_OFFSET}, }; static const struct debugfs_reg32 hpre_com_dfx_regs[] = { - {"READ_CLR_EN ", HPRE_CTRL_CNT_CLR_CE}, - {"AXQOS ", HPRE_VFG_AXQOS}, - {"AWUSR_CFG ", HPRE_AWUSR_FP_CFG}, - {"QM_ARUSR_MCFG1 ", QM_ARUSER_M_CFG_1}, - {"QM_AWUSR_MCFG1 ", QM_AWUSER_M_CFG_1}, - {"BD_ENDIAN ", HPRE_BD_ENDIAN}, - {"ECC_CHECK_CTRL ", HPRE_ECC_BYPASS}, - {"RAS_INT_WIDTH ", HPRE_RAS_WIDTH_CFG}, - {"POISON_BYPASS ", HPRE_POISON_BYPASS}, - {"BD_ARUSER ", HPRE_BD_ARUSR_CFG}, - {"BD_AWUSER ", HPRE_BD_AWUSR_CFG}, - {"DATA_ARUSER ", HPRE_DATA_RUSER_CFG}, - {"DATA_AWUSER ", HPRE_DATA_WUSER_CFG}, - {"INT_STATUS ", HPRE_INT_STATUS}, + {"READ_CLR_EN ", HPRE_CTRL_CNT_CLR_CE}, + {"AXQOS ", HPRE_VFG_AXQOS}, + {"AWUSR_CFG ", HPRE_AWUSR_FP_CFG}, + {"BD_ENDIAN ", HPRE_BD_ENDIAN}, + {"ECC_CHECK_CTRL ", HPRE_ECC_BYPASS}, + {"RAS_INT_WIDTH ", HPRE_RAS_WIDTH_CFG}, + {"POISON_BYPASS ", HPRE_POISON_BYPASS}, + {"BD_ARUSER ", HPRE_BD_ARUSR_CFG}, + {"BD_AWUSER ", HPRE_BD_AWUSR_CFG}, + {"DATA_ARUSER ", HPRE_DATA_RUSER_CFG}, + {"DATA_AWUSER ", HPRE_DATA_WUSER_CFG}, + {"INT_STATUS ", HPRE_INT_STATUS}, + {"INT_MASK ", HPRE_HAC_INT_MSK}, + {"RAS_CE_ENB ", HPRE_HAC_RAS_CE_ENB}, + {"RAS_NFE_ENB ", HPRE_HAC_RAS_NFE_ENB}, + {"RAS_FE_ENB ", HPRE_HAC_RAS_FE_ENB}, + {"INT_SET ", HPRE_HAC_INT_SET}, + {"RNG_TIMEOUT_NUM ", HPRE_RNG_TIMEOUT_NUM}, }; static const char *hpre_dfx_files[HPRE_DFX_FILE_NUM] = { @@ -226,6 +245,53 @@ static const char *hpre_dfx_files[HPRE_DFX_FILE_NUM] = { "invalid_req_cnt" }; +/* define the HPRE's dfx regs region and region length */ +static struct dfx_diff_registers hpre_diff_regs[] = { + { + .reg_offset = HPRE_DFX_BASE, + .reg_len = HPRE_DFX_BASE_LEN, + }, { + .reg_offset = HPRE_DFX_COMMON1, + .reg_len = HPRE_DFX_COMMON1_LEN, + }, { + .reg_offset = HPRE_DFX_COMMON2, + .reg_len = HPRE_DFX_COMMON2_LEN, + }, { + .reg_offset = HPRE_DFX_CORE, + .reg_len = HPRE_DFX_CORE_LEN, + }, +}; + +static int hpre_diff_regs_show(struct seq_file *s, void *unused) +{ + struct hisi_qm *qm = s->private; + + hisi_qm_acc_diff_regs_dump(qm, s, qm->debug.acc_diff_regs, + ARRAY_SIZE(hpre_diff_regs)); + + return 0; +} + +DEFINE_SHOW_ATTRIBUTE(hpre_diff_regs); + +static int hpre_com_regs_show(struct seq_file *s, void *unused) +{ + hisi_qm_regs_dump(s, s->private); + + return 0; +} + +DEFINE_SHOW_ATTRIBUTE(hpre_com_regs); + +static int hpre_cluster_regs_show(struct seq_file *s, void *unused) +{ + hisi_qm_regs_dump(s, s->private); + + return 0; +} + +DEFINE_SHOW_ATTRIBUTE(hpre_cluster_regs); + static const struct kernel_param_ops hpre_uacce_mode_ops = { .set = uacce_mode_set, .get = param_get_int, @@ -779,24 +845,6 @@ static int hpre_debugfs_atomic64_set(void *data, u64 val) DEFINE_DEBUGFS_ATTRIBUTE(hpre_atomic64_ops, hpre_debugfs_atomic64_get, hpre_debugfs_atomic64_set, "%llu\n"); -static int hpre_com_regs_show(struct seq_file *s, void *unused) -{ - hisi_qm_regs_dump(s, s->private); - - return 0; -} - -DEFINE_SHOW_ATTRIBUTE(hpre_com_regs); - -static int hpre_cluster_regs_show(struct seq_file *s, void *unused) -{ - hisi_qm_regs_dump(s, s->private); - - return 0; -} - -DEFINE_SHOW_ATTRIBUTE(hpre_cluster_regs); - static int hpre_create_debugfs_file(struct hisi_qm *qm, struct dentry *dir, enum hpre_ctrl_dbgfs_file type, int indx) { @@ -895,6 +943,7 @@ static int hpre_ctrl_debug_init(struct hisi_qm *qm) static void hpre_dfx_debug_init(struct hisi_qm *qm) { + struct dfx_diff_registers *hpre_regs = qm->debug.acc_diff_regs; struct hpre *hpre = container_of(qm, struct hpre, qm); struct hpre_dfx *dfx = hpre->debug.dfx; struct dentry *parent; @@ -906,6 +955,10 @@ static void hpre_dfx_debug_init(struct hisi_qm *qm) debugfs_create_file(hpre_dfx_files[i], 0644, parent, &dfx[i], &hpre_atomic64_ops); } + + if (qm->fun_type == QM_HW_PF && hpre_regs) + debugfs_create_file("diff_regs", 0444, parent, + qm, &hpre_diff_regs_fops); } static int hpre_debugfs_init(struct hisi_qm *qm) @@ -918,6 +971,13 @@ static int hpre_debugfs_init(struct hisi_qm *qm) qm->debug.sqe_mask_offset = HPRE_SQE_MASK_OFFSET; qm->debug.sqe_mask_len = HPRE_SQE_MASK_LEN; + ret = hisi_qm_diff_regs_init(qm, hpre_diff_regs, + ARRAY_SIZE(hpre_diff_regs)); + if (ret) { + dev_warn(dev, "Failed to init HPRE diff regs!\n"); + goto debugfs_remove; + } + hisi_qm_debug_init(qm); if (qm->pdev->device == PCI_DEVICE_ID_HUAWEI_HPRE_PF) { @@ -931,12 +991,16 @@ static int hpre_debugfs_init(struct hisi_qm *qm) return 0; failed_to_create: + hisi_qm_diff_regs_uninit(qm, ARRAY_SIZE(hpre_diff_regs)); +debugfs_remove: debugfs_remove_recursive(qm->debug.debug_root); return ret; } static void hpre_debugfs_exit(struct hisi_qm *qm) { + hisi_qm_diff_regs_uninit(qm, ARRAY_SIZE(hpre_diff_regs)); + debugfs_remove_recursive(qm->debug.debug_root); } @@ -969,6 +1033,82 @@ static int hpre_qm_init(struct hisi_qm *qm, struct pci_dev *pdev) return hisi_qm_init(qm); } +static int hpre_show_last_regs_init(struct hisi_qm *qm) +{ + int cluster_dfx_regs_num = ARRAY_SIZE(hpre_cluster_dfx_regs); + int com_dfx_regs_num = ARRAY_SIZE(hpre_com_dfx_regs); + u8 clusters_num = hpre_cluster_num(qm); + struct qm_debug *debug = &qm->debug; + void __iomem *io_base; + int i, j, idx; + + debug->last_words = kcalloc(cluster_dfx_regs_num * clusters_num + + com_dfx_regs_num, sizeof(unsigned int), GFP_KERNEL); + if (!debug->last_words) + return -ENOMEM; + + for (i = 0; i < com_dfx_regs_num; i++) + debug->last_words[i] = readl_relaxed(qm->io_base + + hpre_com_dfx_regs[i].offset); + + for (i = 0; i < clusters_num; i++) { + io_base = qm->io_base + hpre_cluster_offsets[i]; + for (j = 0; j < cluster_dfx_regs_num; j++) { + idx = com_dfx_regs_num + i * cluster_dfx_regs_num + j; + debug->last_words[idx] = readl_relaxed( + io_base + hpre_cluster_dfx_regs[j].offset); + } + } + + return 0; +} + +static void hpre_show_last_regs_uninit(struct hisi_qm *qm) +{ + struct qm_debug *debug = &qm->debug; + + if (qm->fun_type == QM_HW_VF || !debug->last_words) + return; + + kfree(debug->last_words); + debug->last_words = NULL; +} + +static void hpre_show_last_dfx_regs(struct hisi_qm *qm) +{ + int cluster_dfx_regs_num = ARRAY_SIZE(hpre_cluster_dfx_regs); + int com_dfx_regs_num = ARRAY_SIZE(hpre_com_dfx_regs); + u8 clusters_num = hpre_cluster_num(qm); + struct qm_debug *debug = &qm->debug; + struct pci_dev *pdev = qm->pdev; + void __iomem *io_base; + int i, j, idx; + u32 val; + + if (qm->fun_type == QM_HW_VF || !debug->last_words) + return; + + /* dumps last word of the debugging registers during controller reset */ + for (i = 0; i < com_dfx_regs_num; i++) { + val = readl_relaxed(qm->io_base + hpre_com_dfx_regs[i].offset); + if (debug->last_words[i] != val) + pci_info(pdev, "Common_core:%s \t= 0x%08x => 0x%08x\n", + hpre_com_dfx_regs[i].name, debug->last_words[i], val); + } + + for (i = 0; i < clusters_num; i++) { + io_base = qm->io_base + hpre_cluster_offsets[i]; + for (j = 0; j < cluster_dfx_regs_num; j++) { + val = readl_relaxed(io_base + + hpre_cluster_dfx_regs[j].offset); + idx = com_dfx_regs_num + i * cluster_dfx_regs_num + j; + if (debug->last_words[idx] != val) + pci_info(pdev, "cluster-%d:%s \t= 0x%08x => 0x%08x\n", + i, hpre_cluster_dfx_regs[j].name, debug->last_words[idx], val); + } + } +} + static void hpre_log_hw_error(struct hisi_qm *qm, u32 err_sts) { const struct hpre_hw_error *err = hpre_hw_errors; @@ -1027,6 +1167,7 @@ static const struct hisi_qm_err_ini hpre_err_ini = { .open_axi_master_ooo = hpre_open_axi_master_ooo, .open_sva_prefetch = hpre_open_sva_prefetch, .close_sva_prefetch = hpre_close_sva_prefetch, + .show_last_dfx_regs = hpre_show_last_dfx_regs, .err_info_init = hpre_err_info_init, }; @@ -1044,8 +1185,11 @@ static int hpre_pf_probe_init(struct hpre *hpre) qm->err_ini = &hpre_err_ini; qm->err_ini->err_info_init(qm); hisi_qm_dev_err_init(qm); + ret = hpre_show_last_regs_init(qm); + if (ret) + pci_err(qm->pdev, "Failed to init last word regs!\n"); - return 0; + return ret; } static int hpre_probe_init(struct hpre *hpre) @@ -1131,6 +1275,7 @@ err_with_qm_start: hisi_qm_stop(qm, QM_NORMAL); err_with_err_init: + hpre_show_last_regs_uninit(qm); hisi_qm_dev_err_uninit(qm); err_with_qm_init: @@ -1161,6 +1306,7 @@ static void hpre_remove(struct pci_dev *pdev) if (qm->fun_type == QM_HW_PF) { hpre_cnt_regs_clear(qm); qm->debug.curr_qm_qp_num = 0; + hpre_show_last_regs_uninit(qm); hisi_qm_dev_err_uninit(qm); } diff --git a/drivers/crypto/hisilicon/qm.c b/drivers/crypto/hisilicon/qm.c index 009132333d2b400b8719fc5fd0e00820980505c2..b4ca2eb034d7d4b5cdcaca3a868c8fdfadf0efae 100644 --- a/drivers/crypto/hisilicon/qm.c +++ b/drivers/crypto/hisilicon/qm.c @@ -253,7 +253,15 @@ #define QM_QOS_MAX_CIR_U 6 #define QM_QOS_MAX_CIR_S 11 #define QM_QOS_VAL_MAX_LEN 32 - +#define QM_DFX_BASE 0x0100000 +#define QM_DFX_STATE1 0x0104000 +#define QM_DFX_STATE2 0x01040C8 +#define QM_DFX_COMMON 0x0000 +#define QM_DFX_BASE_LEN 0x5A +#define QM_DFX_STATE1_LEN 0x2E +#define QM_DFX_STATE2_LEN 0x11 +#define QM_DFX_COMMON_LEN 0xC3 +#define QM_DFX_REGS_LEN 4UL #define QM_AUTOSUSPEND_DELAY 3000 #define QM_MK_CQC_DW3_V1(hop_num, pg_sz, buf_sz, cqe_sz) \ @@ -467,6 +475,23 @@ static const struct hisi_qm_hw_error qm_hw_error[] = { { /* sentinel */ } }; +/* define the QM's dfx regs region and region length */ +static struct dfx_diff_registers qm_diff_regs[] = { + { + .reg_offset = QM_DFX_BASE, + .reg_len = QM_DFX_BASE_LEN, + }, { + .reg_offset = QM_DFX_STATE1, + .reg_len = QM_DFX_STATE1_LEN, + }, { + .reg_offset = QM_DFX_STATE2, + .reg_len = QM_DFX_STATE2_LEN, + }, { + .reg_offset = QM_DFX_COMMON, + .reg_len = QM_DFX_COMMON_LEN, + }, +}; + static const char * const qm_db_timeout[] = { "sq", "cq", "eq", "aeq", }; @@ -687,13 +712,13 @@ static void qm_mb_write(struct hisi_qm *qm, const void *src) if (!IS_ENABLED(CONFIG_ARM64)) { memcpy_toio(fun_base, src, 16); - wmb(); + dma_wmb(); return; } asm volatile("ldp %0, %1, %3\n" "stp %0, %1, %2\n" - "dsb sy\n" + "dmb oshst\n" : "=&r" (tmp0), "=&r" (tmp1), "+Q" (*((char __iomem *)fun_base)) @@ -982,7 +1007,7 @@ static void qm_set_qp_disable(struct hisi_qp *qp, int offset) *addr = 1; /* make sure setup is completed */ - mb(); + smp_wmb(); } static void qm_disable_qp(struct hisi_qm *qm, u32 qp_id) @@ -1625,6 +1650,156 @@ static int qm_regs_show(struct seq_file *s, void *unused) DEFINE_SHOW_ATTRIBUTE(qm_regs); +static struct dfx_diff_registers *dfx_regs_init(struct hisi_qm *qm, + const struct dfx_diff_registers *cregs, int reg_len) +{ + struct dfx_diff_registers *diff_regs; + u32 j, base_offset; + int i; + + diff_regs = kcalloc(reg_len, sizeof(*diff_regs), GFP_KERNEL); + if (!diff_regs) + return ERR_PTR(-ENOMEM); + + for (i = 0; i < reg_len; i++) { + if (!cregs[i].reg_len) + continue; + + diff_regs[i].reg_offset = cregs[i].reg_offset; + diff_regs[i].reg_len = cregs[i].reg_len; + diff_regs[i].regs = kcalloc(QM_DFX_REGS_LEN, cregs[i].reg_len, + GFP_KERNEL); + if (!diff_regs[i].regs) + goto alloc_error; + + for (j = 0; j < diff_regs[i].reg_len; j++) { + base_offset = diff_regs[i].reg_offset + + j * QM_DFX_REGS_LEN; + diff_regs[i].regs[j] = readl(qm->io_base + base_offset); + } + } + + return diff_regs; + +alloc_error: + while (i > 0) { + i--; + kfree(diff_regs[i].regs); + } + kfree(diff_regs); + return ERR_PTR(-ENOMEM); +} + +static void dfx_regs_uninit(struct hisi_qm *qm, + struct dfx_diff_registers *dregs, int reg_len) +{ + int i; + + /* Setting the pointer is NULL to prevent double free */ + for (i = 0; i < reg_len; i++) { + kfree(dregs[i].regs); + dregs[i].regs = NULL; + } + kfree(dregs); + dregs = NULL; +} + +/** + * hisi_qm_diff_regs_init() - Allocate memory for registers. + * @qm: device qm handle. + * @dregs: diff registers handle. + * @reg_len: diff registers region length. + */ +int hisi_qm_diff_regs_init(struct hisi_qm *qm, + struct dfx_diff_registers *dregs, int reg_len) +{ + if (!qm || !dregs || reg_len <= 0) + return -EINVAL; + + if (qm->fun_type != QM_HW_PF) + return 0; + + qm->debug.qm_diff_regs = dfx_regs_init(qm, qm_diff_regs, + ARRAY_SIZE(qm_diff_regs)); + if (IS_ERR(qm->debug.qm_diff_regs)) + return PTR_ERR(qm->debug.qm_diff_regs); + + qm->debug.acc_diff_regs = dfx_regs_init(qm, dregs, reg_len); + if (IS_ERR(qm->debug.acc_diff_regs)) { + dfx_regs_uninit(qm, qm->debug.qm_diff_regs, + ARRAY_SIZE(qm_diff_regs)); + return PTR_ERR(qm->debug.acc_diff_regs); + } + + return 0; +} +EXPORT_SYMBOL_GPL(hisi_qm_diff_regs_init); + +/** + * hisi_qm_diff_regs_uninit() - Free memory for registers. + * @qm: device qm handle. + * @reg_len: diff registers region length. + */ +void hisi_qm_diff_regs_uninit(struct hisi_qm *qm, int reg_len) +{ + if (!qm || reg_len <= 0 || qm->fun_type != QM_HW_PF) + return; + + dfx_regs_uninit(qm, qm->debug.acc_diff_regs, reg_len); + dfx_regs_uninit(qm, qm->debug.qm_diff_regs, ARRAY_SIZE(qm_diff_regs)); +} +EXPORT_SYMBOL_GPL(hisi_qm_diff_regs_uninit); + +/** + * hisi_qm_acc_diff_regs_dump() - Dump registers's value. + * @qm: device qm handle. + * @s: Debugfs file handle. + * @dregs: diff registers handle. + * @regs_len: diff registers region length. + */ +void hisi_qm_acc_diff_regs_dump(struct hisi_qm *qm, struct seq_file *s, + struct dfx_diff_registers *dregs, int regs_len) +{ + u32 j, val, base_offset; + int i, ret; + + if (!qm || !s || !dregs || regs_len <= 0) + return; + + ret = hisi_qm_get_dfx_access(qm); + if (ret) + return; + + down_read(&qm->qps_lock); + for (i = 0; i < regs_len; i++) { + if (!dregs[i].reg_len) + continue; + + for (j = 0; j < dregs[i].reg_len; j++) { + base_offset = dregs[i].reg_offset + j * QM_DFX_REGS_LEN; + val = readl(qm->io_base + base_offset); + if (val != dregs[i].regs[j]) + seq_printf(s, "0x%08x = 0x%08x ---> 0x%08x\n", + base_offset, dregs[i].regs[j], val); + } + } + up_read(&qm->qps_lock); + + hisi_qm_put_dfx_access(qm); +} +EXPORT_SYMBOL_GPL(hisi_qm_acc_diff_regs_dump); + +static int qm_diff_regs_show(struct seq_file *s, void *unused) +{ + struct hisi_qm *qm = s->private; + + hisi_qm_acc_diff_regs_dump(qm, s, qm->debug.qm_diff_regs, + ARRAY_SIZE(qm_diff_regs)); + + return 0; +} +DEFINE_SHOW_ATTRIBUTE(qm_diff_regs); + static ssize_t qm_cmd_read(struct file *filp, char __user *buffer, size_t count, loff_t *pos) { @@ -2660,7 +2835,7 @@ static struct hisi_qp *qm_create_qp_nolock(struct hisi_qm *qm, u8 alg_type) * return created qp, -EBUSY if all qps in qm allocated, -ENOMEM if allocating * qp memory fails. */ -struct hisi_qp *hisi_qm_create_qp(struct hisi_qm *qm, u8 alg_type) +static struct hisi_qp *hisi_qm_create_qp(struct hisi_qm *qm, u8 alg_type) { struct hisi_qp *qp; int ret; @@ -2678,7 +2853,6 @@ struct hisi_qp *hisi_qm_create_qp(struct hisi_qm *qm, u8 alg_type) return qp; } -EXPORT_SYMBOL_GPL(hisi_qm_create_qp); /** * hisi_qm_release_qp() - Release a qp back to its qm. @@ -2686,7 +2860,7 @@ EXPORT_SYMBOL_GPL(hisi_qm_create_qp); * * This function releases the resource of a qp. */ -void hisi_qm_release_qp(struct hisi_qp *qp) +static void hisi_qm_release_qp(struct hisi_qp *qp) { struct hisi_qm *qm = qp->qm; @@ -2704,7 +2878,6 @@ void hisi_qm_release_qp(struct hisi_qp *qp) qm_pm_put_sync(qm); } -EXPORT_SYMBOL_GPL(hisi_qm_release_qp); static int qm_sq_ctx_cfg(struct hisi_qp *qp, int qp_id, u32 pasid) { @@ -3053,9 +3226,17 @@ static void qm_qp_event_notifier(struct hisi_qp *qp) wake_up_interruptible(&qp->uacce_q->wait); } + /* This function returns free number of qp in qm. */ static int hisi_qm_get_available_instances(struct uacce_device *uacce) { - return hisi_qm_get_free_qp_num(uacce->priv); + struct hisi_qm *qm = uacce->priv; + int ret; + + down_read(&qm->qps_lock); + ret = qm->qp_num - qm->qp_in_used; + up_read(&qm->qps_lock); + + return ret; } static void hisi_qm_set_hw_reset(struct hisi_qm *qm, int offset) @@ -3367,24 +3548,6 @@ void hisi_qm_wait_task_finish(struct hisi_qm *qm, struct hisi_qm_list *qm_list) } EXPORT_SYMBOL_GPL(hisi_qm_wait_task_finish); -/** - * hisi_qm_get_free_qp_num() - Get free number of qp in qm. - * @qm: The qm which want to get free qp. - * - * This function return free number of qp in qm. - */ -int hisi_qm_get_free_qp_num(struct hisi_qm *qm) -{ - int ret; - - down_read(&qm->qps_lock); - ret = qm->qp_num - qm->qp_in_used; - up_read(&qm->qps_lock); - - return ret; -} -EXPORT_SYMBOL_GPL(hisi_qm_get_free_qp_num); - static void hisi_qp_memory_uninit(struct hisi_qm *qm, int num) { struct device *dev = &qm->pdev->dev; @@ -3498,6 +3661,17 @@ static void hisi_qm_set_state(struct hisi_qm *qm, u8 state) writel(state, qm->io_base + QM_VF_STATE); } +static void qm_last_regs_uninit(struct hisi_qm *qm) +{ + struct qm_debug *debug = &qm->debug; + + if (qm->fun_type == QM_HW_VF || !debug->qm_last_words) + return; + + kfree(debug->qm_last_words); + debug->qm_last_words = NULL; +} + /** * hisi_qm_uninit() - Uninitialize qm. * @qm: The qm needed uninit. @@ -3509,6 +3683,8 @@ void hisi_qm_uninit(struct hisi_qm *qm) struct pci_dev *pdev = qm->pdev; struct device *dev = &pdev->dev; + qm_last_regs_uninit(qm); + qm_cmd_uninit(qm); kfree(qm->factor); down_write(&qm->qps_lock); @@ -3550,7 +3726,7 @@ EXPORT_SYMBOL_GPL(hisi_qm_uninit); * * qm hw v1 does not support this interface. */ -int hisi_qm_get_vft(struct hisi_qm *qm, u32 *base, u32 *number) +static int hisi_qm_get_vft(struct hisi_qm *qm, u32 *base, u32 *number) { if (!base || !number) return -EINVAL; @@ -3562,7 +3738,6 @@ int hisi_qm_get_vft(struct hisi_qm *qm, u32 *base, u32 *number) return qm->ops->get_vft(qm, base, number); } -EXPORT_SYMBOL_GPL(hisi_qm_get_vft); /** * hisi_qm_set_vft() - Set vft to a qm. @@ -4484,6 +4659,7 @@ static void hisi_qm_set_algqos_init(struct hisi_qm *qm) */ void hisi_qm_debug_init(struct hisi_qm *qm) { + struct dfx_diff_registers *qm_regs = qm->debug.qm_diff_regs; struct qm_dfx *dfx = &qm->debug.dfx; struct dentry *qm_d; void *data; @@ -4499,6 +4675,10 @@ void hisi_qm_debug_init(struct hisi_qm *qm) qm_create_debugfs_file(qm, qm->debug.qm_d, i); } + if (qm_regs) + debugfs_create_file("diff_regs", 0444, qm->debug.qm_d, + qm, &qm_diff_regs_fops); + debugfs_create_file("regs", 0444, qm->debug.qm_d, qm, &qm_regs_fops); debugfs_create_file("cmd", 0600, qm->debug.qm_d, qm, &qm_cmd_fops); @@ -5181,6 +5361,24 @@ static int qm_controller_reset_done(struct hisi_qm *qm) return 0; } +static void qm_show_last_dfx_regs(struct hisi_qm *qm) +{ + struct qm_debug *debug = &qm->debug; + struct pci_dev *pdev = qm->pdev; + u32 val; + int i; + + if (qm->fun_type == QM_HW_VF || !debug->qm_last_words) + return; + + for (i = 0; i < ARRAY_SIZE(qm_dfx_regs); i++) { + val = readl_relaxed(qm->io_base + qm_dfx_regs[i].offset); + if (debug->qm_last_words[i] != val) + pci_info(pdev, "%s \t= 0x%08x => 0x%08x\n", + qm_dfx_regs[i].name, debug->qm_last_words[i], val); + } +} + static int qm_controller_reset(struct hisi_qm *qm) { struct pci_dev *pdev = qm->pdev; @@ -5196,6 +5394,10 @@ static int qm_controller_reset(struct hisi_qm *qm) return ret; } + qm_show_last_dfx_regs(qm); + if (qm->err_ini->show_last_dfx_regs) + qm->err_ini->show_last_dfx_regs(qm); + ret = qm_soft_reset(qm); if (ret) { pci_err(pdev, "Controller reset failed (%d)\n", ret); @@ -5906,6 +6108,26 @@ err_alloc_qdma: return ret; } +static void qm_last_regs_init(struct hisi_qm *qm) +{ + int dfx_regs_num = ARRAY_SIZE(qm_dfx_regs); + struct qm_debug *debug = &qm->debug; + int i; + + if (qm->fun_type == QM_HW_VF) + return; + + debug->qm_last_words = kcalloc(dfx_regs_num, sizeof(unsigned int), + GFP_KERNEL); + if (!debug->qm_last_words) + return; + + for (i = 0; i < dfx_regs_num; i++) { + debug->qm_last_words[i] = readl_relaxed(qm->io_base + + qm_dfx_regs[i].offset); + } +} + /** * hisi_qm_init() - Initialize configures about qm. * @qm: The qm needing init. @@ -5958,6 +6180,8 @@ int hisi_qm_init(struct hisi_qm *qm) qm_cmd_init(qm); atomic_set(&qm->status.flags, QM_INIT); + qm_last_regs_init(qm); + return 0; err_alloc_uacce: diff --git a/drivers/crypto/hisilicon/sec2/sec_crypto.c b/drivers/crypto/hisilicon/sec2/sec_crypto.c index a91635c348b5e093614c0596c06f7a038563d980..6eebe739893c5f6cf6e60d57b525daae23b5c3fe 100644 --- a/drivers/crypto/hisilicon/sec2/sec_crypto.c +++ b/drivers/crypto/hisilicon/sec2/sec_crypto.c @@ -2113,7 +2113,6 @@ static int sec_skcipher_decrypt(struct skcipher_request *sk_req) .cra_driver_name = "hisi_sec_"sec_cra_name,\ .cra_priority = SEC_PRIORITY,\ .cra_flags = CRYPTO_ALG_ASYNC |\ - CRYPTO_ALG_ALLOCATES_MEMORY |\ CRYPTO_ALG_NEED_FALLBACK,\ .cra_blocksize = blk_size,\ .cra_ctxsize = sizeof(struct sec_ctx),\ @@ -2366,7 +2365,6 @@ static int sec_aead_decrypt(struct aead_request *a_req) .cra_driver_name = "hisi_sec_"sec_cra_name,\ .cra_priority = SEC_PRIORITY,\ .cra_flags = CRYPTO_ALG_ASYNC |\ - CRYPTO_ALG_ALLOCATES_MEMORY |\ CRYPTO_ALG_NEED_FALLBACK,\ .cra_blocksize = blk_size,\ .cra_ctxsize = sizeof(struct sec_ctx),\ diff --git a/drivers/crypto/hisilicon/sec2/sec_main.c b/drivers/crypto/hisilicon/sec2/sec_main.c index 92fae706bdb2285d4ed58d33fcd87b7c78587de0..4d85d2cbf37672fe6696cd236a499bbadda7a965 100644 --- a/drivers/crypto/hisilicon/sec2/sec_main.c +++ b/drivers/crypto/hisilicon/sec2/sec_main.c @@ -110,6 +110,15 @@ #define SEC_SQE_MASK_LEN 48 #define SEC_SHAPER_TYPE_RATE 400 +#define SEC_DFX_BASE 0x301000 +#define SEC_DFX_CORE 0x302100 +#define SEC_DFX_COMMON1 0x301600 +#define SEC_DFX_COMMON2 0x301C00 +#define SEC_DFX_BASE_LEN 0x9D +#define SEC_DFX_CORE_LEN 0x32B +#define SEC_DFX_COMMON1_LEN 0x45 +#define SEC_DFX_COMMON2_LEN 0xBA + struct sec_hw_error { u32 int_msk; const char *msg; @@ -226,6 +235,34 @@ static const struct debugfs_reg32 sec_dfx_regs[] = { {"SEC_BD_SAA8 ", 0x301C40}, }; +/* define the SEC's dfx regs region and region length */ +static struct dfx_diff_registers sec_diff_regs[] = { + { + .reg_offset = SEC_DFX_BASE, + .reg_len = SEC_DFX_BASE_LEN, + }, { + .reg_offset = SEC_DFX_COMMON1, + .reg_len = SEC_DFX_COMMON1_LEN, + }, { + .reg_offset = SEC_DFX_COMMON2, + .reg_len = SEC_DFX_COMMON2_LEN, + }, { + .reg_offset = SEC_DFX_CORE, + .reg_len = SEC_DFX_CORE_LEN, + }, +}; + +static int sec_diff_regs_show(struct seq_file *s, void *unused) +{ + struct hisi_qm *qm = s->private; + + hisi_qm_acc_diff_regs_dump(qm, s, qm->debug.acc_diff_regs, + ARRAY_SIZE(sec_diff_regs)); + + return 0; +} +DEFINE_SHOW_ATTRIBUTE(sec_diff_regs); + static int sec_pf_q_num_set(const char *val, const struct kernel_param *kp) { return q_num_set(val, kp, PCI_DEVICE_ID_HUAWEI_SEC_PF); @@ -729,6 +766,7 @@ DEFINE_SHOW_ATTRIBUTE(sec_regs); static int sec_core_debug_init(struct hisi_qm *qm) { + struct dfx_diff_registers *sec_regs = qm->debug.acc_diff_regs; struct sec_dev *sec = container_of(qm, struct sec_dev, qm); struct device *dev = &qm->pdev->dev; struct sec_dfx *dfx = &sec->debug.dfx; @@ -749,6 +787,9 @@ static int sec_core_debug_init(struct hisi_qm *qm) if (qm->pdev->device == PCI_DEVICE_ID_HUAWEI_SEC_PF) debugfs_create_file("regs", 0444, tmp_d, regset, &sec_regs_fops); + if (qm->fun_type == QM_HW_PF && sec_regs) + debugfs_create_file("diff_regs", 0444, tmp_d, + qm, &sec_diff_regs_fops); for (i = 0; i < ARRAY_SIZE(sec_dfx_labels); i++) { atomic64_t *data = (atomic64_t *)((uintptr_t)dfx + @@ -790,6 +831,14 @@ static int sec_debugfs_init(struct hisi_qm *qm) sec_debugfs_root); qm->debug.sqe_mask_offset = SEC_SQE_MASK_OFFSET; qm->debug.sqe_mask_len = SEC_SQE_MASK_LEN; + + ret = hisi_qm_diff_regs_init(qm, sec_diff_regs, + ARRAY_SIZE(sec_diff_regs)); + if (ret) { + dev_warn(dev, "Failed to init SEC diff regs!\n"); + goto debugfs_remove; + } + hisi_qm_debug_init(qm); ret = sec_debug_init(qm); @@ -799,15 +848,66 @@ static int sec_debugfs_init(struct hisi_qm *qm) return 0; failed_to_create: + hisi_qm_diff_regs_uninit(qm, ARRAY_SIZE(sec_diff_regs)); +debugfs_remove: debugfs_remove_recursive(sec_debugfs_root); return ret; } static void sec_debugfs_exit(struct hisi_qm *qm) { + hisi_qm_diff_regs_uninit(qm, ARRAY_SIZE(sec_diff_regs)); + debugfs_remove_recursive(qm->debug.debug_root); } +static int sec_show_last_regs_init(struct hisi_qm *qm) +{ + struct qm_debug *debug = &qm->debug; + int i; + + debug->last_words = kcalloc(ARRAY_SIZE(sec_dfx_regs), + sizeof(unsigned int), GFP_KERNEL); + if (!debug->last_words) + return -ENOMEM; + + for (i = 0; i < ARRAY_SIZE(sec_dfx_regs); i++) + debug->last_words[i] = readl_relaxed(qm->io_base + + sec_dfx_regs[i].offset); + + return 0; +} + +static void sec_show_last_regs_uninit(struct hisi_qm *qm) +{ + struct qm_debug *debug = &qm->debug; + + if (qm->fun_type == QM_HW_VF || !debug->last_words) + return; + + kfree(debug->last_words); + debug->last_words = NULL; +} + +static void sec_show_last_dfx_regs(struct hisi_qm *qm) +{ + struct qm_debug *debug = &qm->debug; + struct pci_dev *pdev = qm->pdev; + u32 val; + int i; + + if (qm->fun_type == QM_HW_VF || !debug->last_words) + return; + + /* dumps last word of the debugging registers during controller reset */ + for (i = 0; i < ARRAY_SIZE(sec_dfx_regs); i++) { + val = readl_relaxed(qm->io_base + sec_dfx_regs[i].offset); + if (val != debug->last_words[i]) + pci_info(pdev, "%s \t= 0x%08x => 0x%08x\n", + sec_dfx_regs[i].name, debug->last_words[i], val); + } +} + static void sec_log_hw_error(struct hisi_qm *qm, u32 err_sts) { const struct sec_hw_error *errs = sec_hw_errors; @@ -874,6 +974,7 @@ static const struct hisi_qm_err_ini sec_err_ini = { .open_axi_master_ooo = sec_open_axi_master_ooo, .open_sva_prefetch = sec_open_sva_prefetch, .close_sva_prefetch = sec_close_sva_prefetch, + .show_last_dfx_regs = sec_show_last_dfx_regs, .err_info_init = sec_err_info_init, }; @@ -892,8 +993,11 @@ static int sec_pf_probe_init(struct sec_dev *sec) sec_open_sva_prefetch(qm); hisi_qm_dev_err_init(qm); sec_debug_regs_clear(qm); + ret = sec_show_last_regs_init(qm); + if (ret) + pci_err(qm->pdev, "Failed to init last word regs!\n"); - return 0; + return ret; } static int sec_qm_init(struct hisi_qm *qm, struct pci_dev *pdev) @@ -1067,6 +1171,7 @@ err_qm_stop: sec_debugfs_exit(qm); hisi_qm_stop(qm, QM_NORMAL); err_probe_uninit: + sec_show_last_regs_uninit(qm); sec_probe_uninit(qm); err_qm_uninit: sec_qm_uninit(qm); @@ -1091,6 +1196,7 @@ static void sec_remove(struct pci_dev *pdev) if (qm->fun_type == QM_HW_PF) sec_debug_regs_clear(qm); + sec_show_last_regs_uninit(qm); sec_probe_uninit(qm); diff --git a/drivers/crypto/hisilicon/sgl.c b/drivers/crypto/hisilicon/sgl.c index f7efc02b065f00060787e0157f2b34fcb9b8514a..2b6f2281cfd6c02a3ea3e4369f62279b4fd96894 100644 --- a/drivers/crypto/hisilicon/sgl.c +++ b/drivers/crypto/hisilicon/sgl.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* Copyright (c) 2019 HiSilicon Limited. */ +#include #include #include #include @@ -64,8 +65,9 @@ struct hisi_acc_sgl_pool *hisi_acc_create_sgl_pool(struct device *dev, if (!dev || !count || !sge_nr || sge_nr > HISI_ACC_SGL_SGE_NR_MAX) return ERR_PTR(-EINVAL); - sgl_size = sizeof(struct acc_hw_sge) * sge_nr + - sizeof(struct hisi_acc_hw_sgl); + sgl_size = ALIGN(sizeof(struct acc_hw_sge) * sge_nr + + sizeof(struct hisi_acc_hw_sgl), + HISI_ACC_SGL_ALIGN_SIZE); /* * the pool may allocate a block of memory of size PAGE_SIZE * 2^(MAX_ORDER - 1), diff --git a/drivers/crypto/hisilicon/zip/zip_crypto.c b/drivers/crypto/hisilicon/zip/zip_crypto.c index 9520a4113c81e5fba635b54b48cc2cc0b87362cb..67869513e48c1a09579634ef3a8e1ce7e0c7123a 100644 --- a/drivers/crypto/hisilicon/zip/zip_crypto.c +++ b/drivers/crypto/hisilicon/zip/zip_crypto.c @@ -521,7 +521,7 @@ static int hisi_zip_start_qp(struct hisi_qp *qp, struct hisi_zip_qp_ctx *ctx, static void hisi_zip_release_qp(struct hisi_zip_qp_ctx *ctx) { hisi_qm_stop_qp(ctx->qp); - hisi_qm_release_qp(ctx->qp); + hisi_qm_free_qps(&ctx->qp, 1); } static const struct hisi_zip_sqe_ops hisi_zip_ops_v1 = { diff --git a/drivers/crypto/hisilicon/zip/zip_main.c b/drivers/crypto/hisilicon/zip/zip_main.c index 4534e1e107d1bec8c8d94d1a709a9c86d21fc3fd..9c925e9c0a2d180c7e2123ad87070989c7cadcf2 100644 --- a/drivers/crypto/hisilicon/zip/zip_main.c +++ b/drivers/crypto/hisilicon/zip/zip_main.c @@ -49,14 +49,18 @@ #define HZIP_QM_IDEL_STATUS 0x3040e4 -#define HZIP_CORE_DEBUG_COMP_0 0x302000 -#define HZIP_CORE_DEBUG_COMP_1 0x303000 -#define HZIP_CORE_DEBUG_DECOMP_0 0x304000 -#define HZIP_CORE_DEBUG_DECOMP_1 0x305000 -#define HZIP_CORE_DEBUG_DECOMP_2 0x306000 -#define HZIP_CORE_DEBUG_DECOMP_3 0x307000 -#define HZIP_CORE_DEBUG_DECOMP_4 0x308000 -#define HZIP_CORE_DEBUG_DECOMP_5 0x309000 +#define HZIP_CORE_DFX_BASE 0x301000 +#define HZIP_CLOCK_GATED_CONTL 0X301004 +#define HZIP_CORE_DFX_COMP_0 0x302000 +#define HZIP_CORE_DFX_COMP_1 0x303000 +#define HZIP_CORE_DFX_DECOMP_0 0x304000 +#define HZIP_CORE_DFX_DECOMP_1 0x305000 +#define HZIP_CORE_DFX_DECOMP_2 0x306000 +#define HZIP_CORE_DFX_DECOMP_3 0x307000 +#define HZIP_CORE_DFX_DECOMP_4 0x308000 +#define HZIP_CORE_DFX_DECOMP_5 0x309000 +#define HZIP_CORE_REGS_BASE_LEN 0xB0 +#define HZIP_CORE_REGS_DFX_LEN 0x28 #define HZIP_CORE_INT_SOURCE 0x3010A0 #define HZIP_CORE_INT_MASK_REG 0x3010A4 @@ -230,6 +234,64 @@ static const struct debugfs_reg32 hzip_dfx_regs[] = { {"HZIP_DECOMP_LZ77_CURR_ST ", 0x9cull}, }; +static const struct debugfs_reg32 hzip_com_dfx_regs[] = { + {"HZIP_CLOCK_GATE_CTRL ", 0x301004}, + {"HZIP_CORE_INT_RAS_CE_ENB ", 0x301160}, + {"HZIP_CORE_INT_RAS_NFE_ENB ", 0x301164}, + {"HZIP_CORE_INT_RAS_FE_ENB ", 0x301168}, + {"HZIP_UNCOM_ERR_RAS_CTRL ", 0x30116C}, +}; + +static const struct debugfs_reg32 hzip_dump_dfx_regs[] = { + {"HZIP_GET_BD_NUM ", 0x00ull}, + {"HZIP_GET_RIGHT_BD ", 0x04ull}, + {"HZIP_GET_ERROR_BD ", 0x08ull}, + {"HZIP_DONE_BD_NUM ", 0x0cull}, + {"HZIP_MAX_DELAY ", 0x20ull}, +}; + +/* define the ZIP's dfx regs region and region length */ +static struct dfx_diff_registers hzip_diff_regs[] = { + { + .reg_offset = HZIP_CORE_DFX_BASE, + .reg_len = HZIP_CORE_REGS_BASE_LEN, + }, { + .reg_offset = HZIP_CORE_DFX_COMP_0, + .reg_len = HZIP_CORE_REGS_DFX_LEN, + }, { + .reg_offset = HZIP_CORE_DFX_COMP_1, + .reg_len = HZIP_CORE_REGS_DFX_LEN, + }, { + .reg_offset = HZIP_CORE_DFX_DECOMP_0, + .reg_len = HZIP_CORE_REGS_DFX_LEN, + }, { + .reg_offset = HZIP_CORE_DFX_DECOMP_1, + .reg_len = HZIP_CORE_REGS_DFX_LEN, + }, { + .reg_offset = HZIP_CORE_DFX_DECOMP_2, + .reg_len = HZIP_CORE_REGS_DFX_LEN, + }, { + .reg_offset = HZIP_CORE_DFX_DECOMP_3, + .reg_len = HZIP_CORE_REGS_DFX_LEN, + }, { + .reg_offset = HZIP_CORE_DFX_DECOMP_4, + .reg_len = HZIP_CORE_REGS_DFX_LEN, + }, { + .reg_offset = HZIP_CORE_DFX_DECOMP_5, + .reg_len = HZIP_CORE_REGS_DFX_LEN, + }, +}; + +static int hzip_diff_regs_show(struct seq_file *s, void *unused) +{ + struct hisi_qm *qm = s->private; + + hisi_qm_acc_diff_regs_dump(qm, s, qm->debug.acc_diff_regs, + ARRAY_SIZE(hzip_diff_regs)); + + return 0; +} +DEFINE_SHOW_ATTRIBUTE(hzip_diff_regs); static const struct kernel_param_ops zip_uacce_mode_ops = { .set = uacce_mode_set, .get = param_get_int, @@ -621,6 +683,7 @@ static int hisi_zip_core_debug_init(struct hisi_qm *qm) static void hisi_zip_dfx_debug_init(struct hisi_qm *qm) { + struct dfx_diff_registers *hzip_regs = qm->debug.acc_diff_regs; struct hisi_zip *zip = container_of(qm, struct hisi_zip, qm); struct hisi_zip_dfx *dfx = &zip->dfx; struct dentry *tmp_dir; @@ -634,6 +697,10 @@ static void hisi_zip_dfx_debug_init(struct hisi_qm *qm) 0644, tmp_dir, data, &zip_atomic64_ops); } + + if (qm->fun_type == QM_HW_PF && hzip_regs) + debugfs_create_file("diff_regs", 0444, tmp_dir, + qm, &hzip_diff_regs_fops); } static int hisi_zip_ctrl_debug_init(struct hisi_qm *qm) @@ -666,6 +733,13 @@ static int hisi_zip_debugfs_init(struct hisi_qm *qm) qm->debug.sqe_mask_offset = HZIP_SQE_MASK_OFFSET; qm->debug.sqe_mask_len = HZIP_SQE_MASK_LEN; qm->debug.debug_root = dev_d; + ret = hisi_qm_diff_regs_init(qm, hzip_diff_regs, + ARRAY_SIZE(hzip_diff_regs)); + if (ret) { + dev_warn(dev, "Failed to init ZIP diff regs!\n"); + goto debugfs_remove; + } + hisi_qm_debug_init(qm); if (qm->fun_type == QM_HW_PF) { @@ -679,6 +753,8 @@ static int hisi_zip_debugfs_init(struct hisi_qm *qm) return 0; failed_to_create: + hisi_qm_diff_regs_uninit(qm, ARRAY_SIZE(hzip_diff_regs)); +debugfs_remove: debugfs_remove_recursive(hzip_debugfs_root); return ret; } @@ -703,6 +779,8 @@ static void hisi_zip_debug_regs_clear(struct hisi_qm *qm) static void hisi_zip_debugfs_exit(struct hisi_qm *qm) { + hisi_qm_diff_regs_uninit(qm, ARRAY_SIZE(hzip_diff_regs)); + debugfs_remove_recursive(qm->debug.debug_root); if (qm->fun_type == QM_HW_PF) { @@ -711,6 +789,87 @@ static void hisi_zip_debugfs_exit(struct hisi_qm *qm) } } +static int hisi_zip_show_last_regs_init(struct hisi_qm *qm) +{ + int core_dfx_regs_num = ARRAY_SIZE(hzip_dump_dfx_regs); + int com_dfx_regs_num = ARRAY_SIZE(hzip_com_dfx_regs); + struct qm_debug *debug = &qm->debug; + void __iomem *io_base; + int i, j, idx; + + debug->last_words = kcalloc(core_dfx_regs_num * HZIP_CORE_NUM + + com_dfx_regs_num, sizeof(unsigned int), GFP_KERNEL); + if (!debug->last_words) + return -ENOMEM; + + for (i = 0; i < com_dfx_regs_num; i++) { + io_base = qm->io_base + hzip_com_dfx_regs[i].offset; + debug->last_words[i] = readl_relaxed(io_base); + } + + for (i = 0; i < HZIP_CORE_NUM; i++) { + io_base = qm->io_base + core_offsets[i]; + for (j = 0; j < core_dfx_regs_num; j++) { + idx = com_dfx_regs_num + i * core_dfx_regs_num + j; + debug->last_words[idx] = readl_relaxed( + io_base + hzip_dump_dfx_regs[j].offset); + } + } + + return 0; +} + +static void hisi_zip_show_last_regs_uninit(struct hisi_qm *qm) +{ + struct qm_debug *debug = &qm->debug; + + if (qm->fun_type == QM_HW_VF || !debug->last_words) + return; + + kfree(debug->last_words); + debug->last_words = NULL; +} + +static void hisi_zip_show_last_dfx_regs(struct hisi_qm *qm) +{ + int core_dfx_regs_num = ARRAY_SIZE(hzip_dump_dfx_regs); + int com_dfx_regs_num = ARRAY_SIZE(hzip_com_dfx_regs); + struct qm_debug *debug = &qm->debug; + char buf[HZIP_BUF_SIZE]; + void __iomem *base; + int i, j, idx; + u32 val; + + if (qm->fun_type == QM_HW_VF || !debug->last_words) + return; + + for (i = 0; i < com_dfx_regs_num; i++) { + val = readl_relaxed(qm->io_base + hzip_com_dfx_regs[i].offset); + if (debug->last_words[i] != val) + pci_info(qm->pdev, "com_dfx: %s \t= 0x%08x => 0x%08x\n", + hzip_com_dfx_regs[i].name, debug->last_words[i], val); + } + + for (i = 0; i < HZIP_CORE_NUM; i++) { + if (i < HZIP_COMP_CORE_NUM) + scnprintf(buf, sizeof(buf), "Comp_core-%d", i); + else + scnprintf(buf, sizeof(buf), "Decomp_core-%d", + i - HZIP_COMP_CORE_NUM); + base = qm->io_base + core_offsets[i]; + + pci_info(qm->pdev, "==>%s:\n", buf); + /* dump last word for dfx regs during control resetting */ + for (j = 0; j < core_dfx_regs_num; j++) { + idx = com_dfx_regs_num + i * core_dfx_regs_num + j; + val = readl_relaxed(base + hzip_dump_dfx_regs[j].offset); + if (debug->last_words[idx] != val) + pci_info(qm->pdev, "%s \t= 0x%08x => 0x%08x\n", + hzip_dump_dfx_regs[j].name, debug->last_words[idx], val); + } + } +} + static void hisi_zip_log_hw_error(struct hisi_qm *qm, u32 err_sts) { const struct hisi_zip_hw_error *err = zip_hw_error; @@ -798,6 +957,7 @@ static const struct hisi_qm_err_ini hisi_zip_err_ini = { .close_axi_master_ooo = hisi_zip_close_axi_master_ooo, .open_sva_prefetch = hisi_zip_open_sva_prefetch, .close_sva_prefetch = hisi_zip_close_sva_prefetch, + .show_last_dfx_regs = hisi_zip_show_last_dfx_regs, .err_info_init = hisi_zip_err_info_init, }; @@ -805,6 +965,7 @@ static int hisi_zip_pf_probe_init(struct hisi_zip *hisi_zip) { struct hisi_qm *qm = &hisi_zip->qm; struct hisi_zip_ctrl *ctrl; + int ret; ctrl = devm_kzalloc(&qm->pdev->dev, sizeof(*ctrl), GFP_KERNEL); if (!ctrl) @@ -820,7 +981,11 @@ static int hisi_zip_pf_probe_init(struct hisi_zip *hisi_zip) hisi_qm_dev_err_init(qm); hisi_zip_debug_regs_clear(qm); - return 0; + ret = hisi_zip_show_last_regs_init(qm); + if (ret) + pci_err(qm->pdev, "Failed to init last word regs!\n"); + + return ret; } static int hisi_zip_qm_init(struct hisi_qm *qm, struct pci_dev *pdev) @@ -964,6 +1129,7 @@ err_qm_stop: hisi_qm_stop(qm, QM_NORMAL); err_dev_err_uninit: + hisi_zip_show_last_regs_uninit(qm); hisi_qm_dev_err_uninit(qm); err_qm_uninit: @@ -985,6 +1151,7 @@ static void hisi_zip_remove(struct pci_dev *pdev) hisi_zip_debugfs_exit(qm); hisi_qm_stop(qm, QM_NORMAL); + hisi_zip_show_last_regs_uninit(qm); hisi_qm_dev_err_uninit(qm); hisi_zip_qm_uninit(qm); } diff --git a/drivers/crypto/inside-secure/safexcel.c b/drivers/crypto/inside-secure/safexcel.c index 9ff885d50edfcdf6878ea9872dc2e650f3d989e3..9b1a158aec299c8ac6905705aa12c890479d82c1 100644 --- a/drivers/crypto/inside-secure/safexcel.c +++ b/drivers/crypto/inside-secure/safexcel.c @@ -1997,3 +1997,12 @@ MODULE_AUTHOR("Igal Liberman "); MODULE_DESCRIPTION("Support for SafeXcel cryptographic engines: EIP97 & EIP197"); MODULE_LICENSE("GPL v2"); MODULE_IMPORT_NS(CRYPTO_INTERNAL); + +MODULE_FIRMWARE("ifpp.bin"); +MODULE_FIRMWARE("ipue.bin"); +MODULE_FIRMWARE("inside-secure/eip197b/ifpp.bin"); +MODULE_FIRMWARE("inside-secure/eip197b/ipue.bin"); +MODULE_FIRMWARE("inside-secure/eip197d/ifpp.bin"); +MODULE_FIRMWARE("inside-secure/eip197d/ipue.bin"); +MODULE_FIRMWARE("inside-secure/eip197_minifw/ifpp.bin"); +MODULE_FIRMWARE("inside-secure/eip197_minifw/ipue.bin"); diff --git a/drivers/crypto/keembay/keembay-ocs-aes-core.c b/drivers/crypto/keembay/keembay-ocs-aes-core.c index e2a39fdaf623e45cd9ddf918bc0876ebbd0e4b0e..9953f5590ac4300eacf1077e5a99f5600be94085 100644 --- a/drivers/crypto/keembay/keembay-ocs-aes-core.c +++ b/drivers/crypto/keembay/keembay-ocs-aes-core.c @@ -1598,7 +1598,6 @@ static int kmb_ocs_aes_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct ocs_aes_dev *aes_dev; - struct resource *aes_mem; int rc; aes_dev = devm_kzalloc(dev, sizeof(*aes_dev), GFP_KERNEL); @@ -1616,13 +1615,7 @@ static int kmb_ocs_aes_probe(struct platform_device *pdev) } /* Get base register address. */ - aes_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!aes_mem) { - dev_err(dev, "Could not retrieve io mem resource\n"); - return -ENODEV; - } - - aes_dev->base_reg = devm_ioremap_resource(&pdev->dev, aes_mem); + aes_dev->base_reg = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(aes_dev->base_reg)) return PTR_ERR(aes_dev->base_reg); diff --git a/drivers/crypto/marvell/cesa/cipher.c b/drivers/crypto/marvell/cesa/cipher.c index b739d3b873dcf28183927586cef43a16374dfd5c..c6f2fa753b7c039fec909c545c3e34ca92ce0e3a 100644 --- a/drivers/crypto/marvell/cesa/cipher.c +++ b/drivers/crypto/marvell/cesa/cipher.c @@ -624,7 +624,6 @@ struct skcipher_alg mv_cesa_ecb_des3_ede_alg = { .decrypt = mv_cesa_ecb_des3_ede_decrypt, .min_keysize = DES3_EDE_KEY_SIZE, .max_keysize = DES3_EDE_KEY_SIZE, - .ivsize = DES3_EDE_BLOCK_SIZE, .base = { .cra_name = "ecb(des3_ede)", .cra_driver_name = "mv-ecb-des3-ede", diff --git a/drivers/crypto/marvell/octeontx2/otx2_cptvf_algs.c b/drivers/crypto/marvell/octeontx2/otx2_cptvf_algs.c index f8f8542ce3e47dd38ab95182bf0541ba5b0f8755..67530e90bbfed3f8aa8fa346b6a9f81e7661fe83 100644 --- a/drivers/crypto/marvell/octeontx2/otx2_cptvf_algs.c +++ b/drivers/crypto/marvell/octeontx2/otx2_cptvf_algs.c @@ -896,7 +896,6 @@ static int otx2_cpt_aead_cbc_aes_sha_setkey(struct crypto_aead *cipher, struct crypto_authenc_key_param *param; int enckeylen = 0, authkeylen = 0; struct rtattr *rta = (void *)key; - int status; if (!RTA_OK(rta, keylen)) return -EINVAL; @@ -938,11 +937,7 @@ static int otx2_cpt_aead_cbc_aes_sha_setkey(struct crypto_aead *cipher, ctx->enc_key_len = enckeylen; ctx->auth_key_len = authkeylen; - status = aead_hmac_init(cipher); - if (status) - return status; - - return 0; + return aead_hmac_init(cipher); } static int otx2_cpt_aead_ecb_null_sha_setkey(struct crypto_aead *cipher, diff --git a/drivers/crypto/nx/nx-common-powernv.c b/drivers/crypto/nx/nx-common-powernv.c index 32a036ada5d0ac25ed56a9f990477f13919b37c2..f418817c0f43e05f8238d0cc7f359c12ed59caa3 100644 --- a/drivers/crypto/nx/nx-common-powernv.c +++ b/drivers/crypto/nx/nx-common-powernv.c @@ -827,7 +827,7 @@ static int __init vas_cfg_coproc_info(struct device_node *dn, int chip_id, goto err_out; vas_init_rx_win_attr(&rxattr, coproc->ct); - rxattr.rx_fifo = (void *)rx_fifo; + rxattr.rx_fifo = rx_fifo; rxattr.rx_fifo_size = fifo_size; rxattr.lnotify_lpid = lpid; rxattr.lnotify_pid = pid; diff --git a/drivers/crypto/qat/qat_4xxx/adf_drv.c b/drivers/crypto/qat/qat_4xxx/adf_drv.c index fa4c350c1bf92f138f61f167ebd0c7937a33e0d1..181fa1c8b3c78f16be495d7f291af65d2383a0f8 100644 --- a/drivers/crypto/qat/qat_4xxx/adf_drv.c +++ b/drivers/crypto/qat/qat_4xxx/adf_drv.c @@ -14,6 +14,7 @@ static const struct pci_device_id adf_pci_tbl[] = { { PCI_VDEVICE(INTEL, ADF_4XXX_PCI_DEVICE_ID), }, + { PCI_VDEVICE(INTEL, ADF_401XX_PCI_DEVICE_ID), }, { } }; MODULE_DEVICE_TABLE(pci, adf_pci_tbl); @@ -75,13 +76,6 @@ static int adf_crypto_dev_config(struct adf_accel_dev *accel_dev) if (ret) goto err; - /* Temporarily set the number of crypto instances to zero to avoid - * registering the crypto algorithms. - * This will be removed when the algorithms will support the - * CRYPTO_TFM_REQ_MAY_BACKLOG flag - */ - instances = 0; - for (i = 0; i < instances; i++) { val = i; bank = i * 2; diff --git a/drivers/crypto/qat/qat_c3xxx/adf_c3xxx_hw_data.c b/drivers/crypto/qat/qat_c3xxx/adf_c3xxx_hw_data.c index b941fe3713ff15a963f864a772e9ff28d7d23e32..50d5afa26a9bee75155345bacb39b9899015bcb2 100644 --- a/drivers/crypto/qat/qat_c3xxx/adf_c3xxx_hw_data.c +++ b/drivers/crypto/qat/qat_c3xxx/adf_c3xxx_hw_data.c @@ -78,19 +78,6 @@ static const u32 *adf_get_arbiter_mapping(void) return thrd_to_arb_map; } -static void adf_enable_ints(struct adf_accel_dev *accel_dev) -{ - void __iomem *addr; - - addr = (&GET_BARS(accel_dev)[ADF_C3XXX_PMISC_BAR])->virt_addr; - - /* Enable bundle and misc interrupts */ - ADF_CSR_WR(addr, ADF_C3XXX_SMIAPF0_MASK_OFFSET, - ADF_C3XXX_SMIA0_MASK); - ADF_CSR_WR(addr, ADF_C3XXX_SMIAPF1_MASK_OFFSET, - ADF_C3XXX_SMIA1_MASK); -} - static void configure_iov_threads(struct adf_accel_dev *accel_dev, bool enable) { adf_gen2_cfg_iov_thds(accel_dev, enable, @@ -133,7 +120,7 @@ void adf_init_hw_data_c3xxx(struct adf_hw_device_data *hw_data) hw_data->init_arb = adf_init_arb; hw_data->exit_arb = adf_exit_arb; hw_data->get_arb_mapping = adf_get_arbiter_mapping; - hw_data->enable_ints = adf_enable_ints; + hw_data->enable_ints = adf_gen2_enable_ints; hw_data->reset_device = adf_reset_flr; hw_data->set_ssm_wdtimer = adf_gen2_set_ssm_wdtimer; hw_data->disable_iov = adf_disable_sriov; diff --git a/drivers/crypto/qat/qat_c3xxx/adf_c3xxx_hw_data.h b/drivers/crypto/qat/qat_c3xxx/adf_c3xxx_hw_data.h index 1b86f828725cb984e00e665923bd50bf1e538fe7..336a06f11dbda2c661aed36359944a82dbdc71cd 100644 --- a/drivers/crypto/qat/qat_c3xxx/adf_c3xxx_hw_data.h +++ b/drivers/crypto/qat/qat_c3xxx/adf_c3xxx_hw_data.h @@ -13,10 +13,6 @@ #define ADF_C3XXX_ACCELERATORS_MASK 0x7 #define ADF_C3XXX_ACCELENGINES_MASK 0x3F #define ADF_C3XXX_ETR_MAX_BANKS 16 -#define ADF_C3XXX_SMIAPF0_MASK_OFFSET (0x3A000 + 0x28) -#define ADF_C3XXX_SMIAPF1_MASK_OFFSET (0x3A000 + 0x30) -#define ADF_C3XXX_SMIA0_MASK 0xFFFF -#define ADF_C3XXX_SMIA1_MASK 0x1 #define ADF_C3XXX_SOFTSTRAP_CSR_OFFSET 0x2EC /* AE to function mapping */ diff --git a/drivers/crypto/qat/qat_c62x/adf_c62x_hw_data.c b/drivers/crypto/qat/qat_c62x/adf_c62x_hw_data.c index b1eac2f81faa7be522b4c2a39911ba41702fc07c..c00386fe6587a684f56dea91da0c1260e3e7a134 100644 --- a/drivers/crypto/qat/qat_c62x/adf_c62x_hw_data.c +++ b/drivers/crypto/qat/qat_c62x/adf_c62x_hw_data.c @@ -80,19 +80,6 @@ static const u32 *adf_get_arbiter_mapping(void) return thrd_to_arb_map; } -static void adf_enable_ints(struct adf_accel_dev *accel_dev) -{ - void __iomem *addr; - - addr = (&GET_BARS(accel_dev)[ADF_C62X_PMISC_BAR])->virt_addr; - - /* Enable bundle and misc interrupts */ - ADF_CSR_WR(addr, ADF_C62X_SMIAPF0_MASK_OFFSET, - ADF_C62X_SMIA0_MASK); - ADF_CSR_WR(addr, ADF_C62X_SMIAPF1_MASK_OFFSET, - ADF_C62X_SMIA1_MASK); -} - static void configure_iov_threads(struct adf_accel_dev *accel_dev, bool enable) { adf_gen2_cfg_iov_thds(accel_dev, enable, @@ -135,7 +122,7 @@ void adf_init_hw_data_c62x(struct adf_hw_device_data *hw_data) hw_data->init_arb = adf_init_arb; hw_data->exit_arb = adf_exit_arb; hw_data->get_arb_mapping = adf_get_arbiter_mapping; - hw_data->enable_ints = adf_enable_ints; + hw_data->enable_ints = adf_gen2_enable_ints; hw_data->reset_device = adf_reset_flr; hw_data->set_ssm_wdtimer = adf_gen2_set_ssm_wdtimer; hw_data->disable_iov = adf_disable_sriov; diff --git a/drivers/crypto/qat/qat_c62x/adf_c62x_hw_data.h b/drivers/crypto/qat/qat_c62x/adf_c62x_hw_data.h index 68c3436bd3aa418dd486c610233f8b9b69aa9b4f..008c0a3a9769714ec4772c76a17f4d152e9ac1dd 100644 --- a/drivers/crypto/qat/qat_c62x/adf_c62x_hw_data.h +++ b/drivers/crypto/qat/qat_c62x/adf_c62x_hw_data.h @@ -13,10 +13,6 @@ #define ADF_C62X_ACCELERATORS_MASK 0x1F #define ADF_C62X_ACCELENGINES_MASK 0x3FF #define ADF_C62X_ETR_MAX_BANKS 16 -#define ADF_C62X_SMIAPF0_MASK_OFFSET (0x3A000 + 0x28) -#define ADF_C62X_SMIAPF1_MASK_OFFSET (0x3A000 + 0x30) -#define ADF_C62X_SMIA0_MASK 0xFFFF -#define ADF_C62X_SMIA1_MASK 0x1 #define ADF_C62X_SOFTSTRAP_CSR_OFFSET 0x2EC /* AE to function mapping */ diff --git a/drivers/crypto/qat/qat_common/Makefile b/drivers/crypto/qat/qat_common/Makefile index f25a6c8edfc7340abfe3a53ef9dbfc7b18193192..04f058acc4d37c286ba540349f4b53f0d7de1212 100644 --- a/drivers/crypto/qat/qat_common/Makefile +++ b/drivers/crypto/qat/qat_common/Makefile @@ -16,6 +16,7 @@ intel_qat-objs := adf_cfg.o \ qat_crypto.o \ qat_algs.o \ qat_asym_algs.o \ + qat_algs_send.o \ qat_uclo.o \ qat_hal.o diff --git a/drivers/crypto/qat/qat_common/adf_accel_devices.h b/drivers/crypto/qat/qat_common/adf_accel_devices.h index a03c6cf723312f8bfd0078aef46c33e3caad07bb..ede6458c9dbfdb4a749621023c61531d88bf7edc 100644 --- a/drivers/crypto/qat/qat_common/adf_accel_devices.h +++ b/drivers/crypto/qat/qat_common/adf_accel_devices.h @@ -19,6 +19,8 @@ #define ADF_4XXX_DEVICE_NAME "4xxx" #define ADF_4XXX_PCI_DEVICE_ID 0x4940 #define ADF_4XXXIOV_PCI_DEVICE_ID 0x4941 +#define ADF_401XX_PCI_DEVICE_ID 0x4942 +#define ADF_401XXIOV_PCI_DEVICE_ID 0x4943 #define ADF_DEVICE_FUSECTL_OFFSET 0x40 #define ADF_DEVICE_LEGFUSE_OFFSET 0x4C #define ADF_DEVICE_FUSECTL_MASK 0x80000000 @@ -152,9 +154,9 @@ struct adf_pfvf_ops { int (*enable_comms)(struct adf_accel_dev *accel_dev); u32 (*get_pf2vf_offset)(u32 i); u32 (*get_vf2pf_offset)(u32 i); - u32 (*get_vf2pf_sources)(void __iomem *pmisc_addr); void (*enable_vf2pf_interrupts)(void __iomem *pmisc_addr, u32 vf_mask); - void (*disable_vf2pf_interrupts)(void __iomem *pmisc_addr, u32 vf_mask); + void (*disable_all_vf2pf_interrupts)(void __iomem *pmisc_addr); + u32 (*disable_pending_vf2pf_interrupts)(void __iomem *pmisc_addr); int (*send_msg)(struct adf_accel_dev *accel_dev, struct pfvf_message msg, u32 pfvf_offset, struct mutex *csr_lock); struct pfvf_message (*recv_msg)(struct adf_accel_dev *accel_dev, diff --git a/drivers/crypto/qat/qat_common/adf_common_drv.h b/drivers/crypto/qat/qat_common/adf_common_drv.h index e8c9b77c0d66b9e316c8f176014ded1a1feefe56..0464fa25792953b82719ecdcdb111c2a7d01b4db 100644 --- a/drivers/crypto/qat/qat_common/adf_common_drv.h +++ b/drivers/crypto/qat/qat_common/adf_common_drv.h @@ -195,10 +195,8 @@ bool adf_misc_wq_queue_work(struct work_struct *work); #if defined(CONFIG_PCI_IOV) int adf_sriov_configure(struct pci_dev *pdev, int numvfs); void adf_disable_sriov(struct adf_accel_dev *accel_dev); -void adf_disable_vf2pf_interrupts(struct adf_accel_dev *accel_dev, - u32 vf_mask); -void adf_enable_vf2pf_interrupts(struct adf_accel_dev *accel_dev, - u32 vf_mask); +void adf_enable_vf2pf_interrupts(struct adf_accel_dev *accel_dev, u32 vf_mask); +void adf_disable_all_vf2pf_interrupts(struct adf_accel_dev *accel_dev); bool adf_recv_and_handle_pf2vf_msg(struct adf_accel_dev *accel_dev); bool adf_recv_and_handle_vf2pf_msg(struct adf_accel_dev *accel_dev, u32 vf_nr); int adf_pf2vf_handle_pf_restarting(struct adf_accel_dev *accel_dev); @@ -217,14 +215,6 @@ static inline void adf_disable_sriov(struct adf_accel_dev *accel_dev) { } -static inline void adf_enable_pf2vf_interrupts(struct adf_accel_dev *accel_dev) -{ -} - -static inline void adf_disable_pf2vf_interrupts(struct adf_accel_dev *accel_dev) -{ -} - static inline int adf_init_pf_wq(void) { return 0; @@ -243,10 +233,6 @@ static inline void adf_exit_vf_wq(void) { } -static inline void adf_flush_vf_wq(struct adf_accel_dev *accel_dev) -{ -} - #endif static inline void __iomem *adf_get_pmisc_base(struct adf_accel_dev *accel_dev) diff --git a/drivers/crypto/qat/qat_common/adf_gen2_hw_data.c b/drivers/crypto/qat/qat_common/adf_gen2_hw_data.c index 57035b7dd4b2053d49adf2b2500747eb170f28dc..d1884547b5a142cab337a51dede4eab2a65b11b9 100644 --- a/drivers/crypto/qat/qat_common/adf_gen2_hw_data.c +++ b/drivers/crypto/qat/qat_common/adf_gen2_hw_data.c @@ -98,6 +98,19 @@ void adf_gen2_get_arb_info(struct arb_info *arb_info) } EXPORT_SYMBOL_GPL(adf_gen2_get_arb_info); +void adf_gen2_enable_ints(struct adf_accel_dev *accel_dev) +{ + void __iomem *addr = adf_get_pmisc_base(accel_dev); + u32 val; + + val = accel_dev->pf.vf_info ? 0 : BIT_ULL(GET_MAX_BANKS(accel_dev)) - 1; + + /* Enable bundle and misc interrupts */ + ADF_CSR_WR(addr, ADF_GEN2_SMIAPF0_MASK_OFFSET, val); + ADF_CSR_WR(addr, ADF_GEN2_SMIAPF1_MASK_OFFSET, ADF_GEN2_SMIA1_MASK); +} +EXPORT_SYMBOL_GPL(adf_gen2_enable_ints); + static u64 build_csr_ring_base_addr(dma_addr_t addr, u32 size) { return BUILD_RING_BASE_ADDR(addr, size); diff --git a/drivers/crypto/qat/qat_common/adf_gen2_hw_data.h b/drivers/crypto/qat/qat_common/adf_gen2_hw_data.h index f2e0451b11c087678b59d1fba7c7eb150210bacf..e4bc07529be41be531f40871fa4e6962b5e15e33 100644 --- a/drivers/crypto/qat/qat_common/adf_gen2_hw_data.h +++ b/drivers/crypto/qat/qat_common/adf_gen2_hw_data.h @@ -145,6 +145,11 @@ do { \ #define ADF_GEN2_CERRSSMSH(i) ((i) * 0x4000 + 0x10) #define ADF_GEN2_ERRSSMSH_EN BIT(3) +/* Interrupts */ +#define ADF_GEN2_SMIAPF0_MASK_OFFSET (0x3A000 + 0x28) +#define ADF_GEN2_SMIAPF1_MASK_OFFSET (0x3A000 + 0x30) +#define ADF_GEN2_SMIA1_MASK 0x1 + u32 adf_gen2_get_num_accels(struct adf_hw_device_data *self); u32 adf_gen2_get_num_aes(struct adf_hw_device_data *self); void adf_gen2_enable_error_correction(struct adf_accel_dev *accel_dev); @@ -153,6 +158,7 @@ void adf_gen2_cfg_iov_thds(struct adf_accel_dev *accel_dev, bool enable, void adf_gen2_init_hw_csr_ops(struct adf_hw_csr_ops *csr_ops); void adf_gen2_get_admin_info(struct admin_info *admin_csrs_info); void adf_gen2_get_arb_info(struct arb_info *arb_info); +void adf_gen2_enable_ints(struct adf_accel_dev *accel_dev); u32 adf_gen2_get_accel_cap(struct adf_accel_dev *accel_dev); void adf_gen2_set_ssm_wdtimer(struct adf_accel_dev *accel_dev); diff --git a/drivers/crypto/qat/qat_common/adf_gen2_pfvf.c b/drivers/crypto/qat/qat_common/adf_gen2_pfvf.c index 1a9072aac2ca944cbc846795c4cc4e11432ef244..70ef1196393814bd28ff5a4813d8e2f6c519cf54 100644 --- a/drivers/crypto/qat/qat_common/adf_gen2_pfvf.c +++ b/drivers/crypto/qat/qat_common/adf_gen2_pfvf.c @@ -13,8 +13,9 @@ #include "adf_pfvf_utils.h" /* VF2PF interrupts */ +#define ADF_GEN2_VF_MSK 0xFFFF #define ADF_GEN2_ERR_REG_VF2PF(vf_src) (((vf_src) & 0x01FFFE00) >> 9) -#define ADF_GEN2_ERR_MSK_VF2PF(vf_mask) (((vf_mask) & 0xFFFF) << 9) +#define ADF_GEN2_ERR_MSK_VF2PF(vf_mask) (((vf_mask) & ADF_GEN2_VF_MSK) << 9) #define ADF_GEN2_PF_PF2VF_OFFSET(i) (0x3A000 + 0x280 + ((i) * 0x04)) #define ADF_GEN2_VF_PF2VF_OFFSET 0x200 @@ -50,43 +51,60 @@ static u32 adf_gen2_vf_get_pfvf_offset(u32 i) return ADF_GEN2_VF_PF2VF_OFFSET; } -static u32 adf_gen2_get_vf2pf_sources(void __iomem *pmisc_addr) -{ - u32 errsou3, errmsk3, vf_int_mask; - - /* Get the interrupt sources triggered by VFs */ - errsou3 = ADF_CSR_RD(pmisc_addr, ADF_GEN2_ERRSOU3); - vf_int_mask = ADF_GEN2_ERR_REG_VF2PF(errsou3); - - /* To avoid adding duplicate entries to work queue, clear - * vf_int_mask_sets bits that are already masked in ERRMSK register. - */ - errmsk3 = ADF_CSR_RD(pmisc_addr, ADF_GEN2_ERRMSK3); - vf_int_mask &= ~ADF_GEN2_ERR_REG_VF2PF(errmsk3); - - return vf_int_mask; -} - -static void adf_gen2_enable_vf2pf_interrupts(void __iomem *pmisc_addr, - u32 vf_mask) +static void adf_gen2_enable_vf2pf_interrupts(void __iomem *pmisc_addr, u32 vf_mask) { /* Enable VF2PF Messaging Ints - VFs 0 through 15 per vf_mask[15:0] */ - if (vf_mask & 0xFFFF) { + if (vf_mask & ADF_GEN2_VF_MSK) { u32 val = ADF_CSR_RD(pmisc_addr, ADF_GEN2_ERRMSK3) & ~ADF_GEN2_ERR_MSK_VF2PF(vf_mask); ADF_CSR_WR(pmisc_addr, ADF_GEN2_ERRMSK3, val); } } -static void adf_gen2_disable_vf2pf_interrupts(void __iomem *pmisc_addr, - u32 vf_mask) +static void adf_gen2_disable_all_vf2pf_interrupts(void __iomem *pmisc_addr) { /* Disable VF2PF interrupts for VFs 0 through 15 per vf_mask[15:0] */ - if (vf_mask & 0xFFFF) { - u32 val = ADF_CSR_RD(pmisc_addr, ADF_GEN2_ERRMSK3) - | ADF_GEN2_ERR_MSK_VF2PF(vf_mask); - ADF_CSR_WR(pmisc_addr, ADF_GEN2_ERRMSK3, val); - } + u32 val = ADF_CSR_RD(pmisc_addr, ADF_GEN2_ERRMSK3) + | ADF_GEN2_ERR_MSK_VF2PF(ADF_GEN2_VF_MSK); + ADF_CSR_WR(pmisc_addr, ADF_GEN2_ERRMSK3, val); +} + +static u32 adf_gen2_disable_pending_vf2pf_interrupts(void __iomem *pmisc_addr) +{ + u32 sources, disabled, pending; + u32 errsou3, errmsk3; + + /* Get the interrupt sources triggered by VFs */ + errsou3 = ADF_CSR_RD(pmisc_addr, ADF_GEN2_ERRSOU3); + sources = ADF_GEN2_ERR_REG_VF2PF(errsou3); + + if (!sources) + return 0; + + /* Get the already disabled interrupts */ + errmsk3 = ADF_CSR_RD(pmisc_addr, ADF_GEN2_ERRMSK3); + disabled = ADF_GEN2_ERR_REG_VF2PF(errmsk3); + + pending = sources & ~disabled; + if (!pending) + return 0; + + /* Due to HW limitations, when disabling the interrupts, we can't + * just disable the requested sources, as this would lead to missed + * interrupts if ERRSOU3 changes just before writing to ERRMSK3. + * To work around it, disable all and re-enable only the sources that + * are not in vf_mask and were not already disabled. Re-enabling will + * trigger a new interrupt for the sources that have changed in the + * meantime, if any. + */ + errmsk3 |= ADF_GEN2_ERR_MSK_VF2PF(ADF_GEN2_VF_MSK); + ADF_CSR_WR(pmisc_addr, ADF_GEN2_ERRMSK3, errmsk3); + + errmsk3 &= ADF_GEN2_ERR_MSK_VF2PF(sources | disabled); + ADF_CSR_WR(pmisc_addr, ADF_GEN2_ERRMSK3, errmsk3); + + /* Return the sources of the (new) interrupt(s) */ + return pending; } static u32 gen2_csr_get_int_bit(enum gen2_csr_pos offset) @@ -362,9 +380,9 @@ void adf_gen2_init_pf_pfvf_ops(struct adf_pfvf_ops *pfvf_ops) pfvf_ops->enable_comms = adf_enable_pf2vf_comms; pfvf_ops->get_pf2vf_offset = adf_gen2_pf_get_pfvf_offset; pfvf_ops->get_vf2pf_offset = adf_gen2_pf_get_pfvf_offset; - pfvf_ops->get_vf2pf_sources = adf_gen2_get_vf2pf_sources; pfvf_ops->enable_vf2pf_interrupts = adf_gen2_enable_vf2pf_interrupts; - pfvf_ops->disable_vf2pf_interrupts = adf_gen2_disable_vf2pf_interrupts; + pfvf_ops->disable_all_vf2pf_interrupts = adf_gen2_disable_all_vf2pf_interrupts; + pfvf_ops->disable_pending_vf2pf_interrupts = adf_gen2_disable_pending_vf2pf_interrupts; pfvf_ops->send_msg = adf_gen2_pf2vf_send; pfvf_ops->recv_msg = adf_gen2_vf2pf_recv; } diff --git a/drivers/crypto/qat/qat_common/adf_gen4_pfvf.c b/drivers/crypto/qat/qat_common/adf_gen4_pfvf.c index d80d493a775689380e46410f3658d26e026ccd2b..8e8efe93f3ee5c99ea6590e4fd9037090d55d8ae 100644 --- a/drivers/crypto/qat/qat_common/adf_gen4_pfvf.c +++ b/drivers/crypto/qat/qat_common/adf_gen4_pfvf.c @@ -15,6 +15,7 @@ /* VF2PF interrupt source registers */ #define ADF_4XXX_VM2PF_SOU 0x41A180 #define ADF_4XXX_VM2PF_MSK 0x41A1C0 +#define ADF_GEN4_VF_MSK 0xFFFF #define ADF_PFVF_GEN4_MSGTYPE_SHIFT 2 #define ADF_PFVF_GEN4_MSGTYPE_MASK 0x3F @@ -36,32 +37,48 @@ static u32 adf_gen4_pf_get_vf2pf_offset(u32 i) return ADF_4XXX_VM2PF_OFFSET(i); } -static u32 adf_gen4_get_vf2pf_sources(void __iomem *pmisc_addr) +static void adf_gen4_enable_vf2pf_interrupts(void __iomem *pmisc_addr, u32 vf_mask) { - u32 sou, mask; + u32 val; - sou = ADF_CSR_RD(pmisc_addr, ADF_4XXX_VM2PF_SOU); - mask = ADF_CSR_RD(pmisc_addr, ADF_4XXX_VM2PF_MSK); - - return sou & ~mask; + val = ADF_CSR_RD(pmisc_addr, ADF_4XXX_VM2PF_MSK) & ~vf_mask; + ADF_CSR_WR(pmisc_addr, ADF_4XXX_VM2PF_MSK, val); } -static void adf_gen4_enable_vf2pf_interrupts(void __iomem *pmisc_addr, - u32 vf_mask) +static void adf_gen4_disable_all_vf2pf_interrupts(void __iomem *pmisc_addr) { - unsigned int val; - - val = ADF_CSR_RD(pmisc_addr, ADF_4XXX_VM2PF_MSK) & ~vf_mask; - ADF_CSR_WR(pmisc_addr, ADF_4XXX_VM2PF_MSK, val); + ADF_CSR_WR(pmisc_addr, ADF_4XXX_VM2PF_MSK, ADF_GEN4_VF_MSK); } -static void adf_gen4_disable_vf2pf_interrupts(void __iomem *pmisc_addr, - u32 vf_mask) +static u32 adf_gen4_disable_pending_vf2pf_interrupts(void __iomem *pmisc_addr) { - unsigned int val; + u32 sources, disabled, pending; + + /* Get the interrupt sources triggered by VFs */ + sources = ADF_CSR_RD(pmisc_addr, ADF_4XXX_VM2PF_SOU); + if (!sources) + return 0; + + /* Get the already disabled interrupts */ + disabled = ADF_CSR_RD(pmisc_addr, ADF_4XXX_VM2PF_MSK); + + pending = sources & ~disabled; + if (!pending) + return 0; + + /* Due to HW limitations, when disabling the interrupts, we can't + * just disable the requested sources, as this would lead to missed + * interrupts if VM2PF_SOU changes just before writing to VM2PF_MSK. + * To work around it, disable all and re-enable only the sources that + * are not in vf_mask and were not already disabled. Re-enabling will + * trigger a new interrupt for the sources that have changed in the + * meantime, if any. + */ + ADF_CSR_WR(pmisc_addr, ADF_4XXX_VM2PF_MSK, ADF_GEN4_VF_MSK); + ADF_CSR_WR(pmisc_addr, ADF_4XXX_VM2PF_MSK, disabled | sources); - val = ADF_CSR_RD(pmisc_addr, ADF_4XXX_VM2PF_MSK) | vf_mask; - ADF_CSR_WR(pmisc_addr, ADF_4XXX_VM2PF_MSK, val); + /* Return the sources of the (new) interrupt(s) */ + return pending; } static int adf_gen4_pfvf_send(struct adf_accel_dev *accel_dev, @@ -96,10 +113,16 @@ static struct pfvf_message adf_gen4_pfvf_recv(struct adf_accel_dev *accel_dev, u32 pfvf_offset, u8 compat_ver) { void __iomem *pmisc_addr = adf_get_pmisc_base(accel_dev); + struct pfvf_message msg = { 0 }; u32 csr_val; /* Read message from the CSR */ csr_val = ADF_CSR_RD(pmisc_addr, pfvf_offset); + if (!(csr_val & ADF_PFVF_INT)) { + dev_info(&GET_DEV(accel_dev), + "Spurious PFVF interrupt, msg 0x%.8x. Ignored\n", csr_val); + return msg; + } /* We can now acknowledge the message reception by clearing the * interrupt bit @@ -115,9 +138,9 @@ void adf_gen4_init_pf_pfvf_ops(struct adf_pfvf_ops *pfvf_ops) pfvf_ops->enable_comms = adf_enable_pf2vf_comms; pfvf_ops->get_pf2vf_offset = adf_gen4_pf_get_pf2vf_offset; pfvf_ops->get_vf2pf_offset = adf_gen4_pf_get_vf2pf_offset; - pfvf_ops->get_vf2pf_sources = adf_gen4_get_vf2pf_sources; pfvf_ops->enable_vf2pf_interrupts = adf_gen4_enable_vf2pf_interrupts; - pfvf_ops->disable_vf2pf_interrupts = adf_gen4_disable_vf2pf_interrupts; + pfvf_ops->disable_all_vf2pf_interrupts = adf_gen4_disable_all_vf2pf_interrupts; + pfvf_ops->disable_pending_vf2pf_interrupts = adf_gen4_disable_pending_vf2pf_interrupts; pfvf_ops->send_msg = adf_gen4_pfvf_send; pfvf_ops->recv_msg = adf_gen4_pfvf_recv; } diff --git a/drivers/crypto/qat/qat_common/adf_isr.c b/drivers/crypto/qat/qat_common/adf_isr.c index a35149f8bf1ee8a74eaac2c112bd17578e91e3bf..ad9e135b8560b6dcf6e941ebd5176f70147aa7e4 100644 --- a/drivers/crypto/qat/qat_common/adf_isr.c +++ b/drivers/crypto/qat/qat_common/adf_isr.c @@ -66,42 +66,39 @@ void adf_enable_vf2pf_interrupts(struct adf_accel_dev *accel_dev, u32 vf_mask) spin_unlock_irqrestore(&accel_dev->pf.vf2pf_ints_lock, flags); } -void adf_disable_vf2pf_interrupts(struct adf_accel_dev *accel_dev, u32 vf_mask) +void adf_disable_all_vf2pf_interrupts(struct adf_accel_dev *accel_dev) { void __iomem *pmisc_addr = adf_get_pmisc_base(accel_dev); unsigned long flags; spin_lock_irqsave(&accel_dev->pf.vf2pf_ints_lock, flags); - GET_PFVF_OPS(accel_dev)->disable_vf2pf_interrupts(pmisc_addr, vf_mask); + GET_PFVF_OPS(accel_dev)->disable_all_vf2pf_interrupts(pmisc_addr); spin_unlock_irqrestore(&accel_dev->pf.vf2pf_ints_lock, flags); } -static void adf_disable_vf2pf_interrupts_irq(struct adf_accel_dev *accel_dev, - u32 vf_mask) +static u32 adf_disable_pending_vf2pf_interrupts(struct adf_accel_dev *accel_dev) { void __iomem *pmisc_addr = adf_get_pmisc_base(accel_dev); + u32 pending; spin_lock(&accel_dev->pf.vf2pf_ints_lock); - GET_PFVF_OPS(accel_dev)->disable_vf2pf_interrupts(pmisc_addr, vf_mask); + pending = GET_PFVF_OPS(accel_dev)->disable_pending_vf2pf_interrupts(pmisc_addr); spin_unlock(&accel_dev->pf.vf2pf_ints_lock); + + return pending; } static bool adf_handle_vf2pf_int(struct adf_accel_dev *accel_dev) { - void __iomem *pmisc_addr = adf_get_pmisc_base(accel_dev); bool irq_handled = false; unsigned long vf_mask; - /* Get the interrupt sources triggered by VFs */ - vf_mask = GET_PFVF_OPS(accel_dev)->get_vf2pf_sources(pmisc_addr); - + /* Get the interrupt sources triggered by VFs, except for those already disabled */ + vf_mask = adf_disable_pending_vf2pf_interrupts(accel_dev); if (vf_mask) { struct adf_accel_vf_info *vf_info; int i; - /* Disable VF2PF interrupts for VFs with pending ints */ - adf_disable_vf2pf_interrupts_irq(accel_dev, vf_mask); - /* * Handle VF2PF interrupt unless the VF is malicious and * is attempting to flood the host OS with VF2PF interrupts. diff --git a/drivers/crypto/qat/qat_common/adf_pfvf_msg.h b/drivers/crypto/qat/qat_common/adf_pfvf_msg.h index 9c37a26613920b9e906b52b4724021dca0a8b78f..204a42438992645960e99b234b77983cc3e54864 100644 --- a/drivers/crypto/qat/qat_common/adf_pfvf_msg.h +++ b/drivers/crypto/qat/qat_common/adf_pfvf_msg.h @@ -8,8 +8,8 @@ /* * PF<->VF Gen2 Messaging format * - * The PF has an array of 32-bit PF2VF registers, one for each VF. The - * PF can access all these registers; each VF can access only the one + * The PF has an array of 32-bit PF2VF registers, one for each VF. The + * PF can access all these registers while each VF can access only the one * register associated with that particular VF. * * The register functionally is split into two parts: diff --git a/drivers/crypto/qat/qat_common/adf_pfvf_pf_proto.c b/drivers/crypto/qat/qat_common/adf_pfvf_pf_proto.c index 588352de1ef0e5f7c426f852cb6110932d226b8e..388e58bcbcaf2683228ae30e8aef99f35f3a513b 100644 --- a/drivers/crypto/qat/qat_common/adf_pfvf_pf_proto.c +++ b/drivers/crypto/qat/qat_common/adf_pfvf_pf_proto.c @@ -154,7 +154,7 @@ static struct pfvf_message handle_blkmsg_req(struct adf_accel_vf_info *vf_info, if (FIELD_GET(ADF_VF2PF_BLOCK_CRC_REQ_MASK, req.data)) { dev_dbg(&GET_DEV(vf_info->accel_dev), "BlockMsg of type %d for CRC over %d bytes received from VF%d\n", - blk_type, blk_byte, vf_info->vf_nr); + blk_type, blk_byte + 1, vf_info->vf_nr); if (!adf_pf2vf_blkmsg_get_data(vf_info, blk_type, blk_byte, byte_max, &resp_data, @@ -242,7 +242,9 @@ static int adf_handle_vf2pf_msg(struct adf_accel_dev *accel_dev, u8 vf_nr, "VersionRequest received from VF%d (vers %d) to PF (vers %d)\n", vf_nr, vf_compat_ver, ADF_PFVF_COMPAT_THIS_VERSION); - if (vf_compat_ver <= ADF_PFVF_COMPAT_THIS_VERSION) + if (vf_compat_ver == 0) + compat = ADF_PF2VF_VF_INCOMPATIBLE; + else if (vf_compat_ver <= ADF_PFVF_COMPAT_THIS_VERSION) compat = ADF_PF2VF_VF_COMPATIBLE; else compat = ADF_PF2VF_VF_COMPAT_UNKNOWN; diff --git a/drivers/crypto/qat/qat_common/adf_sriov.c b/drivers/crypto/qat/qat_common/adf_sriov.c index b960bca1f9d2fdd42ca1065a39de1e321246b41b..f38b2ffde146be15598f8af2205647b5e307a227 100644 --- a/drivers/crypto/qat/qat_common/adf_sriov.c +++ b/drivers/crypto/qat/qat_common/adf_sriov.c @@ -3,7 +3,6 @@ #include #include #include -#include #include "adf_common_drv.h" #include "adf_cfg.h" #include "adf_pfvf_pf_msg.h" @@ -74,8 +73,7 @@ static int adf_enable_sriov(struct adf_accel_dev *accel_dev) hw_data->configure_iov_threads(accel_dev, true); /* Enable VF to PF interrupts for all VFs */ - if (hw_data->pfvf_ops.get_pf2vf_offset) - adf_enable_vf2pf_interrupts(accel_dev, BIT_ULL(totalvfs) - 1); + adf_enable_vf2pf_interrupts(accel_dev, BIT_ULL(totalvfs) - 1); /* * Due to the hardware design, when SR-IOV and the ring arbiter @@ -104,22 +102,18 @@ void adf_disable_sriov(struct adf_accel_dev *accel_dev) if (!accel_dev->pf.vf_info) return; - if (hw_data->pfvf_ops.get_pf2vf_offset) - adf_pf2vf_notify_restarting(accel_dev); - + adf_pf2vf_notify_restarting(accel_dev); pci_disable_sriov(accel_to_pci_dev(accel_dev)); /* Disable VF to PF interrupts */ - if (hw_data->pfvf_ops.get_pf2vf_offset) - adf_disable_vf2pf_interrupts(accel_dev, GENMASK(31, 0)); + adf_disable_all_vf2pf_interrupts(accel_dev); /* Clear Valid bits in AE Thread to PCIe Function Mapping */ if (hw_data->configure_iov_threads) hw_data->configure_iov_threads(accel_dev, false); - for (i = 0, vf = accel_dev->pf.vf_info; i < totalvfs; i++, vf++) { + for (i = 0, vf = accel_dev->pf.vf_info; i < totalvfs; i++, vf++) mutex_destroy(&vf->pf2vf_lock); - } kfree(accel_dev->pf.vf_info); accel_dev->pf.vf_info = NULL; @@ -176,7 +170,7 @@ int adf_sriov_configure(struct pci_dev *pdev, int numvfs) return -EFAULT; } - if (!iommu_present(&pci_bus_type)) + if (!device_iommu_mapped(&pdev->dev)) dev_warn(&pdev->dev, "IOMMU should be enabled for SR-IOV to work correctly\n"); if (accel_dev->pf.vf_info) { diff --git a/drivers/crypto/qat/qat_common/adf_transport.c b/drivers/crypto/qat/qat_common/adf_transport.c index 8ba28409fb74b7ad9da74f6a9ec659a31b4124c2..630d0483c4e0a1a4134f9f73f0def8091e9e4a55 100644 --- a/drivers/crypto/qat/qat_common/adf_transport.c +++ b/drivers/crypto/qat/qat_common/adf_transport.c @@ -8,6 +8,9 @@ #include "adf_cfg.h" #include "adf_common_drv.h" +#define ADF_MAX_RING_THRESHOLD 80 +#define ADF_PERCENT(tot, percent) (((tot) * (percent)) / 100) + static inline u32 adf_modulo(u32 data, u32 shift) { u32 div = data >> shift; @@ -77,6 +80,11 @@ static void adf_disable_ring_irq(struct adf_etr_bank_data *bank, u32 ring) bank->irq_mask); } +bool adf_ring_nearly_full(struct adf_etr_ring_data *ring) +{ + return atomic_read(ring->inflights) > ring->threshold; +} + int adf_send_message(struct adf_etr_ring_data *ring, u32 *msg) { struct adf_hw_csr_ops *csr_ops = GET_CSR_OPS(ring->bank->accel_dev); @@ -217,6 +225,7 @@ int adf_create_ring(struct adf_accel_dev *accel_dev, const char *section, struct adf_etr_bank_data *bank; struct adf_etr_ring_data *ring; char val[ADF_CFG_MAX_VAL_LEN_IN_BYTES]; + int max_inflights; u32 ring_num; int ret; @@ -263,6 +272,8 @@ int adf_create_ring(struct adf_accel_dev *accel_dev, const char *section, ring->ring_size = adf_verify_ring_size(msg_size, num_msgs); ring->head = 0; ring->tail = 0; + max_inflights = ADF_MAX_INFLIGHTS(ring->ring_size, ring->msg_size); + ring->threshold = ADF_PERCENT(max_inflights, ADF_MAX_RING_THRESHOLD); atomic_set(ring->inflights, 0); ret = adf_init_ring(ring); if (ret) diff --git a/drivers/crypto/qat/qat_common/adf_transport.h b/drivers/crypto/qat/qat_common/adf_transport.h index 2c95f1697c76fe2d3589318e8e641c17b84aa04d..e6ef6f9b769133a3b713cf71aaa600ae741edfed 100644 --- a/drivers/crypto/qat/qat_common/adf_transport.h +++ b/drivers/crypto/qat/qat_common/adf_transport.h @@ -14,6 +14,7 @@ int adf_create_ring(struct adf_accel_dev *accel_dev, const char *section, const char *ring_name, adf_callback_fn callback, int poll_mode, struct adf_etr_ring_data **ring_ptr); +bool adf_ring_nearly_full(struct adf_etr_ring_data *ring); int adf_send_message(struct adf_etr_ring_data *ring, u32 *msg); void adf_remove_ring(struct adf_etr_ring_data *ring); #endif diff --git a/drivers/crypto/qat/qat_common/adf_transport_internal.h b/drivers/crypto/qat/qat_common/adf_transport_internal.h index 501bcf0f1809afb34be0633cf0edd4c63d7ee608..8b2c92ba7ca1f029ccd99664f350230db83b1612 100644 --- a/drivers/crypto/qat/qat_common/adf_transport_internal.h +++ b/drivers/crypto/qat/qat_common/adf_transport_internal.h @@ -22,6 +22,7 @@ struct adf_etr_ring_data { spinlock_t lock; /* protects ring data struct */ u16 head; u16 tail; + u32 threshold; u8 ring_number; u8 ring_size; u8 msg_size; diff --git a/drivers/crypto/qat/qat_common/adf_vf_isr.c b/drivers/crypto/qat/qat_common/adf_vf_isr.c index 86c3bd0c9c2bb02f237b23376149cf29c2e52e04..8c95fcd8e64b098e90797c4fed25b564efcf0c86 100644 --- a/drivers/crypto/qat/qat_common/adf_vf_isr.c +++ b/drivers/crypto/qat/qat_common/adf_vf_isr.c @@ -70,6 +70,7 @@ static void adf_dev_stop_async(struct work_struct *work) container_of(work, struct adf_vf_stop_data, work); struct adf_accel_dev *accel_dev = stop_data->accel_dev; + adf_dev_restarting_notify(accel_dev); adf_dev_stop(accel_dev); adf_dev_shutdown(accel_dev); diff --git a/drivers/crypto/qat/qat_common/qat_algs.c b/drivers/crypto/qat/qat_common/qat_algs.c index f998ed58457c24fb260a208ca5a65a9b65bf38d7..148edbe379e311989683f010ff434e6663204aa3 100644 --- a/drivers/crypto/qat/qat_common/qat_algs.c +++ b/drivers/crypto/qat/qat_common/qat_algs.c @@ -17,7 +17,7 @@ #include #include #include "adf_accel_devices.h" -#include "adf_transport.h" +#include "qat_algs_send.h" #include "adf_common_drv.h" #include "qat_crypto.h" #include "icp_qat_hw.h" @@ -46,19 +46,6 @@ static DEFINE_MUTEX(algs_lock); static unsigned int active_devs; -struct qat_alg_buf { - u32 len; - u32 resrvd; - u64 addr; -} __packed; - -struct qat_alg_buf_list { - u64 resrvd; - u32 num_bufs; - u32 num_mapped_bufs; - struct qat_alg_buf bufers[]; -} __packed __aligned(64); - /* Common content descriptor */ struct qat_alg_cd { union { @@ -693,7 +680,10 @@ static void qat_alg_free_bufl(struct qat_crypto_instance *inst, bl->bufers[i].len, DMA_BIDIRECTIONAL); dma_unmap_single(dev, blp, sz, DMA_TO_DEVICE); - kfree(bl); + + if (!qat_req->buf.sgl_src_valid) + kfree(bl); + if (blp != blpout) { /* If out of place operation dma unmap only data */ int bufless = blout->num_bufs - blout->num_mapped_bufs; @@ -704,14 +694,17 @@ static void qat_alg_free_bufl(struct qat_crypto_instance *inst, DMA_BIDIRECTIONAL); } dma_unmap_single(dev, blpout, sz_out, DMA_TO_DEVICE); - kfree(blout); + + if (!qat_req->buf.sgl_dst_valid) + kfree(blout); } } static int qat_alg_sgl_to_bufl(struct qat_crypto_instance *inst, struct scatterlist *sgl, struct scatterlist *sglout, - struct qat_crypto_request *qat_req) + struct qat_crypto_request *qat_req, + gfp_t flags) { struct device *dev = &GET_DEV(inst->accel_dev); int i, sg_nctr = 0; @@ -721,15 +714,24 @@ static int qat_alg_sgl_to_bufl(struct qat_crypto_instance *inst, dma_addr_t blp = DMA_MAPPING_ERROR; dma_addr_t bloutp = DMA_MAPPING_ERROR; struct scatterlist *sg; - size_t sz_out, sz = struct_size(bufl, bufers, n + 1); + size_t sz_out, sz = struct_size(bufl, bufers, n); + int node = dev_to_node(&GET_DEV(inst->accel_dev)); if (unlikely(!n)) return -EINVAL; - bufl = kzalloc_node(sz, GFP_ATOMIC, - dev_to_node(&GET_DEV(inst->accel_dev))); - if (unlikely(!bufl)) - return -ENOMEM; + qat_req->buf.sgl_src_valid = false; + qat_req->buf.sgl_dst_valid = false; + + if (n > QAT_MAX_BUFF_DESC) { + bufl = kzalloc_node(sz, flags, node); + if (unlikely(!bufl)) + return -ENOMEM; + } else { + bufl = &qat_req->buf.sgl_src.sgl_hdr; + memset(bufl, 0, sizeof(struct qat_alg_buf_list)); + qat_req->buf.sgl_src_valid = true; + } for_each_sg(sgl, sg, n, i) bufl->bufers[i].addr = DMA_MAPPING_ERROR; @@ -760,12 +762,18 @@ static int qat_alg_sgl_to_bufl(struct qat_crypto_instance *inst, struct qat_alg_buf *bufers; n = sg_nents(sglout); - sz_out = struct_size(buflout, bufers, n + 1); + sz_out = struct_size(buflout, bufers, n); sg_nctr = 0; - buflout = kzalloc_node(sz_out, GFP_ATOMIC, - dev_to_node(&GET_DEV(inst->accel_dev))); - if (unlikely(!buflout)) - goto err_in; + + if (n > QAT_MAX_BUFF_DESC) { + buflout = kzalloc_node(sz_out, flags, node); + if (unlikely(!buflout)) + goto err_in; + } else { + buflout = &qat_req->buf.sgl_dst.sgl_hdr; + memset(buflout, 0, sizeof(struct qat_alg_buf_list)); + qat_req->buf.sgl_dst_valid = true; + } bufers = buflout->bufers; for_each_sg(sglout, sg, n, i) @@ -810,7 +818,9 @@ err_out: dma_unmap_single(dev, buflout->bufers[i].addr, buflout->bufers[i].len, DMA_BIDIRECTIONAL); - kfree(buflout); + + if (!qat_req->buf.sgl_dst_valid) + kfree(buflout); err_in: if (!dma_mapping_error(dev, blp)) @@ -823,7 +833,8 @@ err_in: bufl->bufers[i].len, DMA_BIDIRECTIONAL); - kfree(bufl); + if (!qat_req->buf.sgl_src_valid) + kfree(bufl); dev_err(dev, "Failed to map buf for dma\n"); return -ENOMEM; @@ -925,8 +936,25 @@ void qat_alg_callback(void *resp) struct icp_qat_fw_la_resp *qat_resp = resp; struct qat_crypto_request *qat_req = (void *)(__force long)qat_resp->opaque_data; + struct qat_instance_backlog *backlog = qat_req->alg_req.backlog; qat_req->cb(qat_resp, qat_req); + + qat_alg_send_backlog(backlog); +} + +static int qat_alg_send_sym_message(struct qat_crypto_request *qat_req, + struct qat_crypto_instance *inst, + struct crypto_async_request *base) +{ + struct qat_alg_req *alg_req = &qat_req->alg_req; + + alg_req->fw_req = (u32 *)&qat_req->req; + alg_req->tx_ring = inst->sym_tx; + alg_req->base = base; + alg_req->backlog = &inst->backlog; + + return qat_alg_send_message(alg_req); } static int qat_alg_aead_dec(struct aead_request *areq) @@ -939,14 +967,15 @@ static int qat_alg_aead_dec(struct aead_request *areq) struct icp_qat_fw_la_auth_req_params *auth_param; struct icp_qat_fw_la_bulk_req *msg; int digst_size = crypto_aead_authsize(aead_tfm); - int ret, ctr = 0; + gfp_t f = qat_algs_alloc_flags(&areq->base); + int ret; u32 cipher_len; cipher_len = areq->cryptlen - digst_size; if (cipher_len % AES_BLOCK_SIZE != 0) return -EINVAL; - ret = qat_alg_sgl_to_bufl(ctx->inst, areq->src, areq->dst, qat_req); + ret = qat_alg_sgl_to_bufl(ctx->inst, areq->src, areq->dst, qat_req, f); if (unlikely(ret)) return ret; @@ -965,15 +994,12 @@ static int qat_alg_aead_dec(struct aead_request *areq) auth_param = (void *)((u8 *)cipher_param + sizeof(*cipher_param)); auth_param->auth_off = 0; auth_param->auth_len = areq->assoclen + cipher_param->cipher_length; - do { - ret = adf_send_message(ctx->inst->sym_tx, (u32 *)msg); - } while (ret == -EAGAIN && ctr++ < 10); - if (ret == -EAGAIN) { + ret = qat_alg_send_sym_message(qat_req, ctx->inst, &areq->base); + if (ret == -ENOSPC) qat_alg_free_bufl(ctx->inst, qat_req); - return -EBUSY; - } - return -EINPROGRESS; + + return ret; } static int qat_alg_aead_enc(struct aead_request *areq) @@ -984,14 +1010,15 @@ static int qat_alg_aead_enc(struct aead_request *areq) struct qat_crypto_request *qat_req = aead_request_ctx(areq); struct icp_qat_fw_la_cipher_req_params *cipher_param; struct icp_qat_fw_la_auth_req_params *auth_param; + gfp_t f = qat_algs_alloc_flags(&areq->base); struct icp_qat_fw_la_bulk_req *msg; u8 *iv = areq->iv; - int ret, ctr = 0; + int ret; if (areq->cryptlen % AES_BLOCK_SIZE != 0) return -EINVAL; - ret = qat_alg_sgl_to_bufl(ctx->inst, areq->src, areq->dst, qat_req); + ret = qat_alg_sgl_to_bufl(ctx->inst, areq->src, areq->dst, qat_req, f); if (unlikely(ret)) return ret; @@ -1013,15 +1040,11 @@ static int qat_alg_aead_enc(struct aead_request *areq) auth_param->auth_off = 0; auth_param->auth_len = areq->assoclen + areq->cryptlen; - do { - ret = adf_send_message(ctx->inst->sym_tx, (u32 *)msg); - } while (ret == -EAGAIN && ctr++ < 10); - - if (ret == -EAGAIN) { + ret = qat_alg_send_sym_message(qat_req, ctx->inst, &areq->base); + if (ret == -ENOSPC) qat_alg_free_bufl(ctx->inst, qat_req); - return -EBUSY; - } - return -EINPROGRESS; + + return ret; } static int qat_alg_skcipher_rekey(struct qat_alg_skcipher_ctx *ctx, @@ -1173,13 +1196,14 @@ static int qat_alg_skcipher_encrypt(struct skcipher_request *req) struct qat_alg_skcipher_ctx *ctx = crypto_tfm_ctx(tfm); struct qat_crypto_request *qat_req = skcipher_request_ctx(req); struct icp_qat_fw_la_cipher_req_params *cipher_param; + gfp_t f = qat_algs_alloc_flags(&req->base); struct icp_qat_fw_la_bulk_req *msg; - int ret, ctr = 0; + int ret; if (req->cryptlen == 0) return 0; - ret = qat_alg_sgl_to_bufl(ctx->inst, req->src, req->dst, qat_req); + ret = qat_alg_sgl_to_bufl(ctx->inst, req->src, req->dst, qat_req, f); if (unlikely(ret)) return ret; @@ -1198,15 +1222,11 @@ static int qat_alg_skcipher_encrypt(struct skcipher_request *req) qat_alg_set_req_iv(qat_req); - do { - ret = adf_send_message(ctx->inst->sym_tx, (u32 *)msg); - } while (ret == -EAGAIN && ctr++ < 10); - - if (ret == -EAGAIN) { + ret = qat_alg_send_sym_message(qat_req, ctx->inst, &req->base); + if (ret == -ENOSPC) qat_alg_free_bufl(ctx->inst, qat_req); - return -EBUSY; - } - return -EINPROGRESS; + + return ret; } static int qat_alg_skcipher_blk_encrypt(struct skcipher_request *req) @@ -1242,13 +1262,14 @@ static int qat_alg_skcipher_decrypt(struct skcipher_request *req) struct qat_alg_skcipher_ctx *ctx = crypto_tfm_ctx(tfm); struct qat_crypto_request *qat_req = skcipher_request_ctx(req); struct icp_qat_fw_la_cipher_req_params *cipher_param; + gfp_t f = qat_algs_alloc_flags(&req->base); struct icp_qat_fw_la_bulk_req *msg; - int ret, ctr = 0; + int ret; if (req->cryptlen == 0) return 0; - ret = qat_alg_sgl_to_bufl(ctx->inst, req->src, req->dst, qat_req); + ret = qat_alg_sgl_to_bufl(ctx->inst, req->src, req->dst, qat_req, f); if (unlikely(ret)) return ret; @@ -1268,15 +1289,11 @@ static int qat_alg_skcipher_decrypt(struct skcipher_request *req) qat_alg_set_req_iv(qat_req); qat_alg_update_iv(qat_req); - do { - ret = adf_send_message(ctx->inst->sym_tx, (u32 *)msg); - } while (ret == -EAGAIN && ctr++ < 10); - - if (ret == -EAGAIN) { + ret = qat_alg_send_sym_message(qat_req, ctx->inst, &req->base); + if (ret == -ENOSPC) qat_alg_free_bufl(ctx->inst, qat_req); - return -EBUSY; - } - return -EINPROGRESS; + + return ret; } static int qat_alg_skcipher_blk_decrypt(struct skcipher_request *req) diff --git a/drivers/crypto/qat/qat_common/qat_algs_send.c b/drivers/crypto/qat/qat_common/qat_algs_send.c new file mode 100644 index 0000000000000000000000000000000000000000..ff5b4347f7831d8489d481c6f8c1d13099cbbb77 --- /dev/null +++ b/drivers/crypto/qat/qat_common/qat_algs_send.c @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0-only) +/* Copyright(c) 2022 Intel Corporation */ +#include "adf_transport.h" +#include "qat_algs_send.h" +#include "qat_crypto.h" + +#define ADF_MAX_RETRIES 20 + +static int qat_alg_send_message_retry(struct qat_alg_req *req) +{ + int ret = 0, ctr = 0; + + do { + ret = adf_send_message(req->tx_ring, req->fw_req); + } while (ret == -EAGAIN && ctr++ < ADF_MAX_RETRIES); + + if (ret == -EAGAIN) + return -ENOSPC; + + return -EINPROGRESS; +} + +void qat_alg_send_backlog(struct qat_instance_backlog *backlog) +{ + struct qat_alg_req *req, *tmp; + + spin_lock_bh(&backlog->lock); + list_for_each_entry_safe(req, tmp, &backlog->list, list) { + if (adf_send_message(req->tx_ring, req->fw_req)) { + /* The HW ring is full. Do nothing. + * qat_alg_send_backlog() will be invoked again by + * another callback. + */ + break; + } + list_del(&req->list); + req->base->complete(req->base, -EINPROGRESS); + } + spin_unlock_bh(&backlog->lock); +} + +static void qat_alg_backlog_req(struct qat_alg_req *req, + struct qat_instance_backlog *backlog) +{ + INIT_LIST_HEAD(&req->list); + + spin_lock_bh(&backlog->lock); + list_add_tail(&req->list, &backlog->list); + spin_unlock_bh(&backlog->lock); +} + +static int qat_alg_send_message_maybacklog(struct qat_alg_req *req) +{ + struct qat_instance_backlog *backlog = req->backlog; + struct adf_etr_ring_data *tx_ring = req->tx_ring; + u32 *fw_req = req->fw_req; + + /* If any request is already backlogged, then add to backlog list */ + if (!list_empty(&backlog->list)) + goto enqueue; + + /* If ring is nearly full, then add to backlog list */ + if (adf_ring_nearly_full(tx_ring)) + goto enqueue; + + /* If adding request to HW ring fails, then add to backlog list */ + if (adf_send_message(tx_ring, fw_req)) + goto enqueue; + + return -EINPROGRESS; + +enqueue: + qat_alg_backlog_req(req, backlog); + + return -EBUSY; +} + +int qat_alg_send_message(struct qat_alg_req *req) +{ + u32 flags = req->base->flags; + + if (flags & CRYPTO_TFM_REQ_MAY_BACKLOG) + return qat_alg_send_message_maybacklog(req); + else + return qat_alg_send_message_retry(req); +} diff --git a/drivers/crypto/qat/qat_common/qat_algs_send.h b/drivers/crypto/qat/qat_common/qat_algs_send.h new file mode 100644 index 0000000000000000000000000000000000000000..5ce9f4f69d8ff8339e9b64c215a19d57da4a13cd --- /dev/null +++ b/drivers/crypto/qat/qat_common/qat_algs_send.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0-only) */ +/* Copyright(c) 2022 Intel Corporation */ +#ifndef QAT_ALGS_SEND_H +#define QAT_ALGS_SEND_H + +#include "qat_crypto.h" + +int qat_alg_send_message(struct qat_alg_req *req); +void qat_alg_send_backlog(struct qat_instance_backlog *backlog); + +#endif diff --git a/drivers/crypto/qat/qat_common/qat_asym_algs.c b/drivers/crypto/qat/qat_common/qat_asym_algs.c index b0b78445418bb48135587cba5884a09d8cb3c208..16d97db9ea15f7bf427d285d219668049bba9bc3 100644 --- a/drivers/crypto/qat/qat_common/qat_asym_algs.c +++ b/drivers/crypto/qat/qat_common/qat_asym_algs.c @@ -12,6 +12,7 @@ #include #include "icp_qat_fw_pke.h" #include "adf_accel_devices.h" +#include "qat_algs_send.h" #include "adf_transport.h" #include "adf_common_drv.h" #include "qat_crypto.h" @@ -135,8 +136,23 @@ struct qat_asym_request { } areq; int err; void (*cb)(struct icp_qat_fw_pke_resp *resp); + struct qat_alg_req alg_req; } __aligned(64); +static int qat_alg_send_asym_message(struct qat_asym_request *qat_req, + struct qat_crypto_instance *inst, + struct crypto_async_request *base) +{ + struct qat_alg_req *alg_req = &qat_req->alg_req; + + alg_req->fw_req = (u32 *)&qat_req->req; + alg_req->tx_ring = inst->pke_tx; + alg_req->base = base; + alg_req->backlog = &inst->backlog; + + return qat_alg_send_message(alg_req); +} + static void qat_dh_cb(struct icp_qat_fw_pke_resp *resp) { struct qat_asym_request *req = (void *)(__force long)resp->opaque; @@ -148,26 +164,21 @@ static void qat_dh_cb(struct icp_qat_fw_pke_resp *resp) err = (err == ICP_QAT_FW_COMN_STATUS_FLAG_OK) ? 0 : -EINVAL; if (areq->src) { - if (req->src_align) - dma_free_coherent(dev, req->ctx.dh->p_size, - req->src_align, req->in.dh.in.b); - else - dma_unmap_single(dev, req->in.dh.in.b, - req->ctx.dh->p_size, DMA_TO_DEVICE); + dma_unmap_single(dev, req->in.dh.in.b, req->ctx.dh->p_size, + DMA_TO_DEVICE); + kfree_sensitive(req->src_align); } areq->dst_len = req->ctx.dh->p_size; if (req->dst_align) { scatterwalk_map_and_copy(req->dst_align, areq->dst, 0, areq->dst_len, 1); - - dma_free_coherent(dev, req->ctx.dh->p_size, req->dst_align, - req->out.dh.r); - } else { - dma_unmap_single(dev, req->out.dh.r, req->ctx.dh->p_size, - DMA_FROM_DEVICE); + kfree_sensitive(req->dst_align); } + dma_unmap_single(dev, req->out.dh.r, req->ctx.dh->p_size, + DMA_FROM_DEVICE); + dma_unmap_single(dev, req->phy_in, sizeof(struct qat_dh_input_params), DMA_TO_DEVICE); dma_unmap_single(dev, req->phy_out, @@ -213,8 +224,10 @@ static int qat_dh_compute_value(struct kpp_request *req) struct qat_asym_request *qat_req = PTR_ALIGN(kpp_request_ctx(req), 64); struct icp_qat_fw_pke_request *msg = &qat_req->req; - int ret, ctr = 0; + gfp_t flags = qat_algs_alloc_flags(&req->base); int n_input_params = 0; + u8 *vaddr; + int ret; if (unlikely(!ctx->xa)) return -EINVAL; @@ -223,6 +236,10 @@ static int qat_dh_compute_value(struct kpp_request *req) req->dst_len = ctx->p_size; return -EOVERFLOW; } + + if (req->src_len > ctx->p_size) + return -EINVAL; + memset(msg, '\0', sizeof(*msg)); ICP_QAT_FW_PKE_HDR_VALID_FLAG_SET(msg->pke_hdr, ICP_QAT_FW_COMN_REQ_FLAG_SET); @@ -271,27 +288,24 @@ static int qat_dh_compute_value(struct kpp_request *req) */ if (sg_is_last(req->src) && req->src_len == ctx->p_size) { qat_req->src_align = NULL; - qat_req->in.dh.in.b = dma_map_single(dev, - sg_virt(req->src), - req->src_len, - DMA_TO_DEVICE); - if (unlikely(dma_mapping_error(dev, - qat_req->in.dh.in.b))) - return ret; - + vaddr = sg_virt(req->src); } else { int shift = ctx->p_size - req->src_len; - qat_req->src_align = dma_alloc_coherent(dev, - ctx->p_size, - &qat_req->in.dh.in.b, - GFP_KERNEL); + qat_req->src_align = kzalloc(ctx->p_size, flags); if (unlikely(!qat_req->src_align)) return ret; scatterwalk_map_and_copy(qat_req->src_align + shift, req->src, 0, req->src_len, 0); + + vaddr = qat_req->src_align; } + + qat_req->in.dh.in.b = dma_map_single(dev, vaddr, ctx->p_size, + DMA_TO_DEVICE); + if (unlikely(dma_mapping_error(dev, qat_req->in.dh.in.b))) + goto unmap_src; } /* * dst can be of any size in valid range, but HW expects it to be the @@ -302,20 +316,18 @@ static int qat_dh_compute_value(struct kpp_request *req) */ if (sg_is_last(req->dst) && req->dst_len == ctx->p_size) { qat_req->dst_align = NULL; - qat_req->out.dh.r = dma_map_single(dev, sg_virt(req->dst), - req->dst_len, - DMA_FROM_DEVICE); - - if (unlikely(dma_mapping_error(dev, qat_req->out.dh.r))) - goto unmap_src; - + vaddr = sg_virt(req->dst); } else { - qat_req->dst_align = dma_alloc_coherent(dev, ctx->p_size, - &qat_req->out.dh.r, - GFP_KERNEL); + qat_req->dst_align = kzalloc(ctx->p_size, flags); if (unlikely(!qat_req->dst_align)) goto unmap_src; + + vaddr = qat_req->dst_align; } + qat_req->out.dh.r = dma_map_single(dev, vaddr, ctx->p_size, + DMA_FROM_DEVICE); + if (unlikely(dma_mapping_error(dev, qat_req->out.dh.r))) + goto unmap_dst; qat_req->in.dh.in_tab[n_input_params] = 0; qat_req->out.dh.out_tab[1] = 0; @@ -338,13 +350,13 @@ static int qat_dh_compute_value(struct kpp_request *req) msg->input_param_count = n_input_params; msg->output_param_count = 1; - do { - ret = adf_send_message(ctx->inst->pke_tx, (u32 *)msg); - } while (ret == -EBUSY && ctr++ < 100); + ret = qat_alg_send_asym_message(qat_req, inst, &req->base); + if (ret == -ENOSPC) + goto unmap_all; - if (!ret) - return -EINPROGRESS; + return ret; +unmap_all: if (!dma_mapping_error(dev, qat_req->phy_out)) dma_unmap_single(dev, qat_req->phy_out, sizeof(struct qat_dh_output_params), @@ -355,23 +367,17 @@ unmap_in_params: sizeof(struct qat_dh_input_params), DMA_TO_DEVICE); unmap_dst: - if (qat_req->dst_align) - dma_free_coherent(dev, ctx->p_size, qat_req->dst_align, - qat_req->out.dh.r); - else - if (!dma_mapping_error(dev, qat_req->out.dh.r)) - dma_unmap_single(dev, qat_req->out.dh.r, ctx->p_size, - DMA_FROM_DEVICE); + if (!dma_mapping_error(dev, qat_req->out.dh.r)) + dma_unmap_single(dev, qat_req->out.dh.r, ctx->p_size, + DMA_FROM_DEVICE); + kfree_sensitive(qat_req->dst_align); unmap_src: if (req->src) { - if (qat_req->src_align) - dma_free_coherent(dev, ctx->p_size, qat_req->src_align, - qat_req->in.dh.in.b); - else - if (!dma_mapping_error(dev, qat_req->in.dh.in.b)) - dma_unmap_single(dev, qat_req->in.dh.in.b, - ctx->p_size, - DMA_TO_DEVICE); + if (!dma_mapping_error(dev, qat_req->in.dh.in.b)) + dma_unmap_single(dev, qat_req->in.dh.in.b, + ctx->p_size, + DMA_TO_DEVICE); + kfree_sensitive(qat_req->src_align); } return ret; } @@ -420,14 +426,17 @@ static int qat_dh_set_params(struct qat_dh_ctx *ctx, struct dh *params) static void qat_dh_clear_ctx(struct device *dev, struct qat_dh_ctx *ctx) { if (ctx->g) { + memset(ctx->g, 0, ctx->p_size); dma_free_coherent(dev, ctx->p_size, ctx->g, ctx->dma_g); ctx->g = NULL; } if (ctx->xa) { + memset(ctx->xa, 0, ctx->p_size); dma_free_coherent(dev, ctx->p_size, ctx->xa, ctx->dma_xa); ctx->xa = NULL; } if (ctx->p) { + memset(ctx->p, 0, ctx->p_size); dma_free_coherent(dev, ctx->p_size, ctx->p, ctx->dma_p); ctx->p = NULL; } @@ -510,25 +519,22 @@ static void qat_rsa_cb(struct icp_qat_fw_pke_resp *resp) err = (err == ICP_QAT_FW_COMN_STATUS_FLAG_OK) ? 0 : -EINVAL; - if (req->src_align) - dma_free_coherent(dev, req->ctx.rsa->key_sz, req->src_align, - req->in.rsa.enc.m); - else - dma_unmap_single(dev, req->in.rsa.enc.m, req->ctx.rsa->key_sz, - DMA_TO_DEVICE); + kfree_sensitive(req->src_align); + + dma_unmap_single(dev, req->in.rsa.enc.m, req->ctx.rsa->key_sz, + DMA_TO_DEVICE); areq->dst_len = req->ctx.rsa->key_sz; if (req->dst_align) { scatterwalk_map_and_copy(req->dst_align, areq->dst, 0, areq->dst_len, 1); - dma_free_coherent(dev, req->ctx.rsa->key_sz, req->dst_align, - req->out.rsa.enc.c); - } else { - dma_unmap_single(dev, req->out.rsa.enc.c, req->ctx.rsa->key_sz, - DMA_FROM_DEVICE); + kfree_sensitive(req->dst_align); } + dma_unmap_single(dev, req->out.rsa.enc.c, req->ctx.rsa->key_sz, + DMA_FROM_DEVICE); + dma_unmap_single(dev, req->phy_in, sizeof(struct qat_rsa_input_params), DMA_TO_DEVICE); dma_unmap_single(dev, req->phy_out, @@ -542,8 +548,11 @@ void qat_alg_asym_callback(void *_resp) { struct icp_qat_fw_pke_resp *resp = _resp; struct qat_asym_request *areq = (void *)(__force long)resp->opaque; + struct qat_instance_backlog *backlog = areq->alg_req.backlog; areq->cb(resp); + + qat_alg_send_backlog(backlog); } #define PKE_RSA_EP_512 0x1c161b21 @@ -642,7 +651,9 @@ static int qat_rsa_enc(struct akcipher_request *req) struct qat_asym_request *qat_req = PTR_ALIGN(akcipher_request_ctx(req), 64); struct icp_qat_fw_pke_request *msg = &qat_req->req; - int ret, ctr = 0; + gfp_t flags = qat_algs_alloc_flags(&req->base); + u8 *vaddr; + int ret; if (unlikely(!ctx->n || !ctx->e)) return -EINVAL; @@ -651,6 +662,10 @@ static int qat_rsa_enc(struct akcipher_request *req) req->dst_len = ctx->key_sz; return -EOVERFLOW; } + + if (req->src_len > ctx->key_sz) + return -EINVAL; + memset(msg, '\0', sizeof(*msg)); ICP_QAT_FW_PKE_HDR_VALID_FLAG_SET(msg->pke_hdr, ICP_QAT_FW_COMN_REQ_FLAG_SET); @@ -679,40 +694,39 @@ static int qat_rsa_enc(struct akcipher_request *req) */ if (sg_is_last(req->src) && req->src_len == ctx->key_sz) { qat_req->src_align = NULL; - qat_req->in.rsa.enc.m = dma_map_single(dev, sg_virt(req->src), - req->src_len, DMA_TO_DEVICE); - if (unlikely(dma_mapping_error(dev, qat_req->in.rsa.enc.m))) - return ret; - + vaddr = sg_virt(req->src); } else { int shift = ctx->key_sz - req->src_len; - qat_req->src_align = dma_alloc_coherent(dev, ctx->key_sz, - &qat_req->in.rsa.enc.m, - GFP_KERNEL); + qat_req->src_align = kzalloc(ctx->key_sz, flags); if (unlikely(!qat_req->src_align)) return ret; scatterwalk_map_and_copy(qat_req->src_align + shift, req->src, 0, req->src_len, 0); + vaddr = qat_req->src_align; } - if (sg_is_last(req->dst) && req->dst_len == ctx->key_sz) { - qat_req->dst_align = NULL; - qat_req->out.rsa.enc.c = dma_map_single(dev, sg_virt(req->dst), - req->dst_len, - DMA_FROM_DEVICE); - if (unlikely(dma_mapping_error(dev, qat_req->out.rsa.enc.c))) - goto unmap_src; + qat_req->in.rsa.enc.m = dma_map_single(dev, vaddr, ctx->key_sz, + DMA_TO_DEVICE); + if (unlikely(dma_mapping_error(dev, qat_req->in.rsa.enc.m))) + goto unmap_src; + if (sg_is_last(req->dst) && req->dst_len == ctx->key_sz) { + qat_req->dst_align = NULL; + vaddr = sg_virt(req->dst); } else { - qat_req->dst_align = dma_alloc_coherent(dev, ctx->key_sz, - &qat_req->out.rsa.enc.c, - GFP_KERNEL); + qat_req->dst_align = kzalloc(ctx->key_sz, flags); if (unlikely(!qat_req->dst_align)) goto unmap_src; - + vaddr = qat_req->dst_align; } + + qat_req->out.rsa.enc.c = dma_map_single(dev, vaddr, ctx->key_sz, + DMA_FROM_DEVICE); + if (unlikely(dma_mapping_error(dev, qat_req->out.rsa.enc.c))) + goto unmap_dst; + qat_req->in.rsa.in_tab[3] = 0; qat_req->out.rsa.out_tab[1] = 0; qat_req->phy_in = dma_map_single(dev, &qat_req->in.rsa.enc.m, @@ -732,13 +746,14 @@ static int qat_rsa_enc(struct akcipher_request *req) msg->pke_mid.opaque = (u64)(__force long)qat_req; msg->input_param_count = 3; msg->output_param_count = 1; - do { - ret = adf_send_message(ctx->inst->pke_tx, (u32 *)msg); - } while (ret == -EBUSY && ctr++ < 100); - if (!ret) - return -EINPROGRESS; + ret = qat_alg_send_asym_message(qat_req, inst, &req->base); + if (ret == -ENOSPC) + goto unmap_all; + return ret; + +unmap_all: if (!dma_mapping_error(dev, qat_req->phy_out)) dma_unmap_single(dev, qat_req->phy_out, sizeof(struct qat_rsa_output_params), @@ -749,21 +764,15 @@ unmap_in_params: sizeof(struct qat_rsa_input_params), DMA_TO_DEVICE); unmap_dst: - if (qat_req->dst_align) - dma_free_coherent(dev, ctx->key_sz, qat_req->dst_align, - qat_req->out.rsa.enc.c); - else - if (!dma_mapping_error(dev, qat_req->out.rsa.enc.c)) - dma_unmap_single(dev, qat_req->out.rsa.enc.c, - ctx->key_sz, DMA_FROM_DEVICE); + if (!dma_mapping_error(dev, qat_req->out.rsa.enc.c)) + dma_unmap_single(dev, qat_req->out.rsa.enc.c, + ctx->key_sz, DMA_FROM_DEVICE); + kfree_sensitive(qat_req->dst_align); unmap_src: - if (qat_req->src_align) - dma_free_coherent(dev, ctx->key_sz, qat_req->src_align, - qat_req->in.rsa.enc.m); - else - if (!dma_mapping_error(dev, qat_req->in.rsa.enc.m)) - dma_unmap_single(dev, qat_req->in.rsa.enc.m, - ctx->key_sz, DMA_TO_DEVICE); + if (!dma_mapping_error(dev, qat_req->in.rsa.enc.m)) + dma_unmap_single(dev, qat_req->in.rsa.enc.m, ctx->key_sz, + DMA_TO_DEVICE); + kfree_sensitive(qat_req->src_align); return ret; } @@ -776,7 +785,9 @@ static int qat_rsa_dec(struct akcipher_request *req) struct qat_asym_request *qat_req = PTR_ALIGN(akcipher_request_ctx(req), 64); struct icp_qat_fw_pke_request *msg = &qat_req->req; - int ret, ctr = 0; + gfp_t flags = qat_algs_alloc_flags(&req->base); + u8 *vaddr; + int ret; if (unlikely(!ctx->n || !ctx->d)) return -EINVAL; @@ -785,6 +796,10 @@ static int qat_rsa_dec(struct akcipher_request *req) req->dst_len = ctx->key_sz; return -EOVERFLOW; } + + if (req->src_len > ctx->key_sz) + return -EINVAL; + memset(msg, '\0', sizeof(*msg)); ICP_QAT_FW_PKE_HDR_VALID_FLAG_SET(msg->pke_hdr, ICP_QAT_FW_COMN_REQ_FLAG_SET); @@ -823,40 +838,37 @@ static int qat_rsa_dec(struct akcipher_request *req) */ if (sg_is_last(req->src) && req->src_len == ctx->key_sz) { qat_req->src_align = NULL; - qat_req->in.rsa.dec.c = dma_map_single(dev, sg_virt(req->src), - req->dst_len, DMA_TO_DEVICE); - if (unlikely(dma_mapping_error(dev, qat_req->in.rsa.dec.c))) - return ret; - + vaddr = sg_virt(req->src); } else { int shift = ctx->key_sz - req->src_len; - qat_req->src_align = dma_alloc_coherent(dev, ctx->key_sz, - &qat_req->in.rsa.dec.c, - GFP_KERNEL); + qat_req->src_align = kzalloc(ctx->key_sz, flags); if (unlikely(!qat_req->src_align)) return ret; scatterwalk_map_and_copy(qat_req->src_align + shift, req->src, 0, req->src_len, 0); + vaddr = qat_req->src_align; } - if (sg_is_last(req->dst) && req->dst_len == ctx->key_sz) { - qat_req->dst_align = NULL; - qat_req->out.rsa.dec.m = dma_map_single(dev, sg_virt(req->dst), - req->dst_len, - DMA_FROM_DEVICE); - if (unlikely(dma_mapping_error(dev, qat_req->out.rsa.dec.m))) - goto unmap_src; + qat_req->in.rsa.dec.c = dma_map_single(dev, vaddr, ctx->key_sz, + DMA_TO_DEVICE); + if (unlikely(dma_mapping_error(dev, qat_req->in.rsa.dec.c))) + goto unmap_src; + if (sg_is_last(req->dst) && req->dst_len == ctx->key_sz) { + qat_req->dst_align = NULL; + vaddr = sg_virt(req->dst); } else { - qat_req->dst_align = dma_alloc_coherent(dev, ctx->key_sz, - &qat_req->out.rsa.dec.m, - GFP_KERNEL); + qat_req->dst_align = kzalloc(ctx->key_sz, flags); if (unlikely(!qat_req->dst_align)) goto unmap_src; - + vaddr = qat_req->dst_align; } + qat_req->out.rsa.dec.m = dma_map_single(dev, vaddr, ctx->key_sz, + DMA_FROM_DEVICE); + if (unlikely(dma_mapping_error(dev, qat_req->out.rsa.dec.m))) + goto unmap_dst; if (ctx->crt_mode) qat_req->in.rsa.in_tab[6] = 0; @@ -884,13 +896,14 @@ static int qat_rsa_dec(struct akcipher_request *req) msg->input_param_count = 3; msg->output_param_count = 1; - do { - ret = adf_send_message(ctx->inst->pke_tx, (u32 *)msg); - } while (ret == -EBUSY && ctr++ < 100); - if (!ret) - return -EINPROGRESS; + ret = qat_alg_send_asym_message(qat_req, inst, &req->base); + if (ret == -ENOSPC) + goto unmap_all; + + return ret; +unmap_all: if (!dma_mapping_error(dev, qat_req->phy_out)) dma_unmap_single(dev, qat_req->phy_out, sizeof(struct qat_rsa_output_params), @@ -901,21 +914,15 @@ unmap_in_params: sizeof(struct qat_rsa_input_params), DMA_TO_DEVICE); unmap_dst: - if (qat_req->dst_align) - dma_free_coherent(dev, ctx->key_sz, qat_req->dst_align, - qat_req->out.rsa.dec.m); - else - if (!dma_mapping_error(dev, qat_req->out.rsa.dec.m)) - dma_unmap_single(dev, qat_req->out.rsa.dec.m, - ctx->key_sz, DMA_FROM_DEVICE); + if (!dma_mapping_error(dev, qat_req->out.rsa.dec.m)) + dma_unmap_single(dev, qat_req->out.rsa.dec.m, + ctx->key_sz, DMA_FROM_DEVICE); + kfree_sensitive(qat_req->dst_align); unmap_src: - if (qat_req->src_align) - dma_free_coherent(dev, ctx->key_sz, qat_req->src_align, - qat_req->in.rsa.dec.c); - else - if (!dma_mapping_error(dev, qat_req->in.rsa.dec.c)) - dma_unmap_single(dev, qat_req->in.rsa.dec.c, - ctx->key_sz, DMA_TO_DEVICE); + if (!dma_mapping_error(dev, qat_req->in.rsa.dec.c)) + dma_unmap_single(dev, qat_req->in.rsa.dec.c, ctx->key_sz, + DMA_TO_DEVICE); + kfree_sensitive(qat_req->src_align); return ret; } @@ -1233,18 +1240,8 @@ static void qat_rsa_exit_tfm(struct crypto_akcipher *tfm) struct qat_rsa_ctx *ctx = akcipher_tfm_ctx(tfm); struct device *dev = &GET_DEV(ctx->inst->accel_dev); - if (ctx->n) - dma_free_coherent(dev, ctx->key_sz, ctx->n, ctx->dma_n); - if (ctx->e) - dma_free_coherent(dev, ctx->key_sz, ctx->e, ctx->dma_e); - if (ctx->d) { - memset(ctx->d, '\0', ctx->key_sz); - dma_free_coherent(dev, ctx->key_sz, ctx->d, ctx->dma_d); - } + qat_rsa_clear_ctx(dev, ctx); qat_crypto_put_instance(ctx->inst); - ctx->n = NULL; - ctx->e = NULL; - ctx->d = NULL; } static struct akcipher_alg rsa = { diff --git a/drivers/crypto/qat/qat_common/qat_crypto.c b/drivers/crypto/qat/qat_common/qat_crypto.c index 67c9588e89df98a64d054ab5ac19799274da8a6b..9341d892533a7ebc57a23a1a0461ec126890dc65 100644 --- a/drivers/crypto/qat/qat_common/qat_crypto.c +++ b/drivers/crypto/qat/qat_common/qat_crypto.c @@ -161,13 +161,6 @@ int qat_crypto_dev_config(struct adf_accel_dev *accel_dev) if (ret) goto err; - /* Temporarily set the number of crypto instances to zero to avoid - * registering the crypto algorithms. - * This will be removed when the algorithms will support the - * CRYPTO_TFM_REQ_MAY_BACKLOG flag - */ - instances = 0; - for (i = 0; i < instances; i++) { val = i; snprintf(key, sizeof(key), ADF_CY "%d" ADF_RING_ASYM_BANK_NUM, i); @@ -353,6 +346,9 @@ static int qat_crypto_create_instances(struct adf_accel_dev *accel_dev) &inst->pke_rx); if (ret) goto err; + + INIT_LIST_HEAD(&inst->backlog.list); + spin_lock_init(&inst->backlog.lock); } return 0; err: diff --git a/drivers/crypto/qat/qat_common/qat_crypto.h b/drivers/crypto/qat/qat_common/qat_crypto.h index b6a4c95ae003f1227c58cacf8b0ab0993c499348..df3c738ce323a99440c3b65fc759df17e63cad03 100644 --- a/drivers/crypto/qat/qat_common/qat_crypto.h +++ b/drivers/crypto/qat/qat_common/qat_crypto.h @@ -9,6 +9,19 @@ #include "adf_accel_devices.h" #include "icp_qat_fw_la.h" +struct qat_instance_backlog { + struct list_head list; + spinlock_t lock; /* protects backlog list */ +}; + +struct qat_alg_req { + u32 *fw_req; + struct adf_etr_ring_data *tx_ring; + struct crypto_async_request *base; + struct list_head list; + struct qat_instance_backlog *backlog; +}; + struct qat_crypto_instance { struct adf_etr_ring_data *sym_tx; struct adf_etr_ring_data *sym_rx; @@ -19,8 +32,29 @@ struct qat_crypto_instance { unsigned long state; int id; atomic_t refctr; + struct qat_instance_backlog backlog; }; +#define QAT_MAX_BUFF_DESC 4 + +struct qat_alg_buf { + u32 len; + u32 resrvd; + u64 addr; +} __packed; + +struct qat_alg_buf_list { + u64 resrvd; + u32 num_bufs; + u32 num_mapped_bufs; + struct qat_alg_buf bufers[]; +} __packed; + +struct qat_alg_fixed_buf_list { + struct qat_alg_buf_list sgl_hdr; + struct qat_alg_buf descriptors[QAT_MAX_BUFF_DESC]; +} __packed __aligned(64); + struct qat_crypto_request_buffs { struct qat_alg_buf_list *bl; dma_addr_t blp; @@ -28,6 +62,10 @@ struct qat_crypto_request_buffs { dma_addr_t bloutp; size_t sz; size_t sz_out; + bool sgl_src_valid; + bool sgl_dst_valid; + struct qat_alg_fixed_buf_list sgl_src; + struct qat_alg_fixed_buf_list sgl_dst; }; struct qat_crypto_request; @@ -53,6 +91,7 @@ struct qat_crypto_request { u8 iv[AES_BLOCK_SIZE]; }; bool encryption; + struct qat_alg_req alg_req; }; static inline bool adf_hw_dev_has_crypto(struct adf_accel_dev *accel_dev) @@ -70,4 +109,9 @@ static inline bool adf_hw_dev_has_crypto(struct adf_accel_dev *accel_dev) return true; } +static inline gfp_t qat_algs_alloc_flags(struct crypto_async_request *req) +{ + return req->flags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL : GFP_ATOMIC; +} + #endif diff --git a/drivers/crypto/qat/qat_common/qat_hal.c b/drivers/crypto/qat/qat_common/qat_hal.c index 4bfd8f3566f7aab29f562fcea9db436c078a77c9..7bba35280dacce2cdef77e0e78af24f3a59c73c6 100644 --- a/drivers/crypto/qat/qat_common/qat_hal.c +++ b/drivers/crypto/qat/qat_common/qat_hal.c @@ -695,6 +695,7 @@ static int qat_hal_chip_init(struct icp_qat_fw_loader_handle *handle, handle->pci_dev = pci_info->pci_dev; switch (handle->pci_dev->device) { case ADF_4XXX_PCI_DEVICE_ID: + case ADF_401XX_PCI_DEVICE_ID: handle->chip_info->mmp_sram_size = 0; handle->chip_info->nn = false; handle->chip_info->lm2lm3 = true; diff --git a/drivers/crypto/qat/qat_common/qat_uclo.c b/drivers/crypto/qat/qat_common/qat_uclo.c index 6356402a2c9e8c1a656301ec006b6f15cbb17655..0fe5a474aa4525f2a00cb76056b6e1cf701a90e6 100644 --- a/drivers/crypto/qat/qat_common/qat_uclo.c +++ b/drivers/crypto/qat/qat_common/qat_uclo.c @@ -519,7 +519,7 @@ qat_uclo_map_chunk(char *buf, struct icp_qat_uof_filehdr *file_hdr, return NULL; } -static unsigned int +static int qat_uclo_check_image_compat(struct icp_qat_uof_encap_obj *encap_uof_obj, struct icp_qat_uof_image *image) { @@ -731,6 +731,7 @@ qat_uclo_get_dev_type(struct icp_qat_fw_loader_handle *handle) case PCI_DEVICE_ID_INTEL_QAT_C3XXX: return ICP_QAT_AC_C3XXX_DEV_TYPE; case ADF_4XXX_PCI_DEVICE_ID: + case ADF_401XX_PCI_DEVICE_ID: return ICP_QAT_AC_4XXX_A_DEV_TYPE; default: pr_err("QAT: unsupported device 0x%x\n", diff --git a/drivers/crypto/qat/qat_dh895xcc/adf_dh895xcc_hw_data.c b/drivers/crypto/qat/qat_dh895xcc/adf_dh895xcc_hw_data.c index 09599fe4d2f3f04b533cfa4029a60c0363961d16..cb3bdd3618fb0e72701d7dc87272462a8a75a587 100644 --- a/drivers/crypto/qat/qat_dh895xcc/adf_dh895xcc_hw_data.c +++ b/drivers/crypto/qat/qat_dh895xcc/adf_dh895xcc_hw_data.c @@ -7,6 +7,8 @@ #include "adf_dh895xcc_hw_data.h" #include "icp_qat_hw.h" +#define ADF_DH895XCC_VF_MSK 0xFFFFFFFF + /* Worker thread to service arbiter mappings */ static const u32 thrd_to_arb_map[ADF_DH895XCC_MAX_ACCELENGINES] = { 0x12222AAA, 0x11666666, 0x12222AAA, 0x11666666, @@ -58,17 +60,24 @@ static u32 get_accel_cap(struct adf_accel_dev *accel_dev) capabilities = ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC | ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC | - ICP_ACCEL_CAPABILITIES_AUTHENTICATION; + ICP_ACCEL_CAPABILITIES_AUTHENTICATION | + ICP_ACCEL_CAPABILITIES_CIPHER | + ICP_ACCEL_CAPABILITIES_COMPRESSION; /* Read accelerator capabilities mask */ pci_read_config_dword(pdev, ADF_DEVICE_LEGFUSE_OFFSET, &legfuses); - if (legfuses & ICP_ACCEL_MASK_CIPHER_SLICE) + /* A set bit in legfuses means the feature is OFF in this SKU */ + if (legfuses & ICP_ACCEL_MASK_CIPHER_SLICE) { capabilities &= ~ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC; + capabilities &= ~ICP_ACCEL_CAPABILITIES_CIPHER; + } if (legfuses & ICP_ACCEL_MASK_PKE_SLICE) capabilities &= ~ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC; - if (legfuses & ICP_ACCEL_MASK_AUTH_SLICE) + if (legfuses & ICP_ACCEL_MASK_AUTH_SLICE) { capabilities &= ~ICP_ACCEL_CAPABILITIES_AUTHENTICATION; + capabilities &= ~ICP_ACCEL_CAPABILITIES_CIPHER; + } if (legfuses & ICP_ACCEL_MASK_COMPRESS_SLICE) capabilities &= ~ICP_ACCEL_CAPABILITIES_COMPRESSION; @@ -100,43 +109,6 @@ static const u32 *adf_get_arbiter_mapping(void) return thrd_to_arb_map; } -static void adf_enable_ints(struct adf_accel_dev *accel_dev) -{ - void __iomem *addr; - - addr = (&GET_BARS(accel_dev)[ADF_DH895XCC_PMISC_BAR])->virt_addr; - - /* Enable bundle and misc interrupts */ - ADF_CSR_WR(addr, ADF_DH895XCC_SMIAPF0_MASK_OFFSET, - accel_dev->pf.vf_info ? 0 : - BIT_ULL(GET_MAX_BANKS(accel_dev)) - 1); - ADF_CSR_WR(addr, ADF_DH895XCC_SMIAPF1_MASK_OFFSET, - ADF_DH895XCC_SMIA1_MASK); -} - -static u32 get_vf2pf_sources(void __iomem *pmisc_bar) -{ - u32 errsou3, errmsk3, errsou5, errmsk5, vf_int_mask; - - /* Get the interrupt sources triggered by VFs */ - errsou3 = ADF_CSR_RD(pmisc_bar, ADF_GEN2_ERRSOU3); - vf_int_mask = ADF_DH895XCC_ERR_REG_VF2PF_L(errsou3); - - /* To avoid adding duplicate entries to work queue, clear - * vf_int_mask_sets bits that are already masked in ERRMSK register. - */ - errmsk3 = ADF_CSR_RD(pmisc_bar, ADF_GEN2_ERRMSK3); - vf_int_mask &= ~ADF_DH895XCC_ERR_REG_VF2PF_L(errmsk3); - - /* Do the same for ERRSOU5 */ - errsou5 = ADF_CSR_RD(pmisc_bar, ADF_GEN2_ERRSOU5); - errmsk5 = ADF_CSR_RD(pmisc_bar, ADF_GEN2_ERRMSK5); - vf_int_mask |= ADF_DH895XCC_ERR_REG_VF2PF_U(errsou5); - vf_int_mask &= ~ADF_DH895XCC_ERR_REG_VF2PF_U(errmsk5); - - return vf_int_mask; -} - static void enable_vf2pf_interrupts(void __iomem *pmisc_addr, u32 vf_mask) { /* Enable VF2PF Messaging Ints - VFs 0 through 15 per vf_mask[15:0] */ @@ -150,27 +122,71 @@ static void enable_vf2pf_interrupts(void __iomem *pmisc_addr, u32 vf_mask) if (vf_mask >> 16) { u32 val = ADF_CSR_RD(pmisc_addr, ADF_GEN2_ERRMSK5) & ~ADF_DH895XCC_ERR_MSK_VF2PF_U(vf_mask); - ADF_CSR_WR(pmisc_addr, ADF_GEN2_ERRMSK5, val); } } -static void disable_vf2pf_interrupts(void __iomem *pmisc_addr, u32 vf_mask) +static void disable_all_vf2pf_interrupts(void __iomem *pmisc_addr) { + u32 val; + /* Disable VF2PF interrupts for VFs 0 through 15 per vf_mask[15:0] */ - if (vf_mask & 0xFFFF) { - u32 val = ADF_CSR_RD(pmisc_addr, ADF_GEN2_ERRMSK3) - | ADF_DH895XCC_ERR_MSK_VF2PF_L(vf_mask); - ADF_CSR_WR(pmisc_addr, ADF_GEN2_ERRMSK3, val); - } + val = ADF_CSR_RD(pmisc_addr, ADF_GEN2_ERRMSK3) + | ADF_DH895XCC_ERR_MSK_VF2PF_L(ADF_DH895XCC_VF_MSK); + ADF_CSR_WR(pmisc_addr, ADF_GEN2_ERRMSK3, val); /* Disable VF2PF interrupts for VFs 16 through 31 per vf_mask[31:16] */ - if (vf_mask >> 16) { - u32 val = ADF_CSR_RD(pmisc_addr, ADF_GEN2_ERRMSK5) - | ADF_DH895XCC_ERR_MSK_VF2PF_U(vf_mask); + val = ADF_CSR_RD(pmisc_addr, ADF_GEN2_ERRMSK5) + | ADF_DH895XCC_ERR_MSK_VF2PF_U(ADF_DH895XCC_VF_MSK); + ADF_CSR_WR(pmisc_addr, ADF_GEN2_ERRMSK5, val); +} - ADF_CSR_WR(pmisc_addr, ADF_GEN2_ERRMSK5, val); - } +static u32 disable_pending_vf2pf_interrupts(void __iomem *pmisc_addr) +{ + u32 sources, pending, disabled; + u32 errsou3, errmsk3; + u32 errsou5, errmsk5; + + /* Get the interrupt sources triggered by VFs */ + errsou3 = ADF_CSR_RD(pmisc_addr, ADF_GEN2_ERRSOU3); + errsou5 = ADF_CSR_RD(pmisc_addr, ADF_GEN2_ERRSOU5); + sources = ADF_DH895XCC_ERR_REG_VF2PF_L(errsou3) + | ADF_DH895XCC_ERR_REG_VF2PF_U(errsou5); + + if (!sources) + return 0; + + /* Get the already disabled interrupts */ + errmsk3 = ADF_CSR_RD(pmisc_addr, ADF_GEN2_ERRMSK3); + errmsk5 = ADF_CSR_RD(pmisc_addr, ADF_GEN2_ERRMSK5); + disabled = ADF_DH895XCC_ERR_REG_VF2PF_L(errmsk3) + | ADF_DH895XCC_ERR_REG_VF2PF_U(errmsk5); + + pending = sources & ~disabled; + if (!pending) + return 0; + + /* Due to HW limitations, when disabling the interrupts, we can't + * just disable the requested sources, as this would lead to missed + * interrupts if sources changes just before writing to ERRMSK3 and + * ERRMSK5. + * To work around it, disable all and re-enable only the sources that + * are not in vf_mask and were not already disabled. Re-enabling will + * trigger a new interrupt for the sources that have changed in the + * meantime, if any. + */ + errmsk3 |= ADF_DH895XCC_ERR_MSK_VF2PF_L(ADF_DH895XCC_VF_MSK); + errmsk5 |= ADF_DH895XCC_ERR_MSK_VF2PF_U(ADF_DH895XCC_VF_MSK); + ADF_CSR_WR(pmisc_addr, ADF_GEN2_ERRMSK3, errmsk3); + ADF_CSR_WR(pmisc_addr, ADF_GEN2_ERRMSK5, errmsk5); + + errmsk3 &= ADF_DH895XCC_ERR_MSK_VF2PF_L(sources | disabled); + errmsk5 &= ADF_DH895XCC_ERR_MSK_VF2PF_U(sources | disabled); + ADF_CSR_WR(pmisc_addr, ADF_GEN2_ERRMSK3, errmsk3); + ADF_CSR_WR(pmisc_addr, ADF_GEN2_ERRMSK5, errmsk5); + + /* Return the sources of the (new) interrupt(s) */ + return pending; } static void configure_iov_threads(struct adf_accel_dev *accel_dev, bool enable) @@ -215,14 +231,14 @@ void adf_init_hw_data_dh895xcc(struct adf_hw_device_data *hw_data) hw_data->init_arb = adf_init_arb; hw_data->exit_arb = adf_exit_arb; hw_data->get_arb_mapping = adf_get_arbiter_mapping; - hw_data->enable_ints = adf_enable_ints; + hw_data->enable_ints = adf_gen2_enable_ints; hw_data->reset_device = adf_reset_sbr; hw_data->disable_iov = adf_disable_sriov; adf_gen2_init_pf_pfvf_ops(&hw_data->pfvf_ops); - hw_data->pfvf_ops.get_vf2pf_sources = get_vf2pf_sources; hw_data->pfvf_ops.enable_vf2pf_interrupts = enable_vf2pf_interrupts; - hw_data->pfvf_ops.disable_vf2pf_interrupts = disable_vf2pf_interrupts; + hw_data->pfvf_ops.disable_all_vf2pf_interrupts = disable_all_vf2pf_interrupts; + hw_data->pfvf_ops.disable_pending_vf2pf_interrupts = disable_pending_vf2pf_interrupts; adf_gen2_init_hw_csr_ops(&hw_data->csr_ops); } diff --git a/drivers/crypto/qat/qat_dh895xcc/adf_dh895xcc_hw_data.h b/drivers/crypto/qat/qat_dh895xcc/adf_dh895xcc_hw_data.h index aa17272a1507b26bdb9c55eaf59b6ce4aaf5f50f..7b674bbe419275aa8609e509ad30312edbbb467c 100644 --- a/drivers/crypto/qat/qat_dh895xcc/adf_dh895xcc_hw_data.h +++ b/drivers/crypto/qat/qat_dh895xcc/adf_dh895xcc_hw_data.h @@ -19,10 +19,6 @@ #define ADF_DH895XCC_ACCELERATORS_MASK 0x3F #define ADF_DH895XCC_ACCELENGINES_MASK 0xFFF #define ADF_DH895XCC_ETR_MAX_BANKS 32 -#define ADF_DH895XCC_SMIAPF0_MASK_OFFSET (0x3A000 + 0x28) -#define ADF_DH895XCC_SMIAPF1_MASK_OFFSET (0x3A000 + 0x30) -#define ADF_DH895XCC_SMIA0_MASK 0xFFFFFFFF -#define ADF_DH895XCC_SMIA1_MASK 0x1 /* Masks for VF2PF interrupts */ #define ADF_DH895XCC_ERR_REG_VF2PF_L(vf_src) (((vf_src) & 0x01FFFE00) >> 9) diff --git a/drivers/crypto/sa2ul.c b/drivers/crypto/sa2ul.c index 51b58e57153f61d24b475db8bd9650a8cea923d7..6957a125b4470b80b7bc9d4a9e9be11c0161f98f 100644 --- a/drivers/crypto/sa2ul.c +++ b/drivers/crypto/sa2ul.c @@ -2379,6 +2379,7 @@ static const struct of_device_id of_match[] = { { .compatible = "ti,j721e-sa2ul", .data = &am654_match_data, }, { .compatible = "ti,am654-sa2ul", .data = &am654_match_data, }, { .compatible = "ti,am64-sa2ul", .data = &am64_match_data, }, + { .compatible = "ti,am62-sa3ul", .data = &am64_match_data, }, {}, }; MODULE_DEVICE_TABLE(of, of_match); diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c index 25c9f825b8b5424d098fa450b6145f6e10de850d..c9ad6c21309018603cdde5cfd903474f7a37c5d5 100644 --- a/drivers/crypto/talitos.c +++ b/drivers/crypto/talitos.c @@ -1709,7 +1709,7 @@ static void common_nonsnoop_hash_unmap(struct device *dev, struct talitos_desc *desc2 = (struct talitos_desc *) (edesc->buf + edesc->dma_len); - unmap_single_talitos_ptr(dev, &edesc->desc.ptr[5], DMA_FROM_DEVICE); + unmap_single_talitos_ptr(dev, &desc->ptr[5], DMA_FROM_DEVICE); if (desc->next_desc && desc->ptr[5].ptr != desc2->ptr[5].ptr) unmap_single_talitos_ptr(dev, &desc2->ptr[5], DMA_FROM_DEVICE); @@ -1721,8 +1721,8 @@ static void common_nonsnoop_hash_unmap(struct device *dev, talitos_sg_unmap(dev, edesc, req_ctx->psrc, NULL, 0, 0); /* When using hashctx-in, must unmap it. */ - if (from_talitos_ptr_len(&edesc->desc.ptr[1], is_sec1)) - unmap_single_talitos_ptr(dev, &edesc->desc.ptr[1], + if (from_talitos_ptr_len(&desc->ptr[1], is_sec1)) + unmap_single_talitos_ptr(dev, &desc->ptr[1], DMA_TO_DEVICE); else if (desc->next_desc) unmap_single_talitos_ptr(dev, &desc2->ptr[1], @@ -1736,8 +1736,8 @@ static void common_nonsnoop_hash_unmap(struct device *dev, dma_unmap_single(dev, edesc->dma_link_tbl, edesc->dma_len, DMA_BIDIRECTIONAL); - if (edesc->desc.next_desc) - dma_unmap_single(dev, be32_to_cpu(edesc->desc.next_desc), + if (desc->next_desc) + dma_unmap_single(dev, be32_to_cpu(desc->next_desc), TALITOS_DESC_SIZE, DMA_BIDIRECTIONAL); } diff --git a/drivers/crypto/ux500/hash/hash_core.c b/drivers/crypto/ux500/hash/hash_core.c index 5157c118d642c497869bcced1799dcdc2e888f3b..265ef3e96fdd39361adafef617b0e0528c754c6e 100644 --- a/drivers/crypto/ux500/hash/hash_core.c +++ b/drivers/crypto/ux500/hash/hash_core.c @@ -877,9 +877,7 @@ static int hash_dma_final(struct ahash_request *req) __func__); goto out; } - } - - if (!req_ctx->updated) { + } else { ret = hash_setconfiguration(device_data, &ctx->config); if (ret) { dev_err(device_data->dev, diff --git a/drivers/crypto/vmx/Makefile b/drivers/crypto/vmx/Makefile index 709670d2b553abb7eb7510621b0ee29196b2945b..2560cfea1dec28414c99b6ba001f4594fe439a4b 100644 --- a/drivers/crypto/vmx/Makefile +++ b/drivers/crypto/vmx/Makefile @@ -2,21 +2,10 @@ obj-$(CONFIG_CRYPTO_DEV_VMX_ENCRYPT) += vmx-crypto.o vmx-crypto-objs := vmx.o aesp8-ppc.o ghashp8-ppc.o aes.o aes_cbc.o aes_ctr.o aes_xts.o ghash.o -ifeq ($(CONFIG_CPU_LITTLE_ENDIAN),y) -override flavour := linux-ppc64le -else -override flavour := linux-ppc64 -endif - -quiet_cmd_perl = PERL $@ - cmd_perl = $(PERL) $(<) $(flavour) > $(@) +quiet_cmd_perl = PERL $@ + cmd_perl = $(PERL) $< $(if $(CONFIG_CPU_LITTLE_ENDIAN), linux-ppc64le, linux-ppc64) > $@ targets += aesp8-ppc.S ghashp8-ppc.S -$(obj)/aesp8-ppc.S: $(src)/aesp8-ppc.pl FORCE - $(call if_changed,perl) - -$(obj)/ghashp8-ppc.S: $(src)/ghashp8-ppc.pl FORCE +$(obj)/aesp8-ppc.S $(obj)/ghashp8-ppc.S: $(obj)/%.S: $(src)/%.pl FORCE $(call if_changed,perl) - -clean-files := aesp8-ppc.S ghashp8-ppc.S diff --git a/drivers/cxl/Kconfig b/drivers/cxl/Kconfig index b88ab956bb7cfe0c3276557a1bfc965d9b1dd1b3..f64e3984689ffad92fcd68af4e0066ca09476604 100644 --- a/drivers/cxl/Kconfig +++ b/drivers/cxl/Kconfig @@ -98,4 +98,8 @@ config CXL_PORT default CXL_BUS tristate +config CXL_SUSPEND + def_bool y + depends on SUSPEND && CXL_MEM + endif diff --git a/drivers/cxl/Makefile b/drivers/cxl/Makefile index ce267ef11d93c062fb3063f2dd6639debebc900f..a78270794150d1bb432fd7c5820cd8f5f50d0a5e 100644 --- a/drivers/cxl/Makefile +++ b/drivers/cxl/Makefile @@ -1,5 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 -obj-$(CONFIG_CXL_BUS) += core/ +obj-y += core/ obj-$(CONFIG_CXL_PCI) += cxl_pci.o obj-$(CONFIG_CXL_MEM) += cxl_mem.o obj-$(CONFIG_CXL_ACPI) += cxl_acpi.o diff --git a/drivers/cxl/acpi.c b/drivers/cxl/acpi.c index d15a6aec033189a797a803009fcb050b3b192182..40286f5df8127810937f16fe01ced51d0652f45e 100644 --- a/drivers/cxl/acpi.c +++ b/drivers/cxl/acpi.c @@ -275,6 +275,13 @@ static int add_root_nvdimm_bridge(struct device *match, void *data) return 1; } +static struct lock_class_key cxl_root_key; + +static void cxl_acpi_lock_reset_class(void *dev) +{ + device_lock_reset_class(dev); +} + static int cxl_acpi_probe(struct platform_device *pdev) { int rc; @@ -283,6 +290,12 @@ static int cxl_acpi_probe(struct platform_device *pdev) struct acpi_device *adev = ACPI_COMPANION(host); struct cxl_cfmws_context ctx; + device_lock_set_class(&pdev->dev, &cxl_root_key); + rc = devm_add_action_or_reset(&pdev->dev, cxl_acpi_lock_reset_class, + &pdev->dev); + if (rc) + return rc; + root_port = devm_cxl_add_port(host, host, CXL_RESOURCE_NONE, NULL); if (IS_ERR(root_port)) return PTR_ERR(root_port); diff --git a/drivers/cxl/core/Makefile b/drivers/cxl/core/Makefile index 6d37cd78b1518e03b2386267d719e0b5169c561a..9d35085d25aff8503574b51ef696dc18d4258752 100644 --- a/drivers/cxl/core/Makefile +++ b/drivers/cxl/core/Makefile @@ -1,5 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_CXL_BUS) += cxl_core.o +obj-$(CONFIG_CXL_SUSPEND) += suspend.o ccflags-y += -I$(srctree)/drivers/cxl cxl_core-y := port.o diff --git a/drivers/cxl/core/mbox.c b/drivers/cxl/core/mbox.c index be61a0d8016bbc4ef7d3359ececd02d7bd9a1eca..54f434733b5623cc35d18c161479e40d8fc372b4 100644 --- a/drivers/cxl/core/mbox.c +++ b/drivers/cxl/core/mbox.c @@ -35,6 +35,7 @@ static bool cxl_raw_allow_all; .flags = _flags, \ } +#define CXL_VARIABLE_PAYLOAD ~0U /* * This table defines the supported mailbox commands for the driver. This table * is made up of a UAPI structure. Non-negative values as parameters in the @@ -44,26 +45,26 @@ static bool cxl_raw_allow_all; static struct cxl_mem_command cxl_mem_commands[CXL_MEM_COMMAND_ID_MAX] = { CXL_CMD(IDENTIFY, 0, 0x43, CXL_CMD_FLAG_FORCE_ENABLE), #ifdef CONFIG_CXL_MEM_RAW_COMMANDS - CXL_CMD(RAW, ~0, ~0, 0), + CXL_CMD(RAW, CXL_VARIABLE_PAYLOAD, CXL_VARIABLE_PAYLOAD, 0), #endif - CXL_CMD(GET_SUPPORTED_LOGS, 0, ~0, CXL_CMD_FLAG_FORCE_ENABLE), + CXL_CMD(GET_SUPPORTED_LOGS, 0, CXL_VARIABLE_PAYLOAD, CXL_CMD_FLAG_FORCE_ENABLE), CXL_CMD(GET_FW_INFO, 0, 0x50, 0), CXL_CMD(GET_PARTITION_INFO, 0, 0x20, 0), - CXL_CMD(GET_LSA, 0x8, ~0, 0), + CXL_CMD(GET_LSA, 0x8, CXL_VARIABLE_PAYLOAD, 0), CXL_CMD(GET_HEALTH_INFO, 0, 0x12, 0), - CXL_CMD(GET_LOG, 0x18, ~0, CXL_CMD_FLAG_FORCE_ENABLE), + CXL_CMD(GET_LOG, 0x18, CXL_VARIABLE_PAYLOAD, CXL_CMD_FLAG_FORCE_ENABLE), CXL_CMD(SET_PARTITION_INFO, 0x0a, 0, 0), - CXL_CMD(SET_LSA, ~0, 0, 0), + CXL_CMD(SET_LSA, CXL_VARIABLE_PAYLOAD, 0, 0), CXL_CMD(GET_ALERT_CONFIG, 0, 0x10, 0), CXL_CMD(SET_ALERT_CONFIG, 0xc, 0, 0), CXL_CMD(GET_SHUTDOWN_STATE, 0, 0x1, 0), CXL_CMD(SET_SHUTDOWN_STATE, 0x1, 0, 0), - CXL_CMD(GET_POISON, 0x10, ~0, 0), + CXL_CMD(GET_POISON, 0x10, CXL_VARIABLE_PAYLOAD, 0), CXL_CMD(INJECT_POISON, 0x8, 0, 0), CXL_CMD(CLEAR_POISON, 0x48, 0, 0), CXL_CMD(GET_SCAN_MEDIA_CAPS, 0x10, 0x4, 0), CXL_CMD(SCAN_MEDIA, 0x11, 0, 0), - CXL_CMD(GET_SCAN_MEDIA, 0, ~0, 0), + CXL_CMD(GET_SCAN_MEDIA, 0, CXL_VARIABLE_PAYLOAD, 0), }; /* @@ -127,6 +128,17 @@ static struct cxl_mem_command *cxl_mem_find_command(u16 opcode) return NULL; } +static const char *cxl_mem_opcode_to_name(u16 opcode) +{ + struct cxl_mem_command *c; + + c = cxl_mem_find_command(opcode); + if (!c) + return NULL; + + return cxl_command_names[c->info.id].name; +} + /** * cxl_mbox_send_cmd() - Send a mailbox command to a device. * @cxlds: The device data for the operation @@ -136,7 +148,7 @@ static struct cxl_mem_command *cxl_mem_find_command(u16 opcode) * @out: Caller allocated buffer for the output. * @out_size: Expected size of output. * - * Context: Any context. Will acquire and release mbox_mutex. + * Context: Any context. * Return: * * %>=0 - Number of bytes returned in @out. * * %-E2BIG - Payload is too large for hardware. @@ -169,17 +181,17 @@ int cxl_mbox_send_cmd(struct cxl_dev_state *cxlds, u16 opcode, void *in, if (rc) return rc; - /* TODO: Map return code to proper kernel style errno */ - if (mbox_cmd.return_code != CXL_MBOX_SUCCESS) - return -ENXIO; + if (mbox_cmd.return_code != CXL_MBOX_CMD_RC_SUCCESS) + return cxl_mbox_cmd_rc2errno(&mbox_cmd); /* * Variable sized commands can't be validated and so it's up to the * caller to do that if they wish. */ - if (cmd->info.size_out >= 0 && mbox_cmd.size_out != out_size) - return -EIO; - + if (cmd->info.size_out != CXL_VARIABLE_PAYLOAD) { + if (mbox_cmd.size_out != out_size) + return -EIO; + } return 0; } EXPORT_SYMBOL_NS_GPL(cxl_mbox_send_cmd, CXL); @@ -208,75 +220,122 @@ static bool cxl_mem_raw_command_allowed(u16 opcode) } /** - * cxl_validate_cmd_from_user() - Check fields for CXL_MEM_SEND_COMMAND. - * @cxlds: The device data for the operation - * @send_cmd: &struct cxl_send_command copied in from userspace. - * @out_cmd: Sanitized and populated &struct cxl_mem_command. + * cxl_payload_from_user_allowed() - Check contents of in_payload. + * @opcode: The mailbox command opcode. + * @payload_in: Pointer to the input payload passed in from user space. * * Return: - * * %0 - @out_cmd is ready to send. - * * %-ENOTTY - Invalid command specified. - * * %-EINVAL - Reserved fields or invalid values were used. - * * %-ENOMEM - Input or output buffer wasn't sized properly. - * * %-EPERM - Attempted to use a protected command. - * * %-EBUSY - Kernel has claimed exclusive access to this opcode + * * true - payload_in passes check for @opcode. + * * false - payload_in contains invalid or unsupported values. * - * The result of this command is a fully validated command in @out_cmd that is - * safe to send to the hardware. + * The driver may inspect payload contents before sending a mailbox + * command from user space to the device. The intent is to reject + * commands with input payloads that are known to be unsafe. This + * check is not intended to replace the users careful selection of + * mailbox command parameters and makes no guarantee that the user + * command will succeed, nor that it is appropriate. * - * See handle_mailbox_cmd_from_user() + * The specific checks are determined by the opcode. */ -static int cxl_validate_cmd_from_user(struct cxl_dev_state *cxlds, - const struct cxl_send_command *send_cmd, - struct cxl_mem_command *out_cmd) +static bool cxl_payload_from_user_allowed(u16 opcode, void *payload_in) { - const struct cxl_command_info *info; - struct cxl_mem_command *c; + switch (opcode) { + case CXL_MBOX_OP_SET_PARTITION_INFO: { + struct cxl_mbox_set_partition_info *pi = payload_in; - if (send_cmd->id == 0 || send_cmd->id >= CXL_MEM_COMMAND_ID_MAX) - return -ENOTTY; + if (pi->flags & CXL_SET_PARTITION_IMMEDIATE_FLAG) + return false; + break; + } + default: + break; + } + return true; +} - /* - * The user can never specify an input payload larger than what hardware - * supports, but output can be arbitrarily large (simply write out as - * much data as the hardware provides). - */ - if (send_cmd->in.size > cxlds->payload_size) +static int cxl_mbox_cmd_ctor(struct cxl_mbox_cmd *mbox, + struct cxl_dev_state *cxlds, u16 opcode, + size_t in_size, size_t out_size, u64 in_payload) +{ + *mbox = (struct cxl_mbox_cmd) { + .opcode = opcode, + .size_in = in_size, + }; + + if (in_size) { + mbox->payload_in = vmemdup_user(u64_to_user_ptr(in_payload), + in_size); + if (IS_ERR(mbox->payload_in)) + return PTR_ERR(mbox->payload_in); + + if (!cxl_payload_from_user_allowed(opcode, mbox->payload_in)) { + dev_dbg(cxlds->dev, "%s: input payload not allowed\n", + cxl_mem_opcode_to_name(opcode)); + kvfree(mbox->payload_in); + return -EBUSY; + } + } + + /* Prepare to handle a full payload for variable sized output */ + if (out_size == CXL_VARIABLE_PAYLOAD) + mbox->size_out = cxlds->payload_size; + else + mbox->size_out = out_size; + + if (mbox->size_out) { + mbox->payload_out = kvzalloc(mbox->size_out, GFP_KERNEL); + if (!mbox->payload_out) { + kvfree(mbox->payload_in); + return -ENOMEM; + } + } + return 0; +} + +static void cxl_mbox_cmd_dtor(struct cxl_mbox_cmd *mbox) +{ + kvfree(mbox->payload_in); + kvfree(mbox->payload_out); +} + +static int cxl_to_mem_cmd_raw(struct cxl_mem_command *mem_cmd, + const struct cxl_send_command *send_cmd, + struct cxl_dev_state *cxlds) +{ + if (send_cmd->raw.rsvd) return -EINVAL; /* - * Checks are bypassed for raw commands but a WARN/taint will occur - * later in the callchain + * Unlike supported commands, the output size of RAW commands + * gets passed along without further checking, so it must be + * validated here. */ - if (send_cmd->id == CXL_MEM_COMMAND_ID_RAW) { - const struct cxl_mem_command temp = { - .info = { - .id = CXL_MEM_COMMAND_ID_RAW, - .flags = 0, - .size_in = send_cmd->in.size, - .size_out = send_cmd->out.size, - }, - .opcode = send_cmd->raw.opcode - }; + if (send_cmd->out.size > cxlds->payload_size) + return -EINVAL; - if (send_cmd->raw.rsvd) - return -EINVAL; + if (!cxl_mem_raw_command_allowed(send_cmd->raw.opcode)) + return -EPERM; - /* - * Unlike supported commands, the output size of RAW commands - * gets passed along without further checking, so it must be - * validated here. - */ - if (send_cmd->out.size > cxlds->payload_size) - return -EINVAL; + dev_WARN_ONCE(cxlds->dev, true, "raw command path used\n"); - if (!cxl_mem_raw_command_allowed(send_cmd->raw.opcode)) - return -EPERM; + *mem_cmd = (struct cxl_mem_command) { + .info = { + .id = CXL_MEM_COMMAND_ID_RAW, + .size_in = send_cmd->in.size, + .size_out = send_cmd->out.size, + }, + .opcode = send_cmd->raw.opcode + }; - memcpy(out_cmd, &temp, sizeof(temp)); + return 0; +} - return 0; - } +static int cxl_to_mem_cmd(struct cxl_mem_command *mem_cmd, + const struct cxl_send_command *send_cmd, + struct cxl_dev_state *cxlds) +{ + struct cxl_mem_command *c = &cxl_mem_commands[send_cmd->id]; + const struct cxl_command_info *info = &c->info; if (send_cmd->flags & ~CXL_MEM_COMMAND_FLAG_MASK) return -EINVAL; @@ -287,10 +346,6 @@ static int cxl_validate_cmd_from_user(struct cxl_dev_state *cxlds, if (send_cmd->in.rsvd || send_cmd->out.rsvd) return -EINVAL; - /* Convert user's command into the internal representation */ - c = &cxl_mem_commands[send_cmd->id]; - info = &c->info; - /* Check that the command is enabled for hardware */ if (!test_bit(info->id, cxlds->enabled_cmds)) return -ENOTTY; @@ -300,22 +355,74 @@ static int cxl_validate_cmd_from_user(struct cxl_dev_state *cxlds, return -EBUSY; /* Check the input buffer is the expected size */ - if (info->size_in >= 0 && info->size_in != send_cmd->in.size) + if (info->size_in != send_cmd->in.size) return -ENOMEM; /* Check the output buffer is at least large enough */ - if (info->size_out >= 0 && send_cmd->out.size < info->size_out) + if (send_cmd->out.size < info->size_out) return -ENOMEM; - memcpy(out_cmd, c, sizeof(*c)); - out_cmd->info.size_in = send_cmd->in.size; + *mem_cmd = (struct cxl_mem_command) { + .info = { + .id = info->id, + .flags = info->flags, + .size_in = send_cmd->in.size, + .size_out = send_cmd->out.size, + }, + .opcode = c->opcode + }; + + return 0; +} + +/** + * cxl_validate_cmd_from_user() - Check fields for CXL_MEM_SEND_COMMAND. + * @mbox_cmd: Sanitized and populated &struct cxl_mbox_cmd. + * @cxlds: The device data for the operation + * @send_cmd: &struct cxl_send_command copied in from userspace. + * + * Return: + * * %0 - @out_cmd is ready to send. + * * %-ENOTTY - Invalid command specified. + * * %-EINVAL - Reserved fields or invalid values were used. + * * %-ENOMEM - Input or output buffer wasn't sized properly. + * * %-EPERM - Attempted to use a protected command. + * * %-EBUSY - Kernel has claimed exclusive access to this opcode + * + * The result of this command is a fully validated command in @mbox_cmd that is + * safe to send to the hardware. + */ +static int cxl_validate_cmd_from_user(struct cxl_mbox_cmd *mbox_cmd, + struct cxl_dev_state *cxlds, + const struct cxl_send_command *send_cmd) +{ + struct cxl_mem_command mem_cmd; + int rc; + + if (send_cmd->id == 0 || send_cmd->id >= CXL_MEM_COMMAND_ID_MAX) + return -ENOTTY; + /* - * XXX: out_cmd->info.size_out will be controlled by the driver, and the - * specified number of bytes @send_cmd->out.size will be copied back out - * to userspace. + * The user can never specify an input payload larger than what hardware + * supports, but output can be arbitrarily large (simply write out as + * much data as the hardware provides). */ + if (send_cmd->in.size > cxlds->payload_size) + return -EINVAL; - return 0; + /* Sanitize and construct a cxl_mem_command */ + if (send_cmd->id == CXL_MEM_COMMAND_ID_RAW) + rc = cxl_to_mem_cmd_raw(&mem_cmd, send_cmd, cxlds); + else + rc = cxl_to_mem_cmd(&mem_cmd, send_cmd, cxlds); + + if (rc) + return rc; + + /* Sanitize and construct a cxl_mbox_cmd */ + return cxl_mbox_cmd_ctor(mbox_cmd, cxlds, mem_cmd.opcode, + mem_cmd.info.size_in, mem_cmd.info.size_out, + send_cmd->in.payload); } int cxl_query_cmd(struct cxl_memdev *cxlmd, @@ -355,8 +462,7 @@ int cxl_query_cmd(struct cxl_memdev *cxlmd, /** * handle_mailbox_cmd_from_user() - Dispatch a mailbox command for userspace. * @cxlds: The device data for the operation - * @cmd: The validated command. - * @in_payload: Pointer to userspace's input payload. + * @mbox_cmd: The validated mailbox command. * @out_payload: Pointer to userspace's output payload. * @size_out: (Input) Max payload size to copy out. * (Output) Payload size hardware generated. @@ -371,51 +477,27 @@ int cxl_query_cmd(struct cxl_memdev *cxlmd, * * %-EINTR - Mailbox acquisition interrupted. * * %-EXXX - Transaction level failures. * - * Creates the appropriate mailbox command and dispatches it on behalf of a - * userspace request. The input and output payloads are copied between - * userspace. + * Dispatches a mailbox command on behalf of a userspace request. + * The output payload is copied to userspace. * * See cxl_send_cmd(). */ static int handle_mailbox_cmd_from_user(struct cxl_dev_state *cxlds, - const struct cxl_mem_command *cmd, - u64 in_payload, u64 out_payload, - s32 *size_out, u32 *retval) + struct cxl_mbox_cmd *mbox_cmd, + u64 out_payload, s32 *size_out, + u32 *retval) { struct device *dev = cxlds->dev; - struct cxl_mbox_cmd mbox_cmd = { - .opcode = cmd->opcode, - .size_in = cmd->info.size_in, - .size_out = cmd->info.size_out, - }; int rc; - if (cmd->info.size_out) { - mbox_cmd.payload_out = kvzalloc(cmd->info.size_out, GFP_KERNEL); - if (!mbox_cmd.payload_out) - return -ENOMEM; - } - - if (cmd->info.size_in) { - mbox_cmd.payload_in = vmemdup_user(u64_to_user_ptr(in_payload), - cmd->info.size_in); - if (IS_ERR(mbox_cmd.payload_in)) { - kvfree(mbox_cmd.payload_out); - return PTR_ERR(mbox_cmd.payload_in); - } - } - dev_dbg(dev, "Submitting %s command for user\n" "\topcode: %x\n" - "\tsize: %ub\n", - cxl_command_names[cmd->info.id].name, mbox_cmd.opcode, - cmd->info.size_in); - - dev_WARN_ONCE(dev, cmd->info.id == CXL_MEM_COMMAND_ID_RAW, - "raw command path used\n"); + "\tsize: %zx\n", + cxl_mem_opcode_to_name(mbox_cmd->opcode), + mbox_cmd->opcode, mbox_cmd->size_in); - rc = cxlds->mbox_send(cxlds, &mbox_cmd); + rc = cxlds->mbox_send(cxlds, mbox_cmd); if (rc) goto out; @@ -424,22 +506,21 @@ static int handle_mailbox_cmd_from_user(struct cxl_dev_state *cxlds, * to userspace. While the payload may have written more output than * this it will have to be ignored. */ - if (mbox_cmd.size_out) { - dev_WARN_ONCE(dev, mbox_cmd.size_out > *size_out, + if (mbox_cmd->size_out) { + dev_WARN_ONCE(dev, mbox_cmd->size_out > *size_out, "Invalid return size\n"); if (copy_to_user(u64_to_user_ptr(out_payload), - mbox_cmd.payload_out, mbox_cmd.size_out)) { + mbox_cmd->payload_out, mbox_cmd->size_out)) { rc = -EFAULT; goto out; } } - *size_out = mbox_cmd.size_out; - *retval = mbox_cmd.return_code; + *size_out = mbox_cmd->size_out; + *retval = mbox_cmd->return_code; out: - kvfree(mbox_cmd.payload_in); - kvfree(mbox_cmd.payload_out); + cxl_mbox_cmd_dtor(mbox_cmd); return rc; } @@ -448,7 +529,7 @@ int cxl_send_cmd(struct cxl_memdev *cxlmd, struct cxl_send_command __user *s) struct cxl_dev_state *cxlds = cxlmd->cxlds; struct device *dev = &cxlmd->dev; struct cxl_send_command send; - struct cxl_mem_command c; + struct cxl_mbox_cmd mbox_cmd; int rc; dev_dbg(dev, "Send IOCTL\n"); @@ -456,17 +537,12 @@ int cxl_send_cmd(struct cxl_memdev *cxlmd, struct cxl_send_command __user *s) if (copy_from_user(&send, s, sizeof(send))) return -EFAULT; - rc = cxl_validate_cmd_from_user(cxlmd->cxlds, &send, &c); + rc = cxl_validate_cmd_from_user(&mbox_cmd, cxlmd->cxlds, &send); if (rc) return rc; - /* Prepare to handle a full payload for variable sized output */ - if (c.info.size_out < 0) - c.info.size_out = cxlds->payload_size; - - rc = handle_mailbox_cmd_from_user(cxlds, &c, send.in.payload, - send.out.payload, &send.out.size, - &send.retval); + rc = handle_mailbox_cmd_from_user(cxlds, &mbox_cmd, send.out.payload, + &send.out.size, &send.retval); if (rc) return rc; diff --git a/drivers/cxl/core/memdev.c b/drivers/cxl/core/memdev.c index 1f76b28f9826b0119ce57402cacb1cbc5a39d32c..f7cdcd33504aa5d800ba14fe37d30cb00af623c8 100644 --- a/drivers/cxl/core/memdev.c +++ b/drivers/cxl/core/memdev.c @@ -228,6 +228,8 @@ static void detach_memdev(struct work_struct *work) put_device(&cxlmd->dev); } +static struct lock_class_key cxl_memdev_key; + static struct cxl_memdev *cxl_memdev_alloc(struct cxl_dev_state *cxlds, const struct file_operations *fops) { @@ -247,6 +249,7 @@ static struct cxl_memdev *cxl_memdev_alloc(struct cxl_dev_state *cxlds, dev = &cxlmd->dev; device_initialize(dev); + lockdep_set_class(&dev->mutex, &cxl_memdev_key); dev->parent = cxlds->dev; dev->bus = &cxl_bus_type; dev->devt = MKDEV(cxl_mem_major, cxlmd->id); diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c index c9a494d6976a45a76593506af685eabd9d284c4b..c4c99ff7b55ef2f8932a1cf2047f6541723003bf 100644 --- a/drivers/cxl/core/pci.c +++ b/drivers/cxl/core/pci.c @@ -1,8 +1,11 @@ // SPDX-License-Identifier: GPL-2.0-only /* Copyright(c) 2021 Intel Corporation. All rights reserved. */ +#include #include +#include #include #include +#include #include #include "core.h" @@ -13,6 +16,10 @@ * a set of helpers for CXL interactions which occur via PCIe. */ +static unsigned short media_ready_timeout = 60; +module_param(media_ready_timeout, ushort, 0644); +MODULE_PARM_DESC(media_ready_timeout, "seconds to wait for media ready"); + struct cxl_walk_context { struct pci_bus *bus; struct cxl_port *port; @@ -94,3 +101,360 @@ int devm_cxl_port_enumerate_dports(struct cxl_port *port) return ctx.count; } EXPORT_SYMBOL_NS_GPL(devm_cxl_port_enumerate_dports, CXL); + +/* + * Wait up to @media_ready_timeout for the device to report memory + * active. + */ +int cxl_await_media_ready(struct cxl_dev_state *cxlds) +{ + struct pci_dev *pdev = to_pci_dev(cxlds->dev); + int d = cxlds->cxl_dvsec; + bool active = false; + u64 md_status; + int rc, i; + + for (i = media_ready_timeout; i; i--) { + u32 temp; + + rc = pci_read_config_dword( + pdev, d + CXL_DVSEC_RANGE_SIZE_LOW(0), &temp); + if (rc) + return rc; + + active = FIELD_GET(CXL_DVSEC_MEM_ACTIVE, temp); + if (active) + break; + msleep(1000); + } + + if (!active) { + dev_err(&pdev->dev, + "timeout awaiting memory active after %d seconds\n", + media_ready_timeout); + return -ETIMEDOUT; + } + + md_status = readq(cxlds->regs.memdev + CXLMDEV_STATUS_OFFSET); + if (!CXLMDEV_READY(md_status)) + return -EIO; + + return 0; +} +EXPORT_SYMBOL_NS_GPL(cxl_await_media_ready, CXL); + +static int wait_for_valid(struct cxl_dev_state *cxlds) +{ + struct pci_dev *pdev = to_pci_dev(cxlds->dev); + int d = cxlds->cxl_dvsec, rc; + u32 val; + + /* + * Memory_Info_Valid: When set, indicates that the CXL Range 1 Size high + * and Size Low registers are valid. Must be set within 1 second of + * deassertion of reset to CXL device. Likely it is already set by the + * time this runs, but otherwise give a 1.5 second timeout in case of + * clock skew. + */ + rc = pci_read_config_dword(pdev, d + CXL_DVSEC_RANGE_SIZE_LOW(0), &val); + if (rc) + return rc; + + if (val & CXL_DVSEC_MEM_INFO_VALID) + return 0; + + msleep(1500); + + rc = pci_read_config_dword(pdev, d + CXL_DVSEC_RANGE_SIZE_LOW(0), &val); + if (rc) + return rc; + + if (val & CXL_DVSEC_MEM_INFO_VALID) + return 0; + + return -ETIMEDOUT; +} + +static int cxl_set_mem_enable(struct cxl_dev_state *cxlds, u16 val) +{ + struct pci_dev *pdev = to_pci_dev(cxlds->dev); + int d = cxlds->cxl_dvsec; + u16 ctrl; + int rc; + + rc = pci_read_config_word(pdev, d + CXL_DVSEC_CTRL_OFFSET, &ctrl); + if (rc < 0) + return rc; + + if ((ctrl & CXL_DVSEC_MEM_ENABLE) == val) + return 1; + ctrl &= ~CXL_DVSEC_MEM_ENABLE; + ctrl |= val; + + rc = pci_write_config_word(pdev, d + CXL_DVSEC_CTRL_OFFSET, ctrl); + if (rc < 0) + return rc; + + return 0; +} + +static void clear_mem_enable(void *cxlds) +{ + cxl_set_mem_enable(cxlds, 0); +} + +static int devm_cxl_enable_mem(struct device *host, struct cxl_dev_state *cxlds) +{ + int rc; + + rc = cxl_set_mem_enable(cxlds, CXL_DVSEC_MEM_ENABLE); + if (rc < 0) + return rc; + if (rc > 0) + return 0; + return devm_add_action_or_reset(host, clear_mem_enable, cxlds); +} + +static bool range_contains(struct range *r1, struct range *r2) +{ + return r1->start <= r2->start && r1->end >= r2->end; +} + +/* require dvsec ranges to be covered by a locked platform window */ +static int dvsec_range_allowed(struct device *dev, void *arg) +{ + struct range *dev_range = arg; + struct cxl_decoder *cxld; + struct range root_range; + + if (!is_root_decoder(dev)) + return 0; + + cxld = to_cxl_decoder(dev); + + if (!(cxld->flags & CXL_DECODER_F_LOCK)) + return 0; + if (!(cxld->flags & CXL_DECODER_F_RAM)) + return 0; + + root_range = (struct range) { + .start = cxld->platform_res.start, + .end = cxld->platform_res.end, + }; + + return range_contains(&root_range, dev_range); +} + +static void disable_hdm(void *_cxlhdm) +{ + u32 global_ctrl; + struct cxl_hdm *cxlhdm = _cxlhdm; + void __iomem *hdm = cxlhdm->regs.hdm_decoder; + + global_ctrl = readl(hdm + CXL_HDM_DECODER_CTRL_OFFSET); + writel(global_ctrl & ~CXL_HDM_DECODER_ENABLE, + hdm + CXL_HDM_DECODER_CTRL_OFFSET); +} + +static int devm_cxl_enable_hdm(struct device *host, struct cxl_hdm *cxlhdm) +{ + void __iomem *hdm = cxlhdm->regs.hdm_decoder; + u32 global_ctrl; + + global_ctrl = readl(hdm + CXL_HDM_DECODER_CTRL_OFFSET); + writel(global_ctrl | CXL_HDM_DECODER_ENABLE, + hdm + CXL_HDM_DECODER_CTRL_OFFSET); + + return devm_add_action_or_reset(host, disable_hdm, cxlhdm); +} + +static bool __cxl_hdm_decode_init(struct cxl_dev_state *cxlds, + struct cxl_hdm *cxlhdm, + struct cxl_endpoint_dvsec_info *info) +{ + void __iomem *hdm = cxlhdm->regs.hdm_decoder; + struct cxl_port *port = cxlhdm->port; + struct device *dev = cxlds->dev; + struct cxl_port *root; + int i, rc, allowed; + u32 global_ctrl; + + global_ctrl = readl(hdm + CXL_HDM_DECODER_CTRL_OFFSET); + + /* + * If the HDM Decoder Capability is already enabled then assume + * that some other agent like platform firmware set it up. + */ + if (global_ctrl & CXL_HDM_DECODER_ENABLE) { + rc = devm_cxl_enable_mem(&port->dev, cxlds); + if (rc) + return false; + return true; + } + + root = to_cxl_port(port->dev.parent); + while (!is_cxl_root(root) && is_cxl_port(root->dev.parent)) + root = to_cxl_port(root->dev.parent); + if (!is_cxl_root(root)) { + dev_err(dev, "Failed to acquire root port for HDM enable\n"); + return false; + } + + for (i = 0, allowed = 0; info->mem_enabled && i < info->ranges; i++) { + struct device *cxld_dev; + + cxld_dev = device_find_child(&root->dev, &info->dvsec_range[i], + dvsec_range_allowed); + if (!cxld_dev) { + dev_dbg(dev, "DVSEC Range%d denied by platform\n", i); + continue; + } + dev_dbg(dev, "DVSEC Range%d allowed by platform\n", i); + put_device(cxld_dev); + allowed++; + } + + if (!allowed) { + cxl_set_mem_enable(cxlds, 0); + info->mem_enabled = 0; + } + + /* + * Per CXL 2.0 Section 8.1.3.8.3 and 8.1.3.8.4 DVSEC CXL Range 1 Base + * [High,Low] when HDM operation is enabled the range register values + * are ignored by the device, but the spec also recommends matching the + * DVSEC Range 1,2 to HDM Decoder Range 0,1. So, non-zero info->ranges + * are expected even though Linux does not require or maintain that + * match. If at least one DVSEC range is enabled and allowed, skip HDM + * Decoder Capability Enable. + */ + if (info->mem_enabled) + return false; + + rc = devm_cxl_enable_hdm(&port->dev, cxlhdm); + if (rc) + return false; + + rc = devm_cxl_enable_mem(&port->dev, cxlds); + if (rc) + return false; + + return true; +} + +/** + * cxl_hdm_decode_init() - Setup HDM decoding for the endpoint + * @cxlds: Device state + * @cxlhdm: Mapped HDM decoder Capability + * + * Try to enable the endpoint's HDM Decoder Capability + */ +int cxl_hdm_decode_init(struct cxl_dev_state *cxlds, struct cxl_hdm *cxlhdm) +{ + struct pci_dev *pdev = to_pci_dev(cxlds->dev); + struct cxl_endpoint_dvsec_info info = { 0 }; + int hdm_count, rc, i, ranges = 0; + struct device *dev = &pdev->dev; + int d = cxlds->cxl_dvsec; + u16 cap, ctrl; + + if (!d) { + dev_dbg(dev, "No DVSEC Capability\n"); + return -ENXIO; + } + + rc = pci_read_config_word(pdev, d + CXL_DVSEC_CAP_OFFSET, &cap); + if (rc) + return rc; + + rc = pci_read_config_word(pdev, d + CXL_DVSEC_CTRL_OFFSET, &ctrl); + if (rc) + return rc; + + if (!(cap & CXL_DVSEC_MEM_CAPABLE)) { + dev_dbg(dev, "Not MEM Capable\n"); + return -ENXIO; + } + + /* + * It is not allowed by spec for MEM.capable to be set and have 0 legacy + * HDM decoders (values > 2 are also undefined as of CXL 2.0). As this + * driver is for a spec defined class code which must be CXL.mem + * capable, there is no point in continuing to enable CXL.mem. + */ + hdm_count = FIELD_GET(CXL_DVSEC_HDM_COUNT_MASK, cap); + if (!hdm_count || hdm_count > 2) + return -EINVAL; + + rc = wait_for_valid(cxlds); + if (rc) { + dev_dbg(dev, "Failure awaiting MEM_INFO_VALID (%d)\n", rc); + return rc; + } + + /* + * The current DVSEC values are moot if the memory capability is + * disabled, and they will remain moot after the HDM Decoder + * capability is enabled. + */ + info.mem_enabled = FIELD_GET(CXL_DVSEC_MEM_ENABLE, ctrl); + if (!info.mem_enabled) + goto hdm_init; + + for (i = 0; i < hdm_count; i++) { + u64 base, size; + u32 temp; + + rc = pci_read_config_dword( + pdev, d + CXL_DVSEC_RANGE_SIZE_HIGH(i), &temp); + if (rc) + return rc; + + size = (u64)temp << 32; + + rc = pci_read_config_dword( + pdev, d + CXL_DVSEC_RANGE_SIZE_LOW(i), &temp); + if (rc) + return rc; + + size |= temp & CXL_DVSEC_MEM_SIZE_LOW_MASK; + + rc = pci_read_config_dword( + pdev, d + CXL_DVSEC_RANGE_BASE_HIGH(i), &temp); + if (rc) + return rc; + + base = (u64)temp << 32; + + rc = pci_read_config_dword( + pdev, d + CXL_DVSEC_RANGE_BASE_LOW(i), &temp); + if (rc) + return rc; + + base |= temp & CXL_DVSEC_MEM_BASE_LOW_MASK; + + info.dvsec_range[i] = (struct range) { + .start = base, + .end = base + size - 1 + }; + + if (size) + ranges++; + } + + info.ranges = ranges; + + /* + * If DVSEC ranges are being used instead of HDM decoder registers there + * is no use in trying to manage those. + */ +hdm_init: + if (!__cxl_hdm_decode_init(cxlds, cxlhdm, &info)) { + dev_err(dev, + "Legacy range registers configuration prevents HDM operation.\n"); + return -EBUSY; + } + + return 0; +} +EXPORT_SYMBOL_NS_GPL(cxl_hdm_decode_init, CXL); diff --git a/drivers/cxl/core/pmem.c b/drivers/cxl/core/pmem.c index 8de240c4d96bba5a7559f95da375e7c74fda584f..bec7cfb54ebfb01fabe91764db9135c2c97d39af 100644 --- a/drivers/cxl/core/pmem.c +++ b/drivers/cxl/core/pmem.c @@ -80,6 +80,8 @@ struct cxl_nvdimm_bridge *cxl_find_nvdimm_bridge(struct cxl_nvdimm *cxl_nvd) } EXPORT_SYMBOL_NS_GPL(cxl_find_nvdimm_bridge, CXL); +static struct lock_class_key cxl_nvdimm_bridge_key; + static struct cxl_nvdimm_bridge *cxl_nvdimm_bridge_alloc(struct cxl_port *port) { struct cxl_nvdimm_bridge *cxl_nvb; @@ -99,6 +101,7 @@ static struct cxl_nvdimm_bridge *cxl_nvdimm_bridge_alloc(struct cxl_port *port) cxl_nvb->port = port; cxl_nvb->state = CXL_NVB_NEW; device_initialize(dev); + lockdep_set_class(&dev->mutex, &cxl_nvdimm_bridge_key); device_set_pm_not_required(dev); dev->parent = &port->dev; dev->bus = &cxl_bus_type; @@ -121,10 +124,10 @@ static void unregister_nvb(void *_cxl_nvb) * work to flush. Once the state has been changed to 'dead' then no new * work can be queued by user-triggered bind. */ - cxl_device_lock(&cxl_nvb->dev); + device_lock(&cxl_nvb->dev); flush = cxl_nvb->state != CXL_NVB_NEW; cxl_nvb->state = CXL_NVB_DEAD; - cxl_device_unlock(&cxl_nvb->dev); + device_unlock(&cxl_nvb->dev); /* * Even though the device core will trigger device_release_driver() @@ -214,6 +217,8 @@ struct cxl_nvdimm *to_cxl_nvdimm(struct device *dev) } EXPORT_SYMBOL_NS_GPL(to_cxl_nvdimm, CXL); +static struct lock_class_key cxl_nvdimm_key; + static struct cxl_nvdimm *cxl_nvdimm_alloc(struct cxl_memdev *cxlmd) { struct cxl_nvdimm *cxl_nvd; @@ -226,6 +231,7 @@ static struct cxl_nvdimm *cxl_nvdimm_alloc(struct cxl_memdev *cxlmd) dev = &cxl_nvd->dev; cxl_nvd->cxlmd = cxlmd; device_initialize(dev); + lockdep_set_class(&dev->mutex, &cxl_nvdimm_key); device_set_pm_not_required(dev); dev->parent = &cxlmd->dev; dev->bus = &cxl_bus_type; diff --git a/drivers/cxl/core/port.c b/drivers/cxl/core/port.c index 2ab1ba4499b309f7e7097e4044cfb90eb415c380..ea60abda65006715cfdf04275dba6704b024c90b 100644 --- a/drivers/cxl/core/port.c +++ b/drivers/cxl/core/port.c @@ -312,10 +312,10 @@ static void cxl_port_release(struct device *dev) struct cxl_port *port = to_cxl_port(dev); struct cxl_ep *ep, *_e; - cxl_device_lock(dev); + device_lock(dev); list_for_each_entry_safe(ep, _e, &port->endpoints, list) cxl_ep_release(ep); - cxl_device_unlock(dev); + device_unlock(dev); ida_free(&cxl_port_ida, port->id); kfree(port); } @@ -391,6 +391,8 @@ static int devm_cxl_link_uport(struct device *host, struct cxl_port *port) return devm_add_action_or_reset(host, cxl_unlink_uport, port); } +static struct lock_class_key cxl_port_key; + static struct cxl_port *cxl_port_alloc(struct device *uport, resource_size_t component_reg_phys, struct cxl_port *parent_port) @@ -415,9 +417,10 @@ static struct cxl_port *cxl_port_alloc(struct device *uport, * description. */ dev = &port->dev; - if (parent_port) + if (parent_port) { dev->parent = &parent_port->dev; - else + port->depth = parent_port->depth + 1; + } else dev->parent = uport; port->uport = uport; @@ -427,6 +430,7 @@ static struct cxl_port *cxl_port_alloc(struct device *uport, INIT_LIST_HEAD(&port->endpoints); device_initialize(dev); + lockdep_set_class_and_subclass(&dev->mutex, &cxl_port_key, port->depth); device_set_pm_not_required(dev); dev->bus = &cxl_bus_type; dev->type = &cxl_port_type; @@ -457,8 +461,6 @@ struct cxl_port *devm_cxl_add_port(struct device *host, struct device *uport, if (IS_ERR(port)) return port; - if (parent_port) - port->depth = parent_port->depth + 1; dev = &port->dev; if (is_cxl_memdev(uport)) rc = dev_set_name(dev, "endpoint%d", port->id); @@ -554,7 +556,7 @@ static int match_root_child(struct device *dev, const void *match) return 0; port = to_cxl_port(dev); - cxl_device_lock(dev); + device_lock(dev); list_for_each_entry(dport, &port->dports, list) { iter = match; while (iter) { @@ -564,7 +566,7 @@ static int match_root_child(struct device *dev, const void *match) } } out: - cxl_device_unlock(dev); + device_unlock(dev); return !!iter; } @@ -623,13 +625,13 @@ static int add_dport(struct cxl_port *port, struct cxl_dport *new) static void cond_cxl_root_lock(struct cxl_port *port) { if (is_cxl_root(port)) - cxl_device_lock(&port->dev); + device_lock(&port->dev); } static void cond_cxl_root_unlock(struct cxl_port *port) { if (is_cxl_root(port)) - cxl_device_unlock(&port->dev); + device_unlock(&port->dev); } static void cxl_dport_remove(void *data) @@ -736,15 +738,15 @@ static int add_ep(struct cxl_port *port, struct cxl_ep *new) { struct cxl_ep *dup; - cxl_device_lock(&port->dev); + device_lock(&port->dev); if (port->dead) { - cxl_device_unlock(&port->dev); + device_unlock(&port->dev); return -ENXIO; } dup = find_ep(port, new->ep); if (!dup) list_add_tail(&new->list, &port->endpoints); - cxl_device_unlock(&port->dev); + device_unlock(&port->dev); return dup ? -EEXIST : 0; } @@ -854,12 +856,12 @@ static void delete_endpoint(void *data) goto out; parent = &parent_port->dev; - cxl_device_lock(parent); + device_lock(parent); if (parent->driver && endpoint->uport) { devm_release_action(parent, cxl_unlink_uport, endpoint); devm_release_action(parent, unregister_port, endpoint); } - cxl_device_unlock(parent); + device_unlock(parent); put_device(parent); out: put_device(&endpoint->dev); @@ -920,7 +922,7 @@ static void cxl_detach_ep(void *data) } parent_port = to_cxl_port(port->dev.parent); - cxl_device_lock(&parent_port->dev); + device_lock(&parent_port->dev); if (!parent_port->dev.driver) { /* * The bottom-up race to delete the port lost to a @@ -928,12 +930,12 @@ static void cxl_detach_ep(void *data) * parent_port ->remove() will have cleaned up all * descendants. */ - cxl_device_unlock(&parent_port->dev); + device_unlock(&parent_port->dev); put_device(&port->dev); continue; } - cxl_device_lock(&port->dev); + device_lock(&port->dev); ep = find_ep(port, &cxlmd->dev); dev_dbg(&cxlmd->dev, "disconnect %s from %s\n", ep ? dev_name(ep->ep) : "", dev_name(&port->dev)); @@ -948,7 +950,7 @@ static void cxl_detach_ep(void *data) port->dead = true; list_splice_init(&port->dports, &reap_dports); } - cxl_device_unlock(&port->dev); + device_unlock(&port->dev); if (!list_empty(&reap_dports)) { dev_dbg(&cxlmd->dev, "delete %s\n", @@ -956,7 +958,7 @@ static void cxl_detach_ep(void *data) delete_switch_port(port, &reap_dports); } put_device(&port->dev); - cxl_device_unlock(&parent_port->dev); + device_unlock(&parent_port->dev); } } @@ -1004,7 +1006,7 @@ static int add_port_attach_ep(struct cxl_memdev *cxlmd, return -EAGAIN; } - cxl_device_lock(&parent_port->dev); + device_lock(&parent_port->dev); if (!parent_port->dev.driver) { dev_warn(&cxlmd->dev, "port %s:%s disabled, failed to enumerate CXL.mem\n", @@ -1022,7 +1024,7 @@ static int add_port_attach_ep(struct cxl_memdev *cxlmd, get_device(&port->dev); } out: - cxl_device_unlock(&parent_port->dev); + device_unlock(&parent_port->dev); if (IS_ERR(port)) rc = PTR_ERR(port); @@ -1133,14 +1135,14 @@ struct cxl_dport *cxl_find_dport_by_dev(struct cxl_port *port, { struct cxl_dport *dport; - cxl_device_lock(&port->dev); + device_lock(&port->dev); list_for_each_entry(dport, &port->dports, list) if (dport->dport == dev) { - cxl_device_unlock(&port->dev); + device_unlock(&port->dev); return dport; } - cxl_device_unlock(&port->dev); + device_unlock(&port->dev); return NULL; } EXPORT_SYMBOL_NS_GPL(cxl_find_dport_by_dev, CXL); @@ -1173,6 +1175,8 @@ static int decoder_populate_targets(struct cxl_decoder *cxld, return rc; } +static struct lock_class_key cxl_decoder_key; + /** * cxl_decoder_alloc - Allocate a new CXL decoder * @port: owning port of this decoder @@ -1214,6 +1218,7 @@ static struct cxl_decoder *cxl_decoder_alloc(struct cxl_port *port, seqlock_init(&cxld->target_lock); dev = &cxld->dev; device_initialize(dev); + lockdep_set_class(&dev->mutex, &cxl_decoder_key); device_set_pm_not_required(dev); dev->parent = &port->dev; dev->bus = &cxl_bus_type; @@ -1379,9 +1384,9 @@ int cxl_decoder_add(struct cxl_decoder *cxld, int *target_map) port = to_cxl_port(cxld->dev.parent); - cxl_device_lock(&port->dev); + device_lock(&port->dev); rc = cxl_decoder_add_locked(cxld, target_map); - cxl_device_unlock(&port->dev); + device_unlock(&port->dev); return rc; } @@ -1452,14 +1457,7 @@ static int cxl_bus_probe(struct device *dev) { int rc; - /* - * Take the CXL nested lock since the driver core only holds - * @dev->mutex and not @dev->lockdep_mutex. - */ - cxl_nested_lock(dev); rc = to_cxl_drv(dev->driver)->probe(dev); - cxl_nested_unlock(dev); - dev_dbg(dev, "probe: %d\n", rc); return rc; } @@ -1468,10 +1466,8 @@ static void cxl_bus_remove(struct device *dev) { struct cxl_driver *cxl_drv = to_cxl_drv(dev->driver); - cxl_nested_lock(dev); if (cxl_drv->remove) cxl_drv->remove(dev); - cxl_nested_unlock(dev); } static struct workqueue_struct *cxl_bus_wq; diff --git a/drivers/cxl/core/suspend.c b/drivers/cxl/core/suspend.c new file mode 100644 index 0000000000000000000000000000000000000000..a5984d96ea1d06a9641ecfc9f0f465f4a74068f4 --- /dev/null +++ b/drivers/cxl/core/suspend.c @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* Copyright(c) 2022 Intel Corporation. All rights reserved. */ +#include +#include +#include "cxlmem.h" + +static atomic_t mem_active; + +bool cxl_mem_active(void) +{ + return atomic_read(&mem_active) != 0; +} + +void cxl_mem_active_inc(void) +{ + atomic_inc(&mem_active); +} +EXPORT_SYMBOL_NS_GPL(cxl_mem_active_inc, CXL); + +void cxl_mem_active_dec(void) +{ + atomic_dec(&mem_active); +} +EXPORT_SYMBOL_NS_GPL(cxl_mem_active_dec, CXL); diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h index 990b6670222ed5f22b527eb1a79ec24fae9ea113..140dc3278cde142b2e5374a7d00c7a0ad51d4035 100644 --- a/drivers/cxl/cxl.h +++ b/drivers/cxl/cxl.h @@ -405,82 +405,4 @@ struct cxl_nvdimm_bridge *cxl_find_nvdimm_bridge(struct cxl_nvdimm *cxl_nvd); #define __mock static #endif -#ifdef CONFIG_PROVE_CXL_LOCKING -enum cxl_lock_class { - CXL_ANON_LOCK, - CXL_NVDIMM_LOCK, - CXL_NVDIMM_BRIDGE_LOCK, - CXL_PORT_LOCK, - /* - * Be careful to add new lock classes here, CXL_PORT_LOCK is - * extended by the port depth, so a maximum CXL port topology - * depth would need to be defined first. - */ -}; - -static inline void cxl_nested_lock(struct device *dev) -{ - if (is_cxl_port(dev)) { - struct cxl_port *port = to_cxl_port(dev); - - mutex_lock_nested(&dev->lockdep_mutex, - CXL_PORT_LOCK + port->depth); - } else if (is_cxl_decoder(dev)) { - struct cxl_port *port = to_cxl_port(dev->parent); - - /* - * A decoder is the immediate child of a port, so set - * its lock class equal to other child device siblings. - */ - mutex_lock_nested(&dev->lockdep_mutex, - CXL_PORT_LOCK + port->depth + 1); - } else if (is_cxl_nvdimm_bridge(dev)) - mutex_lock_nested(&dev->lockdep_mutex, CXL_NVDIMM_BRIDGE_LOCK); - else if (is_cxl_nvdimm(dev)) - mutex_lock_nested(&dev->lockdep_mutex, CXL_NVDIMM_LOCK); - else - mutex_lock_nested(&dev->lockdep_mutex, CXL_ANON_LOCK); -} - -static inline void cxl_nested_unlock(struct device *dev) -{ - mutex_unlock(&dev->lockdep_mutex); -} - -static inline void cxl_device_lock(struct device *dev) -{ - /* - * For double lock errors the lockup will happen before lockdep - * warns at cxl_nested_lock(), so assert explicitly. - */ - lockdep_assert_not_held(&dev->lockdep_mutex); - - device_lock(dev); - cxl_nested_lock(dev); -} - -static inline void cxl_device_unlock(struct device *dev) -{ - cxl_nested_unlock(dev); - device_unlock(dev); -} -#else -static inline void cxl_nested_lock(struct device *dev) -{ -} - -static inline void cxl_nested_unlock(struct device *dev) -{ -} - -static inline void cxl_device_lock(struct device *dev) -{ - device_lock(dev); -} - -static inline void cxl_device_unlock(struct device *dev) -{ - device_unlock(dev); -} -#endif #endif /* __CXL_H__ */ diff --git a/drivers/cxl/cxlmem.h b/drivers/cxl/cxlmem.h index 5d33ce24fe09fac6d8a1550cf8bc6b6d1a8880bc..60d10ee1e7fcd7bc625400e49672b265633b093d 100644 --- a/drivers/cxl/cxlmem.h +++ b/drivers/cxl/cxlmem.h @@ -85,9 +85,60 @@ struct cxl_mbox_cmd { size_t size_in; size_t size_out; u16 return_code; -#define CXL_MBOX_SUCCESS 0 }; +/* + * Per CXL 2.0 Section 8.2.8.4.5.1 + */ +#define CMD_CMD_RC_TABLE \ + C(SUCCESS, 0, NULL), \ + C(BACKGROUND, -ENXIO, "background cmd started successfully"), \ + C(INPUT, -ENXIO, "cmd input was invalid"), \ + C(UNSUPPORTED, -ENXIO, "cmd is not supported"), \ + C(INTERNAL, -ENXIO, "internal device error"), \ + C(RETRY, -ENXIO, "temporary error, retry once"), \ + C(BUSY, -ENXIO, "ongoing background operation"), \ + C(MEDIADISABLED, -ENXIO, "media access is disabled"), \ + C(FWINPROGRESS, -ENXIO, "one FW package can be transferred at a time"), \ + C(FWOOO, -ENXIO, "FW package content was transferred out of order"), \ + C(FWAUTH, -ENXIO, "FW package authentication failed"), \ + C(FWSLOT, -ENXIO, "FW slot is not supported for requested operation"), \ + C(FWROLLBACK, -ENXIO, "rolled back to the previous active FW"), \ + C(FWRESET, -ENXIO, "FW failed to activate, needs cold reset"), \ + C(HANDLE, -ENXIO, "one or more Event Record Handles were invalid"), \ + C(PADDR, -ENXIO, "physical address specified is invalid"), \ + C(POISONLMT, -ENXIO, "poison injection limit has been reached"), \ + C(MEDIAFAILURE, -ENXIO, "permanent issue with the media"), \ + C(ABORT, -ENXIO, "background cmd was aborted by device"), \ + C(SECURITY, -ENXIO, "not valid in the current security state"), \ + C(PASSPHRASE, -ENXIO, "phrase doesn't match current set passphrase"), \ + C(MBUNSUPPORTED, -ENXIO, "unsupported on the mailbox it was issued on"),\ + C(PAYLOADLEN, -ENXIO, "invalid payload length") + +#undef C +#define C(a, b, c) CXL_MBOX_CMD_RC_##a +enum { CMD_CMD_RC_TABLE }; +#undef C +#define C(a, b, c) { b, c } +struct cxl_mbox_cmd_rc { + int err; + const char *desc; +}; + +static const +struct cxl_mbox_cmd_rc cxl_mbox_cmd_rctable[] ={ CMD_CMD_RC_TABLE }; +#undef C + +static inline const char *cxl_mbox_cmd_rc2str(struct cxl_mbox_cmd *mbox_cmd) +{ + return cxl_mbox_cmd_rctable[mbox_cmd->return_code].desc; +} + +static inline int cxl_mbox_cmd_rc2errno(struct cxl_mbox_cmd *mbox_cmd) +{ + return cxl_mbox_cmd_rctable[mbox_cmd->return_code].err; +} + /* * CXL 2.0 - Memory capacity multiplier * See Section 8.2.9.5 @@ -141,7 +192,6 @@ struct cxl_endpoint_dvsec_info { * @info: Cached DVSEC information about the device. * @serial: PCIe Device Serial Number * @mbox_send: @dev specific transport for transmitting mailbox commands - * @wait_media_ready: @dev specific method to await media ready * * See section 8.2.9.5.2 Capacity Configuration and Label Storage for * details on capacity parameters. @@ -172,11 +222,9 @@ struct cxl_dev_state { u64 next_persistent_bytes; resource_size_t component_reg_phys; - struct cxl_endpoint_dvsec_info info; u64 serial; int (*mbox_send)(struct cxl_dev_state *cxlds, struct cxl_mbox_cmd *cmd); - int (*wait_media_ready)(struct cxl_dev_state *cxlds); }; enum cxl_opcode { @@ -262,6 +310,13 @@ struct cxl_mbox_set_lsa { u8 data[]; } __packed; +struct cxl_mbox_set_partition_info { + __le64 volatile_capacity; + u8 flags; +} __packed; + +#define CXL_SET_PARTITION_IMMEDIATE_FLAG BIT(0) + /** * struct cxl_mem_command - Driver representation of a memory device command * @info: Command information as it exists for the UAPI @@ -290,11 +345,23 @@ struct cxl_mem_command { int cxl_mbox_send_cmd(struct cxl_dev_state *cxlds, u16 opcode, void *in, size_t in_size, void *out, size_t out_size); int cxl_dev_state_identify(struct cxl_dev_state *cxlds); +int cxl_await_media_ready(struct cxl_dev_state *cxlds); int cxl_enumerate_cmds(struct cxl_dev_state *cxlds); int cxl_mem_create_range_info(struct cxl_dev_state *cxlds); struct cxl_dev_state *cxl_dev_state_create(struct device *dev); void set_exclusive_cxl_commands(struct cxl_dev_state *cxlds, unsigned long *cmds); void clear_exclusive_cxl_commands(struct cxl_dev_state *cxlds, unsigned long *cmds); +#ifdef CONFIG_CXL_SUSPEND +void cxl_mem_active_inc(void); +void cxl_mem_active_dec(void); +#else +static inline void cxl_mem_active_inc(void) +{ +} +static inline void cxl_mem_active_dec(void) +{ +} +#endif struct cxl_hdm { struct cxl_component_regs regs; diff --git a/drivers/cxl/cxlpci.h b/drivers/cxl/cxlpci.h index 329e7ea3f36a638e10f77db3328a89d2752076ab..fce1c11729c24be3543f62267f12f0a1f0b4c209 100644 --- a/drivers/cxl/cxlpci.h +++ b/drivers/cxl/cxlpci.h @@ -72,4 +72,6 @@ static inline resource_size_t cxl_regmap_to_base(struct pci_dev *pdev, } int devm_cxl_port_enumerate_dports(struct cxl_port *port); +struct cxl_dev_state; +int cxl_hdm_decode_init(struct cxl_dev_state *cxlds, struct cxl_hdm *cxlhdm); #endif /* __CXL_PCI_H__ */ diff --git a/drivers/cxl/mem.c b/drivers/cxl/mem.c index 49a4b1c47299f3308d843ced166c48a04cac0158..c310f1fd3db02eea814c15fdb4c597a62fc1a85e 100644 --- a/drivers/cxl/mem.c +++ b/drivers/cxl/mem.c @@ -24,27 +24,6 @@ * in higher level operations. */ -static int wait_for_media(struct cxl_memdev *cxlmd) -{ - struct cxl_dev_state *cxlds = cxlmd->cxlds; - struct cxl_endpoint_dvsec_info *info = &cxlds->info; - int rc; - - if (!info->mem_enabled) - return -EBUSY; - - rc = cxlds->wait_media_ready(cxlds); - if (rc) - return rc; - - /* - * We know the device is active, and enabled, if any ranges are non-zero - * we'll need to check later before adding the port since that owns the - * HDM decoder registers. - */ - return 0; -} - static int create_endpoint(struct cxl_memdev *cxlmd, struct cxl_port *parent_port) { @@ -67,72 +46,14 @@ static int create_endpoint(struct cxl_memdev *cxlmd, return cxl_endpoint_autoremove(cxlmd, endpoint); } -/** - * cxl_dvsec_decode_init() - Setup HDM decoding for the endpoint - * @cxlds: Device state - * - * Additionally, enables global HDM decoding. Warning: don't call this outside - * of probe. Once probe is complete, the port driver owns all access to the HDM - * decoder registers. - * - * Returns: false if DVSEC Ranges are being used instead of HDM - * decoders, or if it can not be determined if DVSEC Ranges are in use. - * Otherwise, returns true. - */ -__mock bool cxl_dvsec_decode_init(struct cxl_dev_state *cxlds) +static void enable_suspend(void *data) { - struct cxl_endpoint_dvsec_info *info = &cxlds->info; - struct cxl_register_map map; - struct cxl_component_reg_map *cmap = &map.component_map; - bool global_enable, do_hdm_init = false; - void __iomem *crb; - u32 global_ctrl; - - /* map hdm decoder */ - crb = ioremap(cxlds->component_reg_phys, CXL_COMPONENT_REG_BLOCK_SIZE); - if (!crb) { - dev_dbg(cxlds->dev, "Failed to map component registers\n"); - return false; - } - - cxl_probe_component_regs(cxlds->dev, crb, cmap); - if (!cmap->hdm_decoder.valid) { - dev_dbg(cxlds->dev, "Invalid HDM decoder registers\n"); - goto out; - } - - global_ctrl = readl(crb + cmap->hdm_decoder.offset + - CXL_HDM_DECODER_CTRL_OFFSET); - global_enable = global_ctrl & CXL_HDM_DECODER_ENABLE; - if (!global_enable && info->ranges) { - dev_dbg(cxlds->dev, - "DVSEC ranges already programmed and HDM decoders not enabled.\n"); - goto out; - } - - do_hdm_init = true; - - /* - * Permanently (for this boot at least) opt the device into HDM - * operation. Individual HDM decoders still need to be enabled after - * this point. - */ - if (!global_enable) { - dev_dbg(cxlds->dev, "Enabling HDM decode\n"); - writel(global_ctrl | CXL_HDM_DECODER_ENABLE, - crb + cmap->hdm_decoder.offset + - CXL_HDM_DECODER_CTRL_OFFSET); - } - -out: - iounmap(crb); - return do_hdm_init; + cxl_mem_active_dec(); } static int cxl_mem_probe(struct device *dev) { struct cxl_memdev *cxlmd = to_cxl_memdev(dev); - struct cxl_dev_state *cxlds = cxlmd->cxlds; struct cxl_port *parent_port; int rc; @@ -147,44 +68,6 @@ static int cxl_mem_probe(struct device *dev) if (work_pending(&cxlmd->detach_work)) return -EBUSY; - rc = wait_for_media(cxlmd); - if (rc) { - dev_err(dev, "Media not active (%d)\n", rc); - return rc; - } - - /* - * If DVSEC ranges are being used instead of HDM decoder registers there - * is no use in trying to manage those. - */ - if (!cxl_dvsec_decode_init(cxlds)) { - struct cxl_endpoint_dvsec_info *info = &cxlds->info; - int i; - - /* */ - for (i = 0; i < 2; i++) { - u64 base, size; - - /* - * Give a nice warning to the user that BIOS has really - * botched things for them if it didn't place DVSEC - * ranges in the memory map. - */ - base = info->dvsec_range[i].start; - size = range_len(&info->dvsec_range[i]); - if (size && !region_intersects(base, size, - IORESOURCE_SYSTEM_RAM, - IORES_DESC_NONE)) { - dev_err(dev, - "DVSEC range %#llx-%#llx must be reserved by BIOS, but isn't\n", - base, base + size - 1); - } - } - dev_err(dev, - "Active DVSEC range registers in use. Will not bind.\n"); - return -EBUSY; - } - rc = devm_cxl_enumerate_ports(cxlmd); if (rc) return rc; @@ -195,19 +78,36 @@ static int cxl_mem_probe(struct device *dev) return -ENXIO; } - cxl_device_lock(&parent_port->dev); + device_lock(&parent_port->dev); if (!parent_port->dev.driver) { dev_err(dev, "CXL port topology %s not enabled\n", dev_name(&parent_port->dev)); rc = -ENXIO; - goto out; + goto unlock; } rc = create_endpoint(cxlmd, parent_port); -out: - cxl_device_unlock(&parent_port->dev); +unlock: + device_unlock(&parent_port->dev); put_device(&parent_port->dev); - return rc; + if (rc) + return rc; + + /* + * The kernel may be operating out of CXL memory on this device, + * there is no spec defined way to determine whether this device + * preserves contents over suspend, and there is no simple way + * to arrange for the suspend image to avoid CXL memory which + * would setup a circular dependency between PCI resume and save + * state restoration. + * + * TODO: support suspend when all the regions this device is + * hosting are locked and covered by the system address map, + * i.e. platform firmware owns restoring the HDM configuration + * that it locked. + */ + cxl_mem_active_inc(); + return devm_add_action_or_reset(dev, enable_suspend, NULL); } static struct cxl_driver cxl_mem_driver = { diff --git a/drivers/cxl/pci.c b/drivers/cxl/pci.c index 3f2182d6682929681b27adb2cbbcec313d7e6f21..5a0ae46d4989d4f2ae20ff7c00428ed72cae8479 100644 --- a/drivers/cxl/pci.c +++ b/drivers/cxl/pci.c @@ -48,8 +48,7 @@ */ static unsigned short mbox_ready_timeout = 60; module_param(mbox_ready_timeout, ushort, 0644); -MODULE_PARM_DESC(mbox_ready_timeout, - "seconds to wait for mailbox ready / memory active status"); +MODULE_PARM_DESC(mbox_ready_timeout, "seconds to wait for mailbox ready"); static int cxl_pci_mbox_wait_for_doorbell(struct cxl_dev_state *cxlds) { @@ -177,9 +176,10 @@ static int __cxl_pci_mbox_send_cmd(struct cxl_dev_state *cxlds, mbox_cmd->return_code = FIELD_GET(CXLDEV_MBOX_STATUS_RET_CODE_MASK, status_reg); - if (mbox_cmd->return_code != 0) { - dev_dbg(dev, "Mailbox operation had an error\n"); - return 0; + if (mbox_cmd->return_code != CXL_MBOX_CMD_RC_SUCCESS) { + dev_dbg(dev, "Mailbox operation had an error: %s\n", + cxl_mbox_cmd_rc2str(mbox_cmd)); + return 0; /* completed but caller must check return_code */ } /* #7 */ @@ -386,164 +386,6 @@ static int cxl_setup_regs(struct pci_dev *pdev, enum cxl_regloc_type type, return rc; } -static int wait_for_valid(struct cxl_dev_state *cxlds) -{ - struct pci_dev *pdev = to_pci_dev(cxlds->dev); - int d = cxlds->cxl_dvsec, rc; - u32 val; - - /* - * Memory_Info_Valid: When set, indicates that the CXL Range 1 Size high - * and Size Low registers are valid. Must be set within 1 second of - * deassertion of reset to CXL device. Likely it is already set by the - * time this runs, but otherwise give a 1.5 second timeout in case of - * clock skew. - */ - rc = pci_read_config_dword(pdev, d + CXL_DVSEC_RANGE_SIZE_LOW(0), &val); - if (rc) - return rc; - - if (val & CXL_DVSEC_MEM_INFO_VALID) - return 0; - - msleep(1500); - - rc = pci_read_config_dword(pdev, d + CXL_DVSEC_RANGE_SIZE_LOW(0), &val); - if (rc) - return rc; - - if (val & CXL_DVSEC_MEM_INFO_VALID) - return 0; - - return -ETIMEDOUT; -} - -/* - * Wait up to @mbox_ready_timeout for the device to report memory - * active. - */ -static int wait_for_media_ready(struct cxl_dev_state *cxlds) -{ - struct pci_dev *pdev = to_pci_dev(cxlds->dev); - int d = cxlds->cxl_dvsec; - bool active = false; - u64 md_status; - int rc, i; - - rc = wait_for_valid(cxlds); - if (rc) - return rc; - - for (i = mbox_ready_timeout; i; i--) { - u32 temp; - - rc = pci_read_config_dword( - pdev, d + CXL_DVSEC_RANGE_SIZE_LOW(0), &temp); - if (rc) - return rc; - - active = FIELD_GET(CXL_DVSEC_MEM_ACTIVE, temp); - if (active) - break; - msleep(1000); - } - - if (!active) { - dev_err(&pdev->dev, - "timeout awaiting memory active after %d seconds\n", - mbox_ready_timeout); - return -ETIMEDOUT; - } - - md_status = readq(cxlds->regs.memdev + CXLMDEV_STATUS_OFFSET); - if (!CXLMDEV_READY(md_status)) - return -EIO; - - return 0; -} - -static int cxl_dvsec_ranges(struct cxl_dev_state *cxlds) -{ - struct cxl_endpoint_dvsec_info *info = &cxlds->info; - struct pci_dev *pdev = to_pci_dev(cxlds->dev); - int d = cxlds->cxl_dvsec; - int hdm_count, rc, i; - u16 cap, ctrl; - - if (!d) - return -ENXIO; - - rc = pci_read_config_word(pdev, d + CXL_DVSEC_CAP_OFFSET, &cap); - if (rc) - return rc; - - rc = pci_read_config_word(pdev, d + CXL_DVSEC_CTRL_OFFSET, &ctrl); - if (rc) - return rc; - - if (!(cap & CXL_DVSEC_MEM_CAPABLE)) - return -ENXIO; - - /* - * It is not allowed by spec for MEM.capable to be set and have 0 legacy - * HDM decoders (values > 2 are also undefined as of CXL 2.0). As this - * driver is for a spec defined class code which must be CXL.mem - * capable, there is no point in continuing to enable CXL.mem. - */ - hdm_count = FIELD_GET(CXL_DVSEC_HDM_COUNT_MASK, cap); - if (!hdm_count || hdm_count > 2) - return -EINVAL; - - rc = wait_for_valid(cxlds); - if (rc) - return rc; - - info->mem_enabled = FIELD_GET(CXL_DVSEC_MEM_ENABLE, ctrl); - - for (i = 0; i < hdm_count; i++) { - u64 base, size; - u32 temp; - - rc = pci_read_config_dword( - pdev, d + CXL_DVSEC_RANGE_SIZE_HIGH(i), &temp); - if (rc) - return rc; - - size = (u64)temp << 32; - - rc = pci_read_config_dword( - pdev, d + CXL_DVSEC_RANGE_SIZE_LOW(i), &temp); - if (rc) - return rc; - - size |= temp & CXL_DVSEC_MEM_SIZE_LOW_MASK; - - rc = pci_read_config_dword( - pdev, d + CXL_DVSEC_RANGE_BASE_HIGH(i), &temp); - if (rc) - return rc; - - base = (u64)temp << 32; - - rc = pci_read_config_dword( - pdev, d + CXL_DVSEC_RANGE_BASE_LOW(i), &temp); - if (rc) - return rc; - - base |= temp & CXL_DVSEC_MEM_BASE_LOW_MASK; - - info->dvsec_range[i] = (struct range) { - .start = base, - .end = base + size - 1 - }; - - if (size) - info->ranges++; - } - - return 0; -} - static int cxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) { struct cxl_register_map map; @@ -573,8 +415,6 @@ static int cxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) dev_warn(&pdev->dev, "Device DVSEC not present, skip CXL.mem init\n"); - cxlds->wait_media_ready = wait_for_media_ready; - rc = cxl_setup_regs(pdev, CXL_REGLOC_RBI_MEMDEV, &map); if (rc) return rc; @@ -610,11 +450,6 @@ static int cxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) if (rc) return rc; - rc = cxl_dvsec_ranges(cxlds); - if (rc) - dev_warn(&pdev->dev, - "Failed to get DVSEC range information (%d)\n", rc); - cxlmd = devm_cxl_add_memdev(cxlds); if (IS_ERR(cxlmd)) return PTR_ERR(cxlmd); diff --git a/drivers/cxl/pmem.c b/drivers/cxl/pmem.c index 15ad666ab03e31e49cb011da339b1df0e8b2c279..bbeef91e637e9e7f5c3615234f50f0fc3d6b951d 100644 --- a/drivers/cxl/pmem.c +++ b/drivers/cxl/pmem.c @@ -43,7 +43,7 @@ static int cxl_nvdimm_probe(struct device *dev) if (!cxl_nvb) return -ENXIO; - cxl_device_lock(&cxl_nvb->dev); + device_lock(&cxl_nvb->dev); if (!cxl_nvb->nvdimm_bus) { rc = -ENXIO; goto out; @@ -68,7 +68,7 @@ static int cxl_nvdimm_probe(struct device *dev) dev_set_drvdata(dev, nvdimm); rc = devm_add_action_or_reset(dev, unregister_nvdimm, nvdimm); out: - cxl_device_unlock(&cxl_nvb->dev); + device_unlock(&cxl_nvb->dev); put_device(&cxl_nvb->dev); return rc; @@ -233,7 +233,7 @@ static void cxl_nvb_update_state(struct work_struct *work) struct nvdimm_bus *victim_bus = NULL; bool release = false, rescan = false; - cxl_device_lock(&cxl_nvb->dev); + device_lock(&cxl_nvb->dev); switch (cxl_nvb->state) { case CXL_NVB_ONLINE: if (!online_nvdimm_bus(cxl_nvb)) { @@ -251,7 +251,7 @@ static void cxl_nvb_update_state(struct work_struct *work) default: break; } - cxl_device_unlock(&cxl_nvb->dev); + device_unlock(&cxl_nvb->dev); if (release) device_release_driver(&cxl_nvb->dev); @@ -327,9 +327,9 @@ static int cxl_nvdimm_bridge_reset(struct device *dev, void *data) return 0; cxl_nvb = to_cxl_nvdimm_bridge(dev); - cxl_device_lock(dev); + device_lock(dev); cxl_nvb->state = CXL_NVB_NEW; - cxl_device_unlock(dev); + device_unlock(dev); return 0; } @@ -344,7 +344,6 @@ static __init int cxl_pmem_init(void) { int rc; - set_bit(CXL_MEM_COMMAND_ID_SET_PARTITION_INFO, exclusive_cmds); set_bit(CXL_MEM_COMMAND_ID_SET_SHUTDOWN_STATE, exclusive_cmds); set_bit(CXL_MEM_COMMAND_ID_SET_LSA, exclusive_cmds); diff --git a/drivers/cxl/port.c b/drivers/cxl/port.c index d420da5fc39c913017077db9f2c28fdeb58877dc..3cf308f114c473b57e47eb9c149114a5f0818fd8 100644 --- a/drivers/cxl/port.c +++ b/drivers/cxl/port.c @@ -36,14 +36,8 @@ static int cxl_port_probe(struct device *dev) struct cxl_hdm *cxlhdm; int rc; - if (is_cxl_endpoint(port)) { - struct cxl_memdev *cxlmd = to_cxl_memdev(port->uport); - get_device(&cxlmd->dev); - rc = devm_add_action_or_reset(dev, schedule_detach, cxlmd); - if (rc) - return rc; - } else { + if (!is_cxl_endpoint(port)) { rc = devm_cxl_port_enumerate_dports(port); if (rc < 0) return rc; @@ -55,6 +49,26 @@ static int cxl_port_probe(struct device *dev) if (IS_ERR(cxlhdm)) return PTR_ERR(cxlhdm); + if (is_cxl_endpoint(port)) { + struct cxl_memdev *cxlmd = to_cxl_memdev(port->uport); + struct cxl_dev_state *cxlds = cxlmd->cxlds; + + get_device(&cxlmd->dev); + rc = devm_add_action_or_reset(dev, schedule_detach, cxlmd); + if (rc) + return rc; + + rc = cxl_hdm_decode_init(cxlds, cxlhdm); + if (rc) + return rc; + + rc = cxl_await_media_ready(cxlds); + if (rc) { + dev_err(dev, "Media not active (%d)\n", rc); + return rc; + } + } + rc = devm_cxl_enumerate_decoders(cxlhdm); if (rc) { dev_err(dev, "Couldn't enumerate decoders (%d)\n", rc); diff --git a/drivers/dax/super.c b/drivers/dax/super.c index 0211e6f7b47a953b33a340e8650f48cbc07aeb4a..50a08b2ec24749cf8525905822f48e296981e49b 100644 --- a/drivers/dax/super.c +++ b/drivers/dax/super.c @@ -117,6 +117,7 @@ enum dax_device_flags { * @dax_dev: a dax_device instance representing the logical memory range * @pgoff: offset in pages from the start of the device to translate * @nr_pages: number of consecutive pages caller can handle relative to @pfn + * @mode: indicator on normal access or recovery write * @kaddr: output parameter that returns a virtual address mapping of pfn * @pfn: output parameter that returns an absolute pfn translation of @pgoff * @@ -124,7 +125,7 @@ enum dax_device_flags { * pages accessible at the device relative @pgoff. */ long dax_direct_access(struct dax_device *dax_dev, pgoff_t pgoff, long nr_pages, - void **kaddr, pfn_t *pfn) + enum dax_access_mode mode, void **kaddr, pfn_t *pfn) { long avail; @@ -138,7 +139,7 @@ long dax_direct_access(struct dax_device *dax_dev, pgoff_t pgoff, long nr_pages, return -EINVAL; avail = dax_dev->ops->direct_access(dax_dev, pgoff, nr_pages, - kaddr, pfn); + mode, kaddr, pfn); if (!avail) return -ERANGE; return min(avail, nr_pages); @@ -194,6 +195,15 @@ int dax_zero_page_range(struct dax_device *dax_dev, pgoff_t pgoff, } EXPORT_SYMBOL_GPL(dax_zero_page_range); +size_t dax_recovery_write(struct dax_device *dax_dev, pgoff_t pgoff, + void *addr, size_t bytes, struct iov_iter *iter) +{ + if (!dax_dev->ops->recovery_write) + return 0; + return dax_dev->ops->recovery_write(dax_dev, pgoff, addr, bytes, iter); +} +EXPORT_SYMBOL_GPL(dax_recovery_write); + #ifdef CONFIG_ARCH_HAS_PMEM_API void arch_wb_cache_pmem(void *addr, size_t size); void dax_flush(struct dax_device *dax_dev, void *addr, size_t size) diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index d5de3f77d3aa88ca8d6b9711e97e28f2062d80c5..487ed4ddc3bea26f6bdde0fd8c4e0985aa8016ea 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -163,7 +163,7 @@ config DMA_SUN4I config DMA_SUN6I tristate "Allwinner A31 SoCs DMA support" - depends on MACH_SUN6I || MACH_SUN8I || (ARM64 && ARCH_SUNXI) || COMPILE_TEST + depends on ARCH_SUNXI || COMPILE_TEST depends on RESET_CONTROLLER select DMA_ENGINE select DMA_VIRTUAL_CHANNELS @@ -629,6 +629,18 @@ config TXX9_DMAC Support the TXx9 SoC internal DMA controller. This can be integrated in chips such as the Toshiba TX4927/38/39. +config TEGRA186_GPC_DMA + tristate "NVIDIA Tegra GPC DMA support" + depends on (ARCH_TEGRA || COMPILE_TEST) && ARCH_DMA_ADDR_T_64BIT + depends on IOMMU_API + select DMA_ENGINE + help + Support for the NVIDIA Tegra General Purpose Central DMA controller. + The DMA controller has multiple DMA channels which can be configured + for different peripherals like UART, SPI, etc which are on APB bus. + This DMA controller transfers data from memory to peripheral FIFO + or vice versa. It also supports memory to memory data transfer. + config TEGRA20_APB_DMA tristate "NVIDIA Tegra20 APB DMA support" depends on ARCH_TEGRA || COMPILE_TEST diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile index 616d926cf2a5faf919bc2583669e508cc4748317..2f1b87ffd7ab93f231f9b61dacbdc23726f40210 100644 --- a/drivers/dma/Makefile +++ b/drivers/dma/Makefile @@ -72,6 +72,7 @@ obj-$(CONFIG_STM32_MDMA) += stm32-mdma.o obj-$(CONFIG_SPRD_DMA) += sprd-dma.o obj-$(CONFIG_S3C24XX_DMAC) += s3c24xx-dma.o obj-$(CONFIG_TXX9_DMAC) += txx9dmac.o +obj-$(CONFIG_TEGRA186_GPC_DMA) += tegra186-gpc-dma.o obj-$(CONFIG_TEGRA20_APB_DMA) += tegra20-apb-dma.o obj-$(CONFIG_TEGRA210_ADMA) += tegra210-adma.o obj-$(CONFIG_TIMB_DMA) += timb_dma.o diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c index a24882ba37643db58ba982a53e1da00d6873ffbb..a4a794e62ac263f4fcc454aff3201c523ff22765 100644 --- a/drivers/dma/amba-pl08x.c +++ b/drivers/dma/amba-pl08x.c @@ -1535,14 +1535,6 @@ static void pl08x_free_chan_resources(struct dma_chan *chan) vchan_free_chan_resources(to_virt_chan(chan)); } -static struct dma_async_tx_descriptor *pl08x_prep_dma_interrupt( - struct dma_chan *chan, unsigned long flags) -{ - struct dma_async_tx_descriptor *retval = NULL; - - return retval; -} - /* * Code accessing dma_async_is_complete() in a tight loop may give problems. * If slaves are relying on interrupts to signal completion this function @@ -2760,7 +2752,6 @@ static int pl08x_probe(struct amba_device *adev, const struct amba_id *id) pl08x->memcpy.dev = &adev->dev; pl08x->memcpy.device_free_chan_resources = pl08x_free_chan_resources; pl08x->memcpy.device_prep_dma_memcpy = pl08x_prep_dma_memcpy; - pl08x->memcpy.device_prep_dma_interrupt = pl08x_prep_dma_interrupt; pl08x->memcpy.device_tx_status = pl08x_dma_tx_status; pl08x->memcpy.device_issue_pending = pl08x_issue_pending; pl08x->memcpy.device_config = pl08x_config; @@ -2787,8 +2778,6 @@ static int pl08x_probe(struct amba_device *adev, const struct amba_id *id) pl08x->slave.dev = &adev->dev; pl08x->slave.device_free_chan_resources = pl08x_free_chan_resources; - pl08x->slave.device_prep_dma_interrupt = - pl08x_prep_dma_interrupt; pl08x->slave.device_tx_status = pl08x_dma_tx_status; pl08x->slave.device_issue_pending = pl08x_issue_pending; pl08x->slave.device_prep_slave_sg = pl08x_prep_slave_sg; diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index 30ae36124b1db9d031affc1c4a7b6b4cc2564a7c..5a50423b7378e2d3ffe606459bc81f4fc51868ba 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c @@ -942,6 +942,7 @@ atc_prep_dma_memset(struct dma_chan *chan, dma_addr_t dest, int value, struct at_desc *desc; void __iomem *vaddr; dma_addr_t paddr; + char fill_pattern; dev_vdbg(chan2dev(chan), "%s: d%pad v0x%x l0x%zx f0x%lx\n", __func__, &dest, value, len, flags); @@ -963,7 +964,14 @@ atc_prep_dma_memset(struct dma_chan *chan, dma_addr_t dest, int value, __func__); return NULL; } - *(u32*)vaddr = value; + + /* Only the first byte of value is to be used according to dmaengine */ + fill_pattern = (char)value; + + *(u32*)vaddr = (fill_pattern << 24) | + (fill_pattern << 16) | + (fill_pattern << 8) | + fill_pattern; desc = atc_create_memset_desc(chan, paddr, dest, len); if (!desc) { diff --git a/drivers/dma/at_xdmac.c b/drivers/dma/at_xdmac.c index def564d1e8faf714c167f25df26e109658117b29..3e9d726504e2ed776ddc1155ef43130da5811533 100644 --- a/drivers/dma/at_xdmac.c +++ b/drivers/dma/at_xdmac.c @@ -1202,6 +1202,7 @@ static struct at_xdmac_desc *at_xdmac_memset_create_desc(struct dma_chan *chan, unsigned long flags; size_t ublen; u32 dwidth; + char pattern; /* * WARNING: The channel configuration is set here since there is no * dmaengine_slave_config call in this case. Moreover we don't know the @@ -1244,10 +1245,16 @@ static struct at_xdmac_desc *at_xdmac_memset_create_desc(struct dma_chan *chan, chan_cc |= AT_XDMAC_CC_DWIDTH(dwidth); + /* Only the first byte of value is to be used according to dmaengine */ + pattern = (char)value; + ublen = len >> dwidth; desc->lld.mbr_da = dst_addr; - desc->lld.mbr_ds = value; + desc->lld.mbr_ds = (pattern << 24) | + (pattern << 16) | + (pattern << 8) | + pattern; desc->lld.mbr_ubc = AT_XDMAC_MBR_UBC_NDV3 | AT_XDMAC_MBR_UBC_NDEN | AT_XDMAC_MBR_UBC_NSEN diff --git a/drivers/dma/bestcomm/bestcomm.c b/drivers/dma/bestcomm/bestcomm.c index 8c42e5ca00a998f731d00166e849c21349484e24..1822a7034630d2d92371f83171a1a674c60aaae0 100644 --- a/drivers/dma/bestcomm/bestcomm.c +++ b/drivers/dma/bestcomm/bestcomm.c @@ -17,7 +17,9 @@ #include #include #include +#include #include +#include #include #include #include diff --git a/drivers/dma/dma-jz4780.c b/drivers/dma/dma-jz4780.c index fc513eb2b289c0f687723a913d60db542b44b4eb..e2ec540e6519627cc828683fb79a082934ab63be 100644 --- a/drivers/dma/dma-jz4780.c +++ b/drivers/dma/dma-jz4780.c @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -911,6 +912,14 @@ static int jz4780_dma_probe(struct platform_device *pdev) dd = &jzdma->dma_device; + /* + * The real segment size limit is dependent on the size unit selected + * for the transfer. Because the size unit is selected automatically + * and may be as small as 1 byte, use a safe limit of 2^24-1 bytes to + * ensure the 24-bit transfer count in the descriptor cannot overflow. + */ + dma_set_max_seg_size(dev, 0xffffff); + dma_cap_set(DMA_MEMCPY, dd->cap_mask); dma_cap_set(DMA_SLAVE, dd->cap_mask); dma_cap_set(DMA_CYCLIC, dd->cap_mask); diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c index 2cfa8458b51be48d5a6cd1a0309b16ced7d817e9..e80feeea0e018f93dcbc6f70ea789d1b41291be9 100644 --- a/drivers/dma/dmaengine.c +++ b/drivers/dma/dmaengine.c @@ -1053,9 +1053,7 @@ static int __dma_async_device_channel_register(struct dma_device *device, * When the chan_id is a negative value, we are dynamically adding * the channel. Otherwise we are static enumerating. */ - mutex_lock(&device->chan_mutex); chan->chan_id = ida_alloc(&device->chan_ida, GFP_KERNEL); - mutex_unlock(&device->chan_mutex); if (chan->chan_id < 0) { pr_err("%s: unable to alloc ida for chan: %d\n", __func__, chan->chan_id); @@ -1078,9 +1076,7 @@ static int __dma_async_device_channel_register(struct dma_device *device, return 0; err_out_ida: - mutex_lock(&device->chan_mutex); ida_free(&device->chan_ida, chan->chan_id); - mutex_unlock(&device->chan_mutex); err_free_dev: kfree(chan->dev); err_free_local: @@ -1113,9 +1109,7 @@ static void __dma_async_device_channel_unregister(struct dma_device *device, device->chancnt--; chan->dev->chan = NULL; mutex_unlock(&dma_list_mutex); - mutex_lock(&device->chan_mutex); ida_free(&device->chan_ida, chan->chan_id); - mutex_unlock(&device->chan_mutex); device_unregister(&chan->dev->device); free_percpu(chan->local); } @@ -1250,7 +1244,6 @@ int dma_async_device_register(struct dma_device *device) if (rc != 0) return rc; - mutex_init(&device->chan_mutex); ida_init(&device->chan_ida); /* represent channels in sysfs. Probably want devs too */ diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c index f696246f57fdb3734523930610bc650c52872fdb..0a2168a4ccb0cf177ee99b4d7522b1b2c06ae0df 100644 --- a/drivers/dma/dmatest.c +++ b/drivers/dma/dmatest.c @@ -675,10 +675,16 @@ static int dmatest_func(void *data) /* * src and dst buffers are freed by ourselves below */ - if (params->polled) + if (params->polled) { flags = DMA_CTRL_ACK; - else - flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT; + } else { + if (dma_has_cap(DMA_INTERRUPT, dev->cap_mask)) { + flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT; + } else { + pr_err("Channel does not support interrupt!\n"); + goto err_pq_array; + } + } ktime = ktime_get(); while (!(kthread_should_stop() || @@ -906,6 +912,7 @@ error_unmap_continue: runtime = ktime_to_us(ktime); ret = 0; +err_pq_array: kfree(dma_pq); err_srcs_array: kfree(srcs); diff --git a/drivers/dma/dw/Kconfig b/drivers/dma/dw/Kconfig index db25f9b7778c9eed2f5292436be7f0e9e11ebe29..a9828ddd6d0605c18c73ecb3110dbee07cfaf658 100644 --- a/drivers/dma/dw/Kconfig +++ b/drivers/dma/dw/Kconfig @@ -16,6 +16,15 @@ config DW_DMAC Support the Synopsys DesignWare AHB DMA controller. This can be integrated in chips such as the Intel Cherrytrail. +config RZN1_DMAMUX + tristate "Renesas RZ/N1 DMAMUX driver" + depends on DW_DMAC + depends on ARCH_RZN1 || COMPILE_TEST + help + Support the Renesas RZ/N1 DMAMUX which is located in front of + the Synopsys DesignWare AHB DMA controller located on Renesas + SoCs. + config DW_DMAC_PCI tristate "Synopsys DesignWare AHB DMA PCI driver" depends on PCI diff --git a/drivers/dma/dw/Makefile b/drivers/dma/dw/Makefile index a6f358ad859194a73a1821f429f6c90c09f2cdb8..e1796015f213af72ec8c4ce7a60f3b91c672d37c 100644 --- a/drivers/dma/dw/Makefile +++ b/drivers/dma/dw/Makefile @@ -9,3 +9,5 @@ dw_dmac-$(CONFIG_OF) += of.o obj-$(CONFIG_DW_DMAC_PCI) += dw_dmac_pci.o dw_dmac_pci-y := pci.o + +obj-$(CONFIG_RZN1_DMAMUX) += rzn1-dmamux.o diff --git a/drivers/dma/dw/platform.c b/drivers/dma/dw/platform.c index 2461189558770e413222fb0b08f422089086ed5c..47f2292dba983e920f3f799d8c47ed7726eae470 100644 --- a/drivers/dma/dw/platform.c +++ b/drivers/dma/dw/platform.c @@ -137,6 +137,7 @@ static void dw_shutdown(struct platform_device *pdev) #ifdef CONFIG_OF static const struct of_device_id dw_dma_of_id_table[] = { { .compatible = "snps,dma-spear1340", .data = &dw_dma_chip_pdata }, + { .compatible = "renesas,rzn1-dma", .data = &dw_dma_chip_pdata }, {} }; MODULE_DEVICE_TABLE(of, dw_dma_of_id_table); diff --git a/drivers/dma/dw/rzn1-dmamux.c b/drivers/dma/dw/rzn1-dmamux.c new file mode 100644 index 0000000000000000000000000000000000000000..11d254e450b0ccd06e68d6281eae72d3ec09b6f9 --- /dev/null +++ b/drivers/dma/dw/rzn1-dmamux.c @@ -0,0 +1,155 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2022 Schneider-Electric + * Author: Miquel Raynal + */ +#include +#include +#include +#include +#include +#include + +#define RNZ1_DMAMUX_NCELLS 6 +#define RZN1_DMAMUX_MAX_LINES 64 +#define RZN1_DMAMUX_LINES_PER_CTLR 16 + +struct rzn1_dmamux_data { + struct dma_router dmarouter; + DECLARE_BITMAP(used_chans, 2 * RZN1_DMAMUX_LINES_PER_CTLR); +}; + +struct rzn1_dmamux_map { + unsigned int req_idx; +}; + +static void rzn1_dmamux_free(struct device *dev, void *route_data) +{ + struct rzn1_dmamux_data *dmamux = dev_get_drvdata(dev); + struct rzn1_dmamux_map *map = route_data; + + dev_dbg(dev, "Unmapping DMAMUX request %u\n", map->req_idx); + + clear_bit(map->req_idx, dmamux->used_chans); + + kfree(map); +} + +static void *rzn1_dmamux_route_allocate(struct of_phandle_args *dma_spec, + struct of_dma *ofdma) +{ + struct platform_device *pdev = of_find_device_by_node(ofdma->of_node); + struct rzn1_dmamux_data *dmamux = platform_get_drvdata(pdev); + struct rzn1_dmamux_map *map; + unsigned int dmac_idx, chan, val; + u32 mask; + int ret; + + if (dma_spec->args_count != RNZ1_DMAMUX_NCELLS) + return ERR_PTR(-EINVAL); + + map = kzalloc(sizeof(*map), GFP_KERNEL); + if (!map) + return ERR_PTR(-ENOMEM); + + chan = dma_spec->args[0]; + map->req_idx = dma_spec->args[4]; + val = dma_spec->args[5]; + dma_spec->args_count -= 2; + + if (chan >= RZN1_DMAMUX_LINES_PER_CTLR) { + dev_err(&pdev->dev, "Invalid DMA request line: %u\n", chan); + ret = -EINVAL; + goto free_map; + } + + if (map->req_idx >= RZN1_DMAMUX_MAX_LINES || + (map->req_idx % RZN1_DMAMUX_LINES_PER_CTLR) != chan) { + dev_err(&pdev->dev, "Invalid MUX request line: %u\n", map->req_idx); + ret = -EINVAL; + goto free_map; + } + + dmac_idx = map->req_idx >= RZN1_DMAMUX_LINES_PER_CTLR ? 1 : 0; + dma_spec->np = of_parse_phandle(ofdma->of_node, "dma-masters", dmac_idx); + if (!dma_spec->np) { + dev_err(&pdev->dev, "Can't get DMA master\n"); + ret = -EINVAL; + goto free_map; + } + + dev_dbg(&pdev->dev, "Mapping DMAMUX request %u to DMAC%u request %u\n", + map->req_idx, dmac_idx, chan); + + if (test_and_set_bit(map->req_idx, dmamux->used_chans)) { + ret = -EBUSY; + goto free_map; + } + + mask = BIT(map->req_idx); + ret = r9a06g032_sysctrl_set_dmamux(mask, val ? mask : 0); + if (ret) + goto clear_bitmap; + + return map; + +clear_bitmap: + clear_bit(map->req_idx, dmamux->used_chans); +free_map: + kfree(map); + + return ERR_PTR(ret); +} + +static const struct of_device_id rzn1_dmac_match[] = { + { .compatible = "renesas,rzn1-dma" }, + {} +}; + +static int rzn1_dmamux_probe(struct platform_device *pdev) +{ + struct device_node *mux_node = pdev->dev.of_node; + const struct of_device_id *match; + struct device_node *dmac_node; + struct rzn1_dmamux_data *dmamux; + + dmamux = devm_kzalloc(&pdev->dev, sizeof(*dmamux), GFP_KERNEL); + if (!dmamux) + return -ENOMEM; + + dmac_node = of_parse_phandle(mux_node, "dma-masters", 0); + if (!dmac_node) + return dev_err_probe(&pdev->dev, -ENODEV, "Can't get DMA master node\n"); + + match = of_match_node(rzn1_dmac_match, dmac_node); + of_node_put(dmac_node); + if (!match) + return dev_err_probe(&pdev->dev, -EINVAL, "DMA master is not supported\n"); + + dmamux->dmarouter.dev = &pdev->dev; + dmamux->dmarouter.route_free = rzn1_dmamux_free; + + platform_set_drvdata(pdev, dmamux); + + return of_dma_router_register(mux_node, rzn1_dmamux_route_allocate, + &dmamux->dmarouter); +} + +static const struct of_device_id rzn1_dmamux_match[] = { + { .compatible = "renesas,rzn1-dmamux" }, + {} +}; + +static struct platform_driver rzn1_dmamux_driver = { + .driver = { + .name = "renesas,rzn1-dmamux", + .of_match_table = rzn1_dmamux_match, + }, + .probe = rzn1_dmamux_probe, +}; +module_platform_driver(rzn1_dmamux_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Miquel Raynal wq = wq; filp->private_data = ctx; - if (device_pasid_enabled(idxd)) { + if (device_user_pasid_enabled(idxd)) { sva = iommu_sva_bind_device(dev, current->mm, NULL); if (IS_ERR(sva)) { rc = PTR_ERR(sva); @@ -152,7 +152,7 @@ static int idxd_cdev_release(struct inode *node, struct file *filep) if (wq_shared(wq)) { idxd_device_drain_pasid(idxd, ctx->pasid); } else { - if (device_pasid_enabled(idxd)) { + if (device_user_pasid_enabled(idxd)) { /* The wq disable in the disable pasid function will drain the wq */ rc = idxd_wq_disable_pasid(wq); if (rc < 0) @@ -314,7 +314,7 @@ static int idxd_user_drv_probe(struct idxd_dev *idxd_dev) mutex_lock(&wq->wq_lock); wq->type = IDXD_WQT_USER; - rc = __drv_enable_wq(wq); + rc = drv_enable_wq(wq); if (rc < 0) goto err; @@ -329,7 +329,7 @@ static int idxd_user_drv_probe(struct idxd_dev *idxd_dev) return 0; err_cdev: - __drv_disable_wq(wq); + drv_disable_wq(wq); err: wq->type = IDXD_WQT_NONE; mutex_unlock(&wq->wq_lock); @@ -342,7 +342,7 @@ static void idxd_user_drv_remove(struct idxd_dev *idxd_dev) mutex_lock(&wq->wq_lock); idxd_wq_del_cdev(wq); - __drv_disable_wq(wq); + drv_disable_wq(wq); wq->type = IDXD_WQT_NONE; mutex_unlock(&wq->wq_lock); } @@ -369,10 +369,16 @@ int idxd_cdev_register(void) rc = alloc_chrdev_region(&ictx[i].devt, 0, MINORMASK, ictx[i].name); if (rc) - return rc; + goto err_free_chrdev_region; } return 0; + +err_free_chrdev_region: + for (i--; i >= 0; i--) + unregister_chrdev_region(ictx[i].devt, MINORMASK); + + return rc; } void idxd_cdev_remove(void) diff --git a/drivers/dma/idxd/device.c b/drivers/dma/idxd/device.c index f652da6ab47df1b29147136fd17c390d353c9a79..ff0ea60051f0c90e50463de27df0abf5b53f9e27 100644 --- a/drivers/dma/idxd/device.c +++ b/drivers/dma/idxd/device.c @@ -184,7 +184,7 @@ int idxd_wq_enable(struct idxd_wq *wq) if (wq->state == IDXD_WQ_ENABLED) { dev_dbg(dev, "WQ %d already enabled\n", wq->id); - return -ENXIO; + return 0; } idxd_cmd_exec(idxd, IDXD_CMD_ENABLE_WQ, wq->id, &status); @@ -299,24 +299,46 @@ void idxd_wqs_unmap_portal(struct idxd_device *idxd) } } -int idxd_wq_set_pasid(struct idxd_wq *wq, int pasid) +static void __idxd_wq_set_priv_locked(struct idxd_wq *wq, int priv) { struct idxd_device *idxd = wq->idxd; - int rc; union wqcfg wqcfg; unsigned int offset; - rc = idxd_wq_disable(wq, false); - if (rc < 0) - return rc; + offset = WQCFG_OFFSET(idxd, wq->id, WQCFG_PRIVL_IDX); + spin_lock(&idxd->dev_lock); + wqcfg.bits[WQCFG_PRIVL_IDX] = ioread32(idxd->reg_base + offset); + wqcfg.priv = priv; + wq->wqcfg->bits[WQCFG_PRIVL_IDX] = wqcfg.bits[WQCFG_PRIVL_IDX]; + iowrite32(wqcfg.bits[WQCFG_PRIVL_IDX], idxd->reg_base + offset); + spin_unlock(&idxd->dev_lock); +} + +static void __idxd_wq_set_pasid_locked(struct idxd_wq *wq, int pasid) +{ + struct idxd_device *idxd = wq->idxd; + union wqcfg wqcfg; + unsigned int offset; offset = WQCFG_OFFSET(idxd, wq->id, WQCFG_PASID_IDX); spin_lock(&idxd->dev_lock); wqcfg.bits[WQCFG_PASID_IDX] = ioread32(idxd->reg_base + offset); wqcfg.pasid_en = 1; wqcfg.pasid = pasid; + wq->wqcfg->bits[WQCFG_PASID_IDX] = wqcfg.bits[WQCFG_PASID_IDX]; iowrite32(wqcfg.bits[WQCFG_PASID_IDX], idxd->reg_base + offset); spin_unlock(&idxd->dev_lock); +} + +int idxd_wq_set_pasid(struct idxd_wq *wq, int pasid) +{ + int rc; + + rc = idxd_wq_disable(wq, false); + if (rc < 0) + return rc; + + __idxd_wq_set_pasid_locked(wq, pasid); rc = idxd_wq_enable(wq); if (rc < 0) @@ -555,19 +577,15 @@ int idxd_device_disable(struct idxd_device *idxd) return -ENXIO; } - spin_lock(&idxd->dev_lock); idxd_device_clear_state(idxd); - idxd->state = IDXD_DEV_DISABLED; - spin_unlock(&idxd->dev_lock); return 0; } void idxd_device_reset(struct idxd_device *idxd) { idxd_cmd_exec(idxd, IDXD_CMD_RESET_DEVICE, 0, NULL); - spin_lock(&idxd->dev_lock); idxd_device_clear_state(idxd); - idxd->state = IDXD_DEV_DISABLED; + spin_lock(&idxd->dev_lock); idxd_unmask_error_interrupts(idxd); spin_unlock(&idxd->dev_lock); } @@ -694,15 +712,16 @@ static void idxd_device_wqs_clear_state(struct idxd_device *idxd) { int i; - lockdep_assert_held(&idxd->dev_lock); for (i = 0; i < idxd->max_wqs; i++) { struct idxd_wq *wq = idxd->wqs[i]; + mutex_lock(&wq->wq_lock); if (wq->state == IDXD_WQ_ENABLED) { idxd_wq_disable_cleanup(wq); wq->state = IDXD_WQ_DISABLED; } idxd_wq_device_reset_cleanup(wq); + mutex_unlock(&wq->wq_lock); } } @@ -711,9 +730,12 @@ void idxd_device_clear_state(struct idxd_device *idxd) if (!test_bit(IDXD_FLAG_CONFIGURABLE, &idxd->flags)) return; + idxd_device_wqs_clear_state(idxd); + spin_lock(&idxd->dev_lock); idxd_groups_clear_state(idxd); idxd_engines_clear_state(idxd); - idxd_device_wqs_clear_state(idxd); + idxd->state = IDXD_DEV_DISABLED; + spin_unlock(&idxd->dev_lock); } static void idxd_group_config_write(struct idxd_group *group) @@ -799,7 +821,7 @@ static int idxd_wq_config_write(struct idxd_wq *wq) */ for (i = 0; i < WQCFG_STRIDES(idxd); i++) { wq_offset = WQCFG_OFFSET(idxd, wq->id, i); - wq->wqcfg->bits[i] = ioread32(idxd->reg_base + wq_offset); + wq->wqcfg->bits[i] |= ioread32(idxd->reg_base + wq_offset); } if (wq->size == 0 && wq->type != IDXD_WQT_NONE) @@ -815,14 +837,8 @@ static int idxd_wq_config_write(struct idxd_wq *wq) if (wq_dedicated(wq)) wq->wqcfg->mode = 1; - if (device_pasid_enabled(idxd)) { - wq->wqcfg->pasid_en = 1; - if (wq->type == IDXD_WQT_KERNEL && wq_dedicated(wq)) - wq->wqcfg->pasid = idxd->pasid; - } - /* - * Here the priv bit is set depending on the WQ type. priv = 1 if the + * The WQ priv bit is set depending on the WQ type. priv = 1 if the * WQ type is kernel to indicate privileged access. This setting only * matters for dedicated WQ. According to the DSA spec: * If the WQ is in dedicated mode, WQ PASID Enable is 1, and the @@ -832,7 +848,6 @@ static int idxd_wq_config_write(struct idxd_wq *wq) * In the case of a dedicated kernel WQ that is not able to support * the PASID cap, then the configuration will be rejected. */ - wq->wqcfg->priv = !!(wq->type == IDXD_WQT_KERNEL); if (wq_dedicated(wq) && wq->wqcfg->pasid_en && !idxd_device_pasid_priv_enabled(idxd) && wq->type == IDXD_WQT_KERNEL) { @@ -953,7 +968,7 @@ static int idxd_wqs_setup(struct idxd_device *idxd) if (!wq->group) continue; - if (wq_shared(wq) && !device_swq_supported(idxd)) { + if (wq_shared(wq) && !wq_shared_supported(wq)) { idxd->cmd_status = IDXD_SCMD_WQ_NO_SWQ_SUPPORT; dev_warn(dev, "No shared wq support but configured.\n"); return -EINVAL; @@ -1018,6 +1033,9 @@ static int idxd_wq_load_config(struct idxd_wq *wq) wq->priority = wq->wqcfg->priority; + wq->max_xfer_bytes = 1ULL << wq->wqcfg->max_xfer_shift; + wq->max_batch_size = 1ULL << wq->wqcfg->max_batch_shift; + for (i = 0; i < WQCFG_STRIDES(idxd); i++) { wqcfg_offset = WQCFG_OFFSET(idxd, wq->id, i); dev_dbg(dev, "WQ[%d][%d][%#x]: %#x\n", wq->id, i, wqcfg_offset, wq->wqcfg->bits[i]); @@ -1161,7 +1179,9 @@ void idxd_wq_free_irq(struct idxd_wq *wq) struct idxd_device *idxd = wq->idxd; struct idxd_irq_entry *ie = &wq->ie; - synchronize_irq(ie->vector); + if (wq->type != IDXD_WQT_KERNEL) + return; + free_irq(ie->vector, ie); idxd_flush_pending_descs(ie); if (idxd->request_int_handles) @@ -1180,6 +1200,9 @@ int idxd_wq_request_irq(struct idxd_wq *wq) struct idxd_irq_entry *ie; int rc; + if (wq->type != IDXD_WQT_KERNEL) + return 0; + ie = &wq->ie; ie->vector = pci_irq_vector(pdev, ie->id); ie->pasid = device_pasid_enabled(idxd) ? idxd->pasid : INVALID_IOASID; @@ -1211,7 +1234,7 @@ err_irq: return rc; } -int __drv_enable_wq(struct idxd_wq *wq) +int drv_enable_wq(struct idxd_wq *wq) { struct idxd_device *idxd = wq->idxd; struct device *dev = &idxd->pdev->dev; @@ -1245,7 +1268,7 @@ int __drv_enable_wq(struct idxd_wq *wq) /* Shared WQ checks */ if (wq_shared(wq)) { - if (!device_swq_supported(idxd)) { + if (!wq_shared_supported(wq)) { idxd->cmd_status = IDXD_SCMD_WQ_NO_SVM; dev_dbg(dev, "PASID not enabled and shared wq.\n"); goto err; @@ -1265,6 +1288,29 @@ int __drv_enable_wq(struct idxd_wq *wq) } } + /* + * In the event that the WQ is configurable for pasid and priv bits. + * For kernel wq, the driver should setup the pasid, pasid_en, and priv bit. + * However, for non-kernel wq, the driver should only set the pasid_en bit for + * shared wq. A dedicated wq that is not 'kernel' type will configure pasid and + * pasid_en later on so there is no need to setup. + */ + if (test_bit(IDXD_FLAG_CONFIGURABLE, &idxd->flags)) { + int priv = 0; + + if (wq_pasid_enabled(wq)) { + if (is_idxd_wq_kernel(wq) || wq_shared(wq)) { + u32 pasid = wq_dedicated(wq) ? idxd->pasid : 0; + + __idxd_wq_set_pasid_locked(wq, pasid); + } + } + + if (is_idxd_wq_kernel(wq)) + priv = 1; + __idxd_wq_set_priv_locked(wq, priv); + } + rc = 0; spin_lock(&idxd->dev_lock); if (test_bit(IDXD_FLAG_CONFIGURABLE, &idxd->flags)) @@ -1289,8 +1335,36 @@ int __drv_enable_wq(struct idxd_wq *wq) } wq->client_count = 0; + + rc = idxd_wq_request_irq(wq); + if (rc < 0) { + idxd->cmd_status = IDXD_SCMD_WQ_IRQ_ERR; + dev_dbg(dev, "WQ %d irq setup failed: %d\n", wq->id, rc); + goto err_irq; + } + + rc = idxd_wq_alloc_resources(wq); + if (rc < 0) { + idxd->cmd_status = IDXD_SCMD_WQ_RES_ALLOC_ERR; + dev_dbg(dev, "WQ resource alloc failed\n"); + goto err_res_alloc; + } + + rc = idxd_wq_init_percpu_ref(wq); + if (rc < 0) { + idxd->cmd_status = IDXD_SCMD_PERCPU_ERR; + dev_dbg(dev, "percpu_ref setup failed\n"); + goto err_ref; + } + return 0; +err_ref: + idxd_wq_free_resources(wq); +err_res_alloc: + idxd_wq_free_irq(wq); +err_irq: + idxd_wq_unmap_portal(wq); err_map_portal: rc = idxd_wq_disable(wq, false); if (rc < 0) @@ -1299,17 +1373,7 @@ err: return rc; } -int drv_enable_wq(struct idxd_wq *wq) -{ - int rc; - - mutex_lock(&wq->wq_lock); - rc = __drv_enable_wq(wq); - mutex_unlock(&wq->wq_lock); - return rc; -} - -void __drv_disable_wq(struct idxd_wq *wq) +void drv_disable_wq(struct idxd_wq *wq) { struct idxd_device *idxd = wq->idxd; struct device *dev = &idxd->pdev->dev; @@ -1320,21 +1384,16 @@ void __drv_disable_wq(struct idxd_wq *wq) dev_warn(dev, "Clients has claim on wq %d: %d\n", wq->id, idxd_wq_refcount(wq)); + idxd_wq_free_resources(wq); idxd_wq_unmap_portal(wq); - idxd_wq_drain(wq); + idxd_wq_free_irq(wq); idxd_wq_reset(wq); - + percpu_ref_exit(&wq->wq_active); + wq->type = IDXD_WQT_NONE; wq->client_count = 0; } -void drv_disable_wq(struct idxd_wq *wq) -{ - mutex_lock(&wq->wq_lock); - __drv_disable_wq(wq); - mutex_unlock(&wq->wq_lock); -} - int idxd_device_drv_probe(struct idxd_dev *idxd_dev) { struct idxd_device *idxd = idxd_dev_to_idxd(idxd_dev); diff --git a/drivers/dma/idxd/dma.c b/drivers/dma/idxd/dma.c index bfff59617d04778c23600b5d271c46b75ee0654c..e0874cb4721c8a58e456935bd23bde0a50bab3c2 100644 --- a/drivers/dma/idxd/dma.c +++ b/drivers/dma/idxd/dma.c @@ -87,6 +87,27 @@ static inline void idxd_prep_desc_common(struct idxd_wq *wq, hw->completion_addr = compl; } +static struct dma_async_tx_descriptor * +idxd_dma_prep_interrupt(struct dma_chan *c, unsigned long flags) +{ + struct idxd_wq *wq = to_idxd_wq(c); + u32 desc_flags; + struct idxd_desc *desc; + + if (wq->state != IDXD_WQ_ENABLED) + return NULL; + + op_flag_setup(flags, &desc_flags); + desc = idxd_alloc_desc(wq, IDXD_OP_BLOCK); + if (IS_ERR(desc)) + return NULL; + + idxd_prep_desc_common(wq, desc->hw, DSA_OPCODE_NOOP, + 0, 0, 0, desc->compl_dma, desc_flags); + desc->txd.flags = flags; + return &desc->txd; +} + static struct dma_async_tx_descriptor * idxd_dma_submit_memcpy(struct dma_chan *c, dma_addr_t dma_dest, dma_addr_t dma_src, size_t len, unsigned long flags) @@ -193,10 +214,12 @@ int idxd_register_dma_device(struct idxd_device *idxd) INIT_LIST_HEAD(&dma->channels); dma->dev = dev; + dma_cap_set(DMA_INTERRUPT, dma->cap_mask); dma_cap_set(DMA_PRIVATE, dma->cap_mask); dma_cap_set(DMA_COMPLETION_NO_ORDER, dma->cap_mask); dma->device_release = idxd_dma_release; + dma->device_prep_dma_interrupt = idxd_dma_prep_interrupt; if (idxd->hw.opcap.bits[0] & IDXD_OPCAP_MEMMOVE) { dma_cap_set(DMA_MEMCPY, dma->cap_mask); dma->device_prep_dma_memcpy = idxd_dma_submit_memcpy; @@ -227,7 +250,7 @@ void idxd_unregister_dma_device(struct idxd_device *idxd) dma_async_device_unregister(&idxd->idxd_dma->dma); } -int idxd_register_dma_channel(struct idxd_wq *wq) +static int idxd_register_dma_channel(struct idxd_wq *wq) { struct idxd_device *idxd = wq->idxd; struct dma_device *dma = &idxd->idxd_dma->dma; @@ -264,7 +287,7 @@ int idxd_register_dma_channel(struct idxd_wq *wq) return 0; } -void idxd_unregister_dma_channel(struct idxd_wq *wq) +static void idxd_unregister_dma_channel(struct idxd_wq *wq) { struct idxd_dma_chan *idxd_chan = wq->idxd_chan; struct dma_chan *chan = &idxd_chan->chan; @@ -290,34 +313,13 @@ static int idxd_dmaengine_drv_probe(struct idxd_dev *idxd_dev) mutex_lock(&wq->wq_lock); wq->type = IDXD_WQT_KERNEL; - rc = idxd_wq_request_irq(wq); - if (rc < 0) { - idxd->cmd_status = IDXD_SCMD_WQ_IRQ_ERR; - dev_dbg(dev, "WQ %d irq setup failed: %d\n", wq->id, rc); - goto err_irq; - } - - rc = __drv_enable_wq(wq); + rc = drv_enable_wq(wq); if (rc < 0) { dev_dbg(dev, "Enable wq %d failed: %d\n", wq->id, rc); rc = -ENXIO; goto err; } - rc = idxd_wq_alloc_resources(wq); - if (rc < 0) { - idxd->cmd_status = IDXD_SCMD_WQ_RES_ALLOC_ERR; - dev_dbg(dev, "WQ resource alloc failed\n"); - goto err_res_alloc; - } - - rc = idxd_wq_init_percpu_ref(wq); - if (rc < 0) { - idxd->cmd_status = IDXD_SCMD_PERCPU_ERR; - dev_dbg(dev, "percpu_ref setup failed\n"); - goto err_ref; - } - rc = idxd_register_dma_channel(wq); if (rc < 0) { idxd->cmd_status = IDXD_SCMD_DMA_CHAN_ERR; @@ -330,15 +332,8 @@ static int idxd_dmaengine_drv_probe(struct idxd_dev *idxd_dev) return 0; err_dma: - __idxd_wq_quiesce(wq); - percpu_ref_exit(&wq->wq_active); -err_ref: - idxd_wq_free_resources(wq); -err_res_alloc: - __drv_disable_wq(wq); + drv_disable_wq(wq); err: - idxd_wq_free_irq(wq); -err_irq: wq->type = IDXD_WQT_NONE; mutex_unlock(&wq->wq_lock); return rc; @@ -351,11 +346,7 @@ static void idxd_dmaengine_drv_remove(struct idxd_dev *idxd_dev) mutex_lock(&wq->wq_lock); __idxd_wq_quiesce(wq); idxd_unregister_dma_channel(wq); - idxd_wq_free_resources(wq); - __drv_disable_wq(wq); - percpu_ref_exit(&wq->wq_active); - idxd_wq_free_irq(wq); - wq->type = IDXD_WQT_NONE; + drv_disable_wq(wq); mutex_unlock(&wq->wq_lock); } diff --git a/drivers/dma/idxd/idxd.h b/drivers/dma/idxd/idxd.h index da72eb15f610662cbf2168f76290d344509e4666..fed0dfc1eaa83766ed6ae1bc43de994bdba1122d 100644 --- a/drivers/dma/idxd/idxd.h +++ b/drivers/dma/idxd/idxd.h @@ -239,6 +239,7 @@ enum idxd_device_flag { IDXD_FLAG_CONFIGURABLE = 0, IDXD_FLAG_CMD_RUNNING, IDXD_FLAG_PASID_ENABLED, + IDXD_FLAG_USER_PASID_ENABLED, }; struct idxd_dma_dev { @@ -469,9 +470,20 @@ static inline bool device_pasid_enabled(struct idxd_device *idxd) return test_bit(IDXD_FLAG_PASID_ENABLED, &idxd->flags); } -static inline bool device_swq_supported(struct idxd_device *idxd) +static inline bool device_user_pasid_enabled(struct idxd_device *idxd) { - return (support_enqcmd && device_pasid_enabled(idxd)); + return test_bit(IDXD_FLAG_USER_PASID_ENABLED, &idxd->flags); +} + +static inline bool wq_pasid_enabled(struct idxd_wq *wq) +{ + return (is_idxd_wq_kernel(wq) && device_pasid_enabled(wq->idxd)) || + (is_idxd_wq_user(wq) && device_user_pasid_enabled(wq->idxd)); +} + +static inline bool wq_shared_supported(struct idxd_wq *wq) +{ + return (support_enqcmd && wq_pasid_enabled(wq)); } enum idxd_portal_prot { @@ -559,9 +571,7 @@ void idxd_unregister_idxd_drv(void); int idxd_device_drv_probe(struct idxd_dev *idxd_dev); void idxd_device_drv_remove(struct idxd_dev *idxd_dev); int drv_enable_wq(struct idxd_wq *wq); -int __drv_enable_wq(struct idxd_wq *wq); void drv_disable_wq(struct idxd_wq *wq); -void __drv_disable_wq(struct idxd_wq *wq); int idxd_device_init_reset(struct idxd_device *idxd); int idxd_device_enable(struct idxd_device *idxd); int idxd_device_disable(struct idxd_device *idxd); @@ -602,8 +612,6 @@ int idxd_enqcmds(struct idxd_wq *wq, void __iomem *portal, const void *desc); /* dmaengine */ int idxd_register_dma_device(struct idxd_device *idxd); void idxd_unregister_dma_device(struct idxd_device *idxd); -int idxd_register_dma_channel(struct idxd_wq *wq); -void idxd_unregister_dma_channel(struct idxd_wq *wq); void idxd_parse_completion_status(u8 status, enum dmaengine_tx_result *res); void idxd_dma_complete_txd(struct idxd_desc *desc, enum idxd_complete_type comp_type, bool free_desc); diff --git a/drivers/dma/idxd/init.c b/drivers/dma/idxd/init.c index 993a5dcca24f6c76cb0044e47492dc6653d27b06..355fb3ef4cbfaf1ce6d04892a9030aa21418813f 100644 --- a/drivers/dma/idxd/init.c +++ b/drivers/dma/idxd/init.c @@ -512,18 +512,15 @@ static int idxd_probe(struct idxd_device *idxd) dev_dbg(dev, "IDXD reset complete\n"); if (IS_ENABLED(CONFIG_INTEL_IDXD_SVM) && sva) { - rc = iommu_dev_enable_feature(dev, IOMMU_DEV_FEAT_SVA); - if (rc == 0) { - rc = idxd_enable_system_pasid(idxd); - if (rc < 0) { - iommu_dev_disable_feature(dev, IOMMU_DEV_FEAT_SVA); - dev_warn(dev, "Failed to enable PASID. No SVA support: %d\n", rc); - } else { - set_bit(IDXD_FLAG_PASID_ENABLED, &idxd->flags); - } - } else { - dev_warn(dev, "Unable to turn on SVA feature.\n"); - } + if (iommu_dev_enable_feature(dev, IOMMU_DEV_FEAT_SVA)) + dev_warn(dev, "Unable to turn on user SVA feature.\n"); + else + set_bit(IDXD_FLAG_USER_PASID_ENABLED, &idxd->flags); + + if (idxd_enable_system_pasid(idxd)) + dev_warn(dev, "No in-kernel DMA with PASID.\n"); + else + set_bit(IDXD_FLAG_PASID_ENABLED, &idxd->flags); } else if (!sva) { dev_warn(dev, "User forced SVA off via module param.\n"); } @@ -561,7 +558,8 @@ static int idxd_probe(struct idxd_device *idxd) err: if (device_pasid_enabled(idxd)) idxd_disable_system_pasid(idxd); - iommu_dev_disable_feature(dev, IOMMU_DEV_FEAT_SVA); + if (device_user_pasid_enabled(idxd)) + iommu_dev_disable_feature(dev, IOMMU_DEV_FEAT_SVA); return rc; } @@ -574,7 +572,8 @@ static void idxd_cleanup(struct idxd_device *idxd) idxd_cleanup_internals(idxd); if (device_pasid_enabled(idxd)) idxd_disable_system_pasid(idxd); - iommu_dev_disable_feature(dev, IOMMU_DEV_FEAT_SVA); + if (device_user_pasid_enabled(idxd)) + iommu_dev_disable_feature(dev, IOMMU_DEV_FEAT_SVA); } static int idxd_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) @@ -691,7 +690,8 @@ static void idxd_remove(struct pci_dev *pdev) free_irq(irq_entry->vector, irq_entry); pci_free_irq_vectors(pdev); pci_iounmap(pdev, idxd->reg_base); - iommu_dev_disable_feature(&pdev->dev, IOMMU_DEV_FEAT_SVA); + if (device_user_pasid_enabled(idxd)) + iommu_dev_disable_feature(&pdev->dev, IOMMU_DEV_FEAT_SVA); pci_disable_device(pdev); destroy_workqueue(idxd->wq); perfmon_pmu_remove(idxd); diff --git a/drivers/dma/idxd/registers.h b/drivers/dma/idxd/registers.h index aa642aecdc0b3ea451958bdfb830ce7600253de6..02449aa9c454f14e5c8b74d5dc06600dc0dd88a0 100644 --- a/drivers/dma/idxd/registers.h +++ b/drivers/dma/idxd/registers.h @@ -353,6 +353,7 @@ union wqcfg { } __packed; #define WQCFG_PASID_IDX 2 +#define WQCFG_PRIVL_IDX 2 #define WQCFG_OCCUP_IDX 6 #define WQCFG_OCCUP_MASK 0xffff diff --git a/drivers/dma/idxd/sysfs.c b/drivers/dma/idxd/sysfs.c index dfd549685c467ac796c76873b4dca559f33e622c..3f262a57441b47bda8a124462f48254b633d25d9 100644 --- a/drivers/dma/idxd/sysfs.c +++ b/drivers/dma/idxd/sysfs.c @@ -588,7 +588,7 @@ static ssize_t wq_mode_store(struct device *dev, if (sysfs_streq(buf, "dedicated")) { set_bit(WQ_FLAG_DEDICATED, &wq->flags); wq->threshold = 0; - } else if (sysfs_streq(buf, "shared") && device_swq_supported(idxd)) { + } else if (sysfs_streq(buf, "shared")) { clear_bit(WQ_FLAG_DEDICATED, &wq->flags); } else { return -EINVAL; @@ -832,6 +832,7 @@ static ssize_t wq_name_store(struct device *dev, size_t count) { struct idxd_wq *wq = confdev_to_wq(dev); + char *input, *pos; if (wq->state != IDXD_WQ_DISABLED) return -EPERM; @@ -846,9 +847,14 @@ static ssize_t wq_name_store(struct device *dev, if (wq->type == IDXD_WQT_KERNEL && device_pasid_enabled(wq->idxd)) return -EOPNOTSUPP; + input = kstrndup(buf, count, GFP_KERNEL); + if (!input) + return -ENOMEM; + + pos = strim(input); memset(wq->name, 0, WQ_NAME_SIZE + 1); - strncpy(wq->name, buf, WQ_NAME_SIZE); - strreplace(wq->name, '\n', '\0'); + sprintf(wq->name, "%s", pos); + kfree(input); return count; } diff --git a/drivers/dma/mediatek/mtk-cqdma.c b/drivers/dma/mediatek/mtk-cqdma.c index 41ef9f15d3d596fcc2dbf31a72d5473a84639813..f8847c48ba0388f0cacb3d327e0b5bfeb277510f 100644 --- a/drivers/dma/mediatek/mtk-cqdma.c +++ b/drivers/dma/mediatek/mtk-cqdma.c @@ -751,7 +751,6 @@ static int mtk_cqdma_probe(struct platform_device *pdev) struct mtk_cqdma_device *cqdma; struct mtk_cqdma_vchan *vc; struct dma_device *dd; - struct resource *res; int err; u32 i; @@ -824,13 +823,10 @@ static int mtk_cqdma_probe(struct platform_device *pdev) return PTR_ERR(cqdma->pc[i]->base); /* allocate IRQ resource */ - res = platform_get_resource(pdev, IORESOURCE_IRQ, i); - if (!res) { - dev_err(&pdev->dev, "No irq resource for %s\n", - dev_name(&pdev->dev)); - return -EINVAL; - } - cqdma->pc[i]->irq = res->start; + err = platform_get_irq(pdev, i); + if (err < 0) + return err; + cqdma->pc[i]->irq = err; err = devm_request_irq(&pdev->dev, cqdma->pc[i]->irq, mtk_cqdma_irq, 0, dev_name(&pdev->dev), diff --git a/drivers/dma/mediatek/mtk-hsdma.c b/drivers/dma/mediatek/mtk-hsdma.c index 6ad8afbb95f2b3d4dc33cda0d4bb4bbd1e2550d8..9ebd9231f62f447f0aa173762f22ef2fb2c3fe20 100644 --- a/drivers/dma/mediatek/mtk-hsdma.c +++ b/drivers/dma/mediatek/mtk-hsdma.c @@ -601,7 +601,7 @@ static void mtk_hsdma_free_rooms_in_ring(struct mtk_hsdma_device *hsdma) cb->flag = 0; } - cb->vd = 0; + cb->vd = NULL; /* * Recycle the RXD with the helper WRITE_ONCE that can ensure @@ -923,13 +923,10 @@ static int mtk_hsdma_probe(struct platform_device *pdev) return PTR_ERR(hsdma->clk); } - res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (!res) { - dev_err(&pdev->dev, "No irq resource for %s\n", - dev_name(&pdev->dev)); - return -EINVAL; - } - hsdma->irq = res->start; + err = platform_get_irq(pdev, 0); + if (err < 0) + return err; + hsdma->irq = err; refcount_set(&hsdma->pc_refcnt, 0); spin_lock_init(&hsdma->lock); diff --git a/drivers/dma/mmp_pdma.c b/drivers/dma/mmp_pdma.c index 5a53d7fcef0180737ad4f20fbbb74b09deefa7e5..e8d71b35593e38d117579e24fe77a249781e7317 100644 --- a/drivers/dma/mmp_pdma.c +++ b/drivers/dma/mmp_pdma.c @@ -1043,13 +1043,17 @@ static int mmp_pdma_probe(struct platform_device *op) return PTR_ERR(pdev->base); of_id = of_match_device(mmp_pdma_dt_ids, pdev->dev); - if (of_id) - of_property_read_u32(pdev->dev->of_node, "#dma-channels", - &dma_channels); - else if (pdata && pdata->dma_channels) + if (of_id) { + /* Parse new and deprecated dma-channels properties */ + if (of_property_read_u32(pdev->dev->of_node, "dma-channels", + &dma_channels)) + of_property_read_u32(pdev->dev->of_node, "#dma-channels", + &dma_channels); + } else if (pdata && pdata->dma_channels) { dma_channels = pdata->dma_channels; - else + } else { dma_channels = 32; /* default 32 channel */ + } pdev->dma_channels = dma_channels; for (i = 0; i < dma_channels; i++) { diff --git a/drivers/dma/mv_xor_v2.c b/drivers/dma/mv_xor_v2.c index 9c8b4084ba2f37e7f6d7e443dc2cb92f5281abd9..f10b29034da18729722bfde441c2120087d8e7d2 100644 --- a/drivers/dma/mv_xor_v2.c +++ b/drivers/dma/mv_xor_v2.c @@ -591,14 +591,14 @@ static void mv_xor_v2_tasklet(struct tasklet_struct *t) dma_run_dependencies(&next_pending_sw_desc->async_tx); /* Lock the channel */ - spin_lock_bh(&xor_dev->lock); + spin_lock(&xor_dev->lock); /* add the SW descriptor to the free descriptors list */ list_add(&next_pending_sw_desc->free_list, &xor_dev->free_sw_desc); /* Release the channel */ - spin_unlock_bh(&xor_dev->lock); + spin_unlock(&xor_dev->lock); /* increment the next descriptor */ pending_ptr++; diff --git a/drivers/dma/nbpfaxi.c b/drivers/dma/nbpfaxi.c index 9c52c57919c615e36ea79d88930f1262bd79abe4..a7063e9cd551cf230583776c2acc8f8afd6eed66 100644 --- a/drivers/dma/nbpfaxi.c +++ b/drivers/dma/nbpfaxi.c @@ -1294,7 +1294,7 @@ static int nbpf_probe(struct platform_device *pdev) struct device_node *np = dev->of_node; struct nbpf_device *nbpf; struct dma_device *dma_dev; - struct resource *iomem, *irq_res; + struct resource *iomem; const struct nbpf_config *cfg; int num_channels; int ret, irq, eirq, i; @@ -1335,13 +1335,11 @@ static int nbpf_probe(struct platform_device *pdev) nbpf->config = cfg; for (i = 0; irqs < ARRAY_SIZE(irqbuf); i++) { - irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, i); - if (!irq_res) - break; - - for (irq = irq_res->start; irq <= irq_res->end; - irq++, irqs++) - irqbuf[irqs] = irq; + irq = platform_get_irq_optional(pdev, i); + if (irq < 0 && irq != -ENXIO) + return irq; + if (irq > 0) + irqbuf[irqs++] = irq; } /* diff --git a/drivers/dma/plx_dma.c b/drivers/dma/plx_dma.c index 1ffcb5ca97884b7037bf93cdf09a66087746e14f..12725fa1655ff104e4264b148c7252a5bfb7f25a 100644 --- a/drivers/dma/plx_dma.c +++ b/drivers/dma/plx_dma.c @@ -137,7 +137,7 @@ static void plx_dma_process_desc(struct plx_dma_dev *plxdev) struct plx_dma_desc *desc; u32 flags; - spin_lock_bh(&plxdev->ring_lock); + spin_lock(&plxdev->ring_lock); while (plxdev->tail != plxdev->head) { desc = plx_dma_get_desc(plxdev, plxdev->tail); @@ -165,7 +165,7 @@ static void plx_dma_process_desc(struct plx_dma_dev *plxdev) plxdev->tail++; } - spin_unlock_bh(&plxdev->ring_lock); + spin_unlock(&plxdev->ring_lock); } static void plx_dma_abort_desc(struct plx_dma_dev *plxdev) diff --git a/drivers/dma/ptdma/ptdma-dev.c b/drivers/dma/ptdma/ptdma-dev.c index daafea5bc35d9f582dcd72e9b87b72437a72c92a..377da23012ac23e826234673c1095f8dc70aefa3 100644 --- a/drivers/dma/ptdma/ptdma-dev.c +++ b/drivers/dma/ptdma/ptdma-dev.c @@ -100,6 +100,7 @@ int pt_core_perform_passthru(struct pt_cmd_queue *cmd_q, struct pt_passthru_engine *pt_engine) { struct ptdma_desc desc; + struct pt_device *pt = container_of(cmd_q, struct pt_device, cmd_q); cmd_q->cmd_error = 0; cmd_q->total_pt_ops++; @@ -111,17 +112,12 @@ int pt_core_perform_passthru(struct pt_cmd_queue *cmd_q, desc.dst_lo = lower_32_bits(pt_engine->dst_dma); desc.dw5.dst_hi = upper_32_bits(pt_engine->dst_dma); - return pt_core_execute_cmd(&desc, cmd_q); -} - -static inline void pt_core_disable_queue_interrupts(struct pt_device *pt) -{ - iowrite32(0, pt->cmd_q.reg_control + 0x000C); -} + if (cmd_q->int_en) + pt_core_enable_queue_interrupts(pt); + else + pt_core_disable_queue_interrupts(pt); -static inline void pt_core_enable_queue_interrupts(struct pt_device *pt) -{ - iowrite32(SUPPORTED_INTERRUPTS, pt->cmd_q.reg_control + 0x000C); + return pt_core_execute_cmd(&desc, cmd_q); } static void pt_do_cmd_complete(unsigned long data) @@ -144,14 +140,10 @@ static void pt_do_cmd_complete(unsigned long data) cmd->pt_cmd_callback(cmd->data, cmd->ret); } -static irqreturn_t pt_core_irq_handler(int irq, void *data) +void pt_check_status_trans(struct pt_device *pt, struct pt_cmd_queue *cmd_q) { - struct pt_device *pt = data; - struct pt_cmd_queue *cmd_q = &pt->cmd_q; u32 status; - pt_core_disable_queue_interrupts(pt); - pt->total_interrupts++; status = ioread32(cmd_q->reg_control + 0x0010); if (status) { cmd_q->int_status = status; @@ -162,11 +154,21 @@ static irqreturn_t pt_core_irq_handler(int irq, void *data) if ((status & INT_ERROR) && !cmd_q->cmd_error) cmd_q->cmd_error = CMD_Q_ERROR(cmd_q->q_status); - /* Acknowledge the interrupt */ + /* Acknowledge the completion */ iowrite32(status, cmd_q->reg_control + 0x0010); - pt_core_enable_queue_interrupts(pt); pt_do_cmd_complete((ulong)&pt->tdata); } +} + +static irqreturn_t pt_core_irq_handler(int irq, void *data) +{ + struct pt_device *pt = data; + struct pt_cmd_queue *cmd_q = &pt->cmd_q; + + pt_core_disable_queue_interrupts(pt); + pt->total_interrupts++; + pt_check_status_trans(pt, cmd_q); + pt_core_enable_queue_interrupts(pt); return IRQ_HANDLED; } diff --git a/drivers/dma/ptdma/ptdma-dmaengine.c b/drivers/dma/ptdma/ptdma-dmaengine.c index 91b93e8d97799c93eaa2b5bd22c9a737d2e59f42..cc22d162ce250095b06d23273ce1caa011a9cc6f 100644 --- a/drivers/dma/ptdma/ptdma-dmaengine.c +++ b/drivers/dma/ptdma/ptdma-dmaengine.c @@ -171,6 +171,7 @@ static struct pt_dma_desc *pt_alloc_dma_desc(struct pt_dma_chan *chan, vchan_tx_prep(&chan->vc, &desc->vd, flags); desc->pt = chan->pt; + desc->pt->cmd_q.int_en = !!(flags & DMA_PREP_INTERRUPT); desc->issued_to_hw = 0; desc->status = DMA_IN_PROGRESS; @@ -257,6 +258,17 @@ static void pt_issue_pending(struct dma_chan *dma_chan) pt_cmd_callback(desc, 0); } +static enum dma_status +pt_tx_status(struct dma_chan *c, dma_cookie_t cookie, + struct dma_tx_state *txstate) +{ + struct pt_device *pt = to_pt_chan(c)->pt; + struct pt_cmd_queue *cmd_q = &pt->cmd_q; + + pt_check_status_trans(pt, cmd_q); + return dma_cookie_status(c, cookie, txstate); +} + static int pt_pause(struct dma_chan *dma_chan) { struct pt_dma_chan *chan = to_pt_chan(dma_chan); @@ -291,8 +303,10 @@ static int pt_terminate_all(struct dma_chan *dma_chan) { struct pt_dma_chan *chan = to_pt_chan(dma_chan); unsigned long flags; + struct pt_cmd_queue *cmd_q = &chan->pt->cmd_q; LIST_HEAD(head); + iowrite32(SUPPORTED_INTERRUPTS, cmd_q->reg_control + 0x0010); spin_lock_irqsave(&chan->vc.lock, flags); vchan_get_all_descriptors(&chan->vc, &head); spin_unlock_irqrestore(&chan->vc.lock, flags); @@ -362,7 +376,7 @@ int pt_dmaengine_register(struct pt_device *pt) dma_dev->device_prep_dma_memcpy = pt_prep_dma_memcpy; dma_dev->device_prep_dma_interrupt = pt_prep_dma_interrupt; dma_dev->device_issue_pending = pt_issue_pending; - dma_dev->device_tx_status = dma_cookie_status; + dma_dev->device_tx_status = pt_tx_status; dma_dev->device_pause = pt_pause; dma_dev->device_resume = pt_resume; dma_dev->device_terminate_all = pt_terminate_all; diff --git a/drivers/dma/ptdma/ptdma.h b/drivers/dma/ptdma/ptdma.h index afbf192c923056264e237a831ca72b07298685e6..d093c43b7d1343b11227e14b815149085a32696f 100644 --- a/drivers/dma/ptdma/ptdma.h +++ b/drivers/dma/ptdma/ptdma.h @@ -206,6 +206,9 @@ struct pt_cmd_queue { unsigned int active; unsigned int suspended; + /* Interrupt flag */ + bool int_en; + /* Register addresses for queue */ void __iomem *reg_control; u32 qcontrol; /* Cached control register */ @@ -318,7 +321,17 @@ void pt_core_destroy(struct pt_device *pt); int pt_core_perform_passthru(struct pt_cmd_queue *cmd_q, struct pt_passthru_engine *pt_engine); +void pt_check_status_trans(struct pt_device *pt, struct pt_cmd_queue *cmd_q); void pt_start_queue(struct pt_cmd_queue *cmd_q); void pt_stop_queue(struct pt_cmd_queue *cmd_q); +static inline void pt_core_disable_queue_interrupts(struct pt_device *pt) +{ + iowrite32(0, pt->cmd_q.reg_control + 0x000C); +} + +static inline void pt_core_enable_queue_interrupts(struct pt_device *pt) +{ + iowrite32(SUPPORTED_INTERRUPTS, pt->cmd_q.reg_control + 0x000C); +} #endif diff --git a/drivers/dma/pxa_dma.c b/drivers/dma/pxa_dma.c index 6078cc81892e4fae80daca186eb0c72696b32c80..e7034f6f3994a4833b691f096d43a7362e93832e 100644 --- a/drivers/dma/pxa_dma.c +++ b/drivers/dma/pxa_dma.c @@ -1365,10 +1365,17 @@ static int pxad_probe(struct platform_device *op) of_id = of_match_device(pxad_dt_ids, &op->dev); if (of_id) { - of_property_read_u32(op->dev.of_node, "#dma-channels", - &dma_channels); - ret = of_property_read_u32(op->dev.of_node, "#dma-requests", + /* Parse new and deprecated dma-channels properties */ + if (of_property_read_u32(op->dev.of_node, "dma-channels", + &dma_channels)) + of_property_read_u32(op->dev.of_node, "#dma-channels", + &dma_channels); + /* Parse new and deprecated dma-requests properties */ + ret = of_property_read_u32(op->dev.of_node, "dma-requests", &nb_requestors); + if (ret) + ret = of_property_read_u32(op->dev.of_node, "#dma-requests", + &nb_requestors); if (ret) { dev_warn(pdev->slave.dev, "#dma-requests set to default 32 as missing in OF: %d", diff --git a/drivers/dma/qcom/gpi.c b/drivers/dma/qcom/gpi.c index 94f3648f7483b3458d194b8f67dab6aa5bd31e7b..8f0c9c4e2efda0820e48db5a5c19bd8906d84f3c 100644 --- a/drivers/dma/qcom/gpi.c +++ b/drivers/dma/qcom/gpi.c @@ -1754,10 +1754,14 @@ static int gpi_create_spi_tre(struct gchan *chan, struct gpi_desc *desc, tre->dword[2] = u32_encode_bits(spi->rx_len, TRE_RX_LEN); tre->dword[3] = u32_encode_bits(TRE_TYPE_GO, TRE_FLAGS_TYPE); - if (spi->cmd == SPI_RX) + if (spi->cmd == SPI_RX) { tre->dword[3] |= u32_encode_bits(1, TRE_FLAGS_IEOB); - else + } else if (spi->cmd == SPI_TX) { + tre->dword[3] |= u32_encode_bits(1, TRE_FLAGS_CHAIN); + } else { /* SPI_DUPLEX */ tre->dword[3] |= u32_encode_bits(1, TRE_FLAGS_CHAIN); + tre->dword[3] |= u32_encode_bits(1, TRE_FLAGS_LINK); + } } /* create the dma tre */ @@ -2148,6 +2152,7 @@ static int gpi_probe(struct platform_device *pdev) { struct gpi_dev *gpi_dev; unsigned int i; + u32 ee_offset; int ret; gpi_dev = devm_kzalloc(&pdev->dev, sizeof(*gpi_dev), GFP_KERNEL); @@ -2175,6 +2180,9 @@ static int gpi_probe(struct platform_device *pdev) return ret; } + ee_offset = (uintptr_t)device_get_match_data(gpi_dev->dev); + gpi_dev->ee_base = gpi_dev->ee_base - ee_offset; + gpi_dev->ev_factor = EV_FACTOR; ret = dma_set_mask(gpi_dev->dev, DMA_BIT_MASK(64)); @@ -2278,9 +2286,12 @@ static int gpi_probe(struct platform_device *pdev) } static const struct of_device_id gpi_of_match[] = { - { .compatible = "qcom,sdm845-gpi-dma" }, - { .compatible = "qcom,sm8150-gpi-dma" }, - { .compatible = "qcom,sm8250-gpi-dma" }, + { .compatible = "qcom,sc7280-gpi-dma", .data = (void *)0x10000 }, + { .compatible = "qcom,sdm845-gpi-dma", .data = (void *)0x0 }, + { .compatible = "qcom,sm8150-gpi-dma", .data = (void *)0x0 }, + { .compatible = "qcom,sm8250-gpi-dma", .data = (void *)0x0 }, + { .compatible = "qcom,sm8350-gpi-dma", .data = (void *)0x10000 }, + { .compatible = "qcom,sm8450-gpi-dma", .data = (void *)0x10000 }, { }, }; MODULE_DEVICE_TABLE(of, gpi_of_match); diff --git a/drivers/dma/qcom/hidma.c b/drivers/dma/qcom/hidma.c index 51587cf8196b11eb8001cc974e0f2259ffa25150..210f1a9eb44145fb8b7a848cecb395bf6e93e9da 100644 --- a/drivers/dma/qcom/hidma.c +++ b/drivers/dma/qcom/hidma.c @@ -431,6 +431,7 @@ hidma_prep_dma_memset(struct dma_chan *dmach, dma_addr_t dest, int value, struct hidma_desc *mdesc = NULL; struct hidma_dev *mdma = mchan->dmadev; unsigned long irqflags; + u64 byte_pattern, fill_pattern; /* Get free descriptor */ spin_lock_irqsave(&mchan->lock, irqflags); @@ -443,9 +444,19 @@ hidma_prep_dma_memset(struct dma_chan *dmach, dma_addr_t dest, int value, if (!mdesc) return NULL; + byte_pattern = (char)value; + fill_pattern = (byte_pattern << 56) | + (byte_pattern << 48) | + (byte_pattern << 40) | + (byte_pattern << 32) | + (byte_pattern << 24) | + (byte_pattern << 16) | + (byte_pattern << 8) | + byte_pattern; + mdesc->desc.flags = flags; hidma_ll_set_transfer_params(mdma->lldev, mdesc->tre_ch, - value, dest, len, flags, + fill_pattern, dest, len, flags, HIDMA_TRE_MEMSET); /* Place descriptor in prepared list */ diff --git a/drivers/dma/sf-pdma/sf-pdma.c b/drivers/dma/sf-pdma/sf-pdma.c index f12606aeff87c918ef2ec6b74f46fb05324c789d..db5a4ef7607734cf0576948c0029393ef516bd5b 100644 --- a/drivers/dma/sf-pdma/sf-pdma.c +++ b/drivers/dma/sf-pdma/sf-pdma.c @@ -482,23 +482,30 @@ static void sf_pdma_setup_chans(struct sf_pdma *pdma) static int sf_pdma_probe(struct platform_device *pdev) { struct sf_pdma *pdma; - struct sf_pdma_chan *chan; struct resource *res; - int len, chans; - int ret; + int ret, n_chans; const enum dma_slave_buswidth widths = DMA_SLAVE_BUSWIDTH_1_BYTE | DMA_SLAVE_BUSWIDTH_2_BYTES | DMA_SLAVE_BUSWIDTH_4_BYTES | DMA_SLAVE_BUSWIDTH_8_BYTES | DMA_SLAVE_BUSWIDTH_16_BYTES | DMA_SLAVE_BUSWIDTH_32_BYTES | DMA_SLAVE_BUSWIDTH_64_BYTES; - chans = PDMA_NR_CH; - len = sizeof(*pdma) + sizeof(*chan) * chans; - pdma = devm_kzalloc(&pdev->dev, len, GFP_KERNEL); + ret = of_property_read_u32(pdev->dev.of_node, "dma-channels", &n_chans); + if (ret) { + /* backwards-compatibility for no dma-channels property */ + dev_dbg(&pdev->dev, "set number of channels to default value: 4\n"); + n_chans = PDMA_MAX_NR_CH; + } else if (n_chans > PDMA_MAX_NR_CH) { + dev_err(&pdev->dev, "the number of channels exceeds the maximum\n"); + return -EINVAL; + } + + pdma = devm_kzalloc(&pdev->dev, struct_size(pdma, chans, n_chans), + GFP_KERNEL); if (!pdma) return -ENOMEM; - pdma->n_chans = chans; + pdma->n_chans = n_chans; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); pdma->membase = devm_ioremap_resource(&pdev->dev, res); @@ -556,7 +563,7 @@ static int sf_pdma_remove(struct platform_device *pdev) struct sf_pdma_chan *ch; int i; - for (i = 0; i < PDMA_NR_CH; i++) { + for (i = 0; i < pdma->n_chans; i++) { ch = &pdma->chans[i]; devm_free_irq(&pdev->dev, ch->txirq, ch); @@ -574,6 +581,7 @@ static int sf_pdma_remove(struct platform_device *pdev) static const struct of_device_id sf_pdma_dt_ids[] = { { .compatible = "sifive,fu540-c000-pdma" }, + { .compatible = "sifive,pdma0" }, {}, }; MODULE_DEVICE_TABLE(of, sf_pdma_dt_ids); diff --git a/drivers/dma/sf-pdma/sf-pdma.h b/drivers/dma/sf-pdma/sf-pdma.h index 0c20167b097d0eaf08434a3fc3338dea11459545..dcb3687bd5da26341f32d551c786717c1d2da4ce 100644 --- a/drivers/dma/sf-pdma/sf-pdma.h +++ b/drivers/dma/sf-pdma/sf-pdma.h @@ -22,11 +22,7 @@ #include "../dmaengine.h" #include "../virt-dma.h" -#define PDMA_NR_CH 4 - -#if (PDMA_NR_CH != 4) -#error "Please define PDMA_NR_CH to 4" -#endif +#define PDMA_MAX_NR_CH 4 #define PDMA_BASE_ADDR 0x3000000 #define PDMA_CHAN_OFFSET 0x1000 @@ -118,7 +114,7 @@ struct sf_pdma { void __iomem *membase; void __iomem *mappedbase; u32 n_chans; - struct sf_pdma_chan chans[PDMA_NR_CH]; + struct sf_pdma_chan chans[]; }; #endif /* _SF_PDMA_H */ diff --git a/drivers/dma/sh/Kconfig b/drivers/dma/sh/Kconfig index b35d705f79e7e39a13a16793bb222876842b3138..c0b2997ab7fd93c0680cb6e1dbf0afd906d04f23 100644 --- a/drivers/dma/sh/Kconfig +++ b/drivers/dma/sh/Kconfig @@ -50,7 +50,7 @@ config RENESAS_USB_DMAC config RZ_DMAC tristate "Renesas RZ/{G2L,V2L} DMA Controller" - depends on ARCH_R9A07G044 || ARCH_R9A07G054 || COMPILE_TEST + depends on ARCH_RZG2L || COMPILE_TEST select RENESAS_DMA select DMA_VIRTUAL_CHANNELS help diff --git a/drivers/dma/sprd-dma.c b/drivers/dma/sprd-dma.c index 7f158ef5672d79efba7beaf5fe98adafa4f73be0..2138b80435abfd98cde49d31d780e01af67f2385 100644 --- a/drivers/dma/sprd-dma.c +++ b/drivers/dma/sprd-dma.c @@ -1117,7 +1117,11 @@ static int sprd_dma_probe(struct platform_device *pdev) u32 chn_count; int ret, i; - ret = device_property_read_u32(&pdev->dev, "#dma-channels", &chn_count); + /* Parse new and deprecated dma-channels properties */ + ret = device_property_read_u32(&pdev->dev, "dma-channels", &chn_count); + if (ret) + ret = device_property_read_u32(&pdev->dev, "#dma-channels", + &chn_count); if (ret) { dev_err(&pdev->dev, "get dma channels count failed\n"); return ret; diff --git a/drivers/dma/stm32-dma.c b/drivers/dma/stm32-dma.c index d2365fab1b7a4e203bab3f342b4917f4895f7976..adb25a11c70fe00ae170461b9704bf16f1244c91 100644 --- a/drivers/dma/stm32-dma.c +++ b/drivers/dma/stm32-dma.c @@ -208,6 +208,7 @@ struct stm32_dma_chan { u32 threshold; u32 mem_burst; u32 mem_width; + enum dma_status status; }; struct stm32_dma_device { @@ -485,6 +486,7 @@ static void stm32_dma_stop(struct stm32_dma_chan *chan) } chan->busy = false; + chan->status = DMA_COMPLETE; } static int stm32_dma_terminate_all(struct dma_chan *c) @@ -535,6 +537,13 @@ static void stm32_dma_dump_reg(struct stm32_dma_chan *chan) dev_dbg(chan2dev(chan), "SFCR: 0x%08x\n", sfcr); } +static void stm32_dma_sg_inc(struct stm32_dma_chan *chan) +{ + chan->next_sg++; + if (chan->desc->cyclic && (chan->next_sg == chan->desc->num_sgs)) + chan->next_sg = 0; +} + static void stm32_dma_configure_next_sg(struct stm32_dma_chan *chan); static void stm32_dma_start_transfer(struct stm32_dma_chan *chan) @@ -575,7 +584,7 @@ static void stm32_dma_start_transfer(struct stm32_dma_chan *chan) stm32_dma_write(dmadev, STM32_DMA_SM1AR(chan->id), reg->dma_sm1ar); stm32_dma_write(dmadev, STM32_DMA_SNDTR(chan->id), reg->dma_sndtr); - chan->next_sg++; + stm32_dma_sg_inc(chan); /* Clear interrupt status if it is there */ status = stm32_dma_irq_status(chan); @@ -588,11 +597,11 @@ static void stm32_dma_start_transfer(struct stm32_dma_chan *chan) stm32_dma_dump_reg(chan); /* Start DMA */ + chan->busy = true; + chan->status = DMA_IN_PROGRESS; reg->dma_scr |= STM32_DMA_SCR_EN; stm32_dma_write(dmadev, STM32_DMA_SCR(chan->id), reg->dma_scr); - chan->busy = true; - dev_dbg(chan2dev(chan), "vchan %pK: started\n", &chan->vchan); } @@ -605,41 +614,131 @@ static void stm32_dma_configure_next_sg(struct stm32_dma_chan *chan) id = chan->id; dma_scr = stm32_dma_read(dmadev, STM32_DMA_SCR(id)); - if (dma_scr & STM32_DMA_SCR_DBM) { - if (chan->next_sg == chan->desc->num_sgs) - chan->next_sg = 0; + sg_req = &chan->desc->sg_req[chan->next_sg]; - sg_req = &chan->desc->sg_req[chan->next_sg]; + if (dma_scr & STM32_DMA_SCR_CT) { + dma_sm0ar = sg_req->chan_reg.dma_sm0ar; + stm32_dma_write(dmadev, STM32_DMA_SM0AR(id), dma_sm0ar); + dev_dbg(chan2dev(chan), "CT=1 <=> SM0AR: 0x%08x\n", + stm32_dma_read(dmadev, STM32_DMA_SM0AR(id))); + } else { + dma_sm1ar = sg_req->chan_reg.dma_sm1ar; + stm32_dma_write(dmadev, STM32_DMA_SM1AR(id), dma_sm1ar); + dev_dbg(chan2dev(chan), "CT=0 <=> SM1AR: 0x%08x\n", + stm32_dma_read(dmadev, STM32_DMA_SM1AR(id))); + } +} - if (dma_scr & STM32_DMA_SCR_CT) { - dma_sm0ar = sg_req->chan_reg.dma_sm0ar; - stm32_dma_write(dmadev, STM32_DMA_SM0AR(id), dma_sm0ar); - dev_dbg(chan2dev(chan), "CT=1 <=> SM0AR: 0x%08x\n", - stm32_dma_read(dmadev, STM32_DMA_SM0AR(id))); - } else { - dma_sm1ar = sg_req->chan_reg.dma_sm1ar; - stm32_dma_write(dmadev, STM32_DMA_SM1AR(id), dma_sm1ar); - dev_dbg(chan2dev(chan), "CT=0 <=> SM1AR: 0x%08x\n", - stm32_dma_read(dmadev, STM32_DMA_SM1AR(id))); - } +static void stm32_dma_handle_chan_paused(struct stm32_dma_chan *chan) +{ + struct stm32_dma_device *dmadev = stm32_dma_get_dev(chan); + u32 dma_scr; + + /* + * Read and store current remaining data items and peripheral/memory addresses to be + * updated on resume + */ + dma_scr = stm32_dma_read(dmadev, STM32_DMA_SCR(chan->id)); + /* + * Transfer can be paused while between a previous resume and reconfiguration on transfer + * complete. If transfer is cyclic and CIRC and DBM have been deactivated for resume, need + * to set it here in SCR backup to ensure a good reconfiguration on transfer complete. + */ + if (chan->desc && chan->desc->cyclic) { + if (chan->desc->num_sgs == 1) + dma_scr |= STM32_DMA_SCR_CIRC; + else + dma_scr |= STM32_DMA_SCR_DBM; + } + chan->chan_reg.dma_scr = dma_scr; + + /* + * Need to temporarily deactivate CIRC/DBM until next Transfer Complete interrupt, otherwise + * on resume NDTR autoreload value will be wrong (lower than the initial period length) + */ + if (chan->desc && chan->desc->cyclic) { + dma_scr &= ~(STM32_DMA_SCR_DBM | STM32_DMA_SCR_CIRC); + stm32_dma_write(dmadev, STM32_DMA_SCR(chan->id), dma_scr); + } + + chan->chan_reg.dma_sndtr = stm32_dma_read(dmadev, STM32_DMA_SNDTR(chan->id)); + + dev_dbg(chan2dev(chan), "vchan %pK: paused\n", &chan->vchan); +} + +static void stm32_dma_post_resume_reconfigure(struct stm32_dma_chan *chan) +{ + struct stm32_dma_device *dmadev = stm32_dma_get_dev(chan); + struct stm32_dma_sg_req *sg_req; + u32 dma_scr, status, id; + + id = chan->id; + dma_scr = stm32_dma_read(dmadev, STM32_DMA_SCR(id)); + + /* Clear interrupt status if it is there */ + status = stm32_dma_irq_status(chan); + if (status) + stm32_dma_irq_clear(chan, status); + + if (!chan->next_sg) + sg_req = &chan->desc->sg_req[chan->desc->num_sgs - 1]; + else + sg_req = &chan->desc->sg_req[chan->next_sg - 1]; + + /* Reconfigure NDTR with the initial value */ + stm32_dma_write(dmadev, STM32_DMA_SNDTR(chan->id), sg_req->chan_reg.dma_sndtr); + + /* Restore SPAR */ + stm32_dma_write(dmadev, STM32_DMA_SPAR(id), sg_req->chan_reg.dma_spar); + + /* Restore SM0AR/SM1AR whatever DBM/CT as they may have been modified */ + stm32_dma_write(dmadev, STM32_DMA_SM0AR(id), sg_req->chan_reg.dma_sm0ar); + stm32_dma_write(dmadev, STM32_DMA_SM1AR(id), sg_req->chan_reg.dma_sm1ar); + + /* Reactivate CIRC/DBM if needed */ + if (chan->chan_reg.dma_scr & STM32_DMA_SCR_DBM) { + dma_scr |= STM32_DMA_SCR_DBM; + /* Restore CT */ + if (chan->chan_reg.dma_scr & STM32_DMA_SCR_CT) + dma_scr &= ~STM32_DMA_SCR_CT; + else + dma_scr |= STM32_DMA_SCR_CT; + } else if (chan->chan_reg.dma_scr & STM32_DMA_SCR_CIRC) { + dma_scr |= STM32_DMA_SCR_CIRC; } + stm32_dma_write(dmadev, STM32_DMA_SCR(chan->id), dma_scr); + + stm32_dma_configure_next_sg(chan); + + stm32_dma_dump_reg(chan); + + dma_scr |= STM32_DMA_SCR_EN; + stm32_dma_write(dmadev, STM32_DMA_SCR(chan->id), dma_scr); + + dev_dbg(chan2dev(chan), "vchan %pK: reconfigured after pause/resume\n", &chan->vchan); } -static void stm32_dma_handle_chan_done(struct stm32_dma_chan *chan) +static void stm32_dma_handle_chan_done(struct stm32_dma_chan *chan, u32 scr) { - if (chan->desc) { - if (chan->desc->cyclic) { - vchan_cyclic_callback(&chan->desc->vdesc); - chan->next_sg++; + if (!chan->desc) + return; + + if (chan->desc->cyclic) { + vchan_cyclic_callback(&chan->desc->vdesc); + stm32_dma_sg_inc(chan); + /* cyclic while CIRC/DBM disable => post resume reconfiguration needed */ + if (!(scr & (STM32_DMA_SCR_CIRC | STM32_DMA_SCR_DBM))) + stm32_dma_post_resume_reconfigure(chan); + else if (scr & STM32_DMA_SCR_DBM) stm32_dma_configure_next_sg(chan); - } else { - chan->busy = false; - if (chan->next_sg == chan->desc->num_sgs) { - vchan_cookie_complete(&chan->desc->vdesc); - chan->desc = NULL; - } - stm32_dma_start_transfer(chan); + } else { + chan->busy = false; + chan->status = DMA_COMPLETE; + if (chan->next_sg == chan->desc->num_sgs) { + vchan_cookie_complete(&chan->desc->vdesc); + chan->desc = NULL; } + stm32_dma_start_transfer(chan); } } @@ -675,8 +774,12 @@ static irqreturn_t stm32_dma_chan_irq(int irq, void *devid) if (status & STM32_DMA_TCI) { stm32_dma_irq_clear(chan, STM32_DMA_TCI); - if (scr & STM32_DMA_SCR_TCIE) - stm32_dma_handle_chan_done(chan); + if (scr & STM32_DMA_SCR_TCIE) { + if (chan->status == DMA_PAUSED && !(scr & STM32_DMA_SCR_EN)) + stm32_dma_handle_chan_paused(chan); + else + stm32_dma_handle_chan_done(chan, scr); + } status &= ~STM32_DMA_TCI; } @@ -711,6 +814,107 @@ static void stm32_dma_issue_pending(struct dma_chan *c) spin_unlock_irqrestore(&chan->vchan.lock, flags); } +static int stm32_dma_pause(struct dma_chan *c) +{ + struct stm32_dma_chan *chan = to_stm32_dma_chan(c); + unsigned long flags; + int ret; + + if (chan->status != DMA_IN_PROGRESS) + return -EPERM; + + spin_lock_irqsave(&chan->vchan.lock, flags); + ret = stm32_dma_disable_chan(chan); + /* + * A transfer complete flag is set to indicate the end of transfer due to the stream + * interruption, so wait for interrupt + */ + if (!ret) + chan->status = DMA_PAUSED; + spin_unlock_irqrestore(&chan->vchan.lock, flags); + + return ret; +} + +static int stm32_dma_resume(struct dma_chan *c) +{ + struct stm32_dma_chan *chan = to_stm32_dma_chan(c); + struct stm32_dma_device *dmadev = stm32_dma_get_dev(chan); + struct stm32_dma_chan_reg chan_reg = chan->chan_reg; + u32 id = chan->id, scr, ndtr, offset, spar, sm0ar, sm1ar; + struct stm32_dma_sg_req *sg_req; + unsigned long flags; + + if (chan->status != DMA_PAUSED) + return -EPERM; + + scr = stm32_dma_read(dmadev, STM32_DMA_SCR(id)); + if (WARN_ON(scr & STM32_DMA_SCR_EN)) + return -EPERM; + + spin_lock_irqsave(&chan->vchan.lock, flags); + + /* sg_reg[prev_sg] contains original ndtr, sm0ar and sm1ar before pausing the transfer */ + if (!chan->next_sg) + sg_req = &chan->desc->sg_req[chan->desc->num_sgs - 1]; + else + sg_req = &chan->desc->sg_req[chan->next_sg - 1]; + + ndtr = sg_req->chan_reg.dma_sndtr; + offset = (ndtr - chan_reg.dma_sndtr) << STM32_DMA_SCR_PSIZE_GET(chan_reg.dma_scr); + spar = sg_req->chan_reg.dma_spar; + sm0ar = sg_req->chan_reg.dma_sm0ar; + sm1ar = sg_req->chan_reg.dma_sm1ar; + + /* + * The peripheral and/or memory addresses have to be updated in order to adjust the + * address pointers. Need to check increment. + */ + if (chan_reg.dma_scr & STM32_DMA_SCR_PINC) + stm32_dma_write(dmadev, STM32_DMA_SPAR(id), spar + offset); + else + stm32_dma_write(dmadev, STM32_DMA_SPAR(id), spar); + + if (!(chan_reg.dma_scr & STM32_DMA_SCR_MINC)) + offset = 0; + + /* + * In case of DBM, the current target could be SM1AR. + * Need to temporarily deactivate CIRC/DBM to finish the current transfer, so + * SM0AR becomes the current target and must be updated with SM1AR + offset if CT=1. + */ + if ((chan_reg.dma_scr & STM32_DMA_SCR_DBM) && (chan_reg.dma_scr & STM32_DMA_SCR_CT)) + stm32_dma_write(dmadev, STM32_DMA_SM1AR(id), sm1ar + offset); + else + stm32_dma_write(dmadev, STM32_DMA_SM0AR(id), sm0ar + offset); + + /* NDTR must be restored otherwise internal HW counter won't be correctly reset */ + stm32_dma_write(dmadev, STM32_DMA_SNDTR(id), chan_reg.dma_sndtr); + + /* + * Need to temporarily deactivate CIRC/DBM until next Transfer Complete interrupt, + * otherwise NDTR autoreload value will be wrong (lower than the initial period length) + */ + if (chan_reg.dma_scr & (STM32_DMA_SCR_CIRC | STM32_DMA_SCR_DBM)) + chan_reg.dma_scr &= ~(STM32_DMA_SCR_CIRC | STM32_DMA_SCR_DBM); + + if (chan_reg.dma_scr & STM32_DMA_SCR_DBM) + stm32_dma_configure_next_sg(chan); + + stm32_dma_dump_reg(chan); + + /* The stream may then be re-enabled to restart transfer from the point it was stopped */ + chan->status = DMA_IN_PROGRESS; + chan_reg.dma_scr |= STM32_DMA_SCR_EN; + stm32_dma_write(dmadev, STM32_DMA_SCR(id), chan_reg.dma_scr); + + spin_unlock_irqrestore(&chan->vchan.lock, flags); + + dev_dbg(chan2dev(chan), "vchan %pK: resumed\n", &chan->vchan); + + return 0; +} + static int stm32_dma_set_xfer_param(struct stm32_dma_chan *chan, enum dma_transfer_direction direction, enum dma_slave_buswidth *buswidth, @@ -978,10 +1182,12 @@ static struct dma_async_tx_descriptor *stm32_dma_prep_dma_cyclic( } /* Enable Circular mode or double buffer mode */ - if (buf_len == period_len) + if (buf_len == period_len) { chan->chan_reg.dma_scr |= STM32_DMA_SCR_CIRC; - else + } else { chan->chan_reg.dma_scr |= STM32_DMA_SCR_DBM; + chan->chan_reg.dma_scr &= ~STM32_DMA_SCR_CT; + } /* Clear periph ctrl if client set it */ chan->chan_reg.dma_scr &= ~STM32_DMA_SCR_PFCTRL; @@ -1091,24 +1297,36 @@ static bool stm32_dma_is_current_sg(struct stm32_dma_chan *chan) { struct stm32_dma_device *dmadev = stm32_dma_get_dev(chan); struct stm32_dma_sg_req *sg_req; - u32 dma_scr, dma_smar, id; + u32 dma_scr, dma_smar, id, period_len; id = chan->id; dma_scr = stm32_dma_read(dmadev, STM32_DMA_SCR(id)); + /* In cyclic CIRC but not DBM, CT is not used */ if (!(dma_scr & STM32_DMA_SCR_DBM)) return true; sg_req = &chan->desc->sg_req[chan->next_sg]; + period_len = sg_req->len; + /* DBM - take care of a previous pause/resume not yet post reconfigured */ if (dma_scr & STM32_DMA_SCR_CT) { dma_smar = stm32_dma_read(dmadev, STM32_DMA_SM0AR(id)); - return (dma_smar == sg_req->chan_reg.dma_sm0ar); + /* + * If transfer has been pause/resumed, + * SM0AR is in the range of [SM0AR:SM0AR+period_len] + */ + return (dma_smar >= sg_req->chan_reg.dma_sm0ar && + dma_smar < sg_req->chan_reg.dma_sm0ar + period_len); } dma_smar = stm32_dma_read(dmadev, STM32_DMA_SM1AR(id)); - - return (dma_smar == sg_req->chan_reg.dma_sm1ar); + /* + * If transfer has been pause/resumed, + * SM1AR is in the range of [SM1AR:SM1AR+period_len] + */ + return (dma_smar >= sg_req->chan_reg.dma_sm1ar && + dma_smar < sg_req->chan_reg.dma_sm1ar + period_len); } static size_t stm32_dma_desc_residue(struct stm32_dma_chan *chan, @@ -1148,7 +1366,7 @@ static size_t stm32_dma_desc_residue(struct stm32_dma_chan *chan, residue = stm32_dma_get_remaining_bytes(chan); - if (!stm32_dma_is_current_sg(chan)) { + if (chan->desc->cyclic && !stm32_dma_is_current_sg(chan)) { n_sg++; if (n_sg == chan->desc->num_sgs) n_sg = 0; @@ -1188,7 +1406,12 @@ static enum dma_status stm32_dma_tx_status(struct dma_chan *c, u32 residue = 0; status = dma_cookie_status(c, cookie, state); - if (status == DMA_COMPLETE || !state) + if (status == DMA_COMPLETE) + return status; + + status = chan->status; + + if (!state) return status; spin_lock_irqsave(&chan->vchan.lock, flags); @@ -1377,6 +1600,8 @@ static int stm32_dma_probe(struct platform_device *pdev) dd->device_prep_slave_sg = stm32_dma_prep_slave_sg; dd->device_prep_dma_cyclic = stm32_dma_prep_dma_cyclic; dd->device_config = stm32_dma_slave_config; + dd->device_pause = stm32_dma_pause; + dd->device_resume = stm32_dma_resume; dd->device_terminate_all = stm32_dma_terminate_all; dd->device_synchronize = stm32_dma_synchronize; dd->src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | @@ -1482,7 +1707,7 @@ static int stm32_dma_runtime_resume(struct device *dev) #endif #ifdef CONFIG_PM_SLEEP -static int stm32_dma_suspend(struct device *dev) +static int stm32_dma_pm_suspend(struct device *dev) { struct stm32_dma_device *dmadev = dev_get_drvdata(dev); int id, ret, scr; @@ -1506,14 +1731,14 @@ static int stm32_dma_suspend(struct device *dev) return 0; } -static int stm32_dma_resume(struct device *dev) +static int stm32_dma_pm_resume(struct device *dev) { return pm_runtime_force_resume(dev); } #endif static const struct dev_pm_ops stm32_dma_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(stm32_dma_suspend, stm32_dma_resume) + SET_SYSTEM_SLEEP_PM_OPS(stm32_dma_pm_suspend, stm32_dma_pm_resume) SET_RUNTIME_PM_OPS(stm32_dma_runtime_suspend, stm32_dma_runtime_resume, NULL) }; diff --git a/drivers/dma/stm32-dmamux.c b/drivers/dma/stm32-dmamux.c index d5d55732adba10dfb950d2a66f1866996e60b72f..eee0c5aa5fb57fae088a350252ea44b5e3c69003 100644 --- a/drivers/dma/stm32-dmamux.c +++ b/drivers/dma/stm32-dmamux.c @@ -267,7 +267,7 @@ static int stm32_dmamux_probe(struct platform_device *pdev) ret = PTR_ERR(rst); if (ret == -EPROBE_DEFER) goto err_clk; - } else { + } else if (count > 1) { /* Don't reset if there is only one dma-master */ reset_control_assert(rst); udelay(2); reset_control_deassert(rst); diff --git a/drivers/dma/stm32-mdma.c b/drivers/dma/stm32-mdma.c index 6f57ff0e7b37b6b9915fd0c01be9a695de5af35d..caf0cce8f528acac8e91cffedd9e79d316e8a472 100644 --- a/drivers/dma/stm32-mdma.c +++ b/drivers/dma/stm32-mdma.c @@ -34,7 +34,6 @@ #include "virt-dma.h" #define STM32_MDMA_GISR0 0x0000 /* MDMA Int Status Reg 1 */ -#define STM32_MDMA_GISR1 0x0004 /* MDMA Int Status Reg 2 */ /* MDMA Channel x interrupt/status register */ #define STM32_MDMA_CISR(x) (0x40 + 0x40 * (x)) /* x = 0..62 */ @@ -73,6 +72,7 @@ #define STM32_MDMA_CCR_WEX BIT(14) #define STM32_MDMA_CCR_HEX BIT(13) #define STM32_MDMA_CCR_BEX BIT(12) +#define STM32_MDMA_CCR_SM BIT(8) #define STM32_MDMA_CCR_PL_MASK GENMASK(7, 6) #define STM32_MDMA_CCR_PL(n) FIELD_PREP(STM32_MDMA_CCR_PL_MASK, (n)) #define STM32_MDMA_CCR_TCIE BIT(5) @@ -168,7 +168,7 @@ #define STM32_MDMA_MAX_BUF_LEN 128 #define STM32_MDMA_MAX_BLOCK_LEN 65536 -#define STM32_MDMA_MAX_CHANNELS 63 +#define STM32_MDMA_MAX_CHANNELS 32 #define STM32_MDMA_MAX_REQUESTS 256 #define STM32_MDMA_MAX_BURST 128 #define STM32_MDMA_VERY_HIGH_PRIORITY 0x3 @@ -248,6 +248,7 @@ struct stm32_mdma_device { u32 nr_channels; u32 nr_requests; u32 nr_ahb_addr_masks; + u32 chan_reserved; struct stm32_mdma_chan chan[STM32_MDMA_MAX_CHANNELS]; u32 ahb_addr_masks[]; }; @@ -1317,26 +1318,16 @@ static void stm32_mdma_xfer_end(struct stm32_mdma_chan *chan) static irqreturn_t stm32_mdma_irq_handler(int irq, void *devid) { struct stm32_mdma_device *dmadev = devid; - struct stm32_mdma_chan *chan = devid; + struct stm32_mdma_chan *chan; u32 reg, id, ccr, ien, status; /* Find out which channel generates the interrupt */ status = readl_relaxed(dmadev->base + STM32_MDMA_GISR0); - if (status) { - id = __ffs(status); - } else { - status = readl_relaxed(dmadev->base + STM32_MDMA_GISR1); - if (!status) { - dev_dbg(mdma2dev(dmadev), "spurious it\n"); - return IRQ_NONE; - } - id = __ffs(status); - /* - * As GISR0 provides status for channel id from 0 to 31, - * so GISR1 provides status for channel id from 32 to 62 - */ - id += 32; + if (!status) { + dev_dbg(mdma2dev(dmadev), "spurious it\n"); + return IRQ_NONE; } + id = __ffs(status); chan = &dmadev->chan[id]; if (!chan) { @@ -1354,9 +1345,12 @@ static irqreturn_t stm32_mdma_irq_handler(int irq, void *devid) if (!(status & ien)) { spin_unlock(&chan->vchan.lock); - dev_warn(chan2dev(chan), - "spurious it (status=0x%04x, ien=0x%04x)\n", - status, ien); + if (chan->busy) + dev_warn(chan2dev(chan), + "spurious it (status=0x%04x, ien=0x%04x)\n", status, ien); + else + dev_dbg(chan2dev(chan), + "spurious it (status=0x%04x, ien=0x%04x)\n", status, ien); return IRQ_NONE; } @@ -1456,10 +1450,23 @@ static void stm32_mdma_free_chan_resources(struct dma_chan *c) chan->desc_pool = NULL; } +static bool stm32_mdma_filter_fn(struct dma_chan *c, void *fn_param) +{ + struct stm32_mdma_chan *chan = to_stm32_mdma_chan(c); + struct stm32_mdma_device *dmadev = stm32_mdma_get_dev(chan); + + /* Check if chan is marked Secure */ + if (dmadev->chan_reserved & BIT(chan->id)) + return false; + + return true; +} + static struct dma_chan *stm32_mdma_of_xlate(struct of_phandle_args *dma_spec, struct of_dma *ofdma) { struct stm32_mdma_device *dmadev = ofdma->of_dma_data; + dma_cap_mask_t mask = dmadev->ddev.cap_mask; struct stm32_mdma_chan *chan; struct dma_chan *c; struct stm32_mdma_chan_config config; @@ -1485,7 +1492,7 @@ static struct dma_chan *stm32_mdma_of_xlate(struct of_phandle_args *dma_spec, return NULL; } - c = dma_get_any_slave_channel(&dmadev->ddev); + c = __dma_request_channel(&mask, stm32_mdma_filter_fn, &config, ofdma->of_node); if (!c) { dev_err(mdma2dev(dmadev), "No more channels available\n"); return NULL; @@ -1615,6 +1622,10 @@ static int stm32_mdma_probe(struct platform_device *pdev) for (i = 0; i < dmadev->nr_channels; i++) { chan = &dmadev->chan[i]; chan->id = i; + + if (stm32_mdma_read(dmadev, STM32_MDMA_CCR(i)) & STM32_MDMA_CCR_SM) + dmadev->chan_reserved |= BIT(i); + chan->vchan.desc_free = stm32_mdma_desc_free; vchan_init(&chan->vchan, dd); } diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c index 5cadd4d2b82460fe323ec3eb4a9f3ff021254cb5..b7557f43793620de475776b6ca7788d4769bb274 100644 --- a/drivers/dma/sun6i-dma.c +++ b/drivers/dma/sun6i-dma.c @@ -90,6 +90,14 @@ #define DMA_CHAN_CUR_PARA 0x1c +/* + * LLI address mangling + * + * The LLI link physical address is also mangled, but we avoid dealing + * with that by allocating LLIs from the DMA32 zone. + */ +#define SRC_HIGH_ADDR(x) (((x) & 0x3U) << 16) +#define DST_HIGH_ADDR(x) (((x) & 0x3U) << 18) /* * Various hardware related defines @@ -132,6 +140,7 @@ struct sun6i_dma_config { u32 dst_burst_lengths; u32 src_addr_widths; u32 dst_addr_widths; + bool has_high_addr; bool has_mbus_clk; }; @@ -241,9 +250,7 @@ static inline void sun6i_dma_dump_com_regs(struct sun6i_dma_dev *sdev) static inline void sun6i_dma_dump_chan_regs(struct sun6i_dma_dev *sdev, struct sun6i_pchan *pchan) { - phys_addr_t reg = virt_to_phys(pchan->base); - - dev_dbg(sdev->slave.dev, "Chan %d reg: %pa\n" + dev_dbg(sdev->slave.dev, "Chan %d reg:\n" "\t___en(%04x): \t0x%08x\n" "\tpause(%04x): \t0x%08x\n" "\tstart(%04x): \t0x%08x\n" @@ -252,7 +259,7 @@ static inline void sun6i_dma_dump_chan_regs(struct sun6i_dma_dev *sdev, "\t__dst(%04x): \t0x%08x\n" "\tcount(%04x): \t0x%08x\n" "\t_para(%04x): \t0x%08x\n\n", - pchan->idx, ®, + pchan->idx, DMA_CHAN_ENABLE, readl(pchan->base + DMA_CHAN_ENABLE), DMA_CHAN_PAUSE, @@ -385,17 +392,16 @@ static void *sun6i_dma_lli_add(struct sun6i_dma_lli *prev, } static inline void sun6i_dma_dump_lli(struct sun6i_vchan *vchan, - struct sun6i_dma_lli *lli) + struct sun6i_dma_lli *v_lli, + dma_addr_t p_lli) { - phys_addr_t p_lli = virt_to_phys(lli); - dev_dbg(chan2dev(&vchan->vc.chan), - "\n\tdesc: p - %pa v - 0x%p\n" + "\n\tdesc:\tp - %pad v - 0x%p\n" "\t\tc - 0x%08x s - 0x%08x d - 0x%08x\n" "\t\tl - 0x%08x p - 0x%08x n - 0x%08x\n", - &p_lli, lli, - lli->cfg, lli->src, lli->dst, - lli->len, lli->para, lli->p_lli_next); + &p_lli, v_lli, + v_lli->cfg, v_lli->src, v_lli->dst, + v_lli->len, v_lli->para, v_lli->p_lli_next); } static void sun6i_dma_free_desc(struct virt_dma_desc *vd) @@ -445,7 +451,7 @@ static int sun6i_dma_start_desc(struct sun6i_vchan *vchan) pchan->desc = to_sun6i_desc(&desc->tx); pchan->done = NULL; - sun6i_dma_dump_lli(vchan, pchan->desc->v_lli); + sun6i_dma_dump_lli(vchan, pchan->desc->v_lli, pchan->desc->p_lli); irq_reg = pchan->idx / DMA_IRQ_CHAN_NR; irq_offset = pchan->idx % DMA_IRQ_CHAN_NR; @@ -626,6 +632,18 @@ static int set_config(struct sun6i_dma_dev *sdev, return 0; } +static inline void sun6i_dma_set_addr(struct sun6i_dma_dev *sdev, + struct sun6i_dma_lli *v_lli, + dma_addr_t src, dma_addr_t dst) +{ + v_lli->src = lower_32_bits(src); + v_lli->dst = lower_32_bits(dst); + + if (sdev->cfg->has_high_addr) + v_lli->para |= SRC_HIGH_ADDR(upper_32_bits(src)) | + DST_HIGH_ADDR(upper_32_bits(dst)); +} + static struct dma_async_tx_descriptor *sun6i_dma_prep_dma_memcpy( struct dma_chan *chan, dma_addr_t dest, dma_addr_t src, size_t len, unsigned long flags) @@ -648,16 +666,15 @@ static struct dma_async_tx_descriptor *sun6i_dma_prep_dma_memcpy( if (!txd) return NULL; - v_lli = dma_pool_alloc(sdev->pool, GFP_NOWAIT, &p_lli); + v_lli = dma_pool_alloc(sdev->pool, GFP_DMA32 | GFP_NOWAIT, &p_lli); if (!v_lli) { dev_err(sdev->slave.dev, "Failed to alloc lli memory\n"); goto err_txd_free; } - v_lli->src = src; - v_lli->dst = dest; v_lli->len = len; v_lli->para = NORMAL_WAIT; + sun6i_dma_set_addr(sdev, v_lli, src, dest); burst = convert_burst(8); width = convert_buswidth(DMA_SLAVE_BUSWIDTH_4_BYTES); @@ -670,7 +687,7 @@ static struct dma_async_tx_descriptor *sun6i_dma_prep_dma_memcpy( sun6i_dma_lli_add(NULL, v_lli, p_lli, txd); - sun6i_dma_dump_lli(vchan, v_lli); + sun6i_dma_dump_lli(vchan, v_lli, p_lli); return vchan_tx_prep(&vchan->vc, &txd->vd, flags); @@ -708,7 +725,7 @@ static struct dma_async_tx_descriptor *sun6i_dma_prep_slave_sg( return NULL; for_each_sg(sgl, sg, sg_len, i) { - v_lli = dma_pool_alloc(sdev->pool, GFP_NOWAIT, &p_lli); + v_lli = dma_pool_alloc(sdev->pool, GFP_DMA32 | GFP_NOWAIT, &p_lli); if (!v_lli) goto err_lli_free; @@ -716,8 +733,9 @@ static struct dma_async_tx_descriptor *sun6i_dma_prep_slave_sg( v_lli->para = NORMAL_WAIT; if (dir == DMA_MEM_TO_DEV) { - v_lli->src = sg_dma_address(sg); - v_lli->dst = sconfig->dst_addr; + sun6i_dma_set_addr(sdev, v_lli, + sg_dma_address(sg), + sconfig->dst_addr); v_lli->cfg = lli_cfg; sdev->cfg->set_drq(&v_lli->cfg, DRQ_SDRAM, vchan->port); sdev->cfg->set_mode(&v_lli->cfg, LINEAR_MODE, IO_MODE); @@ -729,8 +747,9 @@ static struct dma_async_tx_descriptor *sun6i_dma_prep_slave_sg( sg_dma_len(sg), flags); } else { - v_lli->src = sconfig->src_addr; - v_lli->dst = sg_dma_address(sg); + sun6i_dma_set_addr(sdev, v_lli, + sconfig->src_addr, + sg_dma_address(sg)); v_lli->cfg = lli_cfg; sdev->cfg->set_drq(&v_lli->cfg, vchan->port, DRQ_SDRAM); sdev->cfg->set_mode(&v_lli->cfg, IO_MODE, LINEAR_MODE); @@ -746,14 +765,16 @@ static struct dma_async_tx_descriptor *sun6i_dma_prep_slave_sg( } dev_dbg(chan2dev(chan), "First: %pad\n", &txd->p_lli); - for (prev = txd->v_lli; prev; prev = prev->v_lli_next) - sun6i_dma_dump_lli(vchan, prev); + for (p_lli = txd->p_lli, v_lli = txd->v_lli; v_lli; + p_lli = v_lli->p_lli_next, v_lli = v_lli->v_lli_next) + sun6i_dma_dump_lli(vchan, v_lli, p_lli); return vchan_tx_prep(&vchan->vc, &txd->vd, flags); err_lli_free: - for (prev = txd->v_lli; prev; prev = prev->v_lli_next) - dma_pool_free(sdev->pool, prev, virt_to_phys(prev)); + for (p_lli = txd->p_lli, v_lli = txd->v_lli; v_lli; + p_lli = v_lli->p_lli_next, v_lli = v_lli->v_lli_next) + dma_pool_free(sdev->pool, v_lli, p_lli); kfree(txd); return NULL; } @@ -787,7 +808,7 @@ static struct dma_async_tx_descriptor *sun6i_dma_prep_dma_cyclic( return NULL; for (i = 0; i < periods; i++) { - v_lli = dma_pool_alloc(sdev->pool, GFP_NOWAIT, &p_lli); + v_lli = dma_pool_alloc(sdev->pool, GFP_DMA32 | GFP_NOWAIT, &p_lli); if (!v_lli) { dev_err(sdev->slave.dev, "Failed to alloc lli memory\n"); goto err_lli_free; @@ -797,14 +818,16 @@ static struct dma_async_tx_descriptor *sun6i_dma_prep_dma_cyclic( v_lli->para = NORMAL_WAIT; if (dir == DMA_MEM_TO_DEV) { - v_lli->src = buf_addr + period_len * i; - v_lli->dst = sconfig->dst_addr; + sun6i_dma_set_addr(sdev, v_lli, + buf_addr + period_len * i, + sconfig->dst_addr); v_lli->cfg = lli_cfg; sdev->cfg->set_drq(&v_lli->cfg, DRQ_SDRAM, vchan->port); sdev->cfg->set_mode(&v_lli->cfg, LINEAR_MODE, IO_MODE); } else { - v_lli->src = sconfig->src_addr; - v_lli->dst = buf_addr + period_len * i; + sun6i_dma_set_addr(sdev, v_lli, + sconfig->src_addr, + buf_addr + period_len * i); v_lli->cfg = lli_cfg; sdev->cfg->set_drq(&v_lli->cfg, vchan->port, DRQ_SDRAM); sdev->cfg->set_mode(&v_lli->cfg, IO_MODE, LINEAR_MODE); @@ -820,8 +843,9 @@ static struct dma_async_tx_descriptor *sun6i_dma_prep_dma_cyclic( return vchan_tx_prep(&vchan->vc, &txd->vd, flags); err_lli_free: - for (prev = txd->v_lli; prev; prev = prev->v_lli_next) - dma_pool_free(sdev->pool, prev, virt_to_phys(prev)); + for (p_lli = txd->p_lli, v_lli = txd->v_lli; v_lli; + p_lli = v_lli->p_lli_next, v_lli = v_lli->v_lli_next) + dma_pool_free(sdev->pool, v_lli, p_lli); kfree(txd); return NULL; } @@ -1174,8 +1198,6 @@ static struct sun6i_dma_config sun50i_a64_dma_cfg = { }; /* - * TODO: Add support for more than 4g physical addressing. - * * The A100 binding uses the number of dma channels from the * device tree node. */ @@ -1194,6 +1216,7 @@ static struct sun6i_dma_config sun50i_a100_dma_cfg = { BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) | BIT(DMA_SLAVE_BUSWIDTH_8_BYTES), + .has_high_addr = true, .has_mbus_clk = true, }; @@ -1248,6 +1271,7 @@ static const struct of_device_id sun6i_dma_match[] = { { .compatible = "allwinner,sun8i-a83t-dma", .data = &sun8i_a83t_dma_cfg }, { .compatible = "allwinner,sun8i-h3-dma", .data = &sun8i_h3_dma_cfg }, { .compatible = "allwinner,sun8i-v3s-dma", .data = &sun8i_v3s_dma_cfg }, + { .compatible = "allwinner,sun20i-d1-dma", .data = &sun50i_a100_dma_cfg }, { .compatible = "allwinner,sun50i-a64-dma", .data = &sun50i_a64_dma_cfg }, { .compatible = "allwinner,sun50i-a100-dma", .data = &sun50i_a100_dma_cfg }, { .compatible = "allwinner,sun50i-h6-dma", .data = &sun50i_h6_dma_cfg }, diff --git a/drivers/dma/tegra186-gpc-dma.c b/drivers/dma/tegra186-gpc-dma.c new file mode 100644 index 0000000000000000000000000000000000000000..05cd451f541d87c8de9d6ee71ae872ff77ba47c6 --- /dev/null +++ b/drivers/dma/tegra186-gpc-dma.c @@ -0,0 +1,1498 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * DMA driver for NVIDIA Tegra GPC DMA controller. + * + * Copyright (c) 2014-2022, NVIDIA CORPORATION. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "virt-dma.h" + +/* CSR register */ +#define TEGRA_GPCDMA_CHAN_CSR 0x00 +#define TEGRA_GPCDMA_CSR_ENB BIT(31) +#define TEGRA_GPCDMA_CSR_IE_EOC BIT(30) +#define TEGRA_GPCDMA_CSR_ONCE BIT(27) + +#define TEGRA_GPCDMA_CSR_FC_MODE GENMASK(25, 24) +#define TEGRA_GPCDMA_CSR_FC_MODE_NO_MMIO \ + FIELD_PREP(TEGRA_GPCDMA_CSR_FC_MODE, 0) +#define TEGRA_GPCDMA_CSR_FC_MODE_ONE_MMIO \ + FIELD_PREP(TEGRA_GPCDMA_CSR_FC_MODE, 1) +#define TEGRA_GPCDMA_CSR_FC_MODE_TWO_MMIO \ + FIELD_PREP(TEGRA_GPCDMA_CSR_FC_MODE, 2) +#define TEGRA_GPCDMA_CSR_FC_MODE_FOUR_MMIO \ + FIELD_PREP(TEGRA_GPCDMA_CSR_FC_MODE, 3) + +#define TEGRA_GPCDMA_CSR_DMA GENMASK(23, 21) +#define TEGRA_GPCDMA_CSR_DMA_IO2MEM_NO_FC \ + FIELD_PREP(TEGRA_GPCDMA_CSR_DMA, 0) +#define TEGRA_GPCDMA_CSR_DMA_IO2MEM_FC \ + FIELD_PREP(TEGRA_GPCDMA_CSR_DMA, 1) +#define TEGRA_GPCDMA_CSR_DMA_MEM2IO_NO_FC \ + FIELD_PREP(TEGRA_GPCDMA_CSR_DMA, 2) +#define TEGRA_GPCDMA_CSR_DMA_MEM2IO_FC \ + FIELD_PREP(TEGRA_GPCDMA_CSR_DMA, 3) +#define TEGRA_GPCDMA_CSR_DMA_MEM2MEM \ + FIELD_PREP(TEGRA_GPCDMA_CSR_DMA, 4) +#define TEGRA_GPCDMA_CSR_DMA_FIXED_PAT \ + FIELD_PREP(TEGRA_GPCDMA_CSR_DMA, 6) + +#define TEGRA_GPCDMA_CSR_REQ_SEL_MASK GENMASK(20, 16) +#define TEGRA_GPCDMA_CSR_REQ_SEL_UNUSED \ + FIELD_PREP(TEGRA_GPCDMA_CSR_REQ_SEL_MASK, 4) +#define TEGRA_GPCDMA_CSR_IRQ_MASK BIT(15) +#define TEGRA_GPCDMA_CSR_WEIGHT GENMASK(13, 10) + +/* STATUS register */ +#define TEGRA_GPCDMA_CHAN_STATUS 0x004 +#define TEGRA_GPCDMA_STATUS_BUSY BIT(31) +#define TEGRA_GPCDMA_STATUS_ISE_EOC BIT(30) +#define TEGRA_GPCDMA_STATUS_PING_PONG BIT(28) +#define TEGRA_GPCDMA_STATUS_DMA_ACTIVITY BIT(27) +#define TEGRA_GPCDMA_STATUS_CHANNEL_PAUSE BIT(26) +#define TEGRA_GPCDMA_STATUS_CHANNEL_RX BIT(25) +#define TEGRA_GPCDMA_STATUS_CHANNEL_TX BIT(24) +#define TEGRA_GPCDMA_STATUS_IRQ_INTR_STA BIT(23) +#define TEGRA_GPCDMA_STATUS_IRQ_STA BIT(21) +#define TEGRA_GPCDMA_STATUS_IRQ_TRIG_STA BIT(20) + +#define TEGRA_GPCDMA_CHAN_CSRE 0x008 +#define TEGRA_GPCDMA_CHAN_CSRE_PAUSE BIT(31) + +/* Source address */ +#define TEGRA_GPCDMA_CHAN_SRC_PTR 0x00C + +/* Destination address */ +#define TEGRA_GPCDMA_CHAN_DST_PTR 0x010 + +/* High address pointer */ +#define TEGRA_GPCDMA_CHAN_HIGH_ADDR_PTR 0x014 +#define TEGRA_GPCDMA_HIGH_ADDR_SRC_PTR GENMASK(7, 0) +#define TEGRA_GPCDMA_HIGH_ADDR_DST_PTR GENMASK(23, 16) + +/* MC sequence register */ +#define TEGRA_GPCDMA_CHAN_MCSEQ 0x18 +#define TEGRA_GPCDMA_MCSEQ_DATA_SWAP BIT(31) +#define TEGRA_GPCDMA_MCSEQ_REQ_COUNT GENMASK(30, 25) +#define TEGRA_GPCDMA_MCSEQ_BURST GENMASK(24, 23) +#define TEGRA_GPCDMA_MCSEQ_BURST_2 \ + FIELD_PREP(TEGRA_GPCDMA_MCSEQ_BURST, 0) +#define TEGRA_GPCDMA_MCSEQ_BURST_16 \ + FIELD_PREP(TEGRA_GPCDMA_MCSEQ_BURST, 3) +#define TEGRA_GPCDMA_MCSEQ_WRAP1 GENMASK(22, 20) +#define TEGRA_GPCDMA_MCSEQ_WRAP0 GENMASK(19, 17) +#define TEGRA_GPCDMA_MCSEQ_WRAP_NONE 0 + +#define TEGRA_GPCDMA_MCSEQ_STREAM_ID1_MASK GENMASK(13, 7) +#define TEGRA_GPCDMA_MCSEQ_STREAM_ID0_MASK GENMASK(6, 0) + +/* MMIO sequence register */ +#define TEGRA_GPCDMA_CHAN_MMIOSEQ 0x01c +#define TEGRA_GPCDMA_MMIOSEQ_DBL_BUF BIT(31) +#define TEGRA_GPCDMA_MMIOSEQ_BUS_WIDTH GENMASK(30, 28) +#define TEGRA_GPCDMA_MMIOSEQ_BUS_WIDTH_8 \ + FIELD_PREP(TEGRA_GPCDMA_MMIOSEQ_BUS_WIDTH, 0) +#define TEGRA_GPCDMA_MMIOSEQ_BUS_WIDTH_16 \ + FIELD_PREP(TEGRA_GPCDMA_MMIOSEQ_BUS_WIDTH, 1) +#define TEGRA_GPCDMA_MMIOSEQ_BUS_WIDTH_32 \ + FIELD_PREP(TEGRA_GPCDMA_MMIOSEQ_BUS_WIDTH, 2) +#define TEGRA_GPCDMA_MMIOSEQ_DATA_SWAP BIT(27) +#define TEGRA_GPCDMA_MMIOSEQ_BURST_SHIFT 23 +#define TEGRA_GPCDMA_MMIOSEQ_BURST_MIN 2U +#define TEGRA_GPCDMA_MMIOSEQ_BURST_MAX 32U +#define TEGRA_GPCDMA_MMIOSEQ_BURST(bs) \ + (GENMASK((fls(bs) - 2), 0) << TEGRA_GPCDMA_MMIOSEQ_BURST_SHIFT) +#define TEGRA_GPCDMA_MMIOSEQ_MASTER_ID GENMASK(22, 19) +#define TEGRA_GPCDMA_MMIOSEQ_WRAP_WORD GENMASK(18, 16) +#define TEGRA_GPCDMA_MMIOSEQ_MMIO_PROT GENMASK(8, 7) + +/* Channel WCOUNT */ +#define TEGRA_GPCDMA_CHAN_WCOUNT 0x20 + +/* Transfer count */ +#define TEGRA_GPCDMA_CHAN_XFER_COUNT 0x24 + +/* DMA byte count status */ +#define TEGRA_GPCDMA_CHAN_DMA_BYTE_STATUS 0x28 + +/* Error Status Register */ +#define TEGRA_GPCDMA_CHAN_ERR_STATUS 0x30 +#define TEGRA_GPCDMA_CHAN_ERR_TYPE_SHIFT 8 +#define TEGRA_GPCDMA_CHAN_ERR_TYPE_MASK 0xF +#define TEGRA_GPCDMA_CHAN_ERR_TYPE(err) ( \ + ((err) >> TEGRA_GPCDMA_CHAN_ERR_TYPE_SHIFT) & \ + TEGRA_GPCDMA_CHAN_ERR_TYPE_MASK) +#define TEGRA_DMA_BM_FIFO_FULL_ERR 0xF +#define TEGRA_DMA_PERIPH_FIFO_FULL_ERR 0xE +#define TEGRA_DMA_PERIPH_ID_ERR 0xD +#define TEGRA_DMA_STREAM_ID_ERR 0xC +#define TEGRA_DMA_MC_SLAVE_ERR 0xB +#define TEGRA_DMA_MMIO_SLAVE_ERR 0xA + +/* Fixed Pattern */ +#define TEGRA_GPCDMA_CHAN_FIXED_PATTERN 0x34 + +#define TEGRA_GPCDMA_CHAN_TZ 0x38 +#define TEGRA_GPCDMA_CHAN_TZ_MMIO_PROT_1 BIT(0) +#define TEGRA_GPCDMA_CHAN_TZ_MC_PROT_1 BIT(1) + +#define TEGRA_GPCDMA_CHAN_SPARE 0x3c +#define TEGRA_GPCDMA_CHAN_SPARE_EN_LEGACY_FC BIT(16) + +/* + * If any burst is in flight and DMA paused then this is the time to complete + * on-flight burst and update DMA status register. + */ +#define TEGRA_GPCDMA_BURST_COMPLETE_TIME 20 +#define TEGRA_GPCDMA_BURST_COMPLETION_TIMEOUT 100 + +/* Channel base address offset from GPCDMA base address */ +#define TEGRA_GPCDMA_CHANNEL_BASE_ADD_OFFSET 0x20000 + +struct tegra_dma; +struct tegra_dma_channel; + +/* + * tegra_dma_chip_data Tegra chip specific DMA data + * @nr_channels: Number of channels available in the controller. + * @channel_reg_size: Channel register size. + * @max_dma_count: Maximum DMA transfer count supported by DMA controller. + * @hw_support_pause: DMA HW engine support pause of the channel. + */ +struct tegra_dma_chip_data { + bool hw_support_pause; + unsigned int nr_channels; + unsigned int channel_reg_size; + unsigned int max_dma_count; + int (*terminate)(struct tegra_dma_channel *tdc); +}; + +/* DMA channel registers */ +struct tegra_dma_channel_regs { + u32 csr; + u32 src_ptr; + u32 dst_ptr; + u32 high_addr_ptr; + u32 mc_seq; + u32 mmio_seq; + u32 wcount; + u32 fixed_pattern; +}; + +/* + * tegra_dma_sg_req: DMA request details to configure hardware. This + * contains the details for one transfer to configure DMA hw. + * The client's request for data transfer can be broken into multiple + * sub-transfer as per requester details and hw support. This sub transfer + * get added as an array in Tegra DMA desc which manages the transfer details. + */ +struct tegra_dma_sg_req { + unsigned int len; + struct tegra_dma_channel_regs ch_regs; +}; + +/* + * tegra_dma_desc: Tegra DMA descriptors which uses virt_dma_desc to + * manage client request and keep track of transfer status, callbacks + * and request counts etc. + */ +struct tegra_dma_desc { + bool cyclic; + unsigned int bytes_req; + unsigned int bytes_xfer; + unsigned int sg_idx; + unsigned int sg_count; + struct virt_dma_desc vd; + struct tegra_dma_channel *tdc; + struct tegra_dma_sg_req sg_req[]; +}; + +/* + * tegra_dma_channel: Channel specific information + */ +struct tegra_dma_channel { + bool config_init; + char name[30]; + enum dma_transfer_direction sid_dir; + int id; + int irq; + int slave_id; + struct tegra_dma *tdma; + struct virt_dma_chan vc; + struct tegra_dma_desc *dma_desc; + struct dma_slave_config dma_sconfig; + unsigned int stream_id; + unsigned long chan_base_offset; +}; + +/* + * tegra_dma: Tegra DMA specific information + */ +struct tegra_dma { + const struct tegra_dma_chip_data *chip_data; + unsigned long sid_m2d_reserved; + unsigned long sid_d2m_reserved; + void __iomem *base_addr; + struct device *dev; + struct dma_device dma_dev; + struct reset_control *rst; + struct tegra_dma_channel channels[]; +}; + +static inline void tdc_write(struct tegra_dma_channel *tdc, + u32 reg, u32 val) +{ + writel_relaxed(val, tdc->tdma->base_addr + tdc->chan_base_offset + reg); +} + +static inline u32 tdc_read(struct tegra_dma_channel *tdc, u32 reg) +{ + return readl_relaxed(tdc->tdma->base_addr + tdc->chan_base_offset + reg); +} + +static inline struct tegra_dma_channel *to_tegra_dma_chan(struct dma_chan *dc) +{ + return container_of(dc, struct tegra_dma_channel, vc.chan); +} + +static inline struct tegra_dma_desc *vd_to_tegra_dma_desc(struct virt_dma_desc *vd) +{ + return container_of(vd, struct tegra_dma_desc, vd); +} + +static inline struct device *tdc2dev(struct tegra_dma_channel *tdc) +{ + return tdc->vc.chan.device->dev; +} + +static void tegra_dma_dump_chan_regs(struct tegra_dma_channel *tdc) +{ + dev_dbg(tdc2dev(tdc), "DMA Channel %d name %s register dump:\n", + tdc->id, tdc->name); + dev_dbg(tdc2dev(tdc), "CSR %x STA %x CSRE %x SRC %x DST %x\n", + tdc_read(tdc, TEGRA_GPCDMA_CHAN_CSR), + tdc_read(tdc, TEGRA_GPCDMA_CHAN_STATUS), + tdc_read(tdc, TEGRA_GPCDMA_CHAN_CSRE), + tdc_read(tdc, TEGRA_GPCDMA_CHAN_SRC_PTR), + tdc_read(tdc, TEGRA_GPCDMA_CHAN_DST_PTR) + ); + dev_dbg(tdc2dev(tdc), "MCSEQ %x IOSEQ %x WCNT %x XFER %x BSTA %x\n", + tdc_read(tdc, TEGRA_GPCDMA_CHAN_MCSEQ), + tdc_read(tdc, TEGRA_GPCDMA_CHAN_MMIOSEQ), + tdc_read(tdc, TEGRA_GPCDMA_CHAN_WCOUNT), + tdc_read(tdc, TEGRA_GPCDMA_CHAN_XFER_COUNT), + tdc_read(tdc, TEGRA_GPCDMA_CHAN_DMA_BYTE_STATUS) + ); + dev_dbg(tdc2dev(tdc), "DMA ERR_STA %x\n", + tdc_read(tdc, TEGRA_GPCDMA_CHAN_ERR_STATUS)); +} + +static int tegra_dma_sid_reserve(struct tegra_dma_channel *tdc, + enum dma_transfer_direction direction) +{ + struct tegra_dma *tdma = tdc->tdma; + int sid = tdc->slave_id; + + if (!is_slave_direction(direction)) + return 0; + + switch (direction) { + case DMA_MEM_TO_DEV: + if (test_and_set_bit(sid, &tdma->sid_m2d_reserved)) { + dev_err(tdma->dev, "slave id already in use\n"); + return -EINVAL; + } + break; + case DMA_DEV_TO_MEM: + if (test_and_set_bit(sid, &tdma->sid_d2m_reserved)) { + dev_err(tdma->dev, "slave id already in use\n"); + return -EINVAL; + } + break; + default: + break; + } + + tdc->sid_dir = direction; + + return 0; +} + +static void tegra_dma_sid_free(struct tegra_dma_channel *tdc) +{ + struct tegra_dma *tdma = tdc->tdma; + int sid = tdc->slave_id; + + switch (tdc->sid_dir) { + case DMA_MEM_TO_DEV: + clear_bit(sid, &tdma->sid_m2d_reserved); + break; + case DMA_DEV_TO_MEM: + clear_bit(sid, &tdma->sid_d2m_reserved); + break; + default: + break; + } + + tdc->sid_dir = DMA_TRANS_NONE; +} + +static void tegra_dma_desc_free(struct virt_dma_desc *vd) +{ + kfree(container_of(vd, struct tegra_dma_desc, vd)); +} + +static int tegra_dma_slave_config(struct dma_chan *dc, + struct dma_slave_config *sconfig) +{ + struct tegra_dma_channel *tdc = to_tegra_dma_chan(dc); + + memcpy(&tdc->dma_sconfig, sconfig, sizeof(*sconfig)); + tdc->config_init = true; + + return 0; +} + +static int tegra_dma_pause(struct tegra_dma_channel *tdc) +{ + int ret; + u32 val; + + val = tdc_read(tdc, TEGRA_GPCDMA_CHAN_CSRE); + val |= TEGRA_GPCDMA_CHAN_CSRE_PAUSE; + tdc_write(tdc, TEGRA_GPCDMA_CHAN_CSRE, val); + + /* Wait until busy bit is de-asserted */ + ret = readl_relaxed_poll_timeout_atomic(tdc->tdma->base_addr + + tdc->chan_base_offset + TEGRA_GPCDMA_CHAN_STATUS, + val, + !(val & TEGRA_GPCDMA_STATUS_BUSY), + TEGRA_GPCDMA_BURST_COMPLETE_TIME, + TEGRA_GPCDMA_BURST_COMPLETION_TIMEOUT); + + if (ret) { + dev_err(tdc2dev(tdc), "DMA pause timed out\n"); + tegra_dma_dump_chan_regs(tdc); + } + + return ret; +} + +static int tegra_dma_device_pause(struct dma_chan *dc) +{ + struct tegra_dma_channel *tdc = to_tegra_dma_chan(dc); + unsigned long flags; + int ret; + + if (!tdc->tdma->chip_data->hw_support_pause) + return -ENOSYS; + + spin_lock_irqsave(&tdc->vc.lock, flags); + ret = tegra_dma_pause(tdc); + spin_unlock_irqrestore(&tdc->vc.lock, flags); + + return ret; +} + +static void tegra_dma_resume(struct tegra_dma_channel *tdc) +{ + u32 val; + + val = tdc_read(tdc, TEGRA_GPCDMA_CHAN_CSRE); + val &= ~TEGRA_GPCDMA_CHAN_CSRE_PAUSE; + tdc_write(tdc, TEGRA_GPCDMA_CHAN_CSRE, val); +} + +static int tegra_dma_device_resume(struct dma_chan *dc) +{ + struct tegra_dma_channel *tdc = to_tegra_dma_chan(dc); + unsigned long flags; + + if (!tdc->tdma->chip_data->hw_support_pause) + return -ENOSYS; + + spin_lock_irqsave(&tdc->vc.lock, flags); + tegra_dma_resume(tdc); + spin_unlock_irqrestore(&tdc->vc.lock, flags); + + return 0; +} + +static void tegra_dma_disable(struct tegra_dma_channel *tdc) +{ + u32 csr, status; + + csr = tdc_read(tdc, TEGRA_GPCDMA_CHAN_CSR); + + /* Disable interrupts */ + csr &= ~TEGRA_GPCDMA_CSR_IE_EOC; + + /* Disable DMA */ + csr &= ~TEGRA_GPCDMA_CSR_ENB; + tdc_write(tdc, TEGRA_GPCDMA_CHAN_CSR, csr); + + /* Clear interrupt status if it is there */ + status = tdc_read(tdc, TEGRA_GPCDMA_CHAN_STATUS); + if (status & TEGRA_GPCDMA_STATUS_ISE_EOC) { + dev_dbg(tdc2dev(tdc), "%s():clearing interrupt\n", __func__); + tdc_write(tdc, TEGRA_GPCDMA_CHAN_STATUS, status); + } +} + +static void tegra_dma_configure_next_sg(struct tegra_dma_channel *tdc) +{ + struct tegra_dma_desc *dma_desc = tdc->dma_desc; + struct tegra_dma_channel_regs *ch_regs; + int ret; + u32 val; + + dma_desc->sg_idx++; + + /* Reset the sg index for cyclic transfers */ + if (dma_desc->sg_idx == dma_desc->sg_count) + dma_desc->sg_idx = 0; + + /* Configure next transfer immediately after DMA is busy */ + ret = readl_relaxed_poll_timeout_atomic(tdc->tdma->base_addr + + tdc->chan_base_offset + TEGRA_GPCDMA_CHAN_STATUS, + val, + (val & TEGRA_GPCDMA_STATUS_BUSY), 0, + TEGRA_GPCDMA_BURST_COMPLETION_TIMEOUT); + if (ret) + return; + + ch_regs = &dma_desc->sg_req[dma_desc->sg_idx].ch_regs; + + tdc_write(tdc, TEGRA_GPCDMA_CHAN_WCOUNT, ch_regs->wcount); + tdc_write(tdc, TEGRA_GPCDMA_CHAN_SRC_PTR, ch_regs->src_ptr); + tdc_write(tdc, TEGRA_GPCDMA_CHAN_DST_PTR, ch_regs->dst_ptr); + tdc_write(tdc, TEGRA_GPCDMA_CHAN_HIGH_ADDR_PTR, ch_regs->high_addr_ptr); + + /* Start DMA */ + tdc_write(tdc, TEGRA_GPCDMA_CHAN_CSR, + ch_regs->csr | TEGRA_GPCDMA_CSR_ENB); +} + +static void tegra_dma_start(struct tegra_dma_channel *tdc) +{ + struct tegra_dma_desc *dma_desc = tdc->dma_desc; + struct tegra_dma_channel_regs *ch_regs; + struct virt_dma_desc *vdesc; + + if (!dma_desc) { + vdesc = vchan_next_desc(&tdc->vc); + if (!vdesc) + return; + + dma_desc = vd_to_tegra_dma_desc(vdesc); + list_del(&vdesc->node); + dma_desc->tdc = tdc; + tdc->dma_desc = dma_desc; + + tegra_dma_resume(tdc); + } + + ch_regs = &dma_desc->sg_req[dma_desc->sg_idx].ch_regs; + + tdc_write(tdc, TEGRA_GPCDMA_CHAN_WCOUNT, ch_regs->wcount); + tdc_write(tdc, TEGRA_GPCDMA_CHAN_CSR, 0); + tdc_write(tdc, TEGRA_GPCDMA_CHAN_SRC_PTR, ch_regs->src_ptr); + tdc_write(tdc, TEGRA_GPCDMA_CHAN_DST_PTR, ch_regs->dst_ptr); + tdc_write(tdc, TEGRA_GPCDMA_CHAN_HIGH_ADDR_PTR, ch_regs->high_addr_ptr); + tdc_write(tdc, TEGRA_GPCDMA_CHAN_FIXED_PATTERN, ch_regs->fixed_pattern); + tdc_write(tdc, TEGRA_GPCDMA_CHAN_MMIOSEQ, ch_regs->mmio_seq); + tdc_write(tdc, TEGRA_GPCDMA_CHAN_MCSEQ, ch_regs->mc_seq); + tdc_write(tdc, TEGRA_GPCDMA_CHAN_CSR, ch_regs->csr); + + /* Start DMA */ + tdc_write(tdc, TEGRA_GPCDMA_CHAN_CSR, + ch_regs->csr | TEGRA_GPCDMA_CSR_ENB); +} + +static void tegra_dma_xfer_complete(struct tegra_dma_channel *tdc) +{ + vchan_cookie_complete(&tdc->dma_desc->vd); + + tegra_dma_sid_free(tdc); + tdc->dma_desc = NULL; +} + +static void tegra_dma_chan_decode_error(struct tegra_dma_channel *tdc, + unsigned int err_status) +{ + switch (TEGRA_GPCDMA_CHAN_ERR_TYPE(err_status)) { + case TEGRA_DMA_BM_FIFO_FULL_ERR: + dev_err(tdc->tdma->dev, + "GPCDMA CH%d bm fifo full\n", tdc->id); + break; + + case TEGRA_DMA_PERIPH_FIFO_FULL_ERR: + dev_err(tdc->tdma->dev, + "GPCDMA CH%d peripheral fifo full\n", tdc->id); + break; + + case TEGRA_DMA_PERIPH_ID_ERR: + dev_err(tdc->tdma->dev, + "GPCDMA CH%d illegal peripheral id\n", tdc->id); + break; + + case TEGRA_DMA_STREAM_ID_ERR: + dev_err(tdc->tdma->dev, + "GPCDMA CH%d illegal stream id\n", tdc->id); + break; + + case TEGRA_DMA_MC_SLAVE_ERR: + dev_err(tdc->tdma->dev, + "GPCDMA CH%d mc slave error\n", tdc->id); + break; + + case TEGRA_DMA_MMIO_SLAVE_ERR: + dev_err(tdc->tdma->dev, + "GPCDMA CH%d mmio slave error\n", tdc->id); + break; + + default: + dev_err(tdc->tdma->dev, + "GPCDMA CH%d security violation %x\n", tdc->id, + err_status); + } +} + +static irqreturn_t tegra_dma_isr(int irq, void *dev_id) +{ + struct tegra_dma_channel *tdc = dev_id; + struct tegra_dma_desc *dma_desc = tdc->dma_desc; + struct tegra_dma_sg_req *sg_req; + u32 status; + + /* Check channel error status register */ + status = tdc_read(tdc, TEGRA_GPCDMA_CHAN_ERR_STATUS); + if (status) { + tegra_dma_chan_decode_error(tdc, status); + tegra_dma_dump_chan_regs(tdc); + tdc_write(tdc, TEGRA_GPCDMA_CHAN_ERR_STATUS, 0xFFFFFFFF); + } + + spin_lock(&tdc->vc.lock); + status = tdc_read(tdc, TEGRA_GPCDMA_CHAN_STATUS); + if (!(status & TEGRA_GPCDMA_STATUS_ISE_EOC)) + goto irq_done; + + tdc_write(tdc, TEGRA_GPCDMA_CHAN_STATUS, + TEGRA_GPCDMA_STATUS_ISE_EOC); + + if (!dma_desc) + goto irq_done; + + sg_req = dma_desc->sg_req; + dma_desc->bytes_xfer += sg_req[dma_desc->sg_idx].len; + + if (dma_desc->cyclic) { + vchan_cyclic_callback(&dma_desc->vd); + tegra_dma_configure_next_sg(tdc); + } else { + dma_desc->sg_idx++; + if (dma_desc->sg_idx == dma_desc->sg_count) + tegra_dma_xfer_complete(tdc); + else + tegra_dma_start(tdc); + } + +irq_done: + spin_unlock(&tdc->vc.lock); + return IRQ_HANDLED; +} + +static void tegra_dma_issue_pending(struct dma_chan *dc) +{ + struct tegra_dma_channel *tdc = to_tegra_dma_chan(dc); + unsigned long flags; + + if (tdc->dma_desc) + return; + + spin_lock_irqsave(&tdc->vc.lock, flags); + if (vchan_issue_pending(&tdc->vc)) + tegra_dma_start(tdc); + + /* + * For cyclic DMA transfers, program the second + * transfer parameters as soon as the first DMA + * transfer is started inorder for the DMA + * controller to trigger the second transfer + * with the correct parameters. + */ + if (tdc->dma_desc && tdc->dma_desc->cyclic) + tegra_dma_configure_next_sg(tdc); + + spin_unlock_irqrestore(&tdc->vc.lock, flags); +} + +static int tegra_dma_stop_client(struct tegra_dma_channel *tdc) +{ + int ret; + u32 status, csr; + + /* + * Change the client associated with the DMA channel + * to stop DMA engine from starting any more bursts for + * the given client and wait for in flight bursts to complete + */ + csr = tdc_read(tdc, TEGRA_GPCDMA_CHAN_CSR); + csr &= ~(TEGRA_GPCDMA_CSR_REQ_SEL_MASK); + csr |= TEGRA_GPCDMA_CSR_REQ_SEL_UNUSED; + tdc_write(tdc, TEGRA_GPCDMA_CHAN_CSR, csr); + + /* Wait for in flight data transfer to finish */ + udelay(TEGRA_GPCDMA_BURST_COMPLETE_TIME); + + /* If TX/RX path is still active wait till it becomes + * inactive + */ + + ret = readl_relaxed_poll_timeout_atomic(tdc->tdma->base_addr + + tdc->chan_base_offset + + TEGRA_GPCDMA_CHAN_STATUS, + status, + !(status & (TEGRA_GPCDMA_STATUS_CHANNEL_TX | + TEGRA_GPCDMA_STATUS_CHANNEL_RX)), + 5, + TEGRA_GPCDMA_BURST_COMPLETION_TIMEOUT); + if (ret) { + dev_err(tdc2dev(tdc), "Timeout waiting for DMA burst completion!\n"); + tegra_dma_dump_chan_regs(tdc); + } + + return ret; +} + +static int tegra_dma_terminate_all(struct dma_chan *dc) +{ + struct tegra_dma_channel *tdc = to_tegra_dma_chan(dc); + unsigned long flags; + LIST_HEAD(head); + int err; + + spin_lock_irqsave(&tdc->vc.lock, flags); + + if (tdc->dma_desc) { + err = tdc->tdma->chip_data->terminate(tdc); + if (err) { + spin_unlock_irqrestore(&tdc->vc.lock, flags); + return err; + } + + tegra_dma_disable(tdc); + tdc->dma_desc = NULL; + } + + tegra_dma_sid_free(tdc); + vchan_get_all_descriptors(&tdc->vc, &head); + spin_unlock_irqrestore(&tdc->vc.lock, flags); + + vchan_dma_desc_free_list(&tdc->vc, &head); + + return 0; +} + +static int tegra_dma_get_residual(struct tegra_dma_channel *tdc) +{ + struct tegra_dma_desc *dma_desc = tdc->dma_desc; + struct tegra_dma_sg_req *sg_req = dma_desc->sg_req; + unsigned int bytes_xfer, residual; + u32 wcount = 0, status; + + wcount = tdc_read(tdc, TEGRA_GPCDMA_CHAN_XFER_COUNT); + + /* + * Set wcount = 0 if EOC bit is set. The transfer would have + * already completed and the CHAN_XFER_COUNT could have updated + * for the next transfer, specifically in case of cyclic transfers. + */ + status = tdc_read(tdc, TEGRA_GPCDMA_CHAN_STATUS); + if (status & TEGRA_GPCDMA_STATUS_ISE_EOC) + wcount = 0; + + bytes_xfer = dma_desc->bytes_xfer + + sg_req[dma_desc->sg_idx].len - (wcount * 4); + + residual = dma_desc->bytes_req - (bytes_xfer % dma_desc->bytes_req); + + return residual; +} + +static enum dma_status tegra_dma_tx_status(struct dma_chan *dc, + dma_cookie_t cookie, + struct dma_tx_state *txstate) +{ + struct tegra_dma_channel *tdc = to_tegra_dma_chan(dc); + struct tegra_dma_desc *dma_desc; + struct virt_dma_desc *vd; + unsigned int residual; + unsigned long flags; + enum dma_status ret; + + ret = dma_cookie_status(dc, cookie, txstate); + if (ret == DMA_COMPLETE) + return ret; + + spin_lock_irqsave(&tdc->vc.lock, flags); + vd = vchan_find_desc(&tdc->vc, cookie); + if (vd) { + dma_desc = vd_to_tegra_dma_desc(vd); + residual = dma_desc->bytes_req; + dma_set_residue(txstate, residual); + } else if (tdc->dma_desc && tdc->dma_desc->vd.tx.cookie == cookie) { + residual = tegra_dma_get_residual(tdc); + dma_set_residue(txstate, residual); + } else { + dev_err(tdc2dev(tdc), "cookie %d is not found\n", cookie); + } + spin_unlock_irqrestore(&tdc->vc.lock, flags); + + return ret; +} + +static inline int get_bus_width(struct tegra_dma_channel *tdc, + enum dma_slave_buswidth slave_bw) +{ + switch (slave_bw) { + case DMA_SLAVE_BUSWIDTH_1_BYTE: + return TEGRA_GPCDMA_MMIOSEQ_BUS_WIDTH_8; + case DMA_SLAVE_BUSWIDTH_2_BYTES: + return TEGRA_GPCDMA_MMIOSEQ_BUS_WIDTH_16; + case DMA_SLAVE_BUSWIDTH_4_BYTES: + return TEGRA_GPCDMA_MMIOSEQ_BUS_WIDTH_32; + default: + dev_err(tdc2dev(tdc), "given slave bus width is not supported\n"); + return -EINVAL; + } +} + +static unsigned int get_burst_size(struct tegra_dma_channel *tdc, + u32 burst_size, enum dma_slave_buswidth slave_bw, + int len) +{ + unsigned int burst_mmio_width, burst_byte; + + /* + * burst_size from client is in terms of the bus_width. + * convert that into words. + * If burst_size is not specified from client, then use + * len to calculate the optimum burst size + */ + burst_byte = burst_size ? burst_size * slave_bw : len; + burst_mmio_width = burst_byte / 4; + + if (burst_mmio_width < TEGRA_GPCDMA_MMIOSEQ_BURST_MIN) + return 0; + + burst_mmio_width = min(burst_mmio_width, TEGRA_GPCDMA_MMIOSEQ_BURST_MAX); + + return TEGRA_GPCDMA_MMIOSEQ_BURST(burst_mmio_width); +} + +static int get_transfer_param(struct tegra_dma_channel *tdc, + enum dma_transfer_direction direction, + u32 *apb_addr, + u32 *mmio_seq, + u32 *csr, + unsigned int *burst_size, + enum dma_slave_buswidth *slave_bw) +{ + switch (direction) { + case DMA_MEM_TO_DEV: + *apb_addr = tdc->dma_sconfig.dst_addr; + *mmio_seq = get_bus_width(tdc, tdc->dma_sconfig.dst_addr_width); + *burst_size = tdc->dma_sconfig.dst_maxburst; + *slave_bw = tdc->dma_sconfig.dst_addr_width; + *csr = TEGRA_GPCDMA_CSR_DMA_MEM2IO_FC; + return 0; + case DMA_DEV_TO_MEM: + *apb_addr = tdc->dma_sconfig.src_addr; + *mmio_seq = get_bus_width(tdc, tdc->dma_sconfig.src_addr_width); + *burst_size = tdc->dma_sconfig.src_maxburst; + *slave_bw = tdc->dma_sconfig.src_addr_width; + *csr = TEGRA_GPCDMA_CSR_DMA_IO2MEM_FC; + return 0; + default: + dev_err(tdc2dev(tdc), "DMA direction is not supported\n"); + } + + return -EINVAL; +} + +static struct dma_async_tx_descriptor * +tegra_dma_prep_dma_memset(struct dma_chan *dc, dma_addr_t dest, int value, + size_t len, unsigned long flags) +{ + struct tegra_dma_channel *tdc = to_tegra_dma_chan(dc); + unsigned int max_dma_count = tdc->tdma->chip_data->max_dma_count; + struct tegra_dma_sg_req *sg_req; + struct tegra_dma_desc *dma_desc; + u32 csr, mc_seq; + + if ((len & 3) || (dest & 3) || len > max_dma_count) { + dev_err(tdc2dev(tdc), + "DMA length/memory address is not supported\n"); + return NULL; + } + + /* Set DMA mode to fixed pattern */ + csr = TEGRA_GPCDMA_CSR_DMA_FIXED_PAT; + /* Enable once or continuous mode */ + csr |= TEGRA_GPCDMA_CSR_ONCE; + /* Enable IRQ mask */ + csr |= TEGRA_GPCDMA_CSR_IRQ_MASK; + /* Enable the DMA interrupt */ + if (flags & DMA_PREP_INTERRUPT) + csr |= TEGRA_GPCDMA_CSR_IE_EOC; + /* Configure default priority weight for the channel */ + csr |= FIELD_PREP(TEGRA_GPCDMA_CSR_WEIGHT, 1); + + mc_seq = tdc_read(tdc, TEGRA_GPCDMA_CHAN_MCSEQ); + /* retain stream-id and clean rest */ + mc_seq &= TEGRA_GPCDMA_MCSEQ_STREAM_ID0_MASK; + + /* Set the address wrapping */ + mc_seq |= FIELD_PREP(TEGRA_GPCDMA_MCSEQ_WRAP0, + TEGRA_GPCDMA_MCSEQ_WRAP_NONE); + mc_seq |= FIELD_PREP(TEGRA_GPCDMA_MCSEQ_WRAP1, + TEGRA_GPCDMA_MCSEQ_WRAP_NONE); + + /* Program outstanding MC requests */ + mc_seq |= FIELD_PREP(TEGRA_GPCDMA_MCSEQ_REQ_COUNT, 1); + /* Set burst size */ + mc_seq |= TEGRA_GPCDMA_MCSEQ_BURST_16; + + dma_desc = kzalloc(struct_size(dma_desc, sg_req, 1), GFP_NOWAIT); + if (!dma_desc) + return NULL; + + dma_desc->bytes_req = len; + dma_desc->sg_count = 1; + sg_req = dma_desc->sg_req; + + sg_req[0].ch_regs.src_ptr = 0; + sg_req[0].ch_regs.dst_ptr = dest; + sg_req[0].ch_regs.high_addr_ptr = + FIELD_PREP(TEGRA_GPCDMA_HIGH_ADDR_DST_PTR, (dest >> 32)); + sg_req[0].ch_regs.fixed_pattern = value; + /* Word count reg takes value as (N +1) words */ + sg_req[0].ch_regs.wcount = ((len - 4) >> 2); + sg_req[0].ch_regs.csr = csr; + sg_req[0].ch_regs.mmio_seq = 0; + sg_req[0].ch_regs.mc_seq = mc_seq; + sg_req[0].len = len; + + dma_desc->cyclic = false; + return vchan_tx_prep(&tdc->vc, &dma_desc->vd, flags); +} + +static struct dma_async_tx_descriptor * +tegra_dma_prep_dma_memcpy(struct dma_chan *dc, dma_addr_t dest, + dma_addr_t src, size_t len, unsigned long flags) +{ + struct tegra_dma_channel *tdc = to_tegra_dma_chan(dc); + struct tegra_dma_sg_req *sg_req; + struct tegra_dma_desc *dma_desc; + unsigned int max_dma_count; + u32 csr, mc_seq; + + max_dma_count = tdc->tdma->chip_data->max_dma_count; + if ((len & 3) || (src & 3) || (dest & 3) || len > max_dma_count) { + dev_err(tdc2dev(tdc), + "DMA length/memory address is not supported\n"); + return NULL; + } + + /* Set DMA mode to memory to memory transfer */ + csr = TEGRA_GPCDMA_CSR_DMA_MEM2MEM; + /* Enable once or continuous mode */ + csr |= TEGRA_GPCDMA_CSR_ONCE; + /* Enable IRQ mask */ + csr |= TEGRA_GPCDMA_CSR_IRQ_MASK; + /* Enable the DMA interrupt */ + if (flags & DMA_PREP_INTERRUPT) + csr |= TEGRA_GPCDMA_CSR_IE_EOC; + /* Configure default priority weight for the channel */ + csr |= FIELD_PREP(TEGRA_GPCDMA_CSR_WEIGHT, 1); + + mc_seq = tdc_read(tdc, TEGRA_GPCDMA_CHAN_MCSEQ); + /* retain stream-id and clean rest */ + mc_seq &= (TEGRA_GPCDMA_MCSEQ_STREAM_ID0_MASK) | + (TEGRA_GPCDMA_MCSEQ_STREAM_ID1_MASK); + + /* Set the address wrapping */ + mc_seq |= FIELD_PREP(TEGRA_GPCDMA_MCSEQ_WRAP0, + TEGRA_GPCDMA_MCSEQ_WRAP_NONE); + mc_seq |= FIELD_PREP(TEGRA_GPCDMA_MCSEQ_WRAP1, + TEGRA_GPCDMA_MCSEQ_WRAP_NONE); + + /* Program outstanding MC requests */ + mc_seq |= FIELD_PREP(TEGRA_GPCDMA_MCSEQ_REQ_COUNT, 1); + /* Set burst size */ + mc_seq |= TEGRA_GPCDMA_MCSEQ_BURST_16; + + dma_desc = kzalloc(struct_size(dma_desc, sg_req, 1), GFP_NOWAIT); + if (!dma_desc) + return NULL; + + dma_desc->bytes_req = len; + dma_desc->sg_count = 1; + sg_req = dma_desc->sg_req; + + sg_req[0].ch_regs.src_ptr = src; + sg_req[0].ch_regs.dst_ptr = dest; + sg_req[0].ch_regs.high_addr_ptr = + FIELD_PREP(TEGRA_GPCDMA_HIGH_ADDR_SRC_PTR, (src >> 32)); + sg_req[0].ch_regs.high_addr_ptr |= + FIELD_PREP(TEGRA_GPCDMA_HIGH_ADDR_DST_PTR, (dest >> 32)); + /* Word count reg takes value as (N +1) words */ + sg_req[0].ch_regs.wcount = ((len - 4) >> 2); + sg_req[0].ch_regs.csr = csr; + sg_req[0].ch_regs.mmio_seq = 0; + sg_req[0].ch_regs.mc_seq = mc_seq; + sg_req[0].len = len; + + dma_desc->cyclic = false; + return vchan_tx_prep(&tdc->vc, &dma_desc->vd, flags); +} + +static struct dma_async_tx_descriptor * +tegra_dma_prep_slave_sg(struct dma_chan *dc, struct scatterlist *sgl, + unsigned int sg_len, enum dma_transfer_direction direction, + unsigned long flags, void *context) +{ + struct tegra_dma_channel *tdc = to_tegra_dma_chan(dc); + unsigned int max_dma_count = tdc->tdma->chip_data->max_dma_count; + enum dma_slave_buswidth slave_bw = DMA_SLAVE_BUSWIDTH_UNDEFINED; + u32 csr, mc_seq, apb_ptr = 0, mmio_seq = 0; + struct tegra_dma_sg_req *sg_req; + struct tegra_dma_desc *dma_desc; + struct scatterlist *sg; + u32 burst_size; + unsigned int i; + int ret; + + if (!tdc->config_init) { + dev_err(tdc2dev(tdc), "DMA channel is not configured\n"); + return NULL; + } + if (sg_len < 1) { + dev_err(tdc2dev(tdc), "Invalid segment length %d\n", sg_len); + return NULL; + } + + ret = tegra_dma_sid_reserve(tdc, direction); + if (ret) + return NULL; + + ret = get_transfer_param(tdc, direction, &apb_ptr, &mmio_seq, &csr, + &burst_size, &slave_bw); + if (ret < 0) + return NULL; + + /* Enable once or continuous mode */ + csr |= TEGRA_GPCDMA_CSR_ONCE; + /* Program the slave id in requestor select */ + csr |= FIELD_PREP(TEGRA_GPCDMA_CSR_REQ_SEL_MASK, tdc->slave_id); + /* Enable IRQ mask */ + csr |= TEGRA_GPCDMA_CSR_IRQ_MASK; + /* Configure default priority weight for the channel*/ + csr |= FIELD_PREP(TEGRA_GPCDMA_CSR_WEIGHT, 1); + + /* Enable the DMA interrupt */ + if (flags & DMA_PREP_INTERRUPT) + csr |= TEGRA_GPCDMA_CSR_IE_EOC; + + mc_seq = tdc_read(tdc, TEGRA_GPCDMA_CHAN_MCSEQ); + /* retain stream-id and clean rest */ + mc_seq &= TEGRA_GPCDMA_MCSEQ_STREAM_ID0_MASK; + + /* Set the address wrapping on both MC and MMIO side */ + + mc_seq |= FIELD_PREP(TEGRA_GPCDMA_MCSEQ_WRAP0, + TEGRA_GPCDMA_MCSEQ_WRAP_NONE); + mc_seq |= FIELD_PREP(TEGRA_GPCDMA_MCSEQ_WRAP1, + TEGRA_GPCDMA_MCSEQ_WRAP_NONE); + mmio_seq |= FIELD_PREP(TEGRA_GPCDMA_MMIOSEQ_WRAP_WORD, 1); + + /* Program 2 MC outstanding requests by default. */ + mc_seq |= FIELD_PREP(TEGRA_GPCDMA_MCSEQ_REQ_COUNT, 1); + + /* Setting MC burst size depending on MMIO burst size */ + if (burst_size == 64) + mc_seq |= TEGRA_GPCDMA_MCSEQ_BURST_16; + else + mc_seq |= TEGRA_GPCDMA_MCSEQ_BURST_2; + + dma_desc = kzalloc(struct_size(dma_desc, sg_req, sg_len), GFP_NOWAIT); + if (!dma_desc) + return NULL; + + dma_desc->sg_count = sg_len; + sg_req = dma_desc->sg_req; + + /* Make transfer requests */ + for_each_sg(sgl, sg, sg_len, i) { + u32 len; + dma_addr_t mem; + + mem = sg_dma_address(sg); + len = sg_dma_len(sg); + + if ((len & 3) || (mem & 3) || len > max_dma_count) { + dev_err(tdc2dev(tdc), + "DMA length/memory address is not supported\n"); + kfree(dma_desc); + return NULL; + } + + mmio_seq |= get_burst_size(tdc, burst_size, slave_bw, len); + dma_desc->bytes_req += len; + + if (direction == DMA_MEM_TO_DEV) { + sg_req[i].ch_regs.src_ptr = mem; + sg_req[i].ch_regs.dst_ptr = apb_ptr; + sg_req[i].ch_regs.high_addr_ptr = + FIELD_PREP(TEGRA_GPCDMA_HIGH_ADDR_SRC_PTR, (mem >> 32)); + } else if (direction == DMA_DEV_TO_MEM) { + sg_req[i].ch_regs.src_ptr = apb_ptr; + sg_req[i].ch_regs.dst_ptr = mem; + sg_req[i].ch_regs.high_addr_ptr = + FIELD_PREP(TEGRA_GPCDMA_HIGH_ADDR_DST_PTR, (mem >> 32)); + } + + /* + * Word count register takes input in words. Writing a value + * of N into word count register means a req of (N+1) words. + */ + sg_req[i].ch_regs.wcount = ((len - 4) >> 2); + sg_req[i].ch_regs.csr = csr; + sg_req[i].ch_regs.mmio_seq = mmio_seq; + sg_req[i].ch_regs.mc_seq = mc_seq; + sg_req[i].len = len; + } + + dma_desc->cyclic = false; + return vchan_tx_prep(&tdc->vc, &dma_desc->vd, flags); +} + +static struct dma_async_tx_descriptor * +tegra_dma_prep_dma_cyclic(struct dma_chan *dc, dma_addr_t buf_addr, size_t buf_len, + size_t period_len, enum dma_transfer_direction direction, + unsigned long flags) +{ + enum dma_slave_buswidth slave_bw = DMA_SLAVE_BUSWIDTH_UNDEFINED; + u32 csr, mc_seq, apb_ptr = 0, mmio_seq = 0, burst_size; + unsigned int max_dma_count, len, period_count, i; + struct tegra_dma_channel *tdc = to_tegra_dma_chan(dc); + struct tegra_dma_desc *dma_desc; + struct tegra_dma_sg_req *sg_req; + dma_addr_t mem = buf_addr; + int ret; + + if (!buf_len || !period_len) { + dev_err(tdc2dev(tdc), "Invalid buffer/period len\n"); + return NULL; + } + + if (!tdc->config_init) { + dev_err(tdc2dev(tdc), "DMA slave is not configured\n"); + return NULL; + } + + ret = tegra_dma_sid_reserve(tdc, direction); + if (ret) + return NULL; + + /* + * We only support cycle transfer when buf_len is multiple of + * period_len. + */ + if (buf_len % period_len) { + dev_err(tdc2dev(tdc), "buf_len is not multiple of period_len\n"); + return NULL; + } + + len = period_len; + max_dma_count = tdc->tdma->chip_data->max_dma_count; + if ((len & 3) || (buf_addr & 3) || len > max_dma_count) { + dev_err(tdc2dev(tdc), "Req len/mem address is not correct\n"); + return NULL; + } + + ret = get_transfer_param(tdc, direction, &apb_ptr, &mmio_seq, &csr, + &burst_size, &slave_bw); + if (ret < 0) + return NULL; + + /* Enable once or continuous mode */ + csr &= ~TEGRA_GPCDMA_CSR_ONCE; + /* Program the slave id in requestor select */ + csr |= FIELD_PREP(TEGRA_GPCDMA_CSR_REQ_SEL_MASK, tdc->slave_id); + /* Enable IRQ mask */ + csr |= TEGRA_GPCDMA_CSR_IRQ_MASK; + /* Configure default priority weight for the channel*/ + csr |= FIELD_PREP(TEGRA_GPCDMA_CSR_WEIGHT, 1); + + /* Enable the DMA interrupt */ + if (flags & DMA_PREP_INTERRUPT) + csr |= TEGRA_GPCDMA_CSR_IE_EOC; + + mmio_seq |= FIELD_PREP(TEGRA_GPCDMA_MMIOSEQ_WRAP_WORD, 1); + + mc_seq = tdc_read(tdc, TEGRA_GPCDMA_CHAN_MCSEQ); + /* retain stream-id and clean rest */ + mc_seq &= TEGRA_GPCDMA_MCSEQ_STREAM_ID0_MASK; + + /* Set the address wrapping on both MC and MMIO side */ + mc_seq |= FIELD_PREP(TEGRA_GPCDMA_MCSEQ_WRAP0, + TEGRA_GPCDMA_MCSEQ_WRAP_NONE); + mc_seq |= FIELD_PREP(TEGRA_GPCDMA_MCSEQ_WRAP1, + TEGRA_GPCDMA_MCSEQ_WRAP_NONE); + + /* Program 2 MC outstanding requests by default. */ + mc_seq |= FIELD_PREP(TEGRA_GPCDMA_MCSEQ_REQ_COUNT, 1); + /* Setting MC burst size depending on MMIO burst size */ + if (burst_size == 64) + mc_seq |= TEGRA_GPCDMA_MCSEQ_BURST_16; + else + mc_seq |= TEGRA_GPCDMA_MCSEQ_BURST_2; + + period_count = buf_len / period_len; + dma_desc = kzalloc(struct_size(dma_desc, sg_req, period_count), + GFP_NOWAIT); + if (!dma_desc) + return NULL; + + dma_desc->bytes_req = buf_len; + dma_desc->sg_count = period_count; + sg_req = dma_desc->sg_req; + + /* Split transfer equal to period size */ + for (i = 0; i < period_count; i++) { + mmio_seq |= get_burst_size(tdc, burst_size, slave_bw, len); + if (direction == DMA_MEM_TO_DEV) { + sg_req[i].ch_regs.src_ptr = mem; + sg_req[i].ch_regs.dst_ptr = apb_ptr; + sg_req[i].ch_regs.high_addr_ptr = + FIELD_PREP(TEGRA_GPCDMA_HIGH_ADDR_SRC_PTR, (mem >> 32)); + } else if (direction == DMA_DEV_TO_MEM) { + sg_req[i].ch_regs.src_ptr = apb_ptr; + sg_req[i].ch_regs.dst_ptr = mem; + sg_req[i].ch_regs.high_addr_ptr = + FIELD_PREP(TEGRA_GPCDMA_HIGH_ADDR_DST_PTR, (mem >> 32)); + } + /* + * Word count register takes input in words. Writing a value + * of N into word count register means a req of (N+1) words. + */ + sg_req[i].ch_regs.wcount = ((len - 4) >> 2); + sg_req[i].ch_regs.csr = csr; + sg_req[i].ch_regs.mmio_seq = mmio_seq; + sg_req[i].ch_regs.mc_seq = mc_seq; + sg_req[i].len = len; + + mem += len; + } + + dma_desc->cyclic = true; + + return vchan_tx_prep(&tdc->vc, &dma_desc->vd, flags); +} + +static int tegra_dma_alloc_chan_resources(struct dma_chan *dc) +{ + struct tegra_dma_channel *tdc = to_tegra_dma_chan(dc); + int ret; + + ret = request_irq(tdc->irq, tegra_dma_isr, 0, tdc->name, tdc); + if (ret) { + dev_err(tdc2dev(tdc), "request_irq failed for %s\n", tdc->name); + return ret; + } + + dma_cookie_init(&tdc->vc.chan); + tdc->config_init = false; + return 0; +} + +static void tegra_dma_chan_synchronize(struct dma_chan *dc) +{ + struct tegra_dma_channel *tdc = to_tegra_dma_chan(dc); + + synchronize_irq(tdc->irq); + vchan_synchronize(&tdc->vc); +} + +static void tegra_dma_free_chan_resources(struct dma_chan *dc) +{ + struct tegra_dma_channel *tdc = to_tegra_dma_chan(dc); + + dev_dbg(tdc2dev(tdc), "Freeing channel %d\n", tdc->id); + + tegra_dma_terminate_all(dc); + synchronize_irq(tdc->irq); + + tasklet_kill(&tdc->vc.task); + tdc->config_init = false; + tdc->slave_id = -1; + tdc->sid_dir = DMA_TRANS_NONE; + free_irq(tdc->irq, tdc); + + vchan_free_chan_resources(&tdc->vc); +} + +static struct dma_chan *tegra_dma_of_xlate(struct of_phandle_args *dma_spec, + struct of_dma *ofdma) +{ + struct tegra_dma *tdma = ofdma->of_dma_data; + struct tegra_dma_channel *tdc; + struct dma_chan *chan; + + chan = dma_get_any_slave_channel(&tdma->dma_dev); + if (!chan) + return NULL; + + tdc = to_tegra_dma_chan(chan); + tdc->slave_id = dma_spec->args[0]; + + return chan; +} + +static const struct tegra_dma_chip_data tegra186_dma_chip_data = { + .nr_channels = 31, + .channel_reg_size = SZ_64K, + .max_dma_count = SZ_1G, + .hw_support_pause = false, + .terminate = tegra_dma_stop_client, +}; + +static const struct tegra_dma_chip_data tegra194_dma_chip_data = { + .nr_channels = 31, + .channel_reg_size = SZ_64K, + .max_dma_count = SZ_1G, + .hw_support_pause = true, + .terminate = tegra_dma_pause, +}; + +static const struct of_device_id tegra_dma_of_match[] = { + { + .compatible = "nvidia,tegra186-gpcdma", + .data = &tegra186_dma_chip_data, + }, { + .compatible = "nvidia,tegra194-gpcdma", + .data = &tegra194_dma_chip_data, + }, { + }, +}; +MODULE_DEVICE_TABLE(of, tegra_dma_of_match); + +static int tegra_dma_program_sid(struct tegra_dma_channel *tdc, int stream_id) +{ + unsigned int reg_val = tdc_read(tdc, TEGRA_GPCDMA_CHAN_MCSEQ); + + reg_val &= ~(TEGRA_GPCDMA_MCSEQ_STREAM_ID0_MASK); + reg_val &= ~(TEGRA_GPCDMA_MCSEQ_STREAM_ID1_MASK); + + reg_val |= FIELD_PREP(TEGRA_GPCDMA_MCSEQ_STREAM_ID0_MASK, stream_id); + reg_val |= FIELD_PREP(TEGRA_GPCDMA_MCSEQ_STREAM_ID1_MASK, stream_id); + + tdc_write(tdc, TEGRA_GPCDMA_CHAN_MCSEQ, reg_val); + return 0; +} + +static int tegra_dma_probe(struct platform_device *pdev) +{ + const struct tegra_dma_chip_data *cdata = NULL; + struct iommu_fwspec *iommu_spec; + unsigned int stream_id, i; + struct tegra_dma *tdma; + int ret; + + cdata = of_device_get_match_data(&pdev->dev); + + tdma = devm_kzalloc(&pdev->dev, + struct_size(tdma, channels, cdata->nr_channels), + GFP_KERNEL); + if (!tdma) + return -ENOMEM; + + tdma->dev = &pdev->dev; + tdma->chip_data = cdata; + platform_set_drvdata(pdev, tdma); + + tdma->base_addr = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(tdma->base_addr)) + return PTR_ERR(tdma->base_addr); + + tdma->rst = devm_reset_control_get_exclusive(&pdev->dev, "gpcdma"); + if (IS_ERR(tdma->rst)) { + return dev_err_probe(&pdev->dev, PTR_ERR(tdma->rst), + "Missing controller reset\n"); + } + reset_control_reset(tdma->rst); + + tdma->dma_dev.dev = &pdev->dev; + + iommu_spec = dev_iommu_fwspec_get(&pdev->dev); + if (!iommu_spec) { + dev_err(&pdev->dev, "Missing iommu stream-id\n"); + return -EINVAL; + } + stream_id = iommu_spec->ids[0] & 0xffff; + + INIT_LIST_HEAD(&tdma->dma_dev.channels); + for (i = 0; i < cdata->nr_channels; i++) { + struct tegra_dma_channel *tdc = &tdma->channels[i]; + + tdc->irq = platform_get_irq(pdev, i); + if (tdc->irq < 0) + return tdc->irq; + + tdc->chan_base_offset = TEGRA_GPCDMA_CHANNEL_BASE_ADD_OFFSET + + i * cdata->channel_reg_size; + snprintf(tdc->name, sizeof(tdc->name), "gpcdma.%d", i); + tdc->tdma = tdma; + tdc->id = i; + tdc->slave_id = -1; + + vchan_init(&tdc->vc, &tdma->dma_dev); + tdc->vc.desc_free = tegra_dma_desc_free; + + /* program stream-id for this channel */ + tegra_dma_program_sid(tdc, stream_id); + tdc->stream_id = stream_id; + } + + dma_cap_set(DMA_SLAVE, tdma->dma_dev.cap_mask); + dma_cap_set(DMA_PRIVATE, tdma->dma_dev.cap_mask); + dma_cap_set(DMA_MEMCPY, tdma->dma_dev.cap_mask); + dma_cap_set(DMA_MEMSET, tdma->dma_dev.cap_mask); + dma_cap_set(DMA_CYCLIC, tdma->dma_dev.cap_mask); + + /* + * Only word aligned transfers are supported. Set the copy + * alignment shift. + */ + tdma->dma_dev.copy_align = 2; + tdma->dma_dev.fill_align = 2; + tdma->dma_dev.device_alloc_chan_resources = + tegra_dma_alloc_chan_resources; + tdma->dma_dev.device_free_chan_resources = + tegra_dma_free_chan_resources; + tdma->dma_dev.device_prep_slave_sg = tegra_dma_prep_slave_sg; + tdma->dma_dev.device_prep_dma_memcpy = tegra_dma_prep_dma_memcpy; + tdma->dma_dev.device_prep_dma_memset = tegra_dma_prep_dma_memset; + tdma->dma_dev.device_prep_dma_cyclic = tegra_dma_prep_dma_cyclic; + tdma->dma_dev.device_config = tegra_dma_slave_config; + tdma->dma_dev.device_terminate_all = tegra_dma_terminate_all; + tdma->dma_dev.device_tx_status = tegra_dma_tx_status; + tdma->dma_dev.device_issue_pending = tegra_dma_issue_pending; + tdma->dma_dev.device_pause = tegra_dma_device_pause; + tdma->dma_dev.device_resume = tegra_dma_device_resume; + tdma->dma_dev.device_synchronize = tegra_dma_chan_synchronize; + tdma->dma_dev.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST; + + ret = dma_async_device_register(&tdma->dma_dev); + if (ret < 0) { + dev_err_probe(&pdev->dev, ret, + "GPC DMA driver registration failed\n"); + return ret; + } + + ret = of_dma_controller_register(pdev->dev.of_node, + tegra_dma_of_xlate, tdma); + if (ret < 0) { + dev_err_probe(&pdev->dev, ret, + "GPC DMA OF registration failed\n"); + + dma_async_device_unregister(&tdma->dma_dev); + return ret; + } + + dev_info(&pdev->dev, "GPC DMA driver register %d channels\n", + cdata->nr_channels); + + return 0; +} + +static int tegra_dma_remove(struct platform_device *pdev) +{ + struct tegra_dma *tdma = platform_get_drvdata(pdev); + + of_dma_controller_free(pdev->dev.of_node); + dma_async_device_unregister(&tdma->dma_dev); + + return 0; +} + +static int __maybe_unused tegra_dma_pm_suspend(struct device *dev) +{ + struct tegra_dma *tdma = dev_get_drvdata(dev); + unsigned int i; + + for (i = 0; i < tdma->chip_data->nr_channels; i++) { + struct tegra_dma_channel *tdc = &tdma->channels[i]; + + if (tdc->dma_desc) { + dev_err(tdma->dev, "channel %u busy\n", i); + return -EBUSY; + } + } + + return 0; +} + +static int __maybe_unused tegra_dma_pm_resume(struct device *dev) +{ + struct tegra_dma *tdma = dev_get_drvdata(dev); + unsigned int i; + + reset_control_reset(tdma->rst); + + for (i = 0; i < tdma->chip_data->nr_channels; i++) { + struct tegra_dma_channel *tdc = &tdma->channels[i]; + + tegra_dma_program_sid(tdc, tdc->stream_id); + } + + return 0; +} + +static const struct dev_pm_ops tegra_dma_dev_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(tegra_dma_pm_suspend, tegra_dma_pm_resume) +}; + +static struct platform_driver tegra_dma_driver = { + .driver = { + .name = "tegra-gpcdma", + .pm = &tegra_dma_dev_pm_ops, + .of_match_table = tegra_dma_of_match, + }, + .probe = tegra_dma_probe, + .remove = tegra_dma_remove, +}; + +module_platform_driver(tegra_dma_driver); + +MODULE_DESCRIPTION("NVIDIA Tegra GPC DMA Controller driver"); +MODULE_AUTHOR("Pavan Kunapuli "); +MODULE_AUTHOR("Rajesh Gumasta "); +MODULE_LICENSE("GPL"); diff --git a/drivers/dma/ti/cppi41.c b/drivers/dma/ti/cppi41.c index 062bd9bd4de00e23408f53c909838a6ce07c9a93..695915dba7079a5e28a431c4bad128ebeb30c073 100644 --- a/drivers/dma/ti/cppi41.c +++ b/drivers/dma/ti/cppi41.c @@ -1105,8 +1105,12 @@ static int cppi41_dma_probe(struct platform_device *pdev) cdd->qmgr_num_pend = glue_info->qmgr_num_pend; cdd->first_completion_queue = glue_info->first_completion_queue; + /* Parse new and deprecated dma-channels properties */ ret = of_property_read_u32(dev->of_node, - "#dma-channels", &cdd->n_chans); + "dma-channels", &cdd->n_chans); + if (ret) + ret = of_property_read_u32(dev->of_node, + "#dma-channels", &cdd->n_chans); if (ret) goto err_get_n_chans; diff --git a/drivers/dma/ti/k3-psil-am62.c b/drivers/dma/ti/k3-psil-am62.c index d431e20332378b08ecaf4518f456a3e95c520a26..2b6fd6e37c610741563ca80d6372bb3d21225a40 100644 --- a/drivers/dma/ti/k3-psil-am62.c +++ b/drivers/dma/ti/k3-psil-am62.c @@ -70,10 +70,10 @@ /* PSI-L source thread IDs, used for RX (DMA_DEV_TO_MEM) */ static struct psil_ep am62_src_ep_map[] = { /* SAUL */ - PSIL_SAUL(0x7500, 20, 35, 8, 35, 0), - PSIL_SAUL(0x7501, 21, 35, 8, 36, 0), - PSIL_SAUL(0x7502, 22, 43, 8, 43, 0), - PSIL_SAUL(0x7503, 23, 43, 8, 44, 0), + PSIL_SAUL(0x7504, 20, 35, 8, 35, 0), + PSIL_SAUL(0x7505, 21, 35, 8, 36, 0), + PSIL_SAUL(0x7506, 22, 43, 8, 43, 0), + PSIL_SAUL(0x7507, 23, 43, 8, 44, 0), /* PDMA_MAIN0 - SPI0-3 */ PSIL_PDMA_XY_PKT(0x4302), PSIL_PDMA_XY_PKT(0x4303), diff --git a/drivers/dma/xilinx/zynqmp_dma.c b/drivers/dma/xilinx/zynqmp_dma.c index 7aa63b6520272e235765a243be438b97ec88c87b..dc299ab3681803ce094cafaaba1d7fa92168baf4 100644 --- a/drivers/dma/xilinx/zynqmp_dma.c +++ b/drivers/dma/xilinx/zynqmp_dma.c @@ -229,7 +229,7 @@ struct zynqmp_dma_chan { bool is_dmacoherent; struct tasklet_struct tasklet; bool idle; - u32 desc_size; + size_t desc_size; bool err; u32 bus_width; u32 src_burst_len; @@ -486,7 +486,8 @@ static int zynqmp_dma_alloc_chan_resources(struct dma_chan *dchan) } chan->desc_pool_v = dma_alloc_coherent(chan->dev, - (2 * chan->desc_size * ZYNQMP_DMA_NUM_DESCS), + (2 * ZYNQMP_DMA_DESC_SIZE(chan) * + ZYNQMP_DMA_NUM_DESCS), &chan->desc_pool_p, GFP_KERNEL); if (!chan->desc_pool_v) return -ENOMEM; @@ -1077,7 +1078,11 @@ static int zynqmp_dma_probe(struct platform_device *pdev) pm_runtime_set_autosuspend_delay(zdev->dev, ZDMA_PM_TIMEOUT); pm_runtime_use_autosuspend(zdev->dev); pm_runtime_enable(zdev->dev); - pm_runtime_get_sync(zdev->dev); + ret = pm_runtime_resume_and_get(zdev->dev); + if (ret < 0) { + dev_err(&pdev->dev, "device wakeup failed.\n"); + pm_runtime_disable(zdev->dev); + } if (!pm_runtime_enabled(zdev->dev)) { ret = zynqmp_dma_runtime_resume(zdev->dev); if (ret) @@ -1093,7 +1098,11 @@ static int zynqmp_dma_probe(struct platform_device *pdev) p->dst_addr_widths = BIT(zdev->chan->bus_width / 8); p->src_addr_widths = BIT(zdev->chan->bus_width / 8); - dma_async_device_register(&zdev->common); + ret = dma_async_device_register(&zdev->common); + if (ret) { + dev_err(zdev->dev, "failed to register the dma device\n"); + goto free_chan_resources; + } ret = of_dma_controller_register(pdev->dev.of_node, of_zynqmp_dma_xlate, zdev); diff --git a/drivers/gpio/gpio-rockchip.c b/drivers/gpio/gpio-rockchip.c index 099e358d2491557a1f35ccf3809852d3441f00b8..e342a6dc4c6c1997052756b3f88130218608ed36 100644 --- a/drivers/gpio/gpio-rockchip.c +++ b/drivers/gpio/gpio-rockchip.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include "../pinctrl/core.h" @@ -706,7 +707,7 @@ static int rockchip_gpio_probe(struct platform_device *pdev) struct device_node *pctlnp = of_get_parent(np); struct pinctrl_dev *pctldev = NULL; struct rockchip_pin_bank *bank = NULL; - struct rockchip_pin_output_deferred *cfg; + struct rockchip_pin_deferred *cfg; static int gpio; int id, ret; @@ -747,15 +748,27 @@ static int rockchip_gpio_probe(struct platform_device *pdev) return ret; } - while (!list_empty(&bank->deferred_output)) { - cfg = list_first_entry(&bank->deferred_output, - struct rockchip_pin_output_deferred, head); + while (!list_empty(&bank->deferred_pins)) { + cfg = list_first_entry(&bank->deferred_pins, + struct rockchip_pin_deferred, head); list_del(&cfg->head); - ret = rockchip_gpio_direction_output(&bank->gpio_chip, cfg->pin, cfg->arg); - if (ret) - dev_warn(dev, "setting output pin %u to %u failed\n", cfg->pin, cfg->arg); - + switch (cfg->param) { + case PIN_CONFIG_OUTPUT: + ret = rockchip_gpio_direction_output(&bank->gpio_chip, cfg->pin, cfg->arg); + if (ret) + dev_warn(dev, "setting output pin %u to %u failed\n", cfg->pin, + cfg->arg); + break; + case PIN_CONFIG_INPUT_ENABLE: + ret = rockchip_gpio_direction_input(&bank->gpio_chip, cfg->pin); + if (ret) + dev_warn(dev, "setting input pin %u failed\n", cfg->pin); + break; + default: + dev_warn(dev, "unknown deferred config param %d\n", cfg->param); + break; + } kfree(cfg); } diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index b7ac07f43b95e24f5430c7df5ab0910a2d616da9..3d6c3ffd55766509bf210faddc011260f04e8f7e 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c @@ -930,6 +930,11 @@ static int of_gpiochip_add_pin_range(struct gpio_chip *chip) if (!np) return 0; + if (!of_property_read_bool(np, "gpio-ranges") && + chip->of_gpio_ranges_fallback) { + return chip->of_gpio_ranges_fallback(chip, np); + } + group_names = of_find_property(np, group_names_propname, NULL); for (;; index++) { diff --git a/drivers/gpu/drm/hyperv/hyperv_drm_modeset.c b/drivers/gpu/drm/hyperv/hyperv_drm_modeset.c index e82b815f83a65567564c7d858bf45de59917f924..27f4fcb058f93ece83338829f1e960e918e2cc87 100644 --- a/drivers/gpu/drm/hyperv/hyperv_drm_modeset.c +++ b/drivers/gpu/drm/hyperv/hyperv_drm_modeset.c @@ -123,8 +123,11 @@ static int hyperv_pipe_check(struct drm_simple_display_pipe *pipe, if (fb->format->format != DRM_FORMAT_XRGB8888) return -EINVAL; - if (fb->pitches[0] * fb->height > hv->fb_size) + if (fb->pitches[0] * fb->height > hv->fb_size) { + drm_err(&hv->dev, "fb size requested by %s for %dX%d (pitch %d) greater than %ld\n", + current->comm, fb->width, fb->height, fb->pitches[0], hv->fb_size); return -EINVAL; + } return 0; } diff --git a/drivers/gpu/drm/hyperv/hyperv_drm_proto.c b/drivers/gpu/drm/hyperv/hyperv_drm_proto.c index c0155c6271bf8935f9b1c967a9d2fd739fc4f074..76a182a9a7654736c175c7eac9d3b814c815bb2a 100644 --- a/drivers/gpu/drm/hyperv/hyperv_drm_proto.c +++ b/drivers/gpu/drm/hyperv/hyperv_drm_proto.c @@ -18,16 +18,16 @@ #define SYNTHVID_VERSION(major, minor) ((minor) << 16 | (major)) #define SYNTHVID_VER_GET_MAJOR(ver) (ver & 0x0000ffff) #define SYNTHVID_VER_GET_MINOR(ver) ((ver & 0xffff0000) >> 16) + +/* Support for VERSION_WIN7 is removed. #define is retained for reference. */ #define SYNTHVID_VERSION_WIN7 SYNTHVID_VERSION(3, 0) #define SYNTHVID_VERSION_WIN8 SYNTHVID_VERSION(3, 2) #define SYNTHVID_VERSION_WIN10 SYNTHVID_VERSION(3, 5) -#define SYNTHVID_DEPTH_WIN7 16 #define SYNTHVID_DEPTH_WIN8 32 -#define SYNTHVID_FB_SIZE_WIN7 (4 * 1024 * 1024) +#define SYNTHVID_WIDTH_WIN8 1600 +#define SYNTHVID_HEIGHT_WIN8 1200 #define SYNTHVID_FB_SIZE_WIN8 (8 * 1024 * 1024) -#define SYNTHVID_WIDTH_MAX_WIN7 1600 -#define SYNTHVID_HEIGHT_MAX_WIN7 1200 enum pipe_msg_type { PIPE_MSG_INVALID, @@ -496,12 +496,6 @@ int hyperv_connect_vsp(struct hv_device *hdev) case VERSION_WIN8: case VERSION_WIN8_1: ret = hyperv_negotiate_version(hdev, SYNTHVID_VERSION_WIN8); - if (!ret) - break; - fallthrough; - case VERSION_WS2008: - case VERSION_WIN7: - ret = hyperv_negotiate_version(hdev, SYNTHVID_VERSION_WIN7); break; default: ret = hyperv_negotiate_version(hdev, SYNTHVID_VERSION_WIN10); @@ -513,18 +507,15 @@ int hyperv_connect_vsp(struct hv_device *hdev) goto error; } - if (hv->synthvid_version == SYNTHVID_VERSION_WIN7) - hv->screen_depth = SYNTHVID_DEPTH_WIN7; - else - hv->screen_depth = SYNTHVID_DEPTH_WIN8; + hv->screen_depth = SYNTHVID_DEPTH_WIN8; if (hyperv_version_ge(hv->synthvid_version, SYNTHVID_VERSION_WIN10)) { ret = hyperv_get_supported_resolution(hdev); if (ret) drm_err(dev, "Failed to get supported resolution from host, use default\n"); } else { - hv->screen_width_max = SYNTHVID_WIDTH_MAX_WIN7; - hv->screen_height_max = SYNTHVID_HEIGHT_MAX_WIN7; + hv->screen_width_max = SYNTHVID_WIDTH_WIN8; + hv->screen_height_max = SYNTHVID_HEIGHT_WIN8; } hv->mmio_megabytes = hdev->channel->offermsg.offer.mmio_megabytes; diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c index dc5c35210c16a2f0500145ac0dd8771b514fa783..56f7e06c673e4236ba8d1e01957723a800af63a0 100644 --- a/drivers/hv/channel.c +++ b/drivers/hv/channel.c @@ -1022,11 +1022,13 @@ void vmbus_close(struct vmbus_channel *channel) EXPORT_SYMBOL_GPL(vmbus_close); /** - * vmbus_sendpacket() - Send the specified buffer on the given channel + * vmbus_sendpacket_getid() - Send the specified buffer on the given channel * @channel: Pointer to vmbus_channel structure * @buffer: Pointer to the buffer you want to send the data from. * @bufferlen: Maximum size of what the buffer holds. * @requestid: Identifier of the request + * @trans_id: Identifier of the transaction associated to this request, if + * the send is successful; undefined, otherwise. * @type: Type of packet that is being sent e.g. negotiate, time * packet etc. * @flags: 0 or VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED @@ -1036,8 +1038,8 @@ EXPORT_SYMBOL_GPL(vmbus_close); * * Mainly used by Hyper-V drivers. */ -int vmbus_sendpacket(struct vmbus_channel *channel, void *buffer, - u32 bufferlen, u64 requestid, +int vmbus_sendpacket_getid(struct vmbus_channel *channel, void *buffer, + u32 bufferlen, u64 requestid, u64 *trans_id, enum vmbus_packet_type type, u32 flags) { struct vmpacket_descriptor desc; @@ -1063,7 +1065,31 @@ int vmbus_sendpacket(struct vmbus_channel *channel, void *buffer, bufferlist[2].iov_base = &aligned_data; bufferlist[2].iov_len = (packetlen_aligned - packetlen); - return hv_ringbuffer_write(channel, bufferlist, num_vecs, requestid); + return hv_ringbuffer_write(channel, bufferlist, num_vecs, requestid, trans_id); +} +EXPORT_SYMBOL(vmbus_sendpacket_getid); + +/** + * vmbus_sendpacket() - Send the specified buffer on the given channel + * @channel: Pointer to vmbus_channel structure + * @buffer: Pointer to the buffer you want to send the data from. + * @bufferlen: Maximum size of what the buffer holds. + * @requestid: Identifier of the request + * @type: Type of packet that is being sent e.g. negotiate, time + * packet etc. + * @flags: 0 or VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED + * + * Sends data in @buffer directly to Hyper-V via the vmbus. + * This will send the data unparsed to Hyper-V. + * + * Mainly used by Hyper-V drivers. + */ +int vmbus_sendpacket(struct vmbus_channel *channel, void *buffer, + u32 bufferlen, u64 requestid, + enum vmbus_packet_type type, u32 flags) +{ + return vmbus_sendpacket_getid(channel, buffer, bufferlen, + requestid, NULL, type, flags); } EXPORT_SYMBOL(vmbus_sendpacket); @@ -1122,7 +1148,7 @@ int vmbus_sendpacket_pagebuffer(struct vmbus_channel *channel, bufferlist[2].iov_base = &aligned_data; bufferlist[2].iov_len = (packetlen_aligned - packetlen); - return hv_ringbuffer_write(channel, bufferlist, 3, requestid); + return hv_ringbuffer_write(channel, bufferlist, 3, requestid, NULL); } EXPORT_SYMBOL_GPL(vmbus_sendpacket_pagebuffer); @@ -1160,7 +1186,7 @@ int vmbus_sendpacket_mpb_desc(struct vmbus_channel *channel, bufferlist[2].iov_base = &aligned_data; bufferlist[2].iov_len = (packetlen_aligned - packetlen); - return hv_ringbuffer_write(channel, bufferlist, 3, requestid); + return hv_ringbuffer_write(channel, bufferlist, 3, requestid, NULL); } EXPORT_SYMBOL_GPL(vmbus_sendpacket_mpb_desc); @@ -1226,12 +1252,12 @@ u64 vmbus_next_request_id(struct vmbus_channel *channel, u64 rqst_addr) if (!channel->rqstor_size) return VMBUS_NO_RQSTOR; - spin_lock_irqsave(&rqstor->req_lock, flags); + lock_requestor(channel, flags); current_id = rqstor->next_request_id; /* Requestor array is full */ if (current_id >= rqstor->size) { - spin_unlock_irqrestore(&rqstor->req_lock, flags); + unlock_requestor(channel, flags); return VMBUS_RQST_ERROR; } @@ -1241,27 +1267,23 @@ u64 vmbus_next_request_id(struct vmbus_channel *channel, u64 rqst_addr) /* The already held spin lock provides atomicity */ bitmap_set(rqstor->req_bitmap, current_id, 1); - spin_unlock_irqrestore(&rqstor->req_lock, flags); + unlock_requestor(channel, flags); /* * Cannot return an ID of 0, which is reserved for an unsolicited - * message from Hyper-V. + * message from Hyper-V; Hyper-V does not acknowledge (respond to) + * VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED requests with ID of + * 0 sent by the guest. */ return current_id + 1; } EXPORT_SYMBOL_GPL(vmbus_next_request_id); -/* - * vmbus_request_addr - Returns the memory address stored at @trans_id - * in @rqstor. Uses a spin lock to avoid race conditions. - * @channel: Pointer to the VMbus channel struct - * @trans_id: Request id sent back from Hyper-V. Becomes the requestor's - * next request id. - */ -u64 vmbus_request_addr(struct vmbus_channel *channel, u64 trans_id) +/* As in vmbus_request_addr_match() but without the requestor lock */ +u64 __vmbus_request_addr_match(struct vmbus_channel *channel, u64 trans_id, + u64 rqst_addr) { struct vmbus_requestor *rqstor = &channel->requestor; - unsigned long flags; u64 req_addr; /* Check rqstor has been initialized */ @@ -1270,27 +1292,61 @@ u64 vmbus_request_addr(struct vmbus_channel *channel, u64 trans_id) /* Hyper-V can send an unsolicited message with ID of 0 */ if (!trans_id) - return trans_id; - - spin_lock_irqsave(&rqstor->req_lock, flags); + return VMBUS_RQST_ERROR; /* Data corresponding to trans_id is stored at trans_id - 1 */ trans_id--; /* Invalid trans_id */ - if (trans_id >= rqstor->size || !test_bit(trans_id, rqstor->req_bitmap)) { - spin_unlock_irqrestore(&rqstor->req_lock, flags); + if (trans_id >= rqstor->size || !test_bit(trans_id, rqstor->req_bitmap)) return VMBUS_RQST_ERROR; - } req_addr = rqstor->req_arr[trans_id]; - rqstor->req_arr[trans_id] = rqstor->next_request_id; - rqstor->next_request_id = trans_id; + if (rqst_addr == VMBUS_RQST_ADDR_ANY || req_addr == rqst_addr) { + rqstor->req_arr[trans_id] = rqstor->next_request_id; + rqstor->next_request_id = trans_id; - /* The already held spin lock provides atomicity */ - bitmap_clear(rqstor->req_bitmap, trans_id, 1); + /* The already held spin lock provides atomicity */ + bitmap_clear(rqstor->req_bitmap, trans_id, 1); + } - spin_unlock_irqrestore(&rqstor->req_lock, flags); return req_addr; } +EXPORT_SYMBOL_GPL(__vmbus_request_addr_match); + +/* + * vmbus_request_addr_match - Clears/removes @trans_id from the @channel's + * requestor, provided the memory address stored at @trans_id equals @rqst_addr + * (or provided @rqst_addr matches the sentinel value VMBUS_RQST_ADDR_ANY). + * + * Returns the memory address stored at @trans_id, or VMBUS_RQST_ERROR if + * @trans_id is not contained in the requestor. + * + * Acquires and releases the requestor spin lock. + */ +u64 vmbus_request_addr_match(struct vmbus_channel *channel, u64 trans_id, + u64 rqst_addr) +{ + unsigned long flags; + u64 req_addr; + + lock_requestor(channel, flags); + req_addr = __vmbus_request_addr_match(channel, trans_id, rqst_addr); + unlock_requestor(channel, flags); + + return req_addr; +} +EXPORT_SYMBOL_GPL(vmbus_request_addr_match); + +/* + * vmbus_request_addr - Returns the memory address stored at @trans_id + * in @rqstor. Uses a spin lock to avoid race conditions. + * @channel: Pointer to the VMbus channel struct + * @trans_id: Request id sent back from Hyper-V. Becomes the requestor's + * next request id. + */ +u64 vmbus_request_addr(struct vmbus_channel *channel, u64 trans_id) +{ + return vmbus_request_addr_match(channel, trans_id, VMBUS_RQST_ADDR_ANY); +} EXPORT_SYMBOL_GPL(vmbus_request_addr); diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c index 85a2142c9384007d2bc43a1f072ceb7b96b0c53b..b60f13481bdcb21435a97bd2507ab76f1be6ee38 100644 --- a/drivers/hv/channel_mgmt.c +++ b/drivers/hv/channel_mgmt.c @@ -152,6 +152,7 @@ static const struct { { HV_AVMA1_GUID }, { HV_AVMA2_GUID }, { HV_RDV_GUID }, + { HV_IMC_GUID }, }; /* @@ -442,7 +443,7 @@ void hv_process_channel_removal(struct vmbus_channel *channel) /* * Upon suspend, an in-use hv_sock channel is removed from the array of * channels and the relid is invalidated. After hibernation, when the - * user-space appplication destroys the channel, it's unnecessary and + * user-space application destroys the channel, it's unnecessary and * unsafe to remove the channel from the array of channels. See also * the inline comments before the call of vmbus_release_relid() below. */ @@ -713,15 +714,13 @@ static bool hv_cpuself_used(u32 cpu, struct vmbus_channel *chn) static int next_numa_node_id; /* - * Starting with Win8, we can statically distribute the incoming - * channel interrupt load by binding a channel to VCPU. + * We can statically distribute the incoming channel interrupt load + * by binding a channel to VCPU. * - * For pre-win8 hosts or non-performance critical channels we assign the - * VMBUS_CONNECT_CPU. - * - * Starting with win8, performance critical channels will be distributed - * evenly among all the available NUMA nodes. Once the node is assigned, - * we will assign the CPU based on a simple round robin scheme. + * For non-performance critical channels we assign the VMBUS_CONNECT_CPU. + * Performance critical channels will be distributed evenly among all + * the available NUMA nodes. Once the node is assigned, we will assign + * the CPU based on a simple round robin scheme. */ static void init_vp_index(struct vmbus_channel *channel) { @@ -732,13 +731,10 @@ static void init_vp_index(struct vmbus_channel *channel) u32 target_cpu; int numa_node; - if ((vmbus_proto_version == VERSION_WS2008) || - (vmbus_proto_version == VERSION_WIN7) || (!perf_chn) || + if (!perf_chn || !alloc_cpumask_var(&available_mask, GFP_KERNEL)) { /* - * Prior to win8, all channel interrupts are - * delivered on VMBUS_CONNECT_CPU. - * Also if the channel is not a performance critical + * If the channel is not a performance critical * channel, bind it to VMBUS_CONNECT_CPU. * In case alloc_cpumask_var() fails, bind it to * VMBUS_CONNECT_CPU. @@ -931,11 +927,9 @@ static void vmbus_setup_channel_state(struct vmbus_channel *channel, */ channel->sig_event = VMBUS_EVENT_CONNECTION_ID; - if (vmbus_proto_version != VERSION_WS2008) { - channel->is_dedicated_interrupt = - (offer->is_dedicated_interrupt != 0); - channel->sig_event = offer->connection_id; - } + channel->is_dedicated_interrupt = + (offer->is_dedicated_interrupt != 0); + channel->sig_event = offer->connection_id; memcpy(&channel->offermsg, offer, sizeof(struct vmbus_channel_offer_channel)); @@ -975,13 +969,17 @@ find_primary_channel_by_offer(const struct vmbus_channel_offer_channel *offer) return channel; } -static bool vmbus_is_valid_device(const guid_t *guid) +static bool vmbus_is_valid_offer(const struct vmbus_channel_offer_channel *offer) { + const guid_t *guid = &offer->offer.if_type; u16 i; if (!hv_is_isolation_supported()) return true; + if (is_hvsock_offer(offer)) + return true; + for (i = 0; i < ARRAY_SIZE(vmbus_devs); i++) { if (guid_equal(guid, &vmbus_devs[i].guid)) return vmbus_devs[i].allowed_in_isolated; @@ -1003,7 +1001,7 @@ static void vmbus_onoffer(struct vmbus_channel_message_header *hdr) trace_vmbus_onoffer(offer); - if (!vmbus_is_valid_device(&offer->offer.if_type)) { + if (!vmbus_is_valid_offer(offer)) { pr_err_ratelimited("Invalid offer %d from the host supporting isolation\n", offer->child_relid); atomic_dec(&vmbus_connection.offer_in_progress); diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c index a3d8be8d6cfb07af67e0833ab26ce1267bd0ba29..6218bbf6863a5c6e9b2783dfd46c323703ffa4db 100644 --- a/drivers/hv/connection.c +++ b/drivers/hv/connection.c @@ -47,6 +47,8 @@ EXPORT_SYMBOL_GPL(vmbus_proto_version); /* * Table of VMBus versions listed from newest to oldest. + * VERSION_WIN7 and VERSION_WS2008 are no longer supported in + * Linux guests and are not listed. */ static __u32 vmbus_versions[] = { VERSION_WIN10_V5_3, @@ -56,9 +58,7 @@ static __u32 vmbus_versions[] = { VERSION_WIN10_V4_1, VERSION_WIN10, VERSION_WIN8_1, - VERSION_WIN8, - VERSION_WIN7, - VERSION_WS2008 + VERSION_WIN8 }; /* diff --git a/drivers/hv/hv_balloon.c b/drivers/hv/hv_balloon.c index 3248b48f37f6128aa1dd58ff6db3582edaa5f362..91e8a72eee14b69f7d7f4d396a3bbb767335f4e4 100644 --- a/drivers/hv/hv_balloon.c +++ b/drivers/hv/hv_balloon.c @@ -1842,7 +1842,7 @@ static int balloon_probe(struct hv_device *dev, ret = balloon_connect_vsp(dev); if (ret != 0) - return ret; + goto connect_error; enable_page_reporting(); dm_device.state = DM_INITIALIZED; @@ -1861,6 +1861,7 @@ probe_error: dm_device.thread = NULL; disable_page_reporting(); vmbus_close(dev->channel); +connect_error: #ifdef CONFIG_MEMORY_HOTPLUG unregister_memory_notifier(&hv_memory_nb); restore_online_page_callback(&hv_online_page); @@ -1882,12 +1883,21 @@ static int balloon_remove(struct hv_device *dev) cancel_work_sync(&dm->ha_wrk.wrk); kthread_stop(dm->thread); - disable_page_reporting(); - vmbus_close(dev->channel); + + /* + * This is to handle the case when balloon_resume() + * call has failed and some cleanup has been done as + * a part of the error handling. + */ + if (dm_device.state != DM_INIT_ERROR) { + disable_page_reporting(); + vmbus_close(dev->channel); #ifdef CONFIG_MEMORY_HOTPLUG - unregister_memory_notifier(&hv_memory_nb); - restore_online_page_callback(&hv_online_page); + unregister_memory_notifier(&hv_memory_nb); + restore_online_page_callback(&hv_online_page); #endif + } + spin_lock_irqsave(&dm_device.ha_lock, flags); list_for_each_entry_safe(has, tmp, &dm->ha_region_list, list) { list_for_each_entry_safe(gap, tmp_gap, &has->gap_list, list) { @@ -1948,6 +1958,7 @@ close_channel: vmbus_close(dev->channel); out: dm_device.state = DM_INIT_ERROR; + disable_page_reporting(); #ifdef CONFIG_MEMORY_HOTPLUG unregister_memory_notifier(&hv_memory_nb); restore_online_page_callback(&hv_online_page); diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h index 6b45c22bb717e1fe33ed4cf18e099c58c7a7d1ab..4f5b824b16cf4779fb740e70b13d2181f62fdd65 100644 --- a/drivers/hv/hyperv_vmbus.h +++ b/drivers/hv/hyperv_vmbus.h @@ -181,7 +181,7 @@ void hv_ringbuffer_cleanup(struct hv_ring_buffer_info *ring_info); int hv_ringbuffer_write(struct vmbus_channel *channel, const struct kvec *kv_list, u32 kv_count, - u64 requestid); + u64 requestid, u64 *trans_id); int hv_ringbuffer_read(struct vmbus_channel *channel, void *buffer, u32 buflen, u32 *buffer_actual_len, diff --git a/drivers/hv/ring_buffer.c b/drivers/hv/ring_buffer.c index 3d215d9dec433b33417f69de5513c1b231a27e36..59a4aa86d1f352137157a562d6eb77721fb5adf5 100644 --- a/drivers/hv/ring_buffer.c +++ b/drivers/hv/ring_buffer.c @@ -283,7 +283,7 @@ void hv_ringbuffer_cleanup(struct hv_ring_buffer_info *ring_info) /* Write to the ring buffer. */ int hv_ringbuffer_write(struct vmbus_channel *channel, const struct kvec *kv_list, u32 kv_count, - u64 requestid) + u64 requestid, u64 *trans_id) { int i; u32 bytes_avail_towrite; @@ -294,7 +294,7 @@ int hv_ringbuffer_write(struct vmbus_channel *channel, unsigned long flags; struct hv_ring_buffer_info *outring_info = &channel->outbound; struct vmpacket_descriptor *desc = kv_list[0].iov_base; - u64 rqst_id = VMBUS_NO_RQSTOR; + u64 __trans_id, rqst_id = VMBUS_NO_RQSTOR; if (channel->rescind) return -ENODEV; @@ -353,7 +353,15 @@ int hv_ringbuffer_write(struct vmbus_channel *channel, } } desc = hv_get_ring_buffer(outring_info) + old_write; - desc->trans_id = (rqst_id == VMBUS_NO_RQSTOR) ? requestid : rqst_id; + __trans_id = (rqst_id == VMBUS_NO_RQSTOR) ? requestid : rqst_id; + /* + * Ensure the compiler doesn't generate code that reads the value of + * the transaction ID from the ring buffer, which is shared with the + * Hyper-V host and subject to being changed at any time. + */ + WRITE_ONCE(desc->trans_id, __trans_id); + if (trans_id) + *trans_id = __trans_id; /* Set previous packet start */ prev_indices = hv_get_ring_bufferindices(outring_info); @@ -421,7 +429,7 @@ int hv_ringbuffer_read(struct vmbus_channel *channel, memcpy(buffer, (const char *)desc + offset, packetlen); /* Advance ring index to next packet descriptor */ - __hv_pkt_iter_next(channel, desc, true); + __hv_pkt_iter_next(channel, desc); /* Notify host of update */ hv_pkt_iter_close(channel); @@ -456,22 +464,6 @@ static u32 hv_pkt_iter_avail(const struct hv_ring_buffer_info *rbi) return (rbi->ring_datasize - priv_read_loc) + write_loc; } -/* - * Get first vmbus packet without copying it out of the ring buffer - */ -struct vmpacket_descriptor *hv_pkt_iter_first_raw(struct vmbus_channel *channel) -{ - struct hv_ring_buffer_info *rbi = &channel->inbound; - - hv_debug_delay_test(channel, MESSAGE_DELAY); - - if (hv_pkt_iter_avail(rbi) < sizeof(struct vmpacket_descriptor)) - return NULL; - - return (struct vmpacket_descriptor *)(hv_get_ring_buffer(rbi) + rbi->priv_read_index); -} -EXPORT_SYMBOL_GPL(hv_pkt_iter_first_raw); - /* * Get first vmbus packet from ring buffer after read_index * @@ -483,11 +475,14 @@ struct vmpacket_descriptor *hv_pkt_iter_first(struct vmbus_channel *channel) struct vmpacket_descriptor *desc, *desc_copy; u32 bytes_avail, pkt_len, pkt_offset; - desc = hv_pkt_iter_first_raw(channel); - if (!desc) + hv_debug_delay_test(channel, MESSAGE_DELAY); + + bytes_avail = hv_pkt_iter_avail(rbi); + if (bytes_avail < sizeof(struct vmpacket_descriptor)) return NULL; + bytes_avail = min(rbi->pkt_buffer_size, bytes_avail); - bytes_avail = min(rbi->pkt_buffer_size, hv_pkt_iter_avail(rbi)); + desc = (struct vmpacket_descriptor *)(hv_get_ring_buffer(rbi) + rbi->priv_read_index); /* * Ensure the compiler does not use references to incoming Hyper-V values (which @@ -534,8 +529,7 @@ EXPORT_SYMBOL_GPL(hv_pkt_iter_first); */ struct vmpacket_descriptor * __hv_pkt_iter_next(struct vmbus_channel *channel, - const struct vmpacket_descriptor *desc, - bool copy) + const struct vmpacket_descriptor *desc) { struct hv_ring_buffer_info *rbi = &channel->inbound; u32 packetlen = desc->len8 << 3; @@ -548,7 +542,7 @@ __hv_pkt_iter_next(struct vmbus_channel *channel, rbi->priv_read_index -= dsize; /* more data? */ - return copy ? hv_pkt_iter_first(channel) : hv_pkt_iter_first_raw(channel); + return hv_pkt_iter_first(channel); } EXPORT_SYMBOL_GPL(__hv_pkt_iter_next); diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index 14de17087864ac3a0d1efa475d8a44fb4d684cae..9c1b3620775cbf7dfe6df4b5639700be5be932c7 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c @@ -1263,23 +1263,17 @@ static void vmbus_chan_sched(struct hv_per_cpu_context *hv_cpu) unsigned long *recv_int_page; u32 maxbits, relid; - if (vmbus_proto_version < VERSION_WIN8) { - maxbits = MAX_NUM_CHANNELS_SUPPORTED; - recv_int_page = vmbus_connection.recv_int_page; - } else { - /* - * When the host is win8 and beyond, the event page - * can be directly checked to get the id of the channel - * that has the interrupt pending. - */ - void *page_addr = hv_cpu->synic_event_page; - union hv_synic_event_flags *event - = (union hv_synic_event_flags *)page_addr + - VMBUS_MESSAGE_SINT; + /* + * The event page can be directly checked to get the id of + * the channel that has the interrupt pending. + */ + void *page_addr = hv_cpu->synic_event_page; + union hv_synic_event_flags *event + = (union hv_synic_event_flags *)page_addr + + VMBUS_MESSAGE_SINT; - maxbits = HV_EVENT_FLAGS_COUNT; - recv_int_page = event->flags; - } + maxbits = HV_EVENT_FLAGS_COUNT; + recv_int_page = event->flags; if (unlikely(!recv_int_page)) return; @@ -1351,40 +1345,10 @@ static void vmbus_isr(void) { struct hv_per_cpu_context *hv_cpu = this_cpu_ptr(hv_context.cpu_context); - void *page_addr = hv_cpu->synic_event_page; + void *page_addr; struct hv_message *msg; - union hv_synic_event_flags *event; - bool handled = false; - - if (unlikely(page_addr == NULL)) - return; - - event = (union hv_synic_event_flags *)page_addr + - VMBUS_MESSAGE_SINT; - /* - * Check for events before checking for messages. This is the order - * in which events and messages are checked in Windows guests on - * Hyper-V, and the Windows team suggested we do the same. - */ - - if ((vmbus_proto_version == VERSION_WS2008) || - (vmbus_proto_version == VERSION_WIN7)) { - - /* Since we are a child, we only need to check bit 0 */ - if (sync_test_and_clear_bit(0, event->flags)) - handled = true; - } else { - /* - * Our host is win8 or above. The signaling mechanism - * has changed and we can directly look at the event page. - * If bit n is set then we have an interrup on the channel - * whose id is n. - */ - handled = true; - } - if (handled) - vmbus_chan_sched(hv_cpu); + vmbus_chan_sched(hv_cpu); page_addr = hv_cpu->synic_message_page; msg = (struct hv_message *)page_addr + VMBUS_MESSAGE_SINT; diff --git a/drivers/i2c/busses/i2c-at91-master.c b/drivers/i2c/busses/i2c-at91-master.c index b0eae94909f443a0da32d28a724beb7fb97dbba5..c0c35785a0dc45f04633601c0b33963bfd284db5 100644 --- a/drivers/i2c/busses/i2c-at91-master.c +++ b/drivers/i2c/busses/i2c-at91-master.c @@ -656,6 +656,7 @@ static int at91_twi_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, int num) unsigned int_addr_flag = 0; struct i2c_msg *m_start = msg; bool is_read; + u8 *dma_buf = NULL; dev_dbg(&adap->dev, "at91_xfer: processing %d messages:\n", num); @@ -703,7 +704,17 @@ static int at91_twi_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, int num) dev->msg = m_start; dev->recv_len_abort = false; + if (dev->use_dma) { + dma_buf = i2c_get_dma_safe_msg_buf(m_start, 1); + if (!dma_buf) { + ret = -ENOMEM; + goto out; + } + dev->buf = dma_buf; + } + ret = at91_do_twi_transfer(dev); + i2c_put_dma_safe_msg_buf(dma_buf, m_start, !ret); ret = (ret < 0) ? ret : num; out: diff --git a/drivers/i2c/busses/i2c-cadence.c b/drivers/i2c/busses/i2c-cadence.c index 805c77143a0f9b93f6ed9919fad4e46260a4e049..b4c1ad19cdaec154f2a39186dca5f38932163a4f 100644 --- a/drivers/i2c/busses/i2c-cadence.c +++ b/drivers/i2c/busses/i2c-cadence.c @@ -760,7 +760,7 @@ static void cdns_i2c_master_reset(struct i2c_adapter *adap) static int cdns_i2c_process_msg(struct cdns_i2c *id, struct i2c_msg *msg, struct i2c_adapter *adap) { - unsigned long time_left; + unsigned long time_left, msg_timeout; u32 reg; id->p_msg = msg; @@ -785,8 +785,16 @@ static int cdns_i2c_process_msg(struct cdns_i2c *id, struct i2c_msg *msg, else cdns_i2c_msend(id); + /* Minimal time to execute this message */ + msg_timeout = msecs_to_jiffies((1000 * msg->len * BITS_PER_BYTE) / id->i2c_clk); + /* Plus some wiggle room */ + msg_timeout += msecs_to_jiffies(500); + + if (msg_timeout < adap->timeout) + msg_timeout = adap->timeout; + /* Wait for the signal of completion */ - time_left = wait_for_completion_timeout(&id->xfer_done, adap->timeout); + time_left = wait_for_completion_timeout(&id->xfer_done, msg_timeout); if (time_left == 0) { cdns_i2c_master_reset(adap); dev_err(id->adap.dev.parent, diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c index e9d07323c6049d96e6af5ed2fc7a271fe5013a9c..9e09db31a937e5e72df2399ca0893fc527bd8b91 100644 --- a/drivers/i2c/busses/i2c-davinci.c +++ b/drivers/i2c/busses/i2c-davinci.c @@ -539,10 +539,9 @@ i2c_davinci_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) dev_dbg(dev->dev, "%s: msgs: %d\n", __func__, num); - ret = pm_runtime_get_sync(dev->dev); + ret = pm_runtime_resume_and_get(dev->dev); if (ret < 0) { dev_err(dev->dev, "Failed to runtime_get device: %d\n", ret); - pm_runtime_put_noidle(dev->dev); return ret; } @@ -821,10 +820,9 @@ static int davinci_i2c_probe(struct platform_device *pdev) pm_runtime_enable(dev->dev); - r = pm_runtime_get_sync(dev->dev); + r = pm_runtime_resume_and_get(dev->dev); if (r < 0) { dev_err(dev->dev, "failed to runtime_get device: %d\n", r); - pm_runtime_put_noidle(dev->dev); return r; } @@ -898,11 +896,9 @@ static int davinci_i2c_remove(struct platform_device *pdev) i2c_del_adapter(&dev->adapter); - ret = pm_runtime_get_sync(&pdev->dev); - if (ret < 0) { - pm_runtime_put_noidle(&pdev->dev); + ret = pm_runtime_resume_and_get(&pdev->dev); + if (ret < 0) return ret; - } davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, 0); diff --git a/drivers/i2c/busses/i2c-designware-amdpsp.c b/drivers/i2c/busses/i2c-designware-amdpsp.c index 9b37f2b95abcf20020c7e7248dac534aa71e1d90..b624356c945ffff34058e118f12f32c33d7e1ac9 100644 --- a/drivers/i2c/busses/i2c-designware-amdpsp.c +++ b/drivers/i2c/busses/i2c-designware-amdpsp.c @@ -16,8 +16,8 @@ #define PSP_CMD_TIMEOUT_US (500 * USEC_PER_MSEC) #define PSP_I2C_REQ_BUS_CMD 0x64 -#define PSP_I2C_REQ_RETRY_CNT 10 -#define PSP_I2C_REQ_RETRY_DELAY_US (50 * USEC_PER_MSEC) +#define PSP_I2C_REQ_RETRY_CNT 400 +#define PSP_I2C_REQ_RETRY_DELAY_US (25 * USEC_PER_MSEC) #define PSP_I2C_REQ_STS_OK 0x0 #define PSP_I2C_REQ_STS_BUS_BUSY 0x1 #define PSP_I2C_REQ_STS_INV_PARAM 0x3 diff --git a/drivers/i2c/busses/i2c-designware-common.c b/drivers/i2c/busses/i2c-designware-common.c index 9f8574320eb2dfe3b4bf51bac51b9664e61afa4b..e7d316b1401a121d4d6459949bf6e98eccb15a12 100644 --- a/drivers/i2c/busses/i2c-designware-common.c +++ b/drivers/i2c/busses/i2c-designware-common.c @@ -266,9 +266,9 @@ int i2c_dw_acpi_configure(struct device *device) * selected speed modes. */ i2c_dw_acpi_params(device, "SSCN", &dev->ss_hcnt, &dev->ss_lcnt, &ss_ht); + i2c_dw_acpi_params(device, "FMCN", &dev->fs_hcnt, &dev->fs_lcnt, &fs_ht); i2c_dw_acpi_params(device, "FPCN", &dev->fp_hcnt, &dev->fp_lcnt, &fp_ht); i2c_dw_acpi_params(device, "HSCN", &dev->hs_hcnt, &dev->hs_lcnt, &hs_ht); - i2c_dw_acpi_params(device, "FMCN", &dev->fs_hcnt, &dev->fs_lcnt, &fs_ht); switch (t->bus_freq_hz) { case I2C_MAX_STANDARD_MODE_FREQ: diff --git a/drivers/i2c/busses/i2c-meson.c b/drivers/i2c/busses/i2c-meson.c index 07eb819072c4fdf44a2a570b08aded0ae83c02e4..61cc5b2462c64c6c53278f854dea7611e47d046d 100644 --- a/drivers/i2c/busses/i2c-meson.c +++ b/drivers/i2c/busses/i2c-meson.c @@ -30,18 +30,21 @@ #define REG_TOK_RDATA1 0x1c /* Control register fields */ -#define REG_CTRL_START BIT(0) -#define REG_CTRL_ACK_IGNORE BIT(1) -#define REG_CTRL_STATUS BIT(2) -#define REG_CTRL_ERROR BIT(3) -#define REG_CTRL_CLKDIV GENMASK(21, 12) -#define REG_CTRL_CLKDIVEXT GENMASK(29, 28) - -#define REG_SLV_ADDR GENMASK(7, 0) -#define REG_SLV_SDA_FILTER GENMASK(10, 8) -#define REG_SLV_SCL_FILTER GENMASK(13, 11) -#define REG_SLV_SCL_LOW GENMASK(27, 16) -#define REG_SLV_SCL_LOW_EN BIT(28) +#define REG_CTRL_START BIT(0) +#define REG_CTRL_ACK_IGNORE BIT(1) +#define REG_CTRL_STATUS BIT(2) +#define REG_CTRL_ERROR BIT(3) +#define REG_CTRL_CLKDIV_SHIFT 12 +#define REG_CTRL_CLKDIV_MASK GENMASK(21, REG_CTRL_CLKDIV_SHIFT) +#define REG_CTRL_CLKDIVEXT_SHIFT 28 +#define REG_CTRL_CLKDIVEXT_MASK GENMASK(29, REG_CTRL_CLKDIVEXT_SHIFT) + +#define REG_SLV_ADDR_MASK GENMASK(7, 0) +#define REG_SLV_SDA_FILTER_MASK GENMASK(10, 8) +#define REG_SLV_SCL_FILTER_MASK GENMASK(13, 11) +#define REG_SLV_SCL_LOW_SHIFT 16 +#define REG_SLV_SCL_LOW_MASK GENMASK(27, REG_SLV_SCL_LOW_SHIFT) +#define REG_SLV_SCL_LOW_EN BIT(28) #define I2C_TIMEOUT_MS 500 #define FILTER_DELAY 15 @@ -62,10 +65,6 @@ enum { STATE_WRITE, }; -struct meson_i2c_data { - unsigned char div_factor; -}; - /** * struct meson_i2c - Meson I2C device private data * @@ -83,7 +82,7 @@ struct meson_i2c_data { * @done: Completion used to wait for transfer termination * @tokens: Sequence of tokens to be written to the device * @num_tokens: Number of tokens - * @data: Pointer to the controlller's platform data + * @data: Pointer to the controller's platform data */ struct meson_i2c { struct i2c_adapter adap; @@ -106,6 +105,10 @@ struct meson_i2c { const struct meson_i2c_data *data; }; +struct meson_i2c_data { + void (*set_clk_div)(struct meson_i2c *i2c, unsigned int freq); +}; + static void meson_i2c_set_mask(struct meson_i2c *i2c, int reg, u32 mask, u32 val) { @@ -134,14 +137,62 @@ static void meson_i2c_add_token(struct meson_i2c *i2c, int token) i2c->num_tokens++; } -static void meson_i2c_set_clk_div(struct meson_i2c *i2c, unsigned int freq) +static void meson_gxbb_axg_i2c_set_clk_div(struct meson_i2c *i2c, unsigned int freq) +{ + unsigned long clk_rate = clk_get_rate(i2c->clk); + unsigned int div_h, div_l; + + /* According to I2C-BUS Spec 2.1, in FAST-MODE, the minimum LOW period is 1.3uS, and + * minimum HIGH is least 0.6us. + * For 400000 freq, the period is 2.5us. To keep within the specs, give 40% of period to + * HIGH and 60% to LOW. This means HIGH at 1.0us and LOW 1.5us. + * The same applies for Fast-mode plus, where LOW is 0.5us and HIGH is 0.26us. + * Duty = H/(H + L) = 2/5 + */ + if (freq <= I2C_MAX_STANDARD_MODE_FREQ) { + div_h = DIV_ROUND_UP(clk_rate, freq); + div_l = DIV_ROUND_UP(div_h, 4); + div_h = DIV_ROUND_UP(div_h, 2) - FILTER_DELAY; + } else { + div_h = DIV_ROUND_UP(clk_rate * 2, freq * 5) - FILTER_DELAY; + div_l = DIV_ROUND_UP(clk_rate * 3, freq * 5 * 2); + } + + /* clock divider has 12 bits */ + if (div_h > GENMASK(11, 0)) { + dev_err(i2c->dev, "requested bus frequency too low\n"); + div_h = GENMASK(11, 0); + } + if (div_l > GENMASK(11, 0)) { + dev_err(i2c->dev, "requested bus frequency too low\n"); + div_l = GENMASK(11, 0); + } + + meson_i2c_set_mask(i2c, REG_CTRL, REG_CTRL_CLKDIV_MASK, + FIELD_PREP(REG_CTRL_CLKDIV_MASK, div_h & GENMASK(9, 0))); + + meson_i2c_set_mask(i2c, REG_CTRL, REG_CTRL_CLKDIVEXT_MASK, + FIELD_PREP(REG_CTRL_CLKDIVEXT_MASK, div_h >> 10)); + + /* set SCL low delay */ + meson_i2c_set_mask(i2c, REG_SLAVE_ADDR, REG_SLV_SCL_LOW_MASK, + FIELD_PREP(REG_SLV_SCL_LOW_MASK, div_l)); + + /* Enable HIGH/LOW mode */ + meson_i2c_set_mask(i2c, REG_SLAVE_ADDR, REG_SLV_SCL_LOW_EN, REG_SLV_SCL_LOW_EN); + + dev_dbg(i2c->dev, "%s: clk %lu, freq %u, divh %u, divl %u\n", __func__, + clk_rate, freq, div_h, div_l); +} + +static void meson6_i2c_set_clk_div(struct meson_i2c *i2c, unsigned int freq) { unsigned long clk_rate = clk_get_rate(i2c->clk); unsigned int div; div = DIV_ROUND_UP(clk_rate, freq); div -= FILTER_DELAY; - div = DIV_ROUND_UP(div, i2c->data->div_factor); + div = DIV_ROUND_UP(div, 4); /* clock divider has 12 bits */ if (div > GENMASK(11, 0)) { @@ -149,11 +200,11 @@ static void meson_i2c_set_clk_div(struct meson_i2c *i2c, unsigned int freq) div = GENMASK(11, 0); } - meson_i2c_set_mask(i2c, REG_CTRL, REG_CTRL_CLKDIV, - FIELD_PREP(REG_CTRL_CLKDIV, div & GENMASK(9, 0))); + meson_i2c_set_mask(i2c, REG_CTRL, REG_CTRL_CLKDIV_MASK, + FIELD_PREP(REG_CTRL_CLKDIV_MASK, div & GENMASK(9, 0))); - meson_i2c_set_mask(i2c, REG_CTRL, REG_CTRL_CLKDIVEXT, - FIELD_PREP(REG_CTRL_CLKDIVEXT, div >> 10)); + meson_i2c_set_mask(i2c, REG_CTRL, REG_CTRL_CLKDIVEXT_MASK, + FIELD_PREP(REG_CTRL_CLKDIVEXT_MASK, div >> 10)); /* Disable HIGH/LOW mode */ meson_i2c_set_mask(i2c, REG_SLAVE_ADDR, REG_SLV_SCL_LOW_EN, 0); @@ -292,8 +343,8 @@ static void meson_i2c_do_start(struct meson_i2c *i2c, struct i2c_msg *msg) TOKEN_SLAVE_ADDR_WRITE; - meson_i2c_set_mask(i2c, REG_SLAVE_ADDR, REG_SLV_ADDR, - FIELD_PREP(REG_SLV_ADDR, msg->addr << 1)); + meson_i2c_set_mask(i2c, REG_SLAVE_ADDR, REG_SLV_ADDR_MASK, + FIELD_PREP(REG_SLV_ADDR_MASK, msg->addr << 1)); meson_i2c_add_token(i2c, TOKEN_START); meson_i2c_add_token(i2c, token); @@ -467,9 +518,13 @@ static int meson_i2c_probe(struct platform_device *pdev) /* Disable filtering */ meson_i2c_set_mask(i2c, REG_SLAVE_ADDR, - REG_SLV_SDA_FILTER | REG_SLV_SCL_FILTER, 0); + REG_SLV_SDA_FILTER_MASK | REG_SLV_SCL_FILTER_MASK, 0); - meson_i2c_set_clk_div(i2c, timings.bus_freq_hz); + if (!i2c->data->set_clk_div) { + clk_disable_unprepare(i2c->clk); + return -EINVAL; + } + i2c->data->set_clk_div(i2c, timings.bus_freq_hz); ret = i2c_add_adapter(&i2c->adap); if (ret < 0) { @@ -491,15 +546,15 @@ static int meson_i2c_remove(struct platform_device *pdev) } static const struct meson_i2c_data i2c_meson6_data = { - .div_factor = 4, + .set_clk_div = meson6_i2c_set_clk_div, }; static const struct meson_i2c_data i2c_gxbb_data = { - .div_factor = 4, + .set_clk_div = meson_gxbb_axg_i2c_set_clk_div, }; static const struct meson_i2c_data i2c_axg_data = { - .div_factor = 3, + .set_clk_div = meson_gxbb_axg_i2c_set_clk_div, }; static const struct of_device_id meson_i2c_match[] = { diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c index f651d3e124d6cb2b15651076a73a8fb7b71dce77..bdecb78bfc26d20871ed488a420a39ded5086332 100644 --- a/drivers/i2c/busses/i2c-mt65xx.c +++ b/drivers/i2c/busses/i2c-mt65xx.c @@ -1177,7 +1177,7 @@ static int mtk_i2c_transfer(struct i2c_adapter *adap, int left_num = num; struct mtk_i2c *i2c = i2c_get_adapdata(adap); - ret = clk_bulk_prepare_enable(I2C_MT65XX_CLK_MAX, i2c->clocks); + ret = clk_bulk_enable(I2C_MT65XX_CLK_MAX, i2c->clocks); if (ret) return ret; @@ -1231,7 +1231,7 @@ static int mtk_i2c_transfer(struct i2c_adapter *adap, ret = num; err_exit: - clk_bulk_disable_unprepare(I2C_MT65XX_CLK_MAX, i2c->clocks); + clk_bulk_disable(I2C_MT65XX_CLK_MAX, i2c->clocks); return ret; } @@ -1412,7 +1412,7 @@ static int mtk_i2c_probe(struct platform_device *pdev) return ret; } mtk_i2c_init_hw(i2c); - clk_bulk_disable_unprepare(I2C_MT65XX_CLK_MAX, i2c->clocks); + clk_bulk_disable(I2C_MT65XX_CLK_MAX, i2c->clocks); ret = devm_request_irq(&pdev->dev, irq, mtk_i2c_irq, IRQF_NO_SUSPEND | IRQF_TRIGGER_NONE, @@ -1439,6 +1439,8 @@ static int mtk_i2c_remove(struct platform_device *pdev) i2c_del_adapter(&i2c->adap); + clk_bulk_unprepare(I2C_MT65XX_CLK_MAX, i2c->clocks); + return 0; } @@ -1448,6 +1450,7 @@ static int mtk_i2c_suspend_noirq(struct device *dev) struct mtk_i2c *i2c = dev_get_drvdata(dev); i2c_mark_adapter_suspended(&i2c->adap); + clk_bulk_unprepare(I2C_MT65XX_CLK_MAX, i2c->clocks); return 0; } @@ -1465,7 +1468,7 @@ static int mtk_i2c_resume_noirq(struct device *dev) mtk_i2c_init_hw(i2c); - clk_bulk_disable_unprepare(I2C_MT65XX_CLK_MAX, i2c->clocks); + clk_bulk_disable(I2C_MT65XX_CLK_MAX, i2c->clocks); i2c_mark_adapter_resumed(&i2c->adap); diff --git a/drivers/i2c/busses/i2c-mt7621.c b/drivers/i2c/busses/i2c-mt7621.c index 901f0fb04fee4ba3d09f2ce9650d93f45f75d98f..cfe6de8175dde8abde94a900622bd3f29f59333e 100644 --- a/drivers/i2c/busses/i2c-mt7621.c +++ b/drivers/i2c/busses/i2c-mt7621.c @@ -270,18 +270,15 @@ static void mtk_i2c_init(struct mtk_i2c *i2c) static int mtk_i2c_probe(struct platform_device *pdev) { - struct resource *res; struct mtk_i2c *i2c; struct i2c_adapter *adap; int ret; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - i2c = devm_kzalloc(&pdev->dev, sizeof(struct mtk_i2c), GFP_KERNEL); if (!i2c) return -ENOMEM; - i2c->base = devm_ioremap_resource(&pdev->dev, res); + i2c->base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); if (IS_ERR(i2c->base)) return PTR_ERR(i2c->base); diff --git a/drivers/i2c/busses/i2c-npcm7xx.c b/drivers/i2c/busses/i2c-npcm7xx.c index 71aad029425d86111ecc29f61290cae9dbf134b5..5960ccde6574135a5e04f4018f8075e01de993cd 100644 --- a/drivers/i2c/busses/i2c-npcm7xx.c +++ b/drivers/i2c/busses/i2c-npcm7xx.c @@ -314,6 +314,7 @@ struct npcm_i2c { u64 rec_fail_cnt; u64 nack_cnt; u64 timeout_cnt; + u64 tx_complete_cnt; }; static inline void npcm_i2c_select_bank(struct npcm_i2c *bus, @@ -359,14 +360,14 @@ static int npcm_i2c_get_SCL(struct i2c_adapter *_adap) { struct npcm_i2c *bus = container_of(_adap, struct npcm_i2c, adap); - return !!(I2CCTL3_SCL_LVL & ioread32(bus->reg + NPCM_I2CCTL3)); + return !!(I2CCTL3_SCL_LVL & ioread8(bus->reg + NPCM_I2CCTL3)); } static int npcm_i2c_get_SDA(struct i2c_adapter *_adap) { struct npcm_i2c *bus = container_of(_adap, struct npcm_i2c, adap); - return !!(I2CCTL3_SDA_LVL & ioread32(bus->reg + NPCM_I2CCTL3)); + return !!(I2CCTL3_SDA_LVL & ioread8(bus->reg + NPCM_I2CCTL3)); } static inline u16 npcm_i2c_get_index(struct npcm_i2c *bus) @@ -563,6 +564,15 @@ static inline void npcm_i2c_nack(struct npcm_i2c *bus) iowrite8(val, bus->reg + NPCM_I2CCTL1); } +static inline void npcm_i2c_clear_master_status(struct npcm_i2c *bus) +{ + u8 val; + + /* Clear NEGACK, STASTR and BER bits */ + val = NPCM_I2CST_BER | NPCM_I2CST_NEGACK | NPCM_I2CST_STASTR; + iowrite8(val, bus->reg + NPCM_I2CST); +} + #if IS_ENABLED(CONFIG_I2C_SLAVE) static void npcm_i2c_slave_int_enable(struct npcm_i2c *bus, bool enable) { @@ -642,8 +652,8 @@ static void npcm_i2c_reset(struct npcm_i2c *bus) iowrite8(NPCM_I2CCST_BB, bus->reg + NPCM_I2CCST); iowrite8(0xFF, bus->reg + NPCM_I2CST); - /* Clear EOB bit */ - iowrite8(NPCM_I2CCST3_EO_BUSY, bus->reg + NPCM_I2CCST3); + /* Clear and disable EOB */ + npcm_i2c_eob_int(bus, false); /* Clear all fifo bits: */ iowrite8(NPCM_I2CFIF_CTS_CLR_FIFO, bus->reg + NPCM_I2CFIF_CTS); @@ -655,6 +665,9 @@ static void npcm_i2c_reset(struct npcm_i2c *bus) } #endif + /* clear status bits for spurious interrupts */ + npcm_i2c_clear_master_status(bus); + bus->state = I2C_IDLE; } @@ -684,6 +697,8 @@ static void npcm_i2c_callback(struct npcm_i2c *bus, switch (op_status) { case I2C_MASTER_DONE_IND: bus->cmd_err = bus->msgs_num; + if (bus->tx_complete_cnt < ULLONG_MAX) + bus->tx_complete_cnt++; fallthrough; case I2C_BLOCK_BYTES_ERR_IND: /* Master tx finished and all transmit bytes were sent */ @@ -815,15 +830,6 @@ static void npcm_i2c_read_fifo(struct npcm_i2c *bus, u8 bytes_in_fifo) } } -static inline void npcm_i2c_clear_master_status(struct npcm_i2c *bus) -{ - u8 val; - - /* Clear NEGACK, STASTR and BER bits */ - val = NPCM_I2CST_BER | NPCM_I2CST_NEGACK | NPCM_I2CST_STASTR; - iowrite8(val, bus->reg + NPCM_I2CST); -} - static void npcm_i2c_master_abort(struct npcm_i2c *bus) { /* Only current master is allowed to issue a stop condition */ @@ -1231,7 +1237,16 @@ static irqreturn_t npcm_i2c_int_slave_handler(struct npcm_i2c *bus) ret = IRQ_HANDLED; } /* SDAST */ - return ret; + /* + * if irq is not one of the above, make sure EOB is disabled and all + * status bits are cleared. + */ + if (ret == IRQ_NONE) { + npcm_i2c_eob_int(bus, false); + npcm_i2c_clear_master_status(bus); + } + + return IRQ_HANDLED; } static int npcm_i2c_reg_slave(struct i2c_client *client) @@ -1467,6 +1482,9 @@ static void npcm_i2c_irq_handle_nack(struct npcm_i2c *bus) npcm_i2c_eob_int(bus, false); npcm_i2c_master_stop(bus); + /* Clear SDA Status bit (by reading dummy byte) */ + npcm_i2c_rd_byte(bus); + /* * The bus is released from stall only after the SW clears * NEGACK bit. Then a Stop condition is sent. @@ -1474,6 +1492,8 @@ static void npcm_i2c_irq_handle_nack(struct npcm_i2c *bus) npcm_i2c_clear_master_status(bus); readx_poll_timeout_atomic(ioread8, bus->reg + NPCM_I2CCST, val, !(val & NPCM_I2CCST_BUSY), 10, 200); + /* verify no status bits are still set after bus is released */ + npcm_i2c_clear_master_status(bus); } bus->state = I2C_IDLE; @@ -1672,10 +1692,10 @@ static int npcm_i2c_recovery_tgclk(struct i2c_adapter *_adap) int iter = 27; if ((npcm_i2c_get_SDA(_adap) == 1) && (npcm_i2c_get_SCL(_adap) == 1)) { - dev_dbg(bus->dev, "bus%d recovery skipped, bus not stuck", - bus->num); + dev_dbg(bus->dev, "bus%d-0x%x recovery skipped, bus not stuck", + bus->num, bus->dest_addr); npcm_i2c_reset(bus); - return status; + return 0; } npcm_i2c_int_enable(bus, false); @@ -1909,6 +1929,7 @@ static int npcm_i2c_init_module(struct npcm_i2c *bus, enum i2c_mode mode, bus_freq_hz < I2C_FREQ_MIN_HZ || bus_freq_hz > I2C_FREQ_MAX_HZ) return -EINVAL; + npcm_i2c_int_enable(bus, false); npcm_i2c_disable(bus); /* Configure FIFO mode : */ @@ -1937,10 +1958,17 @@ static int npcm_i2c_init_module(struct npcm_i2c *bus, enum i2c_mode mode, val = (val | NPCM_I2CCTL1_NMINTE) & ~NPCM_I2CCTL1_RWS; iowrite8(val, bus->reg + NPCM_I2CCTL1); - npcm_i2c_int_enable(bus, true); - npcm_i2c_reset(bus); + /* check HW is OK: SDA and SCL should be high at this point. */ + if ((npcm_i2c_get_SDA(&bus->adap) == 0) || (npcm_i2c_get_SCL(&bus->adap) == 0)) { + dev_err(bus->dev, "I2C%d init fail: lines are low\n", bus->num); + dev_err(bus->dev, "SDA=%d SCL=%d\n", npcm_i2c_get_SDA(&bus->adap), + npcm_i2c_get_SCL(&bus->adap)); + return -ENXIO; + } + + npcm_i2c_int_enable(bus, true); return 0; } @@ -1988,10 +2016,14 @@ static irqreturn_t npcm_i2c_bus_irq(int irq, void *dev_id) #if IS_ENABLED(CONFIG_I2C_SLAVE) if (bus->slave) { bus->master_or_slave = I2C_SLAVE; - return npcm_i2c_int_slave_handler(bus); + if (npcm_i2c_int_slave_handler(bus)) + return IRQ_HANDLED; } #endif - return IRQ_NONE; + /* clear status bits for spurious interrupts */ + npcm_i2c_clear_master_status(bus); + + return IRQ_HANDLED; } static bool npcm_i2c_master_start_xmit(struct npcm_i2c *bus, @@ -2047,8 +2079,7 @@ static int npcm_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, u16 nwrite, nread; u8 *write_data, *read_data; u8 slave_addr; - int timeout; - int ret = 0; + unsigned long timeout; bool read_block = false; bool read_PEC = false; u8 bus_busy; @@ -2099,13 +2130,13 @@ static int npcm_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, * 9: bits per transaction (including the ack/nack) */ timeout_usec = (2 * 9 * USEC_PER_SEC / bus->bus_freq) * (2 + nread + nwrite); - timeout = max(msecs_to_jiffies(35), usecs_to_jiffies(timeout_usec)); + timeout = max_t(unsigned long, bus->adap.timeout, usecs_to_jiffies(timeout_usec)); if (nwrite >= 32 * 1024 || nread >= 32 * 1024) { dev_err(bus->dev, "i2c%d buffer too big\n", bus->num); return -EINVAL; } - time_left = jiffies + msecs_to_jiffies(DEFAULT_STALL_COUNT) + 1; + time_left = jiffies + timeout + 1; do { /* * we must clear slave address immediately when the bus is not @@ -2138,12 +2169,12 @@ static int npcm_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, bus->read_block_use = read_block; reinit_completion(&bus->cmd_complete); - if (!npcm_i2c_master_start_xmit(bus, slave_addr, nwrite, nread, - write_data, read_data, read_PEC, - read_block)) - ret = -EBUSY; - if (ret != -EBUSY) { + npcm_i2c_int_enable(bus, true); + + if (npcm_i2c_master_start_xmit(bus, slave_addr, nwrite, nread, + write_data, read_data, read_PEC, + read_block)) { time_left = wait_for_completion_timeout(&bus->cmd_complete, timeout); @@ -2157,26 +2188,31 @@ static int npcm_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, } } } - ret = bus->cmd_err; /* if there was BER, check if need to recover the bus: */ if (bus->cmd_err == -EAGAIN) - ret = i2c_recover_bus(adap); + bus->cmd_err = i2c_recover_bus(adap); /* * After any type of error, check if LAST bit is still set, * due to a HW issue. * It cannot be cleared without resetting the module. */ - if (bus->cmd_err && - (NPCM_I2CRXF_CTL_LAST_PEC & ioread8(bus->reg + NPCM_I2CRXF_CTL))) + else if (bus->cmd_err && + (NPCM_I2CRXF_CTL_LAST_PEC & ioread8(bus->reg + NPCM_I2CRXF_CTL))) npcm_i2c_reset(bus); + /* after any xfer, successful or not, stall and EOB must be disabled */ + npcm_i2c_stall_after_start(bus, false); + npcm_i2c_eob_int(bus, false); + #if IS_ENABLED(CONFIG_I2C_SLAVE) /* reenable slave if it was enabled */ if (bus->slave) iowrite8((bus->slave->addr & 0x7F) | NPCM_I2CADDR_SAEN, bus->reg + NPCM_I2CADDR1); +#else + npcm_i2c_int_enable(bus, false); #endif return bus->cmd_err; } @@ -2223,17 +2259,18 @@ static void npcm_i2c_init_debugfs(struct platform_device *pdev, debugfs_create_u64("rec_succ_cnt", 0444, d, &bus->rec_succ_cnt); debugfs_create_u64("rec_fail_cnt", 0444, d, &bus->rec_fail_cnt); debugfs_create_u64("timeout_cnt", 0444, d, &bus->timeout_cnt); + debugfs_create_u64("tx_complete_cnt", 0444, d, &bus->tx_complete_cnt); bus->debugfs = d; } static int npcm_i2c_probe_bus(struct platform_device *pdev) { - struct npcm_i2c *bus; + struct device_node *np = pdev->dev.of_node; + static struct regmap *gcr_regmap; struct i2c_adapter *adap; + struct npcm_i2c *bus; struct clk *i2c_clk; - static struct regmap *gcr_regmap; - static struct regmap *clk_regmap; int irq; int ret; @@ -2250,15 +2287,14 @@ static int npcm_i2c_probe_bus(struct platform_device *pdev) return PTR_ERR(i2c_clk); bus->apb_clk = clk_get_rate(i2c_clk); - gcr_regmap = syscon_regmap_lookup_by_compatible("nuvoton,npcm750-gcr"); + gcr_regmap = syscon_regmap_lookup_by_phandle(np, "nuvoton,sys-mgr"); + if (IS_ERR(gcr_regmap)) + gcr_regmap = syscon_regmap_lookup_by_compatible("nuvoton,npcm750-gcr"); + if (IS_ERR(gcr_regmap)) return PTR_ERR(gcr_regmap); regmap_write(gcr_regmap, NPCM_I2CSEGCTL, NPCM_I2CSEGCTL_INIT_VAL); - clk_regmap = syscon_regmap_lookup_by_compatible("nuvoton,npcm750-clk"); - if (IS_ERR(clk_regmap)) - return PTR_ERR(clk_regmap); - bus->reg = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(bus->reg)) return PTR_ERR(bus->reg); @@ -2269,7 +2305,7 @@ static int npcm_i2c_probe_bus(struct platform_device *pdev) adap = &bus->adap; adap->owner = THIS_MODULE; adap->retries = 3; - adap->timeout = HZ; + adap->timeout = msecs_to_jiffies(35); adap->algo = &npcm_i2c_algo; adap->quirks = &npcm_i2c_quirks; adap->algo_data = bus; diff --git a/drivers/i2c/busses/i2c-powermac.c b/drivers/i2c/busses/i2c-powermac.c index 5241e6f414e961ecbd4021861b276c1e187de32c..2e74747eec9cef38d467380752584be4221cfae5 100644 --- a/drivers/i2c/busses/i2c-powermac.c +++ b/drivers/i2c/busses/i2c-powermac.c @@ -15,7 +15,7 @@ #include #include #include -#include + #include MODULE_AUTHOR("Benjamin Herrenschmidt "); diff --git a/drivers/i2c/busses/i2c-qcom-geni.c b/drivers/i2c/busses/i2c-qcom-geni.c index 5b920f0fc7dd79c5033d3182cbbc27f46e0bdb64..6ac402ea58fbe1b351fc681ee358479d5310ca5a 100644 --- a/drivers/i2c/busses/i2c-qcom-geni.c +++ b/drivers/i2c/busses/i2c-qcom-geni.c @@ -727,16 +727,14 @@ static int setup_gpi_dma(struct geni_i2c_dev *gi2c) if (IS_ERR(gi2c->tx_c)) { ret = dev_err_probe(gi2c->se.dev, PTR_ERR(gi2c->tx_c), "Failed to get tx DMA ch\n"); - if (ret < 0) - goto err_tx; + goto err_tx; } gi2c->rx_c = dma_request_chan(gi2c->se.dev, "rx"); if (IS_ERR(gi2c->rx_c)) { ret = dev_err_probe(gi2c->se.dev, PTR_ERR(gi2c->rx_c), "Failed to get rx DMA ch\n"); - if (ret < 0) - goto err_rx; + goto err_rx; } dev_dbg(gi2c->se.dev, "Grabbed GPI dma channels\n"); diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c index 0db3d755906627d70193521546354cb07fc52699..6e7be9d9f5043c00f1c2deec0e7219a8d695888c 100644 --- a/drivers/i2c/busses/i2c-rcar.c +++ b/drivers/i2c/busses/i2c-rcar.c @@ -45,44 +45,44 @@ #define ICDMAER 0x3c /* DMA enable (Gen3) */ /* ICSCR */ -#define SDBS (1 << 3) /* slave data buffer select */ -#define SIE (1 << 2) /* slave interface enable */ -#define GCAE (1 << 1) /* general call address enable */ -#define FNA (1 << 0) /* forced non acknowledgment */ +#define SDBS BIT(3) /* slave data buffer select */ +#define SIE BIT(2) /* slave interface enable */ +#define GCAE BIT(1) /* general call address enable */ +#define FNA BIT(0) /* forced non acknowledgment */ /* ICMCR */ -#define MDBS (1 << 7) /* non-fifo mode switch */ -#define FSCL (1 << 6) /* override SCL pin */ -#define FSDA (1 << 5) /* override SDA pin */ -#define OBPC (1 << 4) /* override pins */ -#define MIE (1 << 3) /* master if enable */ -#define TSBE (1 << 2) -#define FSB (1 << 1) /* force stop bit */ -#define ESG (1 << 0) /* enable start bit gen */ +#define MDBS BIT(7) /* non-fifo mode switch */ +#define FSCL BIT(6) /* override SCL pin */ +#define FSDA BIT(5) /* override SDA pin */ +#define OBPC BIT(4) /* override pins */ +#define MIE BIT(3) /* master if enable */ +#define TSBE BIT(2) +#define FSB BIT(1) /* force stop bit */ +#define ESG BIT(0) /* enable start bit gen */ /* ICSSR (also for ICSIER) */ -#define GCAR (1 << 6) /* general call received */ -#define STM (1 << 5) /* slave transmit mode */ -#define SSR (1 << 4) /* stop received */ -#define SDE (1 << 3) /* slave data empty */ -#define SDT (1 << 2) /* slave data transmitted */ -#define SDR (1 << 1) /* slave data received */ -#define SAR (1 << 0) /* slave addr received */ +#define GCAR BIT(6) /* general call received */ +#define STM BIT(5) /* slave transmit mode */ +#define SSR BIT(4) /* stop received */ +#define SDE BIT(3) /* slave data empty */ +#define SDT BIT(2) /* slave data transmitted */ +#define SDR BIT(1) /* slave data received */ +#define SAR BIT(0) /* slave addr received */ /* ICMSR (also for ICMIE) */ -#define MNR (1 << 6) /* nack received */ -#define MAL (1 << 5) /* arbitration lost */ -#define MST (1 << 4) /* sent a stop */ -#define MDE (1 << 3) -#define MDT (1 << 2) -#define MDR (1 << 1) -#define MAT (1 << 0) /* slave addr xfer done */ +#define MNR BIT(6) /* nack received */ +#define MAL BIT(5) /* arbitration lost */ +#define MST BIT(4) /* sent a stop */ +#define MDE BIT(3) +#define MDT BIT(2) +#define MDR BIT(1) +#define MAT BIT(0) /* slave addr xfer done */ /* ICDMAER */ -#define RSDMAE (1 << 3) /* DMA Slave Received Enable */ -#define TSDMAE (1 << 2) /* DMA Slave Transmitted Enable */ -#define RMDMAE (1 << 1) /* DMA Master Received Enable */ -#define TMDMAE (1 << 0) /* DMA Master Transmitted Enable */ +#define RSDMAE BIT(3) /* DMA Slave Received Enable */ +#define TSDMAE BIT(2) /* DMA Slave Transmitted Enable */ +#define RMDMAE BIT(1) /* DMA Master Received Enable */ +#define TMDMAE BIT(0) /* DMA Master Transmitted Enable */ /* ICFBSCR */ #define TCYC17 0x0f /* 17*Tcyc delay 1st bit between SDA and SCL */ @@ -97,17 +97,15 @@ #define RCAR_IRQ_RECV (MNR | MAL | MST | MAT | MDR) #define RCAR_IRQ_STOP (MST) -#define RCAR_IRQ_ACK_SEND (~(MAT | MDE) & 0x7F) -#define RCAR_IRQ_ACK_RECV (~(MAT | MDR) & 0x7F) - -#define ID_LAST_MSG (1 << 0) -#define ID_FIRST_MSG (1 << 1) -#define ID_DONE (1 << 2) -#define ID_ARBLOST (1 << 3) -#define ID_NACK (1 << 4) +#define ID_LAST_MSG BIT(0) +#define ID_REP_AFTER_RD BIT(1) +#define ID_DONE BIT(2) +#define ID_ARBLOST BIT(3) +#define ID_NACK BIT(4) +#define ID_EPROTO BIT(5) /* persistent flags */ -#define ID_P_HOST_NOTIFY BIT(28) -#define ID_P_REP_AFTER_RD BIT(29) +#define ID_P_NOT_ATOMIC BIT(28) +#define ID_P_HOST_NOTIFY BIT(29) #define ID_P_NO_RXDMA BIT(30) /* HW forbids RXDMA sometimes */ #define ID_P_PM_BLOCKED BIT(31) #define ID_P_MASK GENMASK(31, 28) @@ -141,7 +139,6 @@ struct rcar_i2c_priv { enum dma_data_direction dma_direction; struct reset_control *rstc; - bool atomic_xfer; int irq; struct i2c_client *host_notify_client; @@ -160,6 +157,11 @@ static u32 rcar_i2c_read(struct rcar_i2c_priv *priv, int reg) return readl(priv->io + reg); } +static void rcar_i2c_clear_irq(struct rcar_i2c_priv *priv, u32 val) +{ + writel(~val & 0x7f, priv->io + ICMSR); +} + static int rcar_i2c_get_scl(struct i2c_adapter *adap) { struct rcar_i2c_priv *priv = i2c_get_adapdata(adap); @@ -330,41 +332,46 @@ scgd_find: return 0; } +/* + * We don't have a test case but the HW engineers say that the write order of + * ICMSR and ICMCR depends on whether we issue START or REP_START. So, ICMSR + * handling is outside of this function. First messages clear ICMSR before this + * function, interrupt handlers clear the relevant bits after this function. + */ static void rcar_i2c_prepare_msg(struct rcar_i2c_priv *priv) { int read = !!rcar_i2c_is_recv(priv); + bool rep_start = !(priv->flags & ID_REP_AFTER_RD); priv->pos = 0; + priv->flags &= ID_P_MASK; + if (priv->msgs_left == 1) priv->flags |= ID_LAST_MSG; rcar_i2c_write(priv, ICMAR, i2c_8bit_addr_from_msg(priv->msg)); - if (!priv->atomic_xfer) + if (priv->flags & ID_P_NOT_ATOMIC) rcar_i2c_write(priv, ICMIER, read ? RCAR_IRQ_RECV : RCAR_IRQ_SEND); - /* - * We don't have a test case but the HW engineers say that the write order - * of ICMSR and ICMCR depends on whether we issue START or REP_START. Since - * it didn't cause a drawback for me, let's rather be safe than sorry. - */ - if (priv->flags & ID_FIRST_MSG) { - rcar_i2c_write(priv, ICMSR, 0); + if (rep_start) rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_START); - } else { - if (priv->flags & ID_P_REP_AFTER_RD) - priv->flags &= ~ID_P_REP_AFTER_RD; - else - rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_START); - rcar_i2c_write(priv, ICMSR, 0); - } +} + +static void rcar_i2c_first_msg(struct rcar_i2c_priv *priv, + struct i2c_msg *msgs, int num) +{ + priv->msg = msgs; + priv->msgs_left = num; + rcar_i2c_write(priv, ICMSR, 0); /* must be before preparing msg */ + rcar_i2c_prepare_msg(priv); } static void rcar_i2c_next_msg(struct rcar_i2c_priv *priv) { priv->msg++; priv->msgs_left--; - priv->flags &= ID_P_MASK; rcar_i2c_prepare_msg(priv); + /* ICMSR handling must come afterwards in the irq handler */ } static void rcar_i2c_cleanup_dma(struct rcar_i2c_priv *priv, bool terminate) @@ -413,7 +420,7 @@ static bool rcar_i2c_dma(struct rcar_i2c_priv *priv) int len; /* Do various checks to see if DMA is feasible at all */ - if (priv->atomic_xfer || IS_ERR(chan) || msg->len < RCAR_MIN_DMA_LEN || + if (!(priv->flags & ID_P_NOT_ATOMIC) || IS_ERR(chan) || msg->len < RCAR_MIN_DMA_LEN || !(msg->flags & I2C_M_DMA_SAFE) || (read && priv->flags & ID_P_NO_RXDMA)) return false; @@ -475,11 +482,15 @@ static bool rcar_i2c_dma(struct rcar_i2c_priv *priv) static void rcar_i2c_irq_send(struct rcar_i2c_priv *priv, u32 msr) { struct i2c_msg *msg = priv->msg; + u32 irqs_to_clear = MDE; /* FIXME: sometimes, unknown interrupt happened. Do nothing */ if (!(msr & MDE)) return; + if (msr & MAT) + irqs_to_clear |= MAT; + /* Check if DMA can be enabled and take over */ if (priv->pos == 1 && rcar_i2c_dma(priv)) return; @@ -503,31 +514,32 @@ static void rcar_i2c_irq_send(struct rcar_i2c_priv *priv, u32 msr) * [ICRXTX] -> [SHIFT] -> [I2C bus] */ - if (priv->flags & ID_LAST_MSG) { + if (priv->flags & ID_LAST_MSG) /* * If current msg is the _LAST_ msg, * prepare stop condition here. * ID_DONE will be set on STOP irq. */ rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_STOP); - } else { + else rcar_i2c_next_msg(priv); - return; - } } - rcar_i2c_write(priv, ICMSR, RCAR_IRQ_ACK_SEND); + rcar_i2c_clear_irq(priv, irqs_to_clear); } static void rcar_i2c_irq_recv(struct rcar_i2c_priv *priv, u32 msr) { struct i2c_msg *msg = priv->msg; + bool recv_len_init = priv->pos == 0 && msg->flags & I2C_M_RECV_LEN; + u32 irqs_to_clear = MDR; /* FIXME: sometimes, unknown interrupt happened. Do nothing */ if (!(msr & MDR)) return; if (msr & MAT) { + irqs_to_clear |= MAT; /* * Address transfer phase finished, but no data at this point. * Try to use DMA to receive data. @@ -535,24 +547,41 @@ static void rcar_i2c_irq_recv(struct rcar_i2c_priv *priv, u32 msr) rcar_i2c_dma(priv); } else if (priv->pos < msg->len) { /* get received data */ - msg->buf[priv->pos] = rcar_i2c_read(priv, ICRXTX); + u8 data = rcar_i2c_read(priv, ICRXTX); + + msg->buf[priv->pos] = data; + if (recv_len_init) { + if (data == 0 || data > I2C_SMBUS_BLOCK_MAX) { + priv->flags |= ID_DONE | ID_EPROTO; + return; + } + msg->len += msg->buf[0]; + /* Enough data for DMA? */ + if (rcar_i2c_dma(priv)) + return; + /* new length after RECV_LEN now properly initialized */ + recv_len_init = false; + } priv->pos++; } - /* If next received data is the _LAST_, go to new phase. */ - if (priv->pos + 1 == msg->len) { + /* + * If next received data is the _LAST_ and we are not waiting for a new + * length because of RECV_LEN, then go to a new phase. + */ + if (priv->pos + 1 == msg->len && !recv_len_init) { if (priv->flags & ID_LAST_MSG) { rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_STOP); } else { rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_START); - priv->flags |= ID_P_REP_AFTER_RD; + priv->flags |= ID_REP_AFTER_RD; } } if (priv->pos == msg->len && !(priv->flags & ID_LAST_MSG)) rcar_i2c_next_msg(priv); - else - rcar_i2c_write(priv, ICMSR, RCAR_IRQ_ACK_RECV); + + rcar_i2c_clear_irq(priv, irqs_to_clear); } static bool rcar_i2c_slave_irq(struct rcar_i2c_priv *priv) @@ -641,7 +670,7 @@ static irqreturn_t rcar_i2c_irq(int irq, struct rcar_i2c_priv *priv, u32 msr) /* Nack */ if (msr & MNR) { /* HW automatically sends STOP after received NACK */ - if (!priv->atomic_xfer) + if (priv->flags & ID_P_NOT_ATOMIC) rcar_i2c_write(priv, ICMIER, RCAR_IRQ_STOP); priv->flags |= ID_NACK; goto out; @@ -663,7 +692,7 @@ out: if (priv->flags & ID_DONE) { rcar_i2c_write(priv, ICMIER, 0); rcar_i2c_write(priv, ICMSR, 0); - if (!priv->atomic_xfer) + if (priv->flags & ID_P_NOT_ATOMIC) wake_up(&priv->wait); } @@ -676,12 +705,12 @@ static irqreturn_t rcar_i2c_gen2_irq(int irq, void *ptr) u32 msr; /* Clear START or STOP immediately, except for REPSTART after read */ - if (likely(!(priv->flags & ID_P_REP_AFTER_RD))) + if (likely(!(priv->flags & ID_REP_AFTER_RD))) rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_DATA); /* Only handle interrupts that are currently enabled */ msr = rcar_i2c_read(priv, ICMSR); - if (!priv->atomic_xfer) + if (priv->flags & ID_P_NOT_ATOMIC) msr &= rcar_i2c_read(priv, ICMIER); return rcar_i2c_irq(irq, priv, msr); @@ -694,14 +723,14 @@ static irqreturn_t rcar_i2c_gen3_irq(int irq, void *ptr) /* Only handle interrupts that are currently enabled */ msr = rcar_i2c_read(priv, ICMSR); - if (!priv->atomic_xfer) + if (priv->flags & ID_P_NOT_ATOMIC) msr &= rcar_i2c_read(priv, ICMIER); /* * Clear START or STOP immediately, except for REPSTART after read or * if a spurious interrupt was detected. */ - if (likely(!(priv->flags & ID_P_REP_AFTER_RD) && msr)) + if (likely(!(priv->flags & ID_REP_AFTER_RD) && msr)) rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_DATA); return rcar_i2c_irq(irq, priv, msr); @@ -803,7 +832,7 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap, int i, ret; long time_left; - priv->atomic_xfer = false; + priv->flags |= ID_P_NOT_ATOMIC; pm_runtime_get_sync(dev); @@ -827,11 +856,7 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap, for (i = 0; i < num; i++) rcar_i2c_request_dma(priv, msgs + i); - /* init first message */ - priv->msg = msgs; - priv->msgs_left = num; - priv->flags = (priv->flags & ID_P_MASK) | ID_FIRST_MSG; - rcar_i2c_prepare_msg(priv); + rcar_i2c_first_msg(priv, msgs, num); time_left = wait_event_timeout(priv->wait, priv->flags & ID_DONE, num * adap->timeout); @@ -847,6 +872,8 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap, ret = -ENXIO; } else if (priv->flags & ID_ARBLOST) { ret = -EAGAIN; + } else if (priv->flags & ID_EPROTO) { + ret = -EPROTO; } else { ret = num - priv->msgs_left; /* The number of transfer */ } @@ -869,7 +896,7 @@ static int rcar_i2c_master_xfer_atomic(struct i2c_adapter *adap, bool time_left; int ret; - priv->atomic_xfer = true; + priv->flags &= ~ID_P_NOT_ATOMIC; pm_runtime_get_sync(dev); @@ -879,12 +906,7 @@ static int rcar_i2c_master_xfer_atomic(struct i2c_adapter *adap, goto out; rcar_i2c_init(priv); - - /* init first message */ - priv->msg = msgs; - priv->msgs_left = num; - priv->flags = (priv->flags & ID_P_MASK) | ID_FIRST_MSG; - rcar_i2c_prepare_msg(priv); + rcar_i2c_first_msg(priv, msgs, num); j = jiffies + num * adap->timeout; do { @@ -909,6 +931,8 @@ static int rcar_i2c_master_xfer_atomic(struct i2c_adapter *adap, ret = -ENXIO; } else if (priv->flags & ID_ARBLOST) { ret = -EAGAIN; + } else if (priv->flags & ID_EPROTO) { + ret = -EPROTO; } else { ret = num - priv->msgs_left; /* The number of transfer */ } @@ -975,7 +999,7 @@ static u32 rcar_i2c_func(struct i2c_adapter *adap) * I2C_M_IGNORE_NAK (automatically sends STOP after NAK) */ u32 func = I2C_FUNC_I2C | I2C_FUNC_SLAVE | - (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK); + (I2C_FUNC_SMBUS_EMUL_ALL & ~I2C_FUNC_SMBUS_QUICK); if (priv->flags & ID_P_HOST_NOTIFY) func |= I2C_FUNC_SMBUS_HOST_NOTIFY; @@ -1063,8 +1087,10 @@ static int rcar_i2c_probe(struct platform_device *pdev) pm_runtime_enable(dev); pm_runtime_get_sync(dev); ret = rcar_i2c_clock_calculate(priv); - if (ret < 0) - goto out_pm_put; + if (ret < 0) { + pm_runtime_put(dev); + goto out_pm_disable; + } rcar_i2c_write(priv, ICSAR, 0); /* Gen2: must be 0 if not using slave */ @@ -1093,19 +1119,19 @@ static int rcar_i2c_probe(struct platform_device *pdev) ret = platform_get_irq(pdev, 0); if (ret < 0) - goto out_pm_disable; + goto out_pm_put; priv->irq = ret; ret = devm_request_irq(dev, priv->irq, irqhandler, irqflags, dev_name(dev), priv); if (ret < 0) { dev_err(dev, "cannot get irq %d\n", priv->irq); - goto out_pm_disable; + goto out_pm_put; } platform_set_drvdata(pdev, priv); ret = i2c_add_numbered_adapter(adap); if (ret < 0) - goto out_pm_disable; + goto out_pm_put; if (priv->flags & ID_P_HOST_NOTIFY) { priv->host_notify_client = i2c_new_slave_host_notify_device(adap); @@ -1122,7 +1148,8 @@ static int rcar_i2c_probe(struct platform_device *pdev) out_del_device: i2c_del_adapter(&priv->adap); out_pm_put: - pm_runtime_put(dev); + if (priv->flags & ID_P_PM_BLOCKED) + pm_runtime_put(dev); out_pm_disable: pm_runtime_disable(dev); return ret; diff --git a/drivers/i2c/busses/i2c-xiic.c b/drivers/i2c/busses/i2c-xiic.c index ffefe3c482e9c9a67a37dbdb3b4130ecec9f446b..9a1c3f8b7048dc192842e064ea4ead27daa69c65 100644 --- a/drivers/i2c/busses/i2c-xiic.c +++ b/drivers/i2c/busses/i2c-xiic.c @@ -78,24 +78,23 @@ struct xiic_i2c { bool singlemaster; }; - #define XIIC_MSB_OFFSET 0 -#define XIIC_REG_OFFSET (0x100+XIIC_MSB_OFFSET) +#define XIIC_REG_OFFSET (0x100 + XIIC_MSB_OFFSET) /* * Register offsets in bytes from RegisterBase. Three is added to the * base offset to access LSB (IBM style) of the word */ -#define XIIC_CR_REG_OFFSET (0x00+XIIC_REG_OFFSET) /* Control Register */ -#define XIIC_SR_REG_OFFSET (0x04+XIIC_REG_OFFSET) /* Status Register */ -#define XIIC_DTR_REG_OFFSET (0x08+XIIC_REG_OFFSET) /* Data Tx Register */ -#define XIIC_DRR_REG_OFFSET (0x0C+XIIC_REG_OFFSET) /* Data Rx Register */ -#define XIIC_ADR_REG_OFFSET (0x10+XIIC_REG_OFFSET) /* Address Register */ -#define XIIC_TFO_REG_OFFSET (0x14+XIIC_REG_OFFSET) /* Tx FIFO Occupancy */ -#define XIIC_RFO_REG_OFFSET (0x18+XIIC_REG_OFFSET) /* Rx FIFO Occupancy */ -#define XIIC_TBA_REG_OFFSET (0x1C+XIIC_REG_OFFSET) /* 10 Bit Address reg */ -#define XIIC_RFD_REG_OFFSET (0x20+XIIC_REG_OFFSET) /* Rx FIFO Depth reg */ -#define XIIC_GPO_REG_OFFSET (0x24+XIIC_REG_OFFSET) /* Output Register */ +#define XIIC_CR_REG_OFFSET (0x00 + XIIC_REG_OFFSET) /* Control Register */ +#define XIIC_SR_REG_OFFSET (0x04 + XIIC_REG_OFFSET) /* Status Register */ +#define XIIC_DTR_REG_OFFSET (0x08 + XIIC_REG_OFFSET) /* Data Tx Register */ +#define XIIC_DRR_REG_OFFSET (0x0C + XIIC_REG_OFFSET) /* Data Rx Register */ +#define XIIC_ADR_REG_OFFSET (0x10 + XIIC_REG_OFFSET) /* Address Register */ +#define XIIC_TFO_REG_OFFSET (0x14 + XIIC_REG_OFFSET) /* Tx FIFO Occupancy */ +#define XIIC_RFO_REG_OFFSET (0x18 + XIIC_REG_OFFSET) /* Rx FIFO Occupancy */ +#define XIIC_TBA_REG_OFFSET (0x1C + XIIC_REG_OFFSET) /* 10 Bit Address reg */ +#define XIIC_RFD_REG_OFFSET (0x20 + XIIC_REG_OFFSET) /* Rx FIFO Depth reg */ +#define XIIC_GPO_REG_OFFSET (0x24 + XIIC_REG_OFFSET) /* Output Register */ /* Control Register masks */ #define XIIC_CR_ENABLE_DEVICE_MASK 0x01 /* Device enable = 1 */ @@ -233,18 +232,21 @@ static inline int xiic_getreg32(struct xiic_i2c *i2c, int reg) static inline void xiic_irq_dis(struct xiic_i2c *i2c, u32 mask) { u32 ier = xiic_getreg32(i2c, XIIC_IIER_OFFSET); + xiic_setreg32(i2c, XIIC_IIER_OFFSET, ier & ~mask); } static inline void xiic_irq_en(struct xiic_i2c *i2c, u32 mask) { u32 ier = xiic_getreg32(i2c, XIIC_IIER_OFFSET); + xiic_setreg32(i2c, XIIC_IIER_OFFSET, ier | mask); } static inline void xiic_irq_clr(struct xiic_i2c *i2c, u32 mask) { u32 isr = xiic_getreg32(i2c, XIIC_IISR_OFFSET); + xiic_setreg32(i2c, XIIC_IISR_OFFSET, isr & mask); } @@ -355,7 +357,8 @@ static void xiic_fill_tx_fifo(struct xiic_i2c *i2c) while (len--) { u16 data = i2c->tx_msg->buf[i2c->tx_pos++]; - if ((xiic_tx_space(i2c) == 0) && (i2c->nmsgs == 1)) { + + if (!xiic_tx_space(i2c) && i2c->nmsgs == 1) { /* last message in transfer -> STOP */ data |= XIIC_TX_DYN_STOP_MASK; dev_dbg(i2c->adap.dev.parent, "%s TX STOP\n", __func__); @@ -381,6 +384,7 @@ static irqreturn_t xiic_process(int irq, void *dev_id) int xfer_more = 0; int wakeup_req = 0; int wakeup_code = 0; + int ret; /* Get the interrupt Status from the IPIF. There is no clearing of * interrupts in the IPIF. Interrupts must be cleared at the source. @@ -401,8 +405,8 @@ static irqreturn_t xiic_process(int irq, void *dev_id) /* Service requesting interrupt */ if ((pend & XIIC_INTR_ARB_LOST_MASK) || - ((pend & XIIC_INTR_TX_ERROR_MASK) && - !(pend & XIIC_INTR_RX_FULL_MASK))) { + ((pend & XIIC_INTR_TX_ERROR_MASK) && + !(pend & XIIC_INTR_RX_FULL_MASK))) { /* bus arbritration lost, or... * Transmit error _OR_ RX completed * if this happens when RX_FULL is not set @@ -415,7 +419,9 @@ static irqreturn_t xiic_process(int irq, void *dev_id) * fifos and the next message is a TX with len 0 (only addr) * reset the IP instead of just flush fifos */ - xiic_reinit(i2c); + ret = xiic_reinit(i2c); + if (!ret) + dev_dbg(i2c->adap.dev.parent, "reinit failed\n"); if (i2c->rx_msg) { wakeup_req = 1; @@ -462,24 +468,6 @@ static irqreturn_t xiic_process(int irq, void *dev_id) } } } - if (pend & XIIC_INTR_BNB_MASK) { - /* IIC bus has transitioned to not busy */ - clr |= XIIC_INTR_BNB_MASK; - - /* The bus is not busy, disable BusNotBusy interrupt */ - xiic_irq_dis(i2c, XIIC_INTR_BNB_MASK); - - if (!i2c->tx_msg) - goto out; - - wakeup_req = 1; - - if (i2c->nmsgs == 1 && !i2c->rx_msg && - xiic_tx_space(i2c) == 0) - wakeup_code = STATE_DONE; - else - wakeup_code = STATE_ERROR; - } if (pend & (XIIC_INTR_TX_EMPTY_MASK | XIIC_INTR_TX_HALF_MASK)) { /* Transmit register/FIFO is empty or ½ empty */ @@ -516,6 +504,26 @@ static irqreturn_t xiic_process(int irq, void *dev_id) */ xiic_irq_dis(i2c, XIIC_INTR_TX_HALF_MASK); } + + if (pend & XIIC_INTR_BNB_MASK) { + /* IIC bus has transitioned to not busy */ + clr |= XIIC_INTR_BNB_MASK; + + /* The bus is not busy, disable BusNotBusy interrupt */ + xiic_irq_dis(i2c, XIIC_INTR_BNB_MASK); + + if (!i2c->tx_msg) + goto out; + + wakeup_req = 1; + + if (i2c->nmsgs == 1 && !i2c->rx_msg && + xiic_tx_space(i2c) == 0) + wakeup_code = STATE_DONE; + else + wakeup_code = STATE_ERROR; + } + out: dev_dbg(i2c->adap.dev.parent, "%s clr: 0x%x\n", __func__, clr); @@ -570,7 +578,7 @@ static int xiic_busy(struct xiic_i2c *i2c) static void xiic_start_recv(struct xiic_i2c *i2c) { - u8 rx_watermark; + u16 rx_watermark; struct i2c_msg *msg = i2c->rx_msg = i2c->tx_msg; /* Clear and enable Rx full interrupt. */ @@ -585,7 +593,7 @@ static void xiic_start_recv(struct xiic_i2c *i2c) rx_watermark = msg->len; if (rx_watermark > IIC_RX_FIFO_DEPTH) rx_watermark = IIC_RX_FIFO_DEPTH; - xiic_setreg8(i2c, XIIC_RFD_REG_OFFSET, rx_watermark - 1); + xiic_setreg8(i2c, XIIC_RFD_REG_OFFSET, (u8)(rx_watermark - 1)); if (!(msg->flags & I2C_M_NOSTART)) /* write the address */ @@ -638,6 +646,7 @@ static void xiic_start_send(struct xiic_i2c *i2c) static void __xiic_start_xfer(struct xiic_i2c *i2c) { int fifo_space = xiic_tx_fifo_space(i2c); + dev_dbg(i2c->adap.dev.parent, "%s entry, msg: %p, fifos space: %d\n", __func__, i2c->tx_msg, fifo_space); @@ -739,7 +748,6 @@ static const struct i2c_adapter xiic_adapter = { .quirks = &xiic_quirks, }; - static int xiic_i2c_probe(struct platform_device *pdev) { struct xiic_i2c *i2c; @@ -899,6 +907,7 @@ static const struct dev_pm_ops xiic_dev_pm_ops = { SET_RUNTIME_PM_OPS(xiic_i2c_runtime_suspend, xiic_i2c_runtime_resume, NULL) }; + static struct platform_driver xiic_i2c_driver = { .probe = xiic_i2c_probe, .remove = xiic_i2c_remove, @@ -914,4 +923,3 @@ module_platform_driver(xiic_i2c_driver); MODULE_AUTHOR("info@mocean-labs.com"); MODULE_DESCRIPTION("Xilinx I2C bus driver"); MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:"DRIVER_NAME); diff --git a/drivers/input/input.c b/drivers/input/input.c index e5a668ce884d6d7626ea1984ccd79decc40aceb6..1365c9dfb5f299630f9ebf8c5af07af79f002ebd 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -1793,8 +1793,6 @@ EXPORT_SYMBOL(input_reset_device); static int input_inhibit_device(struct input_dev *dev) { - int ret = 0; - mutex_lock(&dev->mutex); if (dev->inhibited) @@ -1816,7 +1814,7 @@ static int input_inhibit_device(struct input_dev *dev) out: mutex_unlock(&dev->mutex); - return ret; + return 0; } static int input_uninhibit_device(struct input_dev *dev) diff --git a/drivers/input/joystick/Kconfig b/drivers/input/joystick/Kconfig index 3b23078bc7b5b9a8eee41fe9a601e292355d4cfd..505a032e2786d2121e8019c35c849e77f4a25ee3 100644 --- a/drivers/input/joystick/Kconfig +++ b/drivers/input/joystick/Kconfig @@ -399,4 +399,15 @@ config JOYSTICK_N64 Say Y here if you want enable support for the four built-in controller ports on the Nintendo 64 console. +config JOYSTICK_SENSEHAT + tristate "Raspberry Pi Sense HAT joystick" + depends on INPUT && I2C + select MFD_SIMPLE_MFD_I2C + help + Say Y here if you want to enable the driver for the + the Raspberry Pi Sense HAT. + + To compile this driver as a module, choose M here: the + module will be called sensehat_joystick. + endif diff --git a/drivers/input/joystick/Makefile b/drivers/input/joystick/Makefile index 5174b8aba2dd01ba0a6cf4e601ae50f250c55901..3937535f00981e52052bea22e449326c3c88716e 100644 --- a/drivers/input/joystick/Makefile +++ b/drivers/input/joystick/Makefile @@ -28,6 +28,7 @@ obj-$(CONFIG_JOYSTICK_N64) += n64joy.o obj-$(CONFIG_JOYSTICK_PSXPAD_SPI) += psxpad-spi.o obj-$(CONFIG_JOYSTICK_PXRC) += pxrc.o obj-$(CONFIG_JOYSTICK_QWIIC) += qwiic-joystick.o +obj-$(CONFIG_JOYSTICK_SENSEHAT) += sensehat-joystick.o obj-$(CONFIG_JOYSTICK_SIDEWINDER) += sidewinder.o obj-$(CONFIG_JOYSTICK_SPACEBALL) += spaceball.o obj-$(CONFIG_JOYSTICK_SPACEORB) += spaceorb.o diff --git a/drivers/input/joystick/sensehat-joystick.c b/drivers/input/joystick/sensehat-joystick.c new file mode 100644 index 0000000000000000000000000000000000000000..5ad1fe4ff496a3afb824fcf1f9706306dda01f9e --- /dev/null +++ b/drivers/input/joystick/sensehat-joystick.c @@ -0,0 +1,137 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Raspberry Pi Sense HAT joystick driver + * http://raspberrypi.org + * + * Copyright (C) 2015 Raspberry Pi + * Copyright (C) 2021 Charles Mirabile, Mwesigwa Guma, Joel Savitz + * + * Original Author: Serge Schneider + * Revised for upstream Linux by: Charles Mirabile, Mwesigwa Guma, Joel Savitz + */ + +#include +#include +#include +#include +#include +#include +#include + +#define JOYSTICK_SMB_REG 0xf2 + +struct sensehat_joystick { + struct platform_device *pdev; + struct input_dev *keys_dev; + unsigned long prev_states; + struct regmap *regmap; +}; + +static const unsigned int keymap[] = { + BTN_DPAD_DOWN, BTN_DPAD_RIGHT, BTN_DPAD_UP, BTN_SELECT, BTN_DPAD_LEFT, +}; + +static irqreturn_t sensehat_joystick_report(int irq, void *cookie) +{ + struct sensehat_joystick *sensehat_joystick = cookie; + unsigned long curr_states, changes; + unsigned int keys; + int error; + int i; + + error = regmap_read(sensehat_joystick->regmap, JOYSTICK_SMB_REG, &keys); + if (error < 0) { + dev_err(&sensehat_joystick->pdev->dev, + "Failed to read joystick state: %d", error); + return IRQ_NONE; + } + curr_states = keys; + bitmap_xor(&changes, &curr_states, &sensehat_joystick->prev_states, + ARRAY_SIZE(keymap)); + + for_each_set_bit(i, &changes, ARRAY_SIZE(keymap)) + input_report_key(sensehat_joystick->keys_dev, keymap[i], + curr_states & BIT(i)); + + input_sync(sensehat_joystick->keys_dev); + sensehat_joystick->prev_states = keys; + return IRQ_HANDLED; +} + +static int sensehat_joystick_probe(struct platform_device *pdev) +{ + struct sensehat_joystick *sensehat_joystick; + int error, i, irq; + + sensehat_joystick = devm_kzalloc(&pdev->dev, sizeof(*sensehat_joystick), + GFP_KERNEL); + if (!sensehat_joystick) + return -ENOMEM; + + sensehat_joystick->pdev = pdev; + + sensehat_joystick->regmap = dev_get_regmap(pdev->dev.parent, NULL); + if (!sensehat_joystick->regmap) { + dev_err(&pdev->dev, "unable to get sensehat regmap"); + return -ENODEV; + } + + sensehat_joystick->keys_dev = devm_input_allocate_device(&pdev->dev); + if (!sensehat_joystick->keys_dev) { + dev_err(&pdev->dev, "Could not allocate input device"); + return -ENOMEM; + } + + sensehat_joystick->keys_dev->name = "Raspberry Pi Sense HAT Joystick"; + sensehat_joystick->keys_dev->phys = "sensehat-joystick/input0"; + sensehat_joystick->keys_dev->id.bustype = BUS_I2C; + + __set_bit(EV_KEY, sensehat_joystick->keys_dev->evbit); + __set_bit(EV_REP, sensehat_joystick->keys_dev->evbit); + for (i = 0; i < ARRAY_SIZE(keymap); i++) + __set_bit(keymap[i], sensehat_joystick->keys_dev->keybit); + + error = input_register_device(sensehat_joystick->keys_dev); + if (error) { + dev_err(&pdev->dev, "Could not register input device"); + return error; + } + + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + dev_err(&pdev->dev, "Could not retrieve interrupt request"); + return irq; + } + + error = devm_request_threaded_irq(&pdev->dev, irq, + NULL, sensehat_joystick_report, + IRQF_ONESHOT, "keys", + sensehat_joystick); + if (error) { + dev_err(&pdev->dev, "IRQ request failed"); + return error; + } + + return 0; +} + +static const struct of_device_id sensehat_joystick_device_id[] = { + { .compatible = "raspberrypi,sensehat-joystick" }, + {}, +}; +MODULE_DEVICE_TABLE(of, sensehat_joystick_device_id); + +static struct platform_driver sensehat_joystick_driver = { + .probe = sensehat_joystick_probe, + .driver = { + .name = "sensehat-joystick", + .of_match_table = sensehat_joystick_device_id, + }, +}; + +module_platform_driver(sensehat_joystick_driver); + +MODULE_DESCRIPTION("Raspberry Pi Sense HAT joystick driver"); +MODULE_AUTHOR("Charles Mirabile "); +MODULE_AUTHOR("Serge Schneider "); +MODULE_LICENSE("GPL"); diff --git a/drivers/input/keyboard/bcm-keypad.c b/drivers/input/keyboard/bcm-keypad.c index 2b771c3a557846631b708b4435b4b605d51804cb..166d6023a53884eac7ebcaf9df2763379c05f8f9 100644 --- a/drivers/input/keyboard/bcm-keypad.c +++ b/drivers/input/keyboard/bcm-keypad.c @@ -183,8 +183,7 @@ static void bcm_kp_stop(const struct bcm_kp *kp) writel(0xFFFFFFFF, kp->base + KPICR0_OFFSET); writel(0xFFFFFFFF, kp->base + KPICR1_OFFSET); - if (kp->clk) - clk_disable_unprepare(kp->clk); + clk_disable_unprepare(kp->clk); } static int bcm_kp_open(struct input_dev *dev) diff --git a/drivers/input/keyboard/clps711x-keypad.c b/drivers/input/keyboard/clps711x-keypad.c index 019dd6ed2c295e1928e9563ae0941f53f59d06bb..939c88655fc02a20adf3a07305a066f73d04084d 100644 --- a/drivers/input/keyboard/clps711x-keypad.c +++ b/drivers/input/keyboard/clps711x-keypad.c @@ -95,8 +95,7 @@ static int clps711x_keypad_probe(struct platform_device *pdev) if (!priv) return -ENOMEM; - priv->syscon = - syscon_regmap_lookup_by_compatible("cirrus,ep7209-syscon1"); + priv->syscon = syscon_regmap_lookup_by_phandle(np, "syscon"); if (IS_ERR(priv->syscon)) return PTR_ERR(priv->syscon); diff --git a/drivers/input/keyboard/cros_ec_keyb.c b/drivers/input/keyboard/cros_ec_keyb.c index 6534dfca60b4d06e29f0c446df5f143a1149c7e6..cc73a149da28f9fd8abdae368b944e7418e0a3f7 100644 --- a/drivers/input/keyboard/cros_ec_keyb.c +++ b/drivers/input/keyboard/cros_ec_keyb.c @@ -435,10 +435,13 @@ static __maybe_unused int cros_ec_keyb_resume(struct device *dev) * but the ckdev->bs_idev will remain NULL when this function exits. * * @ckdev: The keyboard device + * @expect_buttons_switches: Indicates that EC must report button and/or + * switch events * * Returns 0 if no error or -error upon error. */ -static int cros_ec_keyb_register_bs(struct cros_ec_keyb *ckdev) +static int cros_ec_keyb_register_bs(struct cros_ec_keyb *ckdev, + bool expect_buttons_switches) { struct cros_ec_device *ec_dev = ckdev->ec; struct device *dev = ckdev->dev; @@ -465,7 +468,7 @@ static int cros_ec_keyb_register_bs(struct cros_ec_keyb *ckdev) switches = get_unaligned_le32(&event_data.switches); if (!buttons && !switches) - return 0; + return expect_buttons_switches ? -EINVAL : 0; /* * We call the non-matrix buttons/switches 'input1', if present. @@ -516,7 +519,7 @@ static int cros_ec_keyb_register_bs(struct cros_ec_keyb *ckdev) } /** - * cros_ec_keyb_register_bs - Register matrix keys + * cros_ec_keyb_register_matrix - Register matrix keys * * Handles all the bits of the keyboard driver related to matrix keys. * @@ -648,12 +651,12 @@ static const struct attribute_group cros_ec_keyb_attr_group = { .attrs = cros_ec_keyb_attrs, }; - static int cros_ec_keyb_probe(struct platform_device *pdev) { struct cros_ec_device *ec = dev_get_drvdata(pdev->dev.parent); struct device *dev = &pdev->dev; struct cros_ec_keyb *ckdev; + bool buttons_switches_only = device_get_match_data(dev); int err; if (!dev->of_node) @@ -667,13 +670,16 @@ static int cros_ec_keyb_probe(struct platform_device *pdev) ckdev->dev = dev; dev_set_drvdata(dev, ckdev); - err = cros_ec_keyb_register_matrix(ckdev); - if (err) { - dev_err(dev, "cannot register matrix inputs: %d\n", err); - return err; + if (!buttons_switches_only) { + err = cros_ec_keyb_register_matrix(ckdev); + if (err) { + dev_err(dev, "cannot register matrix inputs: %d\n", + err); + return err; + } } - err = cros_ec_keyb_register_bs(ckdev); + err = cros_ec_keyb_register_bs(ckdev, buttons_switches_only); if (err) { dev_err(dev, "cannot register non-matrix inputs: %d\n", err); return err; @@ -681,7 +687,7 @@ static int cros_ec_keyb_probe(struct platform_device *pdev) err = devm_device_add_group(dev, &cros_ec_keyb_attr_group); if (err) { - dev_err(dev, "failed to create attributes. err=%d\n", err); + dev_err(dev, "failed to create attributes: %d\n", err); return err; } @@ -710,7 +716,8 @@ static int cros_ec_keyb_remove(struct platform_device *pdev) #ifdef CONFIG_OF static const struct of_device_id cros_ec_keyb_of_match[] = { { .compatible = "google,cros-ec-keyb" }, - {}, + { .compatible = "google,cros-ec-keyb-switches", .data = (void *)true }, + {} }; MODULE_DEVICE_TABLE(of, cros_ec_keyb_of_match); #endif diff --git a/drivers/input/keyboard/ep93xx_keypad.c b/drivers/input/keyboard/ep93xx_keypad.c index 272a4f1c6e8191f44aa159ecd793c4b05043e567..7a3b0664ab4f47eab4acf4849ca1b94ba33faa74 100644 --- a/drivers/input/keyboard/ep93xx_keypad.c +++ b/drivers/input/keyboard/ep93xx_keypad.c @@ -231,7 +231,6 @@ static int ep93xx_keypad_probe(struct platform_device *pdev) struct ep93xx_keypad *keypad; const struct matrix_keymap_data *keymap_data; struct input_dev *input_dev; - struct resource *res; int err; keypad = devm_kzalloc(&pdev->dev, sizeof(*keypad), GFP_KERNEL); @@ -250,11 +249,7 @@ static int ep93xx_keypad_probe(struct platform_device *pdev) if (keypad->irq < 0) return keypad->irq; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) - return -ENXIO; - - keypad->mmio_base = devm_ioremap_resource(&pdev->dev, res); + keypad->mmio_base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(keypad->mmio_base)) return PTR_ERR(keypad->mmio_base); diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index d75a8b179a8aec74f6642362300e33c472ae0256..a5dc4ab87fa1f5bb2faf392ac98d636e912c858b 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c @@ -131,7 +131,7 @@ static void gpio_keys_quiesce_key(void *data) if (!bdata->gpiod) hrtimer_cancel(&bdata->release_timer); - if (bdata->debounce_use_hrtimer) + else if (bdata->debounce_use_hrtimer) hrtimer_cancel(&bdata->debounce_timer); else cancel_delayed_work_sync(&bdata->work); diff --git a/drivers/input/keyboard/mt6779-keypad.c b/drivers/input/keyboard/mt6779-keypad.c index 0dbbddc7f298048ab90710cd4ce369b4a395a4be..2e7c9187c10f2ab3b506481a6e4971b5bf1e7c54 100644 --- a/drivers/input/keyboard/mt6779-keypad.c +++ b/drivers/input/keyboard/mt6779-keypad.c @@ -24,7 +24,6 @@ struct mt6779_keypad { struct regmap *regmap; struct input_dev *input_dev; struct clk *clk; - void __iomem *base; u32 n_rows; u32 n_cols; DECLARE_BITMAP(keymap_state, MTK_KPD_NUM_BITS); @@ -91,6 +90,7 @@ static void mt6779_keypad_clk_disable(void *data) static int mt6779_keypad_pdrv_probe(struct platform_device *pdev) { struct mt6779_keypad *keypad; + void __iomem *base; int irq; u32 debounce; bool wakeup; @@ -100,11 +100,11 @@ static int mt6779_keypad_pdrv_probe(struct platform_device *pdev) if (!keypad) return -ENOMEM; - keypad->base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(keypad->base)) - return PTR_ERR(keypad->base); + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) + return PTR_ERR(base); - keypad->regmap = devm_regmap_init_mmio(&pdev->dev, keypad->base, + keypad->regmap = devm_regmap_init_mmio(&pdev->dev, base, &mt6779_keypad_regmap_cfg); if (IS_ERR(keypad->regmap)) { dev_err(&pdev->dev, diff --git a/drivers/input/keyboard/sun4i-lradc-keys.c b/drivers/input/keyboard/sun4i-lradc-keys.c index 4a796bed48acc10b13cc235d4871ce82e6ed7368..15c15c0958b00be87bce9ce0ea2f9fffe58f247e 100644 --- a/drivers/input/keyboard/sun4i-lradc-keys.c +++ b/drivers/input/keyboard/sun4i-lradc-keys.c @@ -14,6 +14,7 @@ * there are no boards known to use channel 1. */ +#include #include #include #include @@ -22,7 +23,10 @@ #include #include #include +#include +#include #include +#include #include #define LRADC_CTRL 0x00 @@ -58,10 +62,12 @@ /* struct lradc_variant - Describe sun4i-a10-lradc-keys hardware variant * @divisor_numerator: The numerator of lradc Vref internally divisor * @divisor_denominator: The denominator of lradc Vref internally divisor + * @has_clock_reset: If the binding requires a clock and reset */ struct lradc_variant { u8 divisor_numerator; u8 divisor_denominator; + bool has_clock_reset; }; static const struct lradc_variant lradc_variant_a10 = { @@ -74,6 +80,12 @@ static const struct lradc_variant r_lradc_variant_a83t = { .divisor_denominator = 4 }; +static const struct lradc_variant lradc_variant_r329 = { + .divisor_numerator = 3, + .divisor_denominator = 4, + .has_clock_reset = true, +}; + struct sun4i_lradc_keymap { u32 voltage; u32 keycode; @@ -83,6 +95,8 @@ struct sun4i_lradc_data { struct device *dev; struct input_dev *input; void __iomem *base; + struct clk *clk; + struct reset_control *reset; struct regulator *vref_supply; struct sun4i_lradc_keymap *chan0_map; const struct lradc_variant *variant; @@ -140,6 +154,14 @@ static int sun4i_lradc_open(struct input_dev *dev) if (error) return error; + error = reset_control_deassert(lradc->reset); + if (error) + goto err_disable_reg; + + error = clk_prepare_enable(lradc->clk); + if (error) + goto err_assert_reset; + lradc->vref = regulator_get_voltage(lradc->vref_supply) * lradc->variant->divisor_numerator / lradc->variant->divisor_denominator; @@ -153,6 +175,13 @@ static int sun4i_lradc_open(struct input_dev *dev) writel(CHAN0_KEYUP_IRQ | CHAN0_KEYDOWN_IRQ, lradc->base + LRADC_INTC); return 0; + +err_assert_reset: + reset_control_assert(lradc->reset); +err_disable_reg: + regulator_disable(lradc->vref_supply); + + return error; } static void sun4i_lradc_close(struct input_dev *dev) @@ -164,6 +193,8 @@ static void sun4i_lradc_close(struct input_dev *dev) SAMPLE_RATE(2), lradc->base + LRADC_CTRL); writel(0, lradc->base + LRADC_INTC); + clk_disable_unprepare(lradc->clk); + reset_control_assert(lradc->reset); regulator_disable(lradc->vref_supply); } @@ -226,8 +257,7 @@ static int sun4i_lradc_probe(struct platform_device *pdev) { struct sun4i_lradc_data *lradc; struct device *dev = &pdev->dev; - int i; - int error; + int error, i, irq; lradc = devm_kzalloc(dev, sizeof(struct sun4i_lradc_data), GFP_KERNEL); if (!lradc) @@ -243,6 +273,16 @@ static int sun4i_lradc_probe(struct platform_device *pdev) return -EINVAL; } + if (lradc->variant->has_clock_reset) { + lradc->clk = devm_clk_get(dev, NULL); + if (IS_ERR(lradc->clk)) + return PTR_ERR(lradc->clk); + + lradc->reset = devm_reset_control_get_exclusive(dev, NULL); + if (IS_ERR(lradc->reset)) + return PTR_ERR(lradc->reset); + } + lradc->vref_supply = devm_regulator_get(dev, "vref"); if (IS_ERR(lradc->vref_supply)) return PTR_ERR(lradc->vref_supply); @@ -272,8 +312,11 @@ static int sun4i_lradc_probe(struct platform_device *pdev) if (IS_ERR(lradc->base)) return PTR_ERR(lradc->base); - error = devm_request_irq(dev, platform_get_irq(pdev, 0), - sun4i_lradc_irq, 0, + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; + + error = devm_request_irq(dev, irq, sun4i_lradc_irq, 0, "sun4i-a10-lradc-keys", lradc); if (error) return error; @@ -282,6 +325,16 @@ static int sun4i_lradc_probe(struct platform_device *pdev) if (error) return error; + if (device_property_read_bool(dev, "wakeup-source")) { + error = dev_pm_set_wake_irq(dev, irq); + if (error) + dev_warn(dev, + "Failed to set IRQ %d as a wake IRQ: %d\n", + irq, error); + else + device_set_wakeup_capable(dev, true); + } + return 0; } @@ -290,6 +343,8 @@ static const struct of_device_id sun4i_lradc_of_match[] = { .data = &lradc_variant_a10 }, { .compatible = "allwinner,sun8i-a83t-r-lradc", .data = &r_lradc_variant_a83t }, + { .compatible = "allwinner,sun50i-r329-lradc", + .data = &lradc_variant_r329 }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, sun4i_lradc_of_match); diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index dd5227cf86964b75445709662884af2c4fdc4a41..a18ab7358d8f39c0fea58157ea86dfa467706606 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -762,6 +762,16 @@ config INPUT_IQS626A To compile this driver as a module, choose M here: the module will be called iqs626a. +config INPUT_IQS7222 + tristate "Azoteq IQS7222A/B/C capacitive touch controller" + depends on I2C + help + Say Y to enable support for the Azoteq IQS7222A/B/C family + of capacitive touch controllers. + + To compile this driver as a module, choose M here: the + module will be called iqs7222. + config INPUT_CMA3000 tristate "VTI CMA3000 Tri-axis accelerometer" help diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index b92c53a6b5ae8116f98c97b1d1a6b754f4718c5b..28dfc444f0a96b0d9b1b00ed43b4a1dc990fcce4 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile @@ -44,6 +44,7 @@ obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o obj-$(CONFIG_INPUT_IMS_PCU) += ims-pcu.o obj-$(CONFIG_INPUT_IQS269A) += iqs269a.o obj-$(CONFIG_INPUT_IQS626A) += iqs626a.o +obj-$(CONFIG_INPUT_IQS7222) += iqs7222.o obj-$(CONFIG_INPUT_KEYSPAN_REMOTE) += keyspan_remote.o obj-$(CONFIG_INPUT_KXTJ9) += kxtj9.o obj-$(CONFIG_INPUT_M68K_BEEP) += m68kspkr.o diff --git a/drivers/input/misc/iqs7222.c b/drivers/input/misc/iqs7222.c new file mode 100644 index 0000000000000000000000000000000000000000..6b4138771a3f2e27e8fc6caca9aa8cacefaf9c25 --- /dev/null +++ b/drivers/input/misc/iqs7222.c @@ -0,0 +1,2446 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Azoteq IQS7222A/B/C Capacitive Touch Controller + * + * Copyright (C) 2022 Jeff LaBundy + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define IQS7222_PROD_NUM 0x00 +#define IQS7222_PROD_NUM_A 840 +#define IQS7222_PROD_NUM_B 698 +#define IQS7222_PROD_NUM_C 863 + +#define IQS7222_SYS_STATUS 0x10 +#define IQS7222_SYS_STATUS_RESET BIT(3) +#define IQS7222_SYS_STATUS_ATI_ERROR BIT(1) +#define IQS7222_SYS_STATUS_ATI_ACTIVE BIT(0) + +#define IQS7222_CHAN_SETUP_0_REF_MODE_MASK GENMASK(15, 14) +#define IQS7222_CHAN_SETUP_0_REF_MODE_FOLLOW BIT(15) +#define IQS7222_CHAN_SETUP_0_REF_MODE_REF BIT(14) +#define IQS7222_CHAN_SETUP_0_CHAN_EN BIT(8) + +#define IQS7222_SLDR_SETUP_0_CHAN_CNT_MASK GENMASK(2, 0) +#define IQS7222_SLDR_SETUP_2_RES_MASK GENMASK(15, 8) +#define IQS7222_SLDR_SETUP_2_RES_SHIFT 8 +#define IQS7222_SLDR_SETUP_2_TOP_SPEED_MASK GENMASK(7, 0) +#define IQS7222_SLDR_SETUP_3_CHAN_SEL_MASK GENMASK(9, 0) + +#define IQS7222_GPIO_SETUP_0_GPIO_EN BIT(0) + +#define IQS7222_SYS_SETUP 0xD0 +#define IQS7222_SYS_SETUP_INTF_MODE_MASK GENMASK(7, 6) +#define IQS7222_SYS_SETUP_INTF_MODE_TOUCH BIT(7) +#define IQS7222_SYS_SETUP_INTF_MODE_EVENT BIT(6) +#define IQS7222_SYS_SETUP_PWR_MODE_MASK GENMASK(5, 4) +#define IQS7222_SYS_SETUP_PWR_MODE_AUTO IQS7222_SYS_SETUP_PWR_MODE_MASK +#define IQS7222_SYS_SETUP_REDO_ATI BIT(2) +#define IQS7222_SYS_SETUP_ACK_RESET BIT(0) + +#define IQS7222_EVENT_MASK_ATI BIT(12) + +#define IQS7222_COMMS_HOLD BIT(0) +#define IQS7222_COMMS_ERROR 0xEEEE +#define IQS7222_COMMS_RETRY_MS 50 +#define IQS7222_COMMS_TIMEOUT_MS 100 +#define IQS7222_RESET_TIMEOUT_MS 250 +#define IQS7222_ATI_TIMEOUT_MS 2000 + +#define IQS7222_MAX_COLS_STAT 8 +#define IQS7222_MAX_COLS_CYCLE 3 +#define IQS7222_MAX_COLS_GLBL 3 +#define IQS7222_MAX_COLS_BTN 3 +#define IQS7222_MAX_COLS_CHAN 6 +#define IQS7222_MAX_COLS_FILT 2 +#define IQS7222_MAX_COLS_SLDR 11 +#define IQS7222_MAX_COLS_GPIO 3 +#define IQS7222_MAX_COLS_SYS 13 + +#define IQS7222_MAX_CHAN 20 +#define IQS7222_MAX_SLDR 2 + +#define IQS7222_NUM_RETRIES 5 +#define IQS7222_REG_OFFSET 0x100 + +enum iqs7222_reg_key_id { + IQS7222_REG_KEY_NONE, + IQS7222_REG_KEY_PROX, + IQS7222_REG_KEY_TOUCH, + IQS7222_REG_KEY_DEBOUNCE, + IQS7222_REG_KEY_TAP, + IQS7222_REG_KEY_AXIAL, + IQS7222_REG_KEY_WHEEL, + IQS7222_REG_KEY_NO_WHEEL, + IQS7222_REG_KEY_RESERVED +}; + +enum iqs7222_reg_grp_id { + IQS7222_REG_GRP_STAT, + IQS7222_REG_GRP_CYCLE, + IQS7222_REG_GRP_GLBL, + IQS7222_REG_GRP_BTN, + IQS7222_REG_GRP_CHAN, + IQS7222_REG_GRP_FILT, + IQS7222_REG_GRP_SLDR, + IQS7222_REG_GRP_GPIO, + IQS7222_REG_GRP_SYS, + IQS7222_NUM_REG_GRPS +}; + +static const char * const iqs7222_reg_grp_names[] = { + [IQS7222_REG_GRP_CYCLE] = "cycle", + [IQS7222_REG_GRP_CHAN] = "channel", + [IQS7222_REG_GRP_SLDR] = "slider", + [IQS7222_REG_GRP_GPIO] = "gpio", +}; + +static const unsigned int iqs7222_max_cols[] = { + [IQS7222_REG_GRP_STAT] = IQS7222_MAX_COLS_STAT, + [IQS7222_REG_GRP_CYCLE] = IQS7222_MAX_COLS_CYCLE, + [IQS7222_REG_GRP_GLBL] = IQS7222_MAX_COLS_GLBL, + [IQS7222_REG_GRP_BTN] = IQS7222_MAX_COLS_BTN, + [IQS7222_REG_GRP_CHAN] = IQS7222_MAX_COLS_CHAN, + [IQS7222_REG_GRP_FILT] = IQS7222_MAX_COLS_FILT, + [IQS7222_REG_GRP_SLDR] = IQS7222_MAX_COLS_SLDR, + [IQS7222_REG_GRP_GPIO] = IQS7222_MAX_COLS_GPIO, + [IQS7222_REG_GRP_SYS] = IQS7222_MAX_COLS_SYS, +}; + +static const unsigned int iqs7222_gpio_links[] = { 2, 5, 6, }; + +struct iqs7222_event_desc { + const char *name; + u16 mask; + u16 val; + u16 enable; + enum iqs7222_reg_key_id reg_key; +}; + +static const struct iqs7222_event_desc iqs7222_kp_events[] = { + { + .name = "event-prox", + .enable = BIT(0), + .reg_key = IQS7222_REG_KEY_PROX, + }, + { + .name = "event-touch", + .enable = BIT(1), + .reg_key = IQS7222_REG_KEY_TOUCH, + }, +}; + +static const struct iqs7222_event_desc iqs7222_sl_events[] = { + { .name = "event-press", }, + { + .name = "event-tap", + .mask = BIT(0), + .val = BIT(0), + .enable = BIT(0), + .reg_key = IQS7222_REG_KEY_TAP, + }, + { + .name = "event-swipe-pos", + .mask = BIT(5) | BIT(1), + .val = BIT(1), + .enable = BIT(1), + .reg_key = IQS7222_REG_KEY_AXIAL, + }, + { + .name = "event-swipe-neg", + .mask = BIT(5) | BIT(1), + .val = BIT(5) | BIT(1), + .enable = BIT(1), + .reg_key = IQS7222_REG_KEY_AXIAL, + }, + { + .name = "event-flick-pos", + .mask = BIT(5) | BIT(2), + .val = BIT(2), + .enable = BIT(2), + .reg_key = IQS7222_REG_KEY_AXIAL, + }, + { + .name = "event-flick-neg", + .mask = BIT(5) | BIT(2), + .val = BIT(5) | BIT(2), + .enable = BIT(2), + .reg_key = IQS7222_REG_KEY_AXIAL, + }, +}; + +struct iqs7222_reg_grp_desc { + u16 base; + int num_row; + int num_col; +}; + +struct iqs7222_dev_desc { + u16 prod_num; + u16 fw_major; + u16 fw_minor; + u16 sldr_res; + u16 touch_link; + u16 wheel_enable; + int allow_offset; + int event_offset; + int comms_offset; + struct iqs7222_reg_grp_desc reg_grps[IQS7222_NUM_REG_GRPS]; +}; + +static const struct iqs7222_dev_desc iqs7222_devs[] = { + { + .prod_num = IQS7222_PROD_NUM_A, + .fw_major = 1, + .fw_minor = 12, + .sldr_res = U8_MAX * 16, + .touch_link = 1768, + .allow_offset = 9, + .event_offset = 10, + .comms_offset = 12, + .reg_grps = { + [IQS7222_REG_GRP_STAT] = { + .base = IQS7222_SYS_STATUS, + .num_row = 1, + .num_col = 8, + }, + [IQS7222_REG_GRP_CYCLE] = { + .base = 0x8000, + .num_row = 7, + .num_col = 3, + }, + [IQS7222_REG_GRP_GLBL] = { + .base = 0x8700, + .num_row = 1, + .num_col = 3, + }, + [IQS7222_REG_GRP_BTN] = { + .base = 0x9000, + .num_row = 12, + .num_col = 3, + }, + [IQS7222_REG_GRP_CHAN] = { + .base = 0xA000, + .num_row = 12, + .num_col = 6, + }, + [IQS7222_REG_GRP_FILT] = { + .base = 0xAC00, + .num_row = 1, + .num_col = 2, + }, + [IQS7222_REG_GRP_SLDR] = { + .base = 0xB000, + .num_row = 2, + .num_col = 11, + }, + [IQS7222_REG_GRP_GPIO] = { + .base = 0xC000, + .num_row = 1, + .num_col = 3, + }, + [IQS7222_REG_GRP_SYS] = { + .base = IQS7222_SYS_SETUP, + .num_row = 1, + .num_col = 13, + }, + }, + }, + { + .prod_num = IQS7222_PROD_NUM_B, + .fw_major = 1, + .fw_minor = 43, + .event_offset = 10, + .comms_offset = 11, + .reg_grps = { + [IQS7222_REG_GRP_STAT] = { + .base = IQS7222_SYS_STATUS, + .num_row = 1, + .num_col = 6, + }, + [IQS7222_REG_GRP_CYCLE] = { + .base = 0x8000, + .num_row = 10, + .num_col = 2, + }, + [IQS7222_REG_GRP_GLBL] = { + .base = 0x8A00, + .num_row = 1, + .num_col = 3, + }, + [IQS7222_REG_GRP_BTN] = { + .base = 0x9000, + .num_row = 20, + .num_col = 2, + }, + [IQS7222_REG_GRP_CHAN] = { + .base = 0xB000, + .num_row = 20, + .num_col = 4, + }, + [IQS7222_REG_GRP_FILT] = { + .base = 0xC400, + .num_row = 1, + .num_col = 2, + }, + [IQS7222_REG_GRP_SYS] = { + .base = IQS7222_SYS_SETUP, + .num_row = 1, + .num_col = 13, + }, + }, + }, + { + .prod_num = IQS7222_PROD_NUM_B, + .fw_major = 1, + .fw_minor = 27, + .reg_grps = { + [IQS7222_REG_GRP_STAT] = { + .base = IQS7222_SYS_STATUS, + .num_row = 1, + .num_col = 6, + }, + [IQS7222_REG_GRP_CYCLE] = { + .base = 0x8000, + .num_row = 10, + .num_col = 2, + }, + [IQS7222_REG_GRP_GLBL] = { + .base = 0x8A00, + .num_row = 1, + .num_col = 3, + }, + [IQS7222_REG_GRP_BTN] = { + .base = 0x9000, + .num_row = 20, + .num_col = 2, + }, + [IQS7222_REG_GRP_CHAN] = { + .base = 0xB000, + .num_row = 20, + .num_col = 4, + }, + [IQS7222_REG_GRP_FILT] = { + .base = 0xC400, + .num_row = 1, + .num_col = 2, + }, + [IQS7222_REG_GRP_SYS] = { + .base = IQS7222_SYS_SETUP, + .num_row = 1, + .num_col = 10, + }, + }, + }, + { + .prod_num = IQS7222_PROD_NUM_C, + .fw_major = 2, + .fw_minor = 6, + .sldr_res = U16_MAX, + .touch_link = 1686, + .wheel_enable = BIT(3), + .event_offset = 9, + .comms_offset = 10, + .reg_grps = { + [IQS7222_REG_GRP_STAT] = { + .base = IQS7222_SYS_STATUS, + .num_row = 1, + .num_col = 6, + }, + [IQS7222_REG_GRP_CYCLE] = { + .base = 0x8000, + .num_row = 5, + .num_col = 3, + }, + [IQS7222_REG_GRP_GLBL] = { + .base = 0x8500, + .num_row = 1, + .num_col = 3, + }, + [IQS7222_REG_GRP_BTN] = { + .base = 0x9000, + .num_row = 10, + .num_col = 3, + }, + [IQS7222_REG_GRP_CHAN] = { + .base = 0xA000, + .num_row = 10, + .num_col = 6, + }, + [IQS7222_REG_GRP_FILT] = { + .base = 0xAA00, + .num_row = 1, + .num_col = 2, + }, + [IQS7222_REG_GRP_SLDR] = { + .base = 0xB000, + .num_row = 2, + .num_col = 10, + }, + [IQS7222_REG_GRP_GPIO] = { + .base = 0xC000, + .num_row = 3, + .num_col = 3, + }, + [IQS7222_REG_GRP_SYS] = { + .base = IQS7222_SYS_SETUP, + .num_row = 1, + .num_col = 12, + }, + }, + }, + { + .prod_num = IQS7222_PROD_NUM_C, + .fw_major = 1, + .fw_minor = 13, + .sldr_res = U16_MAX, + .touch_link = 1674, + .wheel_enable = BIT(3), + .event_offset = 9, + .comms_offset = 10, + .reg_grps = { + [IQS7222_REG_GRP_STAT] = { + .base = IQS7222_SYS_STATUS, + .num_row = 1, + .num_col = 6, + }, + [IQS7222_REG_GRP_CYCLE] = { + .base = 0x8000, + .num_row = 5, + .num_col = 3, + }, + [IQS7222_REG_GRP_GLBL] = { + .base = 0x8500, + .num_row = 1, + .num_col = 3, + }, + [IQS7222_REG_GRP_BTN] = { + .base = 0x9000, + .num_row = 10, + .num_col = 3, + }, + [IQS7222_REG_GRP_CHAN] = { + .base = 0xA000, + .num_row = 10, + .num_col = 6, + }, + [IQS7222_REG_GRP_FILT] = { + .base = 0xAA00, + .num_row = 1, + .num_col = 2, + }, + [IQS7222_REG_GRP_SLDR] = { + .base = 0xB000, + .num_row = 2, + .num_col = 10, + }, + [IQS7222_REG_GRP_GPIO] = { + .base = 0xC000, + .num_row = 1, + .num_col = 3, + }, + [IQS7222_REG_GRP_SYS] = { + .base = IQS7222_SYS_SETUP, + .num_row = 1, + .num_col = 11, + }, + }, + }, +}; + +struct iqs7222_prop_desc { + const char *name; + enum iqs7222_reg_grp_id reg_grp; + enum iqs7222_reg_key_id reg_key; + int reg_offset; + int reg_shift; + int reg_width; + int val_pitch; + int val_min; + int val_max; + bool invert; + const char *label; +}; + +static const struct iqs7222_prop_desc iqs7222_props[] = { + { + .name = "azoteq,conv-period", + .reg_grp = IQS7222_REG_GRP_CYCLE, + .reg_offset = 0, + .reg_shift = 8, + .reg_width = 8, + .label = "conversion period", + }, + { + .name = "azoteq,conv-frac", + .reg_grp = IQS7222_REG_GRP_CYCLE, + .reg_offset = 0, + .reg_shift = 0, + .reg_width = 8, + .label = "conversion frequency fractional divider", + }, + { + .name = "azoteq,rx-float-inactive", + .reg_grp = IQS7222_REG_GRP_CYCLE, + .reg_offset = 1, + .reg_shift = 6, + .reg_width = 1, + .invert = true, + }, + { + .name = "azoteq,dead-time-enable", + .reg_grp = IQS7222_REG_GRP_CYCLE, + .reg_offset = 1, + .reg_shift = 5, + .reg_width = 1, + }, + { + .name = "azoteq,tx-freq-fosc", + .reg_grp = IQS7222_REG_GRP_CYCLE, + .reg_offset = 1, + .reg_shift = 4, + .reg_width = 1, + }, + { + .name = "azoteq,vbias-enable", + .reg_grp = IQS7222_REG_GRP_CYCLE, + .reg_offset = 1, + .reg_shift = 3, + .reg_width = 1, + }, + { + .name = "azoteq,sense-mode", + .reg_grp = IQS7222_REG_GRP_CYCLE, + .reg_offset = 1, + .reg_shift = 0, + .reg_width = 3, + .val_max = 3, + .label = "sensing mode", + }, + { + .name = "azoteq,iref-enable", + .reg_grp = IQS7222_REG_GRP_CYCLE, + .reg_offset = 2, + .reg_shift = 10, + .reg_width = 1, + }, + { + .name = "azoteq,iref-level", + .reg_grp = IQS7222_REG_GRP_CYCLE, + .reg_offset = 2, + .reg_shift = 4, + .reg_width = 4, + .label = "current reference level", + }, + { + .name = "azoteq,iref-trim", + .reg_grp = IQS7222_REG_GRP_CYCLE, + .reg_offset = 2, + .reg_shift = 0, + .reg_width = 4, + .label = "current reference trim", + }, + { + .name = "azoteq,rf-filt-enable", + .reg_grp = IQS7222_REG_GRP_GLBL, + .reg_offset = 0, + .reg_shift = 15, + .reg_width = 1, + }, + { + .name = "azoteq,max-counts", + .reg_grp = IQS7222_REG_GRP_GLBL, + .reg_offset = 0, + .reg_shift = 13, + .reg_width = 2, + .label = "maximum counts", + }, + { + .name = "azoteq,auto-mode", + .reg_grp = IQS7222_REG_GRP_GLBL, + .reg_offset = 0, + .reg_shift = 2, + .reg_width = 2, + .label = "number of conversions", + }, + { + .name = "azoteq,ati-frac-div-fine", + .reg_grp = IQS7222_REG_GRP_GLBL, + .reg_offset = 1, + .reg_shift = 9, + .reg_width = 5, + .label = "ATI fine fractional divider", + }, + { + .name = "azoteq,ati-frac-div-coarse", + .reg_grp = IQS7222_REG_GRP_GLBL, + .reg_offset = 1, + .reg_shift = 0, + .reg_width = 5, + .label = "ATI coarse fractional divider", + }, + { + .name = "azoteq,ati-comp-select", + .reg_grp = IQS7222_REG_GRP_GLBL, + .reg_offset = 2, + .reg_shift = 0, + .reg_width = 10, + .label = "ATI compensation selection", + }, + { + .name = "azoteq,ati-band", + .reg_grp = IQS7222_REG_GRP_CHAN, + .reg_offset = 0, + .reg_shift = 12, + .reg_width = 2, + .label = "ATI band", + }, + { + .name = "azoteq,global-halt", + .reg_grp = IQS7222_REG_GRP_CHAN, + .reg_offset = 0, + .reg_shift = 11, + .reg_width = 1, + }, + { + .name = "azoteq,invert-enable", + .reg_grp = IQS7222_REG_GRP_CHAN, + .reg_offset = 0, + .reg_shift = 10, + .reg_width = 1, + }, + { + .name = "azoteq,dual-direction", + .reg_grp = IQS7222_REG_GRP_CHAN, + .reg_offset = 0, + .reg_shift = 9, + .reg_width = 1, + }, + { + .name = "azoteq,samp-cap-double", + .reg_grp = IQS7222_REG_GRP_CHAN, + .reg_offset = 0, + .reg_shift = 3, + .reg_width = 1, + }, + { + .name = "azoteq,vref-half", + .reg_grp = IQS7222_REG_GRP_CHAN, + .reg_offset = 0, + .reg_shift = 2, + .reg_width = 1, + }, + { + .name = "azoteq,proj-bias", + .reg_grp = IQS7222_REG_GRP_CHAN, + .reg_offset = 0, + .reg_shift = 0, + .reg_width = 2, + .label = "projected bias current", + }, + { + .name = "azoteq,ati-target", + .reg_grp = IQS7222_REG_GRP_CHAN, + .reg_offset = 1, + .reg_shift = 8, + .reg_width = 8, + .val_pitch = 8, + .label = "ATI target", + }, + { + .name = "azoteq,ati-base", + .reg_grp = IQS7222_REG_GRP_CHAN, + .reg_offset = 1, + .reg_shift = 3, + .reg_width = 5, + .val_pitch = 16, + .label = "ATI base", + }, + { + .name = "azoteq,ati-mode", + .reg_grp = IQS7222_REG_GRP_CHAN, + .reg_offset = 1, + .reg_shift = 0, + .reg_width = 3, + .val_max = 5, + .label = "ATI mode", + }, + { + .name = "azoteq,ati-frac-div-fine", + .reg_grp = IQS7222_REG_GRP_CHAN, + .reg_offset = 2, + .reg_shift = 9, + .reg_width = 5, + .label = "ATI fine fractional divider", + }, + { + .name = "azoteq,ati-frac-mult-coarse", + .reg_grp = IQS7222_REG_GRP_CHAN, + .reg_offset = 2, + .reg_shift = 5, + .reg_width = 4, + .label = "ATI coarse fractional multiplier", + }, + { + .name = "azoteq,ati-frac-div-coarse", + .reg_grp = IQS7222_REG_GRP_CHAN, + .reg_offset = 2, + .reg_shift = 0, + .reg_width = 5, + .label = "ATI coarse fractional divider", + }, + { + .name = "azoteq,ati-comp-div", + .reg_grp = IQS7222_REG_GRP_CHAN, + .reg_offset = 3, + .reg_shift = 11, + .reg_width = 5, + .label = "ATI compensation divider", + }, + { + .name = "azoteq,ati-comp-select", + .reg_grp = IQS7222_REG_GRP_CHAN, + .reg_offset = 3, + .reg_shift = 0, + .reg_width = 10, + .label = "ATI compensation selection", + }, + { + .name = "azoteq,debounce-exit", + .reg_grp = IQS7222_REG_GRP_BTN, + .reg_key = IQS7222_REG_KEY_DEBOUNCE, + .reg_offset = 0, + .reg_shift = 12, + .reg_width = 4, + .label = "debounce exit factor", + }, + { + .name = "azoteq,debounce-enter", + .reg_grp = IQS7222_REG_GRP_BTN, + .reg_key = IQS7222_REG_KEY_DEBOUNCE, + .reg_offset = 0, + .reg_shift = 8, + .reg_width = 4, + .label = "debounce entrance factor", + }, + { + .name = "azoteq,thresh", + .reg_grp = IQS7222_REG_GRP_BTN, + .reg_key = IQS7222_REG_KEY_PROX, + .reg_offset = 0, + .reg_shift = 0, + .reg_width = 8, + .val_max = 127, + .label = "threshold", + }, + { + .name = "azoteq,thresh", + .reg_grp = IQS7222_REG_GRP_BTN, + .reg_key = IQS7222_REG_KEY_TOUCH, + .reg_offset = 1, + .reg_shift = 0, + .reg_width = 8, + .label = "threshold", + }, + { + .name = "azoteq,hyst", + .reg_grp = IQS7222_REG_GRP_BTN, + .reg_key = IQS7222_REG_KEY_TOUCH, + .reg_offset = 1, + .reg_shift = 8, + .reg_width = 8, + .label = "hysteresis", + }, + { + .name = "azoteq,lta-beta-lp", + .reg_grp = IQS7222_REG_GRP_FILT, + .reg_offset = 0, + .reg_shift = 12, + .reg_width = 4, + .label = "low-power mode long-term average beta", + }, + { + .name = "azoteq,lta-beta-np", + .reg_grp = IQS7222_REG_GRP_FILT, + .reg_offset = 0, + .reg_shift = 8, + .reg_width = 4, + .label = "normal-power mode long-term average beta", + }, + { + .name = "azoteq,counts-beta-lp", + .reg_grp = IQS7222_REG_GRP_FILT, + .reg_offset = 0, + .reg_shift = 4, + .reg_width = 4, + .label = "low-power mode counts beta", + }, + { + .name = "azoteq,counts-beta-np", + .reg_grp = IQS7222_REG_GRP_FILT, + .reg_offset = 0, + .reg_shift = 0, + .reg_width = 4, + .label = "normal-power mode counts beta", + }, + { + .name = "azoteq,lta-fast-beta-lp", + .reg_grp = IQS7222_REG_GRP_FILT, + .reg_offset = 1, + .reg_shift = 4, + .reg_width = 4, + .label = "low-power mode long-term average fast beta", + }, + { + .name = "azoteq,lta-fast-beta-np", + .reg_grp = IQS7222_REG_GRP_FILT, + .reg_offset = 1, + .reg_shift = 0, + .reg_width = 4, + .label = "normal-power mode long-term average fast beta", + }, + { + .name = "azoteq,lower-cal", + .reg_grp = IQS7222_REG_GRP_SLDR, + .reg_offset = 0, + .reg_shift = 8, + .reg_width = 8, + .label = "lower calibration", + }, + { + .name = "azoteq,static-beta", + .reg_grp = IQS7222_REG_GRP_SLDR, + .reg_key = IQS7222_REG_KEY_NO_WHEEL, + .reg_offset = 0, + .reg_shift = 6, + .reg_width = 1, + }, + { + .name = "azoteq,bottom-beta", + .reg_grp = IQS7222_REG_GRP_SLDR, + .reg_key = IQS7222_REG_KEY_NO_WHEEL, + .reg_offset = 0, + .reg_shift = 3, + .reg_width = 3, + .label = "bottom beta", + }, + { + .name = "azoteq,static-beta", + .reg_grp = IQS7222_REG_GRP_SLDR, + .reg_key = IQS7222_REG_KEY_WHEEL, + .reg_offset = 0, + .reg_shift = 7, + .reg_width = 1, + }, + { + .name = "azoteq,bottom-beta", + .reg_grp = IQS7222_REG_GRP_SLDR, + .reg_key = IQS7222_REG_KEY_WHEEL, + .reg_offset = 0, + .reg_shift = 4, + .reg_width = 3, + .label = "bottom beta", + }, + { + .name = "azoteq,bottom-speed", + .reg_grp = IQS7222_REG_GRP_SLDR, + .reg_offset = 1, + .reg_shift = 8, + .reg_width = 8, + .label = "bottom speed", + }, + { + .name = "azoteq,upper-cal", + .reg_grp = IQS7222_REG_GRP_SLDR, + .reg_offset = 1, + .reg_shift = 0, + .reg_width = 8, + .label = "upper calibration", + }, + { + .name = "azoteq,gesture-max-ms", + .reg_grp = IQS7222_REG_GRP_SLDR, + .reg_key = IQS7222_REG_KEY_TAP, + .reg_offset = 9, + .reg_shift = 8, + .reg_width = 8, + .val_pitch = 4, + .label = "maximum gesture time", + }, + { + .name = "azoteq,gesture-min-ms", + .reg_grp = IQS7222_REG_GRP_SLDR, + .reg_key = IQS7222_REG_KEY_TAP, + .reg_offset = 9, + .reg_shift = 3, + .reg_width = 5, + .val_pitch = 4, + .label = "minimum gesture time", + }, + { + .name = "azoteq,gesture-dist", + .reg_grp = IQS7222_REG_GRP_SLDR, + .reg_key = IQS7222_REG_KEY_AXIAL, + .reg_offset = 10, + .reg_shift = 8, + .reg_width = 8, + .val_pitch = 16, + .label = "gesture distance", + }, + { + .name = "azoteq,gesture-max-ms", + .reg_grp = IQS7222_REG_GRP_SLDR, + .reg_key = IQS7222_REG_KEY_AXIAL, + .reg_offset = 10, + .reg_shift = 0, + .reg_width = 8, + .val_pitch = 4, + .label = "maximum gesture time", + }, + { + .name = "drive-open-drain", + .reg_grp = IQS7222_REG_GRP_GPIO, + .reg_offset = 0, + .reg_shift = 1, + .reg_width = 1, + }, + { + .name = "azoteq,timeout-ati-ms", + .reg_grp = IQS7222_REG_GRP_SYS, + .reg_offset = 1, + .reg_shift = 0, + .reg_width = 16, + .val_pitch = 500, + .label = "ATI error timeout", + }, + { + .name = "azoteq,rate-ati-ms", + .reg_grp = IQS7222_REG_GRP_SYS, + .reg_offset = 2, + .reg_shift = 0, + .reg_width = 16, + .label = "ATI report rate", + }, + { + .name = "azoteq,timeout-np-ms", + .reg_grp = IQS7222_REG_GRP_SYS, + .reg_offset = 3, + .reg_shift = 0, + .reg_width = 16, + .label = "normal-power mode timeout", + }, + { + .name = "azoteq,rate-np-ms", + .reg_grp = IQS7222_REG_GRP_SYS, + .reg_offset = 4, + .reg_shift = 0, + .reg_width = 16, + .val_max = 3000, + .label = "normal-power mode report rate", + }, + { + .name = "azoteq,timeout-lp-ms", + .reg_grp = IQS7222_REG_GRP_SYS, + .reg_offset = 5, + .reg_shift = 0, + .reg_width = 16, + .label = "low-power mode timeout", + }, + { + .name = "azoteq,rate-lp-ms", + .reg_grp = IQS7222_REG_GRP_SYS, + .reg_offset = 6, + .reg_shift = 0, + .reg_width = 16, + .val_max = 3000, + .label = "low-power mode report rate", + }, + { + .name = "azoteq,timeout-ulp-ms", + .reg_grp = IQS7222_REG_GRP_SYS, + .reg_offset = 7, + .reg_shift = 0, + .reg_width = 16, + .label = "ultra-low-power mode timeout", + }, + { + .name = "azoteq,rate-ulp-ms", + .reg_grp = IQS7222_REG_GRP_SYS, + .reg_offset = 8, + .reg_shift = 0, + .reg_width = 16, + .val_max = 3000, + .label = "ultra-low-power mode report rate", + }, +}; + +struct iqs7222_private { + const struct iqs7222_dev_desc *dev_desc; + struct gpio_desc *reset_gpio; + struct gpio_desc *irq_gpio; + struct i2c_client *client; + struct input_dev *keypad; + unsigned int kp_type[IQS7222_MAX_CHAN][ARRAY_SIZE(iqs7222_kp_events)]; + unsigned int kp_code[IQS7222_MAX_CHAN][ARRAY_SIZE(iqs7222_kp_events)]; + unsigned int sl_code[IQS7222_MAX_SLDR][ARRAY_SIZE(iqs7222_sl_events)]; + unsigned int sl_axis[IQS7222_MAX_SLDR]; + u16 cycle_setup[IQS7222_MAX_CHAN / 2][IQS7222_MAX_COLS_CYCLE]; + u16 glbl_setup[IQS7222_MAX_COLS_GLBL]; + u16 btn_setup[IQS7222_MAX_CHAN][IQS7222_MAX_COLS_BTN]; + u16 chan_setup[IQS7222_MAX_CHAN][IQS7222_MAX_COLS_CHAN]; + u16 filt_setup[IQS7222_MAX_COLS_FILT]; + u16 sldr_setup[IQS7222_MAX_SLDR][IQS7222_MAX_COLS_SLDR]; + u16 gpio_setup[ARRAY_SIZE(iqs7222_gpio_links)][IQS7222_MAX_COLS_GPIO]; + u16 sys_setup[IQS7222_MAX_COLS_SYS]; +}; + +static u16 *iqs7222_setup(struct iqs7222_private *iqs7222, + enum iqs7222_reg_grp_id reg_grp, int row) +{ + switch (reg_grp) { + case IQS7222_REG_GRP_CYCLE: + return iqs7222->cycle_setup[row]; + + case IQS7222_REG_GRP_GLBL: + return iqs7222->glbl_setup; + + case IQS7222_REG_GRP_BTN: + return iqs7222->btn_setup[row]; + + case IQS7222_REG_GRP_CHAN: + return iqs7222->chan_setup[row]; + + case IQS7222_REG_GRP_FILT: + return iqs7222->filt_setup; + + case IQS7222_REG_GRP_SLDR: + return iqs7222->sldr_setup[row]; + + case IQS7222_REG_GRP_GPIO: + return iqs7222->gpio_setup[row]; + + case IQS7222_REG_GRP_SYS: + return iqs7222->sys_setup; + + default: + return NULL; + } +} + +static int iqs7222_irq_poll(struct iqs7222_private *iqs7222, u16 timeout_ms) +{ + ktime_t irq_timeout = ktime_add_ms(ktime_get(), timeout_ms); + int ret; + + do { + usleep_range(1000, 1100); + + ret = gpiod_get_value_cansleep(iqs7222->irq_gpio); + if (ret < 0) + return ret; + else if (ret > 0) + return 0; + } while (ktime_compare(ktime_get(), irq_timeout) < 0); + + return -EBUSY; +} + +static int iqs7222_hard_reset(struct iqs7222_private *iqs7222) +{ + struct i2c_client *client = iqs7222->client; + int error; + + if (!iqs7222->reset_gpio) + return 0; + + gpiod_set_value_cansleep(iqs7222->reset_gpio, 1); + usleep_range(1000, 1100); + + gpiod_set_value_cansleep(iqs7222->reset_gpio, 0); + + error = iqs7222_irq_poll(iqs7222, IQS7222_RESET_TIMEOUT_MS); + if (error) + dev_err(&client->dev, "Failed to reset device: %d\n", error); + + return error; +} + +static int iqs7222_force_comms(struct iqs7222_private *iqs7222) +{ + u8 msg_buf[] = { 0xFF, 0x00, }; + int ret; + + /* + * The device cannot communicate until it asserts its interrupt (RDY) + * pin. Attempts to do so while RDY is deasserted return an ACK; how- + * ever all write data is ignored, and all read data returns 0xEE. + * + * Unsolicited communication must be preceded by a special force com- + * munication command, after which the device eventually asserts its + * RDY pin and agrees to communicate. + * + * Regardless of whether communication is forced or the result of an + * interrupt, the device automatically deasserts its RDY pin once it + * detects an I2C stop condition, or a timeout expires. + */ + ret = gpiod_get_value_cansleep(iqs7222->irq_gpio); + if (ret < 0) + return ret; + else if (ret > 0) + return 0; + + ret = i2c_master_send(iqs7222->client, msg_buf, sizeof(msg_buf)); + if (ret < (int)sizeof(msg_buf)) { + if (ret >= 0) + ret = -EIO; + + /* + * The datasheet states that the host must wait to retry any + * failed attempt to communicate over I2C. + */ + msleep(IQS7222_COMMS_RETRY_MS); + return ret; + } + + return iqs7222_irq_poll(iqs7222, IQS7222_COMMS_TIMEOUT_MS); +} + +static int iqs7222_read_burst(struct iqs7222_private *iqs7222, + u16 reg, void *val, u16 num_val) +{ + u8 reg_buf[sizeof(__be16)]; + int ret, i; + struct i2c_client *client = iqs7222->client; + struct i2c_msg msg[] = { + { + .addr = client->addr, + .flags = 0, + .len = reg > U8_MAX ? sizeof(reg) : sizeof(u8), + .buf = reg_buf, + }, + { + .addr = client->addr, + .flags = I2C_M_RD, + .len = num_val * sizeof(__le16), + .buf = (u8 *)val, + }, + }; + + if (reg > U8_MAX) + put_unaligned_be16(reg, reg_buf); + else + *reg_buf = (u8)reg; + + /* + * The following loop protects against an edge case in which the RDY + * pin is automatically deasserted just as the read is initiated. In + * that case, the read must be retried using forced communication. + */ + for (i = 0; i < IQS7222_NUM_RETRIES; i++) { + ret = iqs7222_force_comms(iqs7222); + if (ret < 0) + continue; + + ret = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg)); + if (ret < (int)ARRAY_SIZE(msg)) { + if (ret >= 0) + ret = -EIO; + + msleep(IQS7222_COMMS_RETRY_MS); + continue; + } + + if (get_unaligned_le16(msg[1].buf) == IQS7222_COMMS_ERROR) { + ret = -ENODATA; + continue; + } + + ret = 0; + break; + } + + /* + * The following delay ensures the device has deasserted the RDY pin + * following the I2C stop condition. + */ + usleep_range(50, 100); + + if (ret < 0) + dev_err(&client->dev, + "Failed to read from address 0x%04X: %d\n", reg, ret); + + return ret; +} + +static int iqs7222_read_word(struct iqs7222_private *iqs7222, u16 reg, u16 *val) +{ + __le16 val_buf; + int error; + + error = iqs7222_read_burst(iqs7222, reg, &val_buf, 1); + if (error) + return error; + + *val = le16_to_cpu(val_buf); + + return 0; +} + +static int iqs7222_write_burst(struct iqs7222_private *iqs7222, + u16 reg, const void *val, u16 num_val) +{ + int reg_len = reg > U8_MAX ? sizeof(reg) : sizeof(u8); + int val_len = num_val * sizeof(__le16); + int msg_len = reg_len + val_len; + int ret, i; + struct i2c_client *client = iqs7222->client; + u8 *msg_buf; + + msg_buf = kzalloc(msg_len, GFP_KERNEL); + if (!msg_buf) + return -ENOMEM; + + if (reg > U8_MAX) + put_unaligned_be16(reg, msg_buf); + else + *msg_buf = (u8)reg; + + memcpy(msg_buf + reg_len, val, val_len); + + /* + * The following loop protects against an edge case in which the RDY + * pin is automatically asserted just before the force communication + * command is sent. + * + * In that case, the subsequent I2C stop condition tricks the device + * into preemptively deasserting the RDY pin and the command must be + * sent again. + */ + for (i = 0; i < IQS7222_NUM_RETRIES; i++) { + ret = iqs7222_force_comms(iqs7222); + if (ret < 0) + continue; + + ret = i2c_master_send(client, msg_buf, msg_len); + if (ret < msg_len) { + if (ret >= 0) + ret = -EIO; + + msleep(IQS7222_COMMS_RETRY_MS); + continue; + } + + ret = 0; + break; + } + + kfree(msg_buf); + + usleep_range(50, 100); + + if (ret < 0) + dev_err(&client->dev, + "Failed to write to address 0x%04X: %d\n", reg, ret); + + return ret; +} + +static int iqs7222_write_word(struct iqs7222_private *iqs7222, u16 reg, u16 val) +{ + __le16 val_buf = cpu_to_le16(val); + + return iqs7222_write_burst(iqs7222, reg, &val_buf, 1); +} + +static int iqs7222_ati_trigger(struct iqs7222_private *iqs7222) +{ + struct i2c_client *client = iqs7222->client; + ktime_t ati_timeout; + u16 sys_status = 0; + u16 sys_setup = iqs7222->sys_setup[0] & ~IQS7222_SYS_SETUP_ACK_RESET; + int error, i; + + for (i = 0; i < IQS7222_NUM_RETRIES; i++) { + /* + * Trigger ATI from streaming and normal-power modes so that + * the RDY pin continues to be asserted during ATI. + */ + error = iqs7222_write_word(iqs7222, IQS7222_SYS_SETUP, + sys_setup | + IQS7222_SYS_SETUP_REDO_ATI); + if (error) + return error; + + ati_timeout = ktime_add_ms(ktime_get(), IQS7222_ATI_TIMEOUT_MS); + + do { + error = iqs7222_irq_poll(iqs7222, + IQS7222_COMMS_TIMEOUT_MS); + if (error) + continue; + + error = iqs7222_read_word(iqs7222, IQS7222_SYS_STATUS, + &sys_status); + if (error) + return error; + + if (sys_status & IQS7222_SYS_STATUS_ATI_ACTIVE) + continue; + + if (sys_status & IQS7222_SYS_STATUS_ATI_ERROR) + break; + + /* + * Use stream-in-touch mode if either slider reports + * absolute position. + */ + sys_setup |= test_bit(EV_ABS, iqs7222->keypad->evbit) + ? IQS7222_SYS_SETUP_INTF_MODE_TOUCH + : IQS7222_SYS_SETUP_INTF_MODE_EVENT; + sys_setup |= IQS7222_SYS_SETUP_PWR_MODE_AUTO; + + return iqs7222_write_word(iqs7222, IQS7222_SYS_SETUP, + sys_setup); + } while (ktime_compare(ktime_get(), ati_timeout) < 0); + + dev_err(&client->dev, + "ATI attempt %d of %d failed with status 0x%02X, %s\n", + i + 1, IQS7222_NUM_RETRIES, (u8)sys_status, + i < IQS7222_NUM_RETRIES ? "retrying..." : "stopping"); + } + + return -ETIMEDOUT; +} + +static int iqs7222_dev_init(struct iqs7222_private *iqs7222, int dir) +{ + const struct iqs7222_dev_desc *dev_desc = iqs7222->dev_desc; + int comms_offset = dev_desc->comms_offset; + int error, i, j, k; + + /* + * Take advantage of the stop-bit disable function, if available, to + * save the trouble of having to reopen a communication window after + * each burst read or write. + */ + if (comms_offset) { + u16 comms_setup; + + error = iqs7222_read_word(iqs7222, + IQS7222_SYS_SETUP + comms_offset, + &comms_setup); + if (error) + return error; + + error = iqs7222_write_word(iqs7222, + IQS7222_SYS_SETUP + comms_offset, + comms_setup | IQS7222_COMMS_HOLD); + if (error) + return error; + } + + for (i = 0; i < IQS7222_NUM_REG_GRPS; i++) { + int num_row = dev_desc->reg_grps[i].num_row; + int num_col = dev_desc->reg_grps[i].num_col; + u16 reg = dev_desc->reg_grps[i].base; + __le16 *val_buf; + u16 *val; + + if (!num_col) + continue; + + val = iqs7222_setup(iqs7222, i, 0); + if (!val) + continue; + + val_buf = kcalloc(num_col, sizeof(__le16), GFP_KERNEL); + if (!val_buf) + return -ENOMEM; + + for (j = 0; j < num_row; j++) { + switch (dir) { + case READ: + error = iqs7222_read_burst(iqs7222, reg, + val_buf, num_col); + for (k = 0; k < num_col; k++) + val[k] = le16_to_cpu(val_buf[k]); + break; + + case WRITE: + for (k = 0; k < num_col; k++) + val_buf[k] = cpu_to_le16(val[k]); + error = iqs7222_write_burst(iqs7222, reg, + val_buf, num_col); + break; + + default: + error = -EINVAL; + } + + if (error) + break; + + reg += IQS7222_REG_OFFSET; + val += iqs7222_max_cols[i]; + } + + kfree(val_buf); + + if (error) + return error; + } + + if (comms_offset) { + u16 comms_setup; + + error = iqs7222_read_word(iqs7222, + IQS7222_SYS_SETUP + comms_offset, + &comms_setup); + if (error) + return error; + + error = iqs7222_write_word(iqs7222, + IQS7222_SYS_SETUP + comms_offset, + comms_setup & ~IQS7222_COMMS_HOLD); + if (error) + return error; + } + + if (dir == READ) + return 0; + + return iqs7222_ati_trigger(iqs7222); +} + +static int iqs7222_dev_info(struct iqs7222_private *iqs7222) +{ + struct i2c_client *client = iqs7222->client; + bool prod_num_valid = false; + __le16 dev_id[3]; + int error, i; + + error = iqs7222_read_burst(iqs7222, IQS7222_PROD_NUM, dev_id, + ARRAY_SIZE(dev_id)); + if (error) + return error; + + for (i = 0; i < ARRAY_SIZE(iqs7222_devs); i++) { + if (le16_to_cpu(dev_id[0]) != iqs7222_devs[i].prod_num) + continue; + + prod_num_valid = true; + + if (le16_to_cpu(dev_id[1]) < iqs7222_devs[i].fw_major) + continue; + + if (le16_to_cpu(dev_id[2]) < iqs7222_devs[i].fw_minor) + continue; + + iqs7222->dev_desc = &iqs7222_devs[i]; + return 0; + } + + if (prod_num_valid) + dev_err(&client->dev, "Unsupported firmware revision: %u.%u\n", + le16_to_cpu(dev_id[1]), le16_to_cpu(dev_id[2])); + else + dev_err(&client->dev, "Unrecognized product number: %u\n", + le16_to_cpu(dev_id[0])); + + return -EINVAL; +} + +static int iqs7222_gpio_select(struct iqs7222_private *iqs7222, + struct fwnode_handle *child_node, + int child_enable, u16 child_link) +{ + const struct iqs7222_dev_desc *dev_desc = iqs7222->dev_desc; + struct i2c_client *client = iqs7222->client; + int num_gpio = dev_desc->reg_grps[IQS7222_REG_GRP_GPIO].num_row; + int error, count, i; + unsigned int gpio_sel[ARRAY_SIZE(iqs7222_gpio_links)]; + + if (!num_gpio) + return 0; + + if (!fwnode_property_present(child_node, "azoteq,gpio-select")) + return 0; + + count = fwnode_property_count_u32(child_node, "azoteq,gpio-select"); + if (count > num_gpio) { + dev_err(&client->dev, "Invalid number of %s GPIOs\n", + fwnode_get_name(child_node)); + return -EINVAL; + } else if (count < 0) { + dev_err(&client->dev, "Failed to count %s GPIOs: %d\n", + fwnode_get_name(child_node), count); + return count; + } + + error = fwnode_property_read_u32_array(child_node, + "azoteq,gpio-select", + gpio_sel, count); + if (error) { + dev_err(&client->dev, "Failed to read %s GPIOs: %d\n", + fwnode_get_name(child_node), error); + return error; + } + + for (i = 0; i < count; i++) { + u16 *gpio_setup; + + if (gpio_sel[i] >= num_gpio) { + dev_err(&client->dev, "Invalid %s GPIO: %u\n", + fwnode_get_name(child_node), gpio_sel[i]); + return -EINVAL; + } + + gpio_setup = iqs7222->gpio_setup[gpio_sel[i]]; + + if (gpio_setup[2] && child_link != gpio_setup[2]) { + dev_err(&client->dev, + "Conflicting GPIO %u event types\n", + gpio_sel[i]); + return -EINVAL; + } + + gpio_setup[0] |= IQS7222_GPIO_SETUP_0_GPIO_EN; + gpio_setup[1] |= child_enable; + gpio_setup[2] = child_link; + } + + return 0; +} + +static int iqs7222_parse_props(struct iqs7222_private *iqs7222, + struct fwnode_handle **child_node, + int child_index, + enum iqs7222_reg_grp_id reg_grp, + enum iqs7222_reg_key_id reg_key) +{ + u16 *setup = iqs7222_setup(iqs7222, reg_grp, child_index); + struct i2c_client *client = iqs7222->client; + struct fwnode_handle *reg_grp_node; + char reg_grp_name[16]; + int i; + + switch (reg_grp) { + case IQS7222_REG_GRP_CYCLE: + case IQS7222_REG_GRP_CHAN: + case IQS7222_REG_GRP_SLDR: + case IQS7222_REG_GRP_GPIO: + case IQS7222_REG_GRP_BTN: + /* + * These groups derive a child node and return it to the caller + * for additional group-specific processing. In some cases, the + * child node may have already been derived. + */ + reg_grp_node = *child_node; + if (reg_grp_node) + break; + + snprintf(reg_grp_name, sizeof(reg_grp_name), "%s-%d", + iqs7222_reg_grp_names[reg_grp], child_index); + + reg_grp_node = device_get_named_child_node(&client->dev, + reg_grp_name); + if (!reg_grp_node) + return 0; + + *child_node = reg_grp_node; + break; + + case IQS7222_REG_GRP_GLBL: + case IQS7222_REG_GRP_FILT: + case IQS7222_REG_GRP_SYS: + /* + * These groups are not organized beneath a child node, nor are + * they subject to any additional processing by the caller. + */ + reg_grp_node = dev_fwnode(&client->dev); + break; + + default: + return -EINVAL; + } + + for (i = 0; i < ARRAY_SIZE(iqs7222_props); i++) { + const char *name = iqs7222_props[i].name; + int reg_offset = iqs7222_props[i].reg_offset; + int reg_shift = iqs7222_props[i].reg_shift; + int reg_width = iqs7222_props[i].reg_width; + int val_pitch = iqs7222_props[i].val_pitch ? : 1; + int val_min = iqs7222_props[i].val_min; + int val_max = iqs7222_props[i].val_max; + bool invert = iqs7222_props[i].invert; + const char *label = iqs7222_props[i].label ? : name; + unsigned int val; + int error; + + if (iqs7222_props[i].reg_grp != reg_grp || + iqs7222_props[i].reg_key != reg_key) + continue; + + /* + * Boolean register fields are one bit wide; they are forcibly + * reset to provide a means to undo changes by a bootloader if + * necessary. + * + * Scalar fields, on the other hand, are left untouched unless + * their corresponding properties are present. + */ + if (reg_width == 1) { + if (invert) + setup[reg_offset] |= BIT(reg_shift); + else + setup[reg_offset] &= ~BIT(reg_shift); + } + + if (!fwnode_property_present(reg_grp_node, name)) + continue; + + if (reg_width == 1) { + if (invert) + setup[reg_offset] &= ~BIT(reg_shift); + else + setup[reg_offset] |= BIT(reg_shift); + + continue; + } + + error = fwnode_property_read_u32(reg_grp_node, name, &val); + if (error) { + dev_err(&client->dev, "Failed to read %s %s: %d\n", + fwnode_get_name(reg_grp_node), label, error); + return error; + } + + if (!val_max) + val_max = GENMASK(reg_width - 1, 0) * val_pitch; + + if (val < val_min || val > val_max) { + dev_err(&client->dev, "Invalid %s %s: %u\n", + fwnode_get_name(reg_grp_node), label, val); + return -EINVAL; + } + + setup[reg_offset] &= ~GENMASK(reg_shift + reg_width - 1, + reg_shift); + setup[reg_offset] |= (val / val_pitch << reg_shift); + } + + return 0; +} + +static int iqs7222_parse_cycle(struct iqs7222_private *iqs7222, int cycle_index) +{ + u16 *cycle_setup = iqs7222->cycle_setup[cycle_index]; + struct i2c_client *client = iqs7222->client; + struct fwnode_handle *cycle_node = NULL; + unsigned int pins[9]; + int error, count, i; + + /* + * Each channel shares a cycle with one other channel; the mapping of + * channels to cycles is fixed. Properties defined for a cycle impact + * both channels tied to the cycle. + */ + error = iqs7222_parse_props(iqs7222, &cycle_node, cycle_index, + IQS7222_REG_GRP_CYCLE, + IQS7222_REG_KEY_NONE); + if (error) + return error; + + if (!cycle_node) + return 0; + + /* + * Unlike channels which are restricted to a select range of CRx pins + * based on channel number, any cycle can claim any of the device's 9 + * CTx pins (CTx0-8). + */ + if (!fwnode_property_present(cycle_node, "azoteq,tx-enable")) + return 0; + + count = fwnode_property_count_u32(cycle_node, "azoteq,tx-enable"); + if (count < 0) { + dev_err(&client->dev, "Failed to count %s CTx pins: %d\n", + fwnode_get_name(cycle_node), count); + return count; + } else if (count > ARRAY_SIZE(pins)) { + dev_err(&client->dev, "Invalid number of %s CTx pins\n", + fwnode_get_name(cycle_node)); + return -EINVAL; + } + + error = fwnode_property_read_u32_array(cycle_node, "azoteq,tx-enable", + pins, count); + if (error) { + dev_err(&client->dev, "Failed to read %s CTx pins: %d\n", + fwnode_get_name(cycle_node), error); + return error; + } + + cycle_setup[1] &= ~GENMASK(7 + ARRAY_SIZE(pins) - 1, 7); + + for (i = 0; i < count; i++) { + if (pins[i] > 8) { + dev_err(&client->dev, "Invalid %s CTx pin: %u\n", + fwnode_get_name(cycle_node), pins[i]); + return -EINVAL; + } + + cycle_setup[1] |= BIT(pins[i] + 7); + } + + return 0; +} + +static int iqs7222_parse_chan(struct iqs7222_private *iqs7222, int chan_index) +{ + const struct iqs7222_dev_desc *dev_desc = iqs7222->dev_desc; + struct i2c_client *client = iqs7222->client; + struct fwnode_handle *chan_node = NULL; + int num_chan = dev_desc->reg_grps[IQS7222_REG_GRP_CHAN].num_row; + int ext_chan = rounddown(num_chan, 10); + int error, i; + u16 *chan_setup = iqs7222->chan_setup[chan_index]; + u16 *sys_setup = iqs7222->sys_setup; + unsigned int val; + + error = iqs7222_parse_props(iqs7222, &chan_node, chan_index, + IQS7222_REG_GRP_CHAN, + IQS7222_REG_KEY_NONE); + if (error) + return error; + + if (!chan_node) + return 0; + + if (dev_desc->allow_offset) { + sys_setup[dev_desc->allow_offset] |= BIT(chan_index); + if (fwnode_property_present(chan_node, "azoteq,ulp-allow")) + sys_setup[dev_desc->allow_offset] &= ~BIT(chan_index); + } + + chan_setup[0] |= IQS7222_CHAN_SETUP_0_CHAN_EN; + + /* + * The reference channel function allows for differential measurements + * and is only available in the case of IQS7222A or IQS7222C. + */ + if (dev_desc->reg_grps[IQS7222_REG_GRP_CHAN].num_col > 4 && + fwnode_property_present(chan_node, "azoteq,ref-select")) { + u16 *ref_setup; + + error = fwnode_property_read_u32(chan_node, "azoteq,ref-select", + &val); + if (error) { + dev_err(&client->dev, + "Failed to read %s reference channel: %d\n", + fwnode_get_name(chan_node), error); + return error; + } + + if (val >= ext_chan) { + dev_err(&client->dev, + "Invalid %s reference channel: %u\n", + fwnode_get_name(chan_node), val); + return -EINVAL; + } + + ref_setup = iqs7222->chan_setup[val]; + + /* + * Configure the current channel as a follower of the selected + * reference channel. + */ + chan_setup[0] |= IQS7222_CHAN_SETUP_0_REF_MODE_FOLLOW; + chan_setup[4] = val * 42 + 1048; + + if (!fwnode_property_read_u32(chan_node, "azoteq,ref-weight", + &val)) { + if (val > U16_MAX) { + dev_err(&client->dev, + "Invalid %s reference weight: %u\n", + fwnode_get_name(chan_node), val); + return -EINVAL; + } + + chan_setup[5] = val; + } + + /* + * Configure the selected channel as a reference channel which + * serves the current channel. + */ + ref_setup[0] |= IQS7222_CHAN_SETUP_0_REF_MODE_REF; + ref_setup[5] |= BIT(chan_index); + + ref_setup[4] = dev_desc->touch_link; + if (fwnode_property_present(chan_node, "azoteq,use-prox")) + ref_setup[4] -= 2; + } + + if (fwnode_property_present(chan_node, "azoteq,rx-enable")) { + /* + * Each channel can claim up to 4 CRx pins. The first half of + * the channels can use CRx0-3, while the second half can use + * CRx4-7. + */ + unsigned int pins[4]; + int count; + + count = fwnode_property_count_u32(chan_node, + "azoteq,rx-enable"); + if (count < 0) { + dev_err(&client->dev, + "Failed to count %s CRx pins: %d\n", + fwnode_get_name(chan_node), count); + return count; + } else if (count > ARRAY_SIZE(pins)) { + dev_err(&client->dev, + "Invalid number of %s CRx pins\n", + fwnode_get_name(chan_node)); + return -EINVAL; + } + + error = fwnode_property_read_u32_array(chan_node, + "azoteq,rx-enable", + pins, count); + if (error) { + dev_err(&client->dev, + "Failed to read %s CRx pins: %d\n", + fwnode_get_name(chan_node), error); + return error; + } + + chan_setup[0] &= ~GENMASK(4 + ARRAY_SIZE(pins) - 1, 4); + + for (i = 0; i < count; i++) { + int min_crx = chan_index < ext_chan / 2 ? 0 : 4; + + if (pins[i] < min_crx || pins[i] > min_crx + 3) { + dev_err(&client->dev, + "Invalid %s CRx pin: %u\n", + fwnode_get_name(chan_node), pins[i]); + return -EINVAL; + } + + chan_setup[0] |= BIT(pins[i] + 4 - min_crx); + } + } + + for (i = 0; i < ARRAY_SIZE(iqs7222_kp_events); i++) { + const char *event_name = iqs7222_kp_events[i].name; + u16 event_enable = iqs7222_kp_events[i].enable; + struct fwnode_handle *event_node; + + event_node = fwnode_get_named_child_node(chan_node, event_name); + if (!event_node) + continue; + + error = iqs7222_parse_props(iqs7222, &event_node, chan_index, + IQS7222_REG_GRP_BTN, + iqs7222_kp_events[i].reg_key); + if (error) + return error; + + error = iqs7222_gpio_select(iqs7222, event_node, + BIT(chan_index), + dev_desc->touch_link - (i ? 0 : 2)); + if (error) + return error; + + if (!fwnode_property_read_u32(event_node, + "azoteq,timeout-press-ms", + &val)) { + /* + * The IQS7222B employs a global pair of press timeout + * registers as opposed to channel-specific registers. + */ + u16 *setup = dev_desc->reg_grps + [IQS7222_REG_GRP_BTN].num_col > 2 ? + &iqs7222->btn_setup[chan_index][2] : + &sys_setup[9]; + + if (val > U8_MAX * 500) { + dev_err(&client->dev, + "Invalid %s press timeout: %u\n", + fwnode_get_name(chan_node), val); + return -EINVAL; + } + + *setup &= ~(U8_MAX << i * 8); + *setup |= (val / 500 << i * 8); + } + + error = fwnode_property_read_u32(event_node, "linux,code", + &val); + if (error) { + dev_err(&client->dev, "Failed to read %s code: %d\n", + fwnode_get_name(chan_node), error); + return error; + } + + iqs7222->kp_code[chan_index][i] = val; + iqs7222->kp_type[chan_index][i] = EV_KEY; + + if (fwnode_property_present(event_node, "linux,input-type")) { + error = fwnode_property_read_u32(event_node, + "linux,input-type", + &val); + if (error) { + dev_err(&client->dev, + "Failed to read %s input type: %d\n", + fwnode_get_name(chan_node), error); + return error; + } + + if (val != EV_KEY && val != EV_SW) { + dev_err(&client->dev, + "Invalid %s input type: %u\n", + fwnode_get_name(chan_node), val); + return -EINVAL; + } + + iqs7222->kp_type[chan_index][i] = val; + } + + /* + * Reference channels can opt out of event reporting by using + * KEY_RESERVED in place of a true key or switch code. + */ + if (iqs7222->kp_type[chan_index][i] == EV_KEY && + iqs7222->kp_code[chan_index][i] == KEY_RESERVED) + continue; + + input_set_capability(iqs7222->keypad, + iqs7222->kp_type[chan_index][i], + iqs7222->kp_code[chan_index][i]); + + if (!dev_desc->event_offset) + continue; + + sys_setup[dev_desc->event_offset] |= event_enable; + } + + /* + * The following call handles a special pair of properties that apply + * to a channel node, but reside within the button (event) group. + */ + return iqs7222_parse_props(iqs7222, &chan_node, chan_index, + IQS7222_REG_GRP_BTN, + IQS7222_REG_KEY_DEBOUNCE); +} + +static int iqs7222_parse_sldr(struct iqs7222_private *iqs7222, int sldr_index) +{ + const struct iqs7222_dev_desc *dev_desc = iqs7222->dev_desc; + struct i2c_client *client = iqs7222->client; + struct fwnode_handle *sldr_node = NULL; + int num_chan = dev_desc->reg_grps[IQS7222_REG_GRP_CHAN].num_row; + int ext_chan = rounddown(num_chan, 10); + int count, error, reg_offset, i; + u16 *sldr_setup = iqs7222->sldr_setup[sldr_index]; + u16 *sys_setup = iqs7222->sys_setup; + unsigned int chan_sel[4], val; + + error = iqs7222_parse_props(iqs7222, &sldr_node, sldr_index, + IQS7222_REG_GRP_SLDR, + IQS7222_REG_KEY_NONE); + if (error) + return error; + + if (!sldr_node) + return 0; + + /* + * Each slider can be spread across 3 to 4 channels. It is possible to + * select only 2 channels, but doing so prevents the slider from using + * the specified resolution. + */ + count = fwnode_property_count_u32(sldr_node, "azoteq,channel-select"); + if (count < 0) { + dev_err(&client->dev, "Failed to count %s channels: %d\n", + fwnode_get_name(sldr_node), count); + return count; + } else if (count < 3 || count > ARRAY_SIZE(chan_sel)) { + dev_err(&client->dev, "Invalid number of %s channels\n", + fwnode_get_name(sldr_node)); + return -EINVAL; + } + + error = fwnode_property_read_u32_array(sldr_node, + "azoteq,channel-select", + chan_sel, count); + if (error) { + dev_err(&client->dev, "Failed to read %s channels: %d\n", + fwnode_get_name(sldr_node), error); + return error; + } + + /* + * Resolution and top speed, if small enough, are packed into a single + * register. Otherwise, each occupies its own register and the rest of + * the slider-related register addresses are offset by one. + */ + reg_offset = dev_desc->sldr_res < U16_MAX ? 0 : 1; + + sldr_setup[0] |= count; + sldr_setup[3 + reg_offset] &= ~IQS7222_SLDR_SETUP_3_CHAN_SEL_MASK; + + for (i = 0; i < ARRAY_SIZE(chan_sel); i++) { + sldr_setup[5 + reg_offset + i] = 0; + if (i >= count) + continue; + + if (chan_sel[i] >= ext_chan) { + dev_err(&client->dev, "Invalid %s channel: %u\n", + fwnode_get_name(sldr_node), chan_sel[i]); + return -EINVAL; + } + + /* + * The following fields indicate which channels participate in + * the slider, as well as each channel's relative placement. + */ + sldr_setup[3 + reg_offset] |= BIT(chan_sel[i]); + sldr_setup[5 + reg_offset + i] = chan_sel[i] * 42 + 1080; + } + + sldr_setup[4 + reg_offset] = dev_desc->touch_link; + if (fwnode_property_present(sldr_node, "azoteq,use-prox")) + sldr_setup[4 + reg_offset] -= 2; + + if (!fwnode_property_read_u32(sldr_node, "azoteq,slider-size", &val)) { + if (!val || val > dev_desc->sldr_res) { + dev_err(&client->dev, "Invalid %s size: %u\n", + fwnode_get_name(sldr_node), val); + return -EINVAL; + } + + if (reg_offset) { + sldr_setup[3] = val; + } else { + sldr_setup[2] &= ~IQS7222_SLDR_SETUP_2_RES_MASK; + sldr_setup[2] |= (val / 16 << + IQS7222_SLDR_SETUP_2_RES_SHIFT); + } + } + + if (!fwnode_property_read_u32(sldr_node, "azoteq,top-speed", &val)) { + if (val > (reg_offset ? U16_MAX : U8_MAX * 4)) { + dev_err(&client->dev, "Invalid %s top speed: %u\n", + fwnode_get_name(sldr_node), val); + return -EINVAL; + } + + if (reg_offset) { + sldr_setup[2] = val; + } else { + sldr_setup[2] &= ~IQS7222_SLDR_SETUP_2_TOP_SPEED_MASK; + sldr_setup[2] |= (val / 4); + } + } + + if (!fwnode_property_read_u32(sldr_node, "linux,axis", &val)) { + u16 sldr_max = sldr_setup[3] - 1; + + if (!reg_offset) { + sldr_max = sldr_setup[2]; + + sldr_max &= IQS7222_SLDR_SETUP_2_RES_MASK; + sldr_max >>= IQS7222_SLDR_SETUP_2_RES_SHIFT; + + sldr_max = sldr_max * 16 - 1; + } + + input_set_abs_params(iqs7222->keypad, val, 0, sldr_max, 0, 0); + iqs7222->sl_axis[sldr_index] = val; + } + + if (dev_desc->wheel_enable) { + sldr_setup[0] &= ~dev_desc->wheel_enable; + if (iqs7222->sl_axis[sldr_index] == ABS_WHEEL) + sldr_setup[0] |= dev_desc->wheel_enable; + } + + for (i = 0; i < ARRAY_SIZE(iqs7222_sl_events); i++) { + const char *event_name = iqs7222_sl_events[i].name; + struct fwnode_handle *event_node; + + /* + * The absence of a register offset means the remaining fields + * in the group represent gesture settings. + */ + if (iqs7222_sl_events[i].enable && !reg_offset) + sldr_setup[9] &= ~iqs7222_sl_events[i].enable; + + event_node = fwnode_get_named_child_node(sldr_node, event_name); + if (!event_node) + continue; + + error = iqs7222_parse_props(iqs7222, &event_node, sldr_index, + IQS7222_REG_GRP_SLDR, + reg_offset ? + IQS7222_REG_KEY_RESERVED : + iqs7222_sl_events[i].reg_key); + if (error) + return error; + + error = fwnode_property_read_u32(event_node, "linux,code", + &val); + if (error) { + dev_err(&client->dev, "Failed to read %s code: %d\n", + fwnode_get_name(sldr_node), error); + return error; + } + + iqs7222->sl_code[sldr_index][i] = val; + input_set_capability(iqs7222->keypad, EV_KEY, val); + + /* + * The press/release event is determined based on whether the + * coordinate field reports 0xFFFF and has no explicit enable + * control. + */ + if (!iqs7222_sl_events[i].enable || reg_offset) + continue; + + sldr_setup[9] |= iqs7222_sl_events[i].enable; + + error = iqs7222_gpio_select(iqs7222, event_node, + iqs7222_sl_events[i].enable, + 1568 + sldr_index * 30); + if (error) + return error; + + if (!dev_desc->event_offset) + continue; + + sys_setup[dev_desc->event_offset] |= BIT(10 + sldr_index); + } + + /* + * The following call handles a special pair of properties that shift + * to make room for a wheel enable control in the case of IQS7222C. + */ + return iqs7222_parse_props(iqs7222, &sldr_node, sldr_index, + IQS7222_REG_GRP_SLDR, + dev_desc->wheel_enable ? + IQS7222_REG_KEY_WHEEL : + IQS7222_REG_KEY_NO_WHEEL); +} + +static int iqs7222_parse_all(struct iqs7222_private *iqs7222) +{ + const struct iqs7222_dev_desc *dev_desc = iqs7222->dev_desc; + const struct iqs7222_reg_grp_desc *reg_grps = dev_desc->reg_grps; + u16 *sys_setup = iqs7222->sys_setup; + int error, i; + + if (dev_desc->event_offset) + sys_setup[dev_desc->event_offset] = IQS7222_EVENT_MASK_ATI; + + for (i = 0; i < reg_grps[IQS7222_REG_GRP_CYCLE].num_row; i++) { + error = iqs7222_parse_cycle(iqs7222, i); + if (error) + return error; + } + + error = iqs7222_parse_props(iqs7222, NULL, 0, IQS7222_REG_GRP_GLBL, + IQS7222_REG_KEY_NONE); + if (error) + return error; + + for (i = 0; i < reg_grps[IQS7222_REG_GRP_GPIO].num_row; i++) { + struct fwnode_handle *gpio_node = NULL; + u16 *gpio_setup = iqs7222->gpio_setup[i]; + int j; + + gpio_setup[0] &= ~IQS7222_GPIO_SETUP_0_GPIO_EN; + gpio_setup[1] = 0; + gpio_setup[2] = 0; + + error = iqs7222_parse_props(iqs7222, &gpio_node, i, + IQS7222_REG_GRP_GPIO, + IQS7222_REG_KEY_NONE); + if (error) + return error; + + if (reg_grps[IQS7222_REG_GRP_GPIO].num_row == 1) + continue; + + /* + * The IQS7222C exposes multiple GPIO and must be informed + * as to which GPIO this group represents. + */ + for (j = 0; j < ARRAY_SIZE(iqs7222_gpio_links); j++) + gpio_setup[0] &= ~BIT(iqs7222_gpio_links[j]); + + gpio_setup[0] |= BIT(iqs7222_gpio_links[i]); + } + + for (i = 0; i < reg_grps[IQS7222_REG_GRP_CHAN].num_row; i++) { + u16 *chan_setup = iqs7222->chan_setup[i]; + + chan_setup[0] &= ~IQS7222_CHAN_SETUP_0_REF_MODE_MASK; + chan_setup[0] &= ~IQS7222_CHAN_SETUP_0_CHAN_EN; + + chan_setup[5] = 0; + } + + for (i = 0; i < reg_grps[IQS7222_REG_GRP_CHAN].num_row; i++) { + error = iqs7222_parse_chan(iqs7222, i); + if (error) + return error; + } + + error = iqs7222_parse_props(iqs7222, NULL, 0, IQS7222_REG_GRP_FILT, + IQS7222_REG_KEY_NONE); + if (error) + return error; + + for (i = 0; i < reg_grps[IQS7222_REG_GRP_SLDR].num_row; i++) { + u16 *sldr_setup = iqs7222->sldr_setup[i]; + + sldr_setup[0] &= ~IQS7222_SLDR_SETUP_0_CHAN_CNT_MASK; + + error = iqs7222_parse_sldr(iqs7222, i); + if (error) + return error; + } + + sys_setup[0] &= ~IQS7222_SYS_SETUP_INTF_MODE_MASK; + sys_setup[0] &= ~IQS7222_SYS_SETUP_PWR_MODE_MASK; + + sys_setup[0] |= IQS7222_SYS_SETUP_ACK_RESET; + + return iqs7222_parse_props(iqs7222, NULL, 0, IQS7222_REG_GRP_SYS, + IQS7222_REG_KEY_NONE); +} + +static int iqs7222_report(struct iqs7222_private *iqs7222) +{ + const struct iqs7222_dev_desc *dev_desc = iqs7222->dev_desc; + struct i2c_client *client = iqs7222->client; + int num_chan = dev_desc->reg_grps[IQS7222_REG_GRP_CHAN].num_row; + int num_stat = dev_desc->reg_grps[IQS7222_REG_GRP_STAT].num_col; + int error, i, j; + __le16 status[IQS7222_MAX_COLS_STAT]; + + error = iqs7222_read_burst(iqs7222, IQS7222_SYS_STATUS, status, + num_stat); + if (error) + return error; + + if (le16_to_cpu(status[0]) & IQS7222_SYS_STATUS_RESET) { + dev_err(&client->dev, "Unexpected device reset\n"); + return iqs7222_dev_init(iqs7222, WRITE); + } + + if (le16_to_cpu(status[0]) & IQS7222_SYS_STATUS_ATI_ERROR) { + dev_err(&client->dev, "Unexpected ATI error\n"); + return iqs7222_ati_trigger(iqs7222); + } + + if (le16_to_cpu(status[0]) & IQS7222_SYS_STATUS_ATI_ACTIVE) + return 0; + + for (i = 0; i < num_chan; i++) { + u16 *chan_setup = iqs7222->chan_setup[i]; + + if (!(chan_setup[0] & IQS7222_CHAN_SETUP_0_CHAN_EN)) + continue; + + for (j = 0; j < ARRAY_SIZE(iqs7222_kp_events); j++) { + /* + * Proximity state begins at offset 2 and spills into + * offset 3 for devices with more than 16 channels. + * + * Touch state begins at the first offset immediately + * following proximity state. + */ + int k = 2 + j * (num_chan > 16 ? 2 : 1); + u16 state = le16_to_cpu(status[k + i / 16]); + + input_event(iqs7222->keypad, + iqs7222->kp_type[i][j], + iqs7222->kp_code[i][j], + !!(state & BIT(i % 16))); + } + } + + for (i = 0; i < dev_desc->reg_grps[IQS7222_REG_GRP_SLDR].num_row; i++) { + u16 *sldr_setup = iqs7222->sldr_setup[i]; + u16 sldr_pos = le16_to_cpu(status[4 + i]); + u16 state = le16_to_cpu(status[6 + i]); + + if (!(sldr_setup[0] & IQS7222_SLDR_SETUP_0_CHAN_CNT_MASK)) + continue; + + if (sldr_pos < dev_desc->sldr_res) + input_report_abs(iqs7222->keypad, iqs7222->sl_axis[i], + sldr_pos); + + for (j = 0; j < ARRAY_SIZE(iqs7222_sl_events); j++) { + u16 mask = iqs7222_sl_events[j].mask; + u16 val = iqs7222_sl_events[j].val; + + if (!iqs7222_sl_events[j].enable) { + input_report_key(iqs7222->keypad, + iqs7222->sl_code[i][j], + sldr_pos < dev_desc->sldr_res); + continue; + } + + /* + * The remaining offsets represent gesture state, and + * are discarded in the case of IQS7222C because only + * absolute position is reported. + */ + if (num_stat < IQS7222_MAX_COLS_STAT) + continue; + + input_report_key(iqs7222->keypad, + iqs7222->sl_code[i][j], + (state & mask) == val); + } + } + + input_sync(iqs7222->keypad); + + return 0; +} + +static irqreturn_t iqs7222_irq(int irq, void *context) +{ + struct iqs7222_private *iqs7222 = context; + + return iqs7222_report(iqs7222) ? IRQ_NONE : IRQ_HANDLED; +} + +static int iqs7222_probe(struct i2c_client *client) +{ + struct iqs7222_private *iqs7222; + unsigned long irq_flags; + int error, irq; + + iqs7222 = devm_kzalloc(&client->dev, sizeof(*iqs7222), GFP_KERNEL); + if (!iqs7222) + return -ENOMEM; + + i2c_set_clientdata(client, iqs7222); + iqs7222->client = client; + + iqs7222->keypad = devm_input_allocate_device(&client->dev); + if (!iqs7222->keypad) + return -ENOMEM; + + iqs7222->keypad->name = client->name; + iqs7222->keypad->id.bustype = BUS_I2C; + + /* + * The RDY pin behaves as an interrupt, but must also be polled ahead + * of unsolicited I2C communication. As such, it is first opened as a + * GPIO and then passed to gpiod_to_irq() to register the interrupt. + */ + iqs7222->irq_gpio = devm_gpiod_get(&client->dev, "irq", GPIOD_IN); + if (IS_ERR(iqs7222->irq_gpio)) { + error = PTR_ERR(iqs7222->irq_gpio); + dev_err(&client->dev, "Failed to request IRQ GPIO: %d\n", + error); + return error; + } + + iqs7222->reset_gpio = devm_gpiod_get_optional(&client->dev, "reset", + GPIOD_OUT_HIGH); + if (IS_ERR(iqs7222->reset_gpio)) { + error = PTR_ERR(iqs7222->reset_gpio); + dev_err(&client->dev, "Failed to request reset GPIO: %d\n", + error); + return error; + } + + error = iqs7222_hard_reset(iqs7222); + if (error) + return error; + + error = iqs7222_dev_info(iqs7222); + if (error) + return error; + + error = iqs7222_dev_init(iqs7222, READ); + if (error) + return error; + + error = iqs7222_parse_all(iqs7222); + if (error) + return error; + + error = iqs7222_dev_init(iqs7222, WRITE); + if (error) + return error; + + error = iqs7222_report(iqs7222); + if (error) + return error; + + error = input_register_device(iqs7222->keypad); + if (error) { + dev_err(&client->dev, "Failed to register device: %d\n", error); + return error; + } + + irq = gpiod_to_irq(iqs7222->irq_gpio); + if (irq < 0) + return irq; + + irq_flags = gpiod_is_active_low(iqs7222->irq_gpio) ? IRQF_TRIGGER_LOW + : IRQF_TRIGGER_HIGH; + irq_flags |= IRQF_ONESHOT; + + error = devm_request_threaded_irq(&client->dev, irq, NULL, iqs7222_irq, + irq_flags, client->name, iqs7222); + if (error) + dev_err(&client->dev, "Failed to request IRQ: %d\n", error); + + return error; +} + +static const struct of_device_id iqs7222_of_match[] = { + { .compatible = "azoteq,iqs7222a" }, + { .compatible = "azoteq,iqs7222b" }, + { .compatible = "azoteq,iqs7222c" }, + { } +}; +MODULE_DEVICE_TABLE(of, iqs7222_of_match); + +static struct i2c_driver iqs7222_i2c_driver = { + .driver = { + .name = "iqs7222", + .of_match_table = iqs7222_of_match, + }, + .probe_new = iqs7222_probe, +}; +module_i2c_driver(iqs7222_i2c_driver); + +MODULE_AUTHOR("Jeff LaBundy "); +MODULE_DESCRIPTION("Azoteq IQS7222A/B/C Capacitive Touch Controller"); +MODULE_LICENSE("GPL"); diff --git a/drivers/input/misc/pm8941-pwrkey.c b/drivers/input/misc/pm8941-pwrkey.c index 89af52498c96960453138f4a11bc070095a8657a..549df01b6ee33eb29b3ecf9fd22c351948745ce0 100644 --- a/drivers/input/misc/pm8941-pwrkey.c +++ b/drivers/input/misc/pm8941-pwrkey.c @@ -9,9 +9,11 @@ #include #include #include +#include #include #include #include +#include #include #include #include @@ -19,6 +21,16 @@ #define PON_REV2 0x01 +#define PON_SUBTYPE 0x05 + +#define PON_SUBTYPE_PRIMARY 0x01 +#define PON_SUBTYPE_SECONDARY 0x02 +#define PON_SUBTYPE_1REG 0x03 +#define PON_SUBTYPE_GEN2_PRIMARY 0x04 +#define PON_SUBTYPE_GEN2_SECONDARY 0x05 +#define PON_SUBTYPE_GEN3_PBS 0x08 +#define PON_SUBTYPE_GEN3_HLOS 0x09 + #define PON_RT_STS 0x10 #define PON_KPDPWR_N_SET BIT(0) #define PON_RESIN_N_SET BIT(1) @@ -45,6 +57,7 @@ struct pm8941_data { unsigned int status_bit; bool supports_ps_hold_poff_config; bool supports_debounce_config; + bool has_pon_pbs; const char *name; const char *phys; }; @@ -53,13 +66,18 @@ struct pm8941_pwrkey { struct device *dev; int irq; u32 baseaddr; + u32 pon_pbs_baseaddr; struct regmap *regmap; struct input_dev *input; unsigned int revision; + unsigned int subtype; struct notifier_block reboot_notifier; u32 code; + u32 sw_debounce_time_us; + ktime_t sw_debounce_end_time; + bool last_status; const struct pm8941_data *data; }; @@ -129,20 +147,76 @@ static irqreturn_t pm8941_pwrkey_irq(int irq, void *_data) { struct pm8941_pwrkey *pwrkey = _data; unsigned int sts; - int error; + int err; + + if (pwrkey->sw_debounce_time_us) { + if (ktime_before(ktime_get(), pwrkey->sw_debounce_end_time)) { + dev_dbg(pwrkey->dev, + "ignoring key event received before debounce end %llu us\n", + pwrkey->sw_debounce_end_time); + return IRQ_HANDLED; + } + } - error = regmap_read(pwrkey->regmap, - pwrkey->baseaddr + PON_RT_STS, &sts); - if (error) + err = regmap_read(pwrkey->regmap, pwrkey->baseaddr + PON_RT_STS, &sts); + if (err) return IRQ_HANDLED; - input_report_key(pwrkey->input, pwrkey->code, - sts & pwrkey->data->status_bit); + sts &= pwrkey->data->status_bit; + + if (pwrkey->sw_debounce_time_us && !sts) + pwrkey->sw_debounce_end_time = ktime_add_us(ktime_get(), + pwrkey->sw_debounce_time_us); + + /* + * Simulate a press event in case a release event occurred without a + * corresponding press event. + */ + if (!pwrkey->last_status && !sts) { + input_report_key(pwrkey->input, pwrkey->code, 1); + input_sync(pwrkey->input); + } + pwrkey->last_status = sts; + + input_report_key(pwrkey->input, pwrkey->code, sts); input_sync(pwrkey->input); return IRQ_HANDLED; } +static int pm8941_pwrkey_sw_debounce_init(struct pm8941_pwrkey *pwrkey) +{ + unsigned int val, addr, mask; + int error; + + if (pwrkey->data->has_pon_pbs && !pwrkey->pon_pbs_baseaddr) { + dev_err(pwrkey->dev, + "PON_PBS address missing, can't read HW debounce time\n"); + return 0; + } + + if (pwrkey->pon_pbs_baseaddr) + addr = pwrkey->pon_pbs_baseaddr + PON_DBC_CTL; + else + addr = pwrkey->baseaddr + PON_DBC_CTL; + error = regmap_read(pwrkey->regmap, addr, &val); + if (error) + return error; + + if (pwrkey->subtype >= PON_SUBTYPE_GEN2_PRIMARY) + mask = 0xf; + else + mask = 0x7; + + pwrkey->sw_debounce_time_us = + 2 * USEC_PER_SEC / (1 << (mask - (val & mask))); + + dev_dbg(pwrkey->dev, "SW debounce time = %u us\n", + pwrkey->sw_debounce_time_us); + + return 0; +} + static int __maybe_unused pm8941_pwrkey_suspend(struct device *dev) { struct pm8941_pwrkey *pwrkey = dev_get_drvdata(dev); @@ -171,6 +245,8 @@ static int pm8941_pwrkey_probe(struct platform_device *pdev) struct pm8941_pwrkey *pwrkey; bool pull_up; struct device *parent; + struct device_node *regmap_node; + const __be32 *addr; u32 req_delay; int error; @@ -192,8 +268,10 @@ static int pm8941_pwrkey_probe(struct platform_device *pdev) pwrkey->data = of_device_get_match_data(&pdev->dev); parent = pdev->dev.parent; + regmap_node = pdev->dev.of_node; pwrkey->regmap = dev_get_regmap(parent, NULL); if (!pwrkey->regmap) { + regmap_node = parent->of_node; /* * We failed to get regmap for parent. Let's see if we are * a child of pon node and read regmap and reg from its @@ -204,15 +282,21 @@ static int pm8941_pwrkey_probe(struct platform_device *pdev) dev_err(&pdev->dev, "failed to locate regmap\n"); return -ENODEV; } + } - error = of_property_read_u32(parent->of_node, - "reg", &pwrkey->baseaddr); - } else { - error = of_property_read_u32(pdev->dev.of_node, "reg", - &pwrkey->baseaddr); + addr = of_get_address(regmap_node, 0, NULL, NULL); + if (!addr) { + dev_err(&pdev->dev, "reg property missing\n"); + return -EINVAL; + } + pwrkey->baseaddr = be32_to_cpup(addr); + + if (pwrkey->data->has_pon_pbs) { + /* PON_PBS base address is optional */ + addr = of_get_address(regmap_node, 1, NULL, NULL); + if (addr) + pwrkey->pon_pbs_baseaddr = be32_to_cpup(addr); } - if (error) - return error; pwrkey->irq = platform_get_irq(pdev, 0); if (pwrkey->irq < 0) @@ -221,7 +305,14 @@ static int pm8941_pwrkey_probe(struct platform_device *pdev) error = regmap_read(pwrkey->regmap, pwrkey->baseaddr + PON_REV2, &pwrkey->revision); if (error) { - dev_err(&pdev->dev, "failed to set debounce: %d\n", error); + dev_err(&pdev->dev, "failed to read revision: %d\n", error); + return error; + } + + error = regmap_read(pwrkey->regmap, pwrkey->baseaddr + PON_SUBTYPE, + &pwrkey->subtype); + if (error) { + dev_err(&pdev->dev, "failed to read subtype: %d\n", error); return error; } @@ -259,6 +350,10 @@ static int pm8941_pwrkey_probe(struct platform_device *pdev) } } + error = pm8941_pwrkey_sw_debounce_init(pwrkey); + if (error) + return error; + if (pwrkey->data->pull_up_bit) { error = regmap_update_bits(pwrkey->regmap, pwrkey->baseaddr + PON_PULL_CTL, @@ -320,6 +415,7 @@ static const struct pm8941_data pwrkey_data = { .phys = "pm8941_pwrkey/input0", .supports_ps_hold_poff_config = true, .supports_debounce_config = true, + .has_pon_pbs = false, }; static const struct pm8941_data resin_data = { @@ -329,6 +425,7 @@ static const struct pm8941_data resin_data = { .phys = "pm8941_resin/input0", .supports_ps_hold_poff_config = true, .supports_debounce_config = true, + .has_pon_pbs = false, }; static const struct pm8941_data pon_gen3_pwrkey_data = { @@ -337,6 +434,7 @@ static const struct pm8941_data pon_gen3_pwrkey_data = { .phys = "pmic_pwrkey/input0", .supports_ps_hold_poff_config = false, .supports_debounce_config = false, + .has_pon_pbs = true, }; static const struct pm8941_data pon_gen3_resin_data = { @@ -345,6 +443,7 @@ static const struct pm8941_data pon_gen3_resin_data = { .phys = "pmic_resin/input0", .supports_ps_hold_poff_config = false, .supports_debounce_config = false, + .has_pon_pbs = true, }; static const struct of_device_id pm8941_pwr_key_id_table[] = { diff --git a/drivers/input/misc/sparcspkr.c b/drivers/input/misc/sparcspkr.c index fe43e5557ed72b1b8b942b7a3b78d8807a700980..cdcb7737c46aa50a91d5205d8728f13f9d8215a1 100644 --- a/drivers/input/misc/sparcspkr.c +++ b/drivers/input/misc/sparcspkr.c @@ -205,6 +205,7 @@ static int bbc_beep_probe(struct platform_device *op) info = &state->u.bbc; info->clock_freq = of_getintprop_default(dp, "clock-frequency", 0); + of_node_put(dp); if (!info->clock_freq) goto out_free; diff --git a/drivers/input/mouse/cypress_ps2.c b/drivers/input/mouse/cypress_ps2.c index 5f868009d35bb498cc7abd61da32e0461a2f3abd..d272f1ec27ba50f5adbaaea04e2f881f3715c2ca 100644 --- a/drivers/input/mouse/cypress_ps2.c +++ b/drivers/input/mouse/cypress_ps2.c @@ -696,7 +696,7 @@ int cypress_init(struct psmouse *psmouse) err_exit: /* * Reset Cypress Trackpad as a standard mouse. Then - * let psmouse driver commmunicating with it as default PS2 mouse. + * let psmouse driver communicating with it as default PS2 mouse. */ cypress_reset(psmouse); diff --git a/drivers/input/mouse/psmouse-smbus.c b/drivers/input/mouse/psmouse-smbus.c index 164f6c757f6bed637b9e04c0ce8677888b93c33a..2a2459b1b4f2cb91b0465f77637f22a0b71bcf62 100644 --- a/drivers/input/mouse/psmouse-smbus.c +++ b/drivers/input/mouse/psmouse-smbus.c @@ -26,6 +26,8 @@ struct psmouse_smbus_dev { static LIST_HEAD(psmouse_smbus_list); static DEFINE_MUTEX(psmouse_smbus_mutex); +static struct workqueue_struct *psmouse_smbus_wq; + static void psmouse_smbus_check_adapter(struct i2c_adapter *adapter) { struct psmouse_smbus_dev *smbdev; @@ -161,7 +163,7 @@ static void psmouse_smbus_schedule_remove(struct i2c_client *client) INIT_WORK(&rwork->work, psmouse_smbus_remove_i2c_device); rwork->client = client; - schedule_work(&rwork->work); + queue_work(psmouse_smbus_wq, &rwork->work); } } @@ -305,9 +307,14 @@ int __init psmouse_smbus_module_init(void) { int error; + psmouse_smbus_wq = alloc_workqueue("psmouse-smbus", 0, 0); + if (!psmouse_smbus_wq) + return -ENOMEM; + error = bus_register_notifier(&i2c_bus_type, &psmouse_smbus_notifier); if (error) { pr_err("failed to register i2c bus notifier: %d\n", error); + destroy_workqueue(psmouse_smbus_wq); return error; } @@ -317,5 +324,5 @@ int __init psmouse_smbus_module_init(void) void psmouse_smbus_module_exit(void) { bus_unregister_notifier(&i2c_bus_type, &psmouse_smbus_notifier); - flush_scheduled_work(); + destroy_workqueue(psmouse_smbus_wq); } diff --git a/drivers/input/mouse/vmmouse.c b/drivers/input/mouse/vmmouse.c index 42443ffba7c4d8a6b5c4ded3d167b02cd4ab9cbe..ea9eff7c8099b8e4f8a88987066cb47cc4f0d726 100644 --- a/drivers/input/mouse/vmmouse.c +++ b/drivers/input/mouse/vmmouse.c @@ -365,6 +365,19 @@ int vmmouse_detect(struct psmouse *psmouse, bool set_properties) return 0; } +/** + * vmmouse_reset - Disable vmmouse and reset + * + * @psmouse: Pointer to the psmouse struct + * + * Tries to disable vmmouse mode before enter suspend. + */ +static void vmmouse_reset(struct psmouse *psmouse) +{ + vmmouse_disable(psmouse); + psmouse_reset(psmouse); +} + /** * vmmouse_disconnect - Take down vmmouse driver * @@ -472,6 +485,7 @@ int vmmouse_init(struct psmouse *psmouse) psmouse->protocol_handler = vmmouse_process_byte; psmouse->disconnect = vmmouse_disconnect; psmouse->reconnect = vmmouse_reconnect; + psmouse->cleanup = vmmouse_reset; return 0; diff --git a/drivers/input/rmi4/rmi_f54.c b/drivers/input/rmi4/rmi_f54.c index 93b328c796c643006b3589673dd79813b3d6067d..c5ce907535ef998ba5616e5beee0c11fdf8a87de 100644 --- a/drivers/input/rmi4/rmi_f54.c +++ b/drivers/input/rmi4/rmi_f54.c @@ -733,7 +733,6 @@ remove_v4l2: v4l2_device_unregister(&f54->v4l2); remove_wq: cancel_delayed_work_sync(&f54->work); - flush_workqueue(f54->workqueue); destroy_workqueue(f54->workqueue); return ret; } diff --git a/drivers/input/tablet/aiptek.c b/drivers/input/tablet/aiptek.c index 1581f6ef0927933118affc39a47a11870fc8aa1a..24ec4844a5c3e67fa078211879143b44bb4340c0 100644 --- a/drivers/input/tablet/aiptek.c +++ b/drivers/input/tablet/aiptek.c @@ -931,8 +931,7 @@ aiptek_query(struct aiptek *aiptek, unsigned char command, unsigned char data) } msleep(aiptek->curSetting.programmableDelay); - if ((ret = - aiptek_get_report(aiptek, 3, 2, buf, sizeof_buf)) != sizeof_buf) { + if (aiptek_get_report(aiptek, 3, 2, buf, sizeof_buf) != sizeof_buf) { dev_dbg(&aiptek->intf->dev, "aiptek_query failed: returned 0x%02x 0x%02x 0x%02x\n", buf[0], buf[1], buf[2]); diff --git a/drivers/input/touchscreen/stmfts.c b/drivers/input/touchscreen/stmfts.c index 72e0b767e1ba4c87c31b5346c45746f82ff9773b..c175d44c52f37011d8d29d7a664240733e129302 100644 --- a/drivers/input/touchscreen/stmfts.c +++ b/drivers/input/touchscreen/stmfts.c @@ -337,13 +337,15 @@ static int stmfts_input_open(struct input_dev *dev) struct stmfts_data *sdata = input_get_drvdata(dev); int err; - err = pm_runtime_get_sync(&sdata->client->dev); - if (err < 0) - goto out; + err = pm_runtime_resume_and_get(&sdata->client->dev); + if (err) + return err; err = i2c_smbus_write_byte(sdata->client, STMFTS_MS_MT_SENSE_ON); - if (err) - goto out; + if (err) { + pm_runtime_put_sync(&sdata->client->dev); + return err; + } mutex_lock(&sdata->mutex); sdata->running = true; @@ -366,9 +368,7 @@ static int stmfts_input_open(struct input_dev *dev) "failed to enable touchkey\n"); } -out: - pm_runtime_put_noidle(&sdata->client->dev); - return err; + return 0; } static void stmfts_input_close(struct input_dev *dev) diff --git a/drivers/iommu/amd/amd_iommu_types.h b/drivers/iommu/amd/amd_iommu_types.h index 47108ed44fbba5dbba19365891ea98b83df13da8..72d0f5e2f651a50fdac7d1c0f83f58ef7e62e947 100644 --- a/drivers/iommu/amd/amd_iommu_types.h +++ b/drivers/iommu/amd/amd_iommu_types.h @@ -407,6 +407,7 @@ /* IOMMU IVINFO */ #define IOMMU_IVINFO_OFFSET 36 #define IOMMU_IVINFO_EFRSUP BIT(0) +#define IOMMU_IVINFO_DMA_REMAP BIT(1) /* IOMMU Feature Reporting Field (for IVHD type 10h */ #define IOMMU_FEAT_GASUP_SHIFT 6 @@ -449,6 +450,9 @@ extern struct irq_remap_table **irq_lookup_table; /* Interrupt remapping feature used? */ extern bool amd_iommu_irq_remap; +/* IVRS indicates that pre-boot remapping was enabled */ +extern bool amdr_ivrs_remap_support; + /* kmem_cache to get tables with 128 byte alignement */ extern struct kmem_cache *amd_iommu_irq_cache; diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c index 1a3ad58ba84653e8a9cbf5466720334568fa2f31..1d08f87e734bd3af7a393bdf043bf53a395783f0 100644 --- a/drivers/iommu/amd/init.c +++ b/drivers/iommu/amd/init.c @@ -83,7 +83,7 @@ #define ACPI_DEVFLAG_LINT1 0x80 #define ACPI_DEVFLAG_ATSDIS 0x10000000 -#define LOOP_TIMEOUT 100000 +#define LOOP_TIMEOUT 2000000 /* * ACPI table definitions * @@ -181,6 +181,7 @@ u32 amd_iommu_max_pasid __read_mostly = ~0; bool amd_iommu_v2_present __read_mostly; static bool amd_iommu_pc_present __read_mostly; +bool amdr_ivrs_remap_support __read_mostly; bool amd_iommu_force_isolation __read_mostly; @@ -325,6 +326,8 @@ static void __init early_iommu_features_init(struct amd_iommu *iommu, { if (amd_iommu_ivinfo & IOMMU_IVINFO_EFRSUP) iommu->features = h->efr_reg; + if (amd_iommu_ivinfo & IOMMU_IVINFO_DMA_REMAP) + amdr_ivrs_remap_support = true; } /* Access to l1 and l2 indexed register spaces */ @@ -1985,8 +1988,7 @@ static int __init amd_iommu_init_pci(void) for_each_iommu(iommu) iommu_flush_all_caches(iommu); - if (!ret) - print_iommu_info(); + print_iommu_info(); out: return ret; diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c index b47220ac09eaa56585be13ee4826438f33546aec..840831d5d2ad95769095eb80b607591d8dafc8b9 100644 --- a/drivers/iommu/amd/iommu.c +++ b/drivers/iommu/amd/iommu.c @@ -1838,20 +1838,10 @@ void amd_iommu_domain_update(struct protection_domain *domain) amd_iommu_domain_flush_complete(domain); } -static void __init amd_iommu_init_dma_ops(void) -{ - if (iommu_default_passthrough() || sme_me_mask) - x86_swiotlb_enable = true; - else - x86_swiotlb_enable = false; -} - int __init amd_iommu_init_api(void) { int err; - amd_iommu_init_dma_ops(); - err = bus_set_iommu(&pci_bus_type, &amd_iommu_ops); if (err) return err; @@ -2165,6 +2155,8 @@ static bool amd_iommu_capable(enum iommu_cap cap) return (irq_remapping_enabled == 1); case IOMMU_CAP_NOEXEC: return false; + case IOMMU_CAP_PRE_BOOT_PROTECTION: + return amdr_ivrs_remap_support; default: break; } @@ -2274,6 +2266,12 @@ static int amd_iommu_def_domain_type(struct device *dev) return 0; } +static bool amd_iommu_enforce_cache_coherency(struct iommu_domain *domain) +{ + /* IOMMU_PTE_FC is always set */ + return true; +} + const struct iommu_ops amd_iommu_ops = { .capable = amd_iommu_capable, .domain_alloc = amd_iommu_domain_alloc, @@ -2296,6 +2294,7 @@ const struct iommu_ops amd_iommu_ops = { .flush_iotlb_all = amd_iommu_flush_iotlb_all, .iotlb_sync = amd_iommu_iotlb_sync, .free = amd_iommu_domain_free, + .enforce_cache_coherency = amd_iommu_enforce_cache_coherency, } }; diff --git a/drivers/iommu/amd/iommu_v2.c b/drivers/iommu/amd/iommu_v2.c index e56b137ceabd142dd36217f5062fe64933e317a7..afb3efd565b78ed9f84ff5a5b1ffc9904b5c2f48 100644 --- a/drivers/iommu/amd/iommu_v2.c +++ b/drivers/iommu/amd/iommu_v2.c @@ -956,6 +956,7 @@ static void __exit amd_iommu_v2_exit(void) { struct device_state *dev_state, *next; unsigned long flags; + LIST_HEAD(freelist); if (!amd_iommu_v2_supported()) return; @@ -975,11 +976,20 @@ static void __exit amd_iommu_v2_exit(void) put_device_state(dev_state); list_del(&dev_state->list); - free_device_state(dev_state); + list_add_tail(&dev_state->list, &freelist); } spin_unlock_irqrestore(&state_lock, flags); + /* + * Since free_device_state waits on the count to be zero, + * we need to free dev_state outside the spinlock. + */ + list_for_each_entry_safe(dev_state, next, &freelist, list) { + list_del(&dev_state->list); + free_device_state(dev_state); + } + destroy_workqueue(iommu_wq); } diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c index c623dae1e1154573bfddc4697c4ecdb72fe7b380..1ef7bbb4acf30d64dc48b3bcc8131a6aec027f67 100644 --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include "arm-smmu-v3.h" @@ -96,9 +97,14 @@ static struct arm_smmu_ctx_desc *arm_smmu_alloc_shared_cd(struct mm_struct *mm) struct arm_smmu_ctx_desc *cd; struct arm_smmu_ctx_desc *ret = NULL; + /* Don't free the mm until we release the ASID */ + mmgrab(mm); + asid = arm64_mm_context_get(mm); - if (!asid) - return ERR_PTR(-ESRCH); + if (!asid) { + err = -ESRCH; + goto out_drop_mm; + } cd = kzalloc(sizeof(*cd), GFP_KERNEL); if (!cd) { @@ -165,6 +171,8 @@ out_free_cd: kfree(cd); out_put_context: arm64_mm_context_put(mm); +out_drop_mm: + mmdrop(mm); return err < 0 ? ERR_PTR(err) : ret; } @@ -173,6 +181,7 @@ static void arm_smmu_free_shared_cd(struct arm_smmu_ctx_desc *cd) if (arm_smmu_free_asid(cd)) { /* Unpin ASID */ arm64_mm_context_put(cd->mm); + mmdrop(cd->mm); kfree(cd); } } diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c index 627a3ed5ee8fd1ed743835cf764f08cc7d1a7e67..88817a3376ef01a92f217639dea8351ff6fb140b 100644 --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c @@ -3770,6 +3770,8 @@ static int arm_smmu_device_probe(struct platform_device *pdev) /* Base address */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -EINVAL; if (resource_size(res) < arm_smmu_resource_size(smmu)) { dev_err(dev, "MMIO region too small (%pr)\n", res); return -EINVAL; diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-impl.c b/drivers/iommu/arm/arm-smmu/arm-smmu-impl.c index 2c25cce3806032486c4957c2bdca6e03839fe870..658f3cc832781b0d7134dd1471568e3f4e7c732e 100644 --- a/drivers/iommu/arm/arm-smmu/arm-smmu-impl.c +++ b/drivers/iommu/arm/arm-smmu/arm-smmu-impl.c @@ -211,7 +211,8 @@ struct arm_smmu_device *arm_smmu_impl_init(struct arm_smmu_device *smmu) if (of_property_read_bool(np, "calxeda,smmu-secure-config-access")) smmu->impl = &calxeda_impl; - if (of_device_is_compatible(np, "nvidia,tegra194-smmu") || + if (of_device_is_compatible(np, "nvidia,tegra234-smmu") || + of_device_is_compatible(np, "nvidia,tegra194-smmu") || of_device_is_compatible(np, "nvidia,tegra186-smmu")) return nvidia_smmu_impl_init(smmu); diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c index ba6298c7140ee9304c11120d60f4197fbcf34aaa..7820711c456084ffb3b2cd1131e80896da5dabdb 100644 --- a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c +++ b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c @@ -408,6 +408,7 @@ static const struct of_device_id __maybe_unused qcom_smmu_impl_of_match[] = { { .compatible = "qcom,sc7180-smmu-500" }, { .compatible = "qcom,sc7280-smmu-500" }, { .compatible = "qcom,sc8180x-smmu-500" }, + { .compatible = "qcom,sc8280xp-smmu-500" }, { .compatible = "qcom,sdm630-smmu-v2" }, { .compatible = "qcom,sdm845-smmu-500" }, { .compatible = "qcom,sm6125-smmu-500" }, diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c b/drivers/iommu/arm/arm-smmu/arm-smmu.c index 568cce590ccc13990c46b7b70a02d2db5b3bc506..2ed3594f384ef6b9ec4162b284a7e6fce4b4158b 100644 --- a/drivers/iommu/arm/arm-smmu/arm-smmu.c +++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c @@ -1574,6 +1574,9 @@ static int arm_smmu_def_domain_type(struct device *dev) struct arm_smmu_master_cfg *cfg = dev_iommu_priv_get(dev); const struct arm_smmu_impl *impl = cfg->smmu->impl; + if (using_legacy_binding) + return IOMMU_DOMAIN_IDENTITY; + if (impl && impl->def_domain_type) return impl->def_domain_type(dev); @@ -2092,11 +2095,10 @@ static int arm_smmu_device_probe(struct platform_device *pdev) if (err) return err; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - ioaddr = res->start; - smmu->base = devm_ioremap_resource(dev, res); + smmu->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); if (IS_ERR(smmu->base)) return PTR_ERR(smmu->base); + ioaddr = res->start; /* * The resource size should effectively match the value of SMMU_TOP; * stash that temporarily until we know PAGESIZE to validate it with. diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c index ddce34ce173fcc85bdd9b798e72ea2d631902ccf..86925728c910f822dc055eb3908c222bdab4ae11 100644 --- a/drivers/iommu/dma-iommu.c +++ b/drivers/iommu/dma-iommu.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -415,6 +416,15 @@ static int cookie_init_hw_msi_region(struct iommu_dma_cookie *cookie, return 0; } +static int iommu_dma_ranges_sort(void *priv, const struct list_head *a, + const struct list_head *b) +{ + struct resource_entry *res_a = list_entry(a, typeof(*res_a), node); + struct resource_entry *res_b = list_entry(b, typeof(*res_b), node); + + return res_a->res->start > res_b->res->start; +} + static int iova_reserve_pci_windows(struct pci_dev *dev, struct iova_domain *iovad) { @@ -433,6 +443,7 @@ static int iova_reserve_pci_windows(struct pci_dev *dev, } /* Get reserved DMA windows from host bridge */ + list_sort(NULL, &bridge->dma_ranges, iommu_dma_ranges_sort); resource_list_for_each_entry(window, &bridge->dma_ranges) { end = window->res->start - window->offset; resv_iova: @@ -441,7 +452,7 @@ resv_iova: hi = iova_pfn(iovad, end); reserve_iova(iovad, lo, hi); } else if (end < start) { - /* dma_ranges list should be sorted */ + /* DMA ranges should be non-overlapping */ dev_err(&dev->dev, "Failed to reserve IOVA [%pa-%pa]\n", &start, &end); @@ -781,6 +792,7 @@ static struct page **__iommu_dma_alloc_noncontiguous(struct device *dev, unsigned int count, min_size, alloc_sizes = domain->pgsize_bitmap; struct page **pages; dma_addr_t iova; + ssize_t ret; if (static_branch_unlikely(&iommu_deferred_attach_enabled) && iommu_deferred_attach(dev, domain)) @@ -818,8 +830,8 @@ static struct page **__iommu_dma_alloc_noncontiguous(struct device *dev, arch_dma_prep_coherent(sg_page(sg), sg->length); } - if (iommu_map_sg_atomic(domain, iova, sgt->sgl, sgt->orig_nents, ioprot) - < size) + ret = iommu_map_sg_atomic(domain, iova, sgt->sgl, sgt->orig_nents, ioprot); + if (ret < 0 || ret < size) goto out_free_sg; sgt->sgl->dma_address = iova; @@ -976,6 +988,11 @@ static dma_addr_t iommu_dma_map_page(struct device *dev, struct page *page, void *padding_start; size_t padding_size, aligned_size; + if (!is_swiotlb_active(dev)) { + dev_warn_once(dev, "DMA bounce buffers are inactive, unable to map unaligned transaction.\n"); + return DMA_MAPPING_ERROR; + } + aligned_size = iova_align(iovad, size); phys = swiotlb_tbl_map_single(dev, phys, size, aligned_size, iova_mask(iovad), dir, attrs); @@ -1214,7 +1231,7 @@ static int iommu_dma_map_sg(struct device *dev, struct scatterlist *sg, * implementation - it knows better than we do. */ ret = iommu_map_sg_atomic(domain, iova, sg, nents, prot); - if (ret < iova_len) + if (ret < 0 || ret < iova_len) goto out_free_iova; return __finalise_sg(dev, sg, nents, iova); diff --git a/drivers/iommu/fsl_pamu.c b/drivers/iommu/fsl_pamu.c index fc38b1fba7cff0a72f4c5a23b76f56a6c2d063dd..0d03f837a5d4e7ff820a223dd4a6349424a42647 100644 --- a/drivers/iommu/fsl_pamu.c +++ b/drivers/iommu/fsl_pamu.c @@ -11,6 +11,9 @@ #include #include #include +#include +#include +#include #include diff --git a/drivers/iommu/fsl_pamu_domain.c b/drivers/iommu/fsl_pamu_domain.c index 69a4a62dc3b9c7f9f2a7fef87cd988d983663d6d..94b4589dc67c8e60e4554f5c75f8340fc91b155f 100644 --- a/drivers/iommu/fsl_pamu_domain.c +++ b/drivers/iommu/fsl_pamu_domain.c @@ -9,6 +9,7 @@ #include "fsl_pamu_domain.h" +#include #include /* diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c index ba9a63cac47ccafbc28ded4365eb41d57b4531bc..44016594831de562b80c59e2d964f26a4e1a27fe 100644 --- a/drivers/iommu/intel/iommu.c +++ b/drivers/iommu/intel/iommu.c @@ -533,33 +533,6 @@ static void domain_update_iommu_coherency(struct dmar_domain *domain) rcu_read_unlock(); } -static bool domain_update_iommu_snooping(struct intel_iommu *skip) -{ - struct dmar_drhd_unit *drhd; - struct intel_iommu *iommu; - bool ret = true; - - rcu_read_lock(); - for_each_active_iommu(iommu, drhd) { - if (iommu != skip) { - /* - * If the hardware is operating in the scalable mode, - * the snooping control is always supported since we - * always set PASID-table-entry.PGSNP bit if the domain - * is managed outside (UNMANAGED). - */ - if (!sm_supported(iommu) && - !ecap_sc_support(iommu->ecap)) { - ret = false; - break; - } - } - } - rcu_read_unlock(); - - return ret; -} - static int domain_update_iommu_superpage(struct dmar_domain *domain, struct intel_iommu *skip) { @@ -641,7 +614,6 @@ static unsigned long domain_super_pgsize_bitmap(struct dmar_domain *domain) static void domain_update_iommu_cap(struct dmar_domain *domain) { domain_update_iommu_coherency(domain); - domain->iommu_snooping = domain_update_iommu_snooping(NULL); domain->iommu_superpage = domain_update_iommu_superpage(domain, NULL); /* @@ -2460,7 +2432,7 @@ static int domain_setup_first_level(struct intel_iommu *iommu, if (level == 5) flags |= PASID_FLAG_FL5LP; - if (domain->domain.type == IOMMU_DOMAIN_UNMANAGED) + if (domain->force_snooping) flags |= PASID_FLAG_PAGE_SNOOP; return intel_pasid_setup_first_level(iommu, dev, (pgd_t *)pgd, pasid, @@ -2474,64 +2446,6 @@ static bool dev_is_real_dma_subdevice(struct device *dev) pci_real_dma_dev(to_pci_dev(dev)) != to_pci_dev(dev); } -static struct dmar_domain *dmar_insert_one_dev_info(struct intel_iommu *iommu, - int bus, int devfn, - struct device *dev, - struct dmar_domain *domain) -{ - struct device_domain_info *info = dev_iommu_priv_get(dev); - unsigned long flags; - int ret; - - spin_lock_irqsave(&device_domain_lock, flags); - info->domain = domain; - spin_lock(&iommu->lock); - ret = domain_attach_iommu(domain, iommu); - spin_unlock(&iommu->lock); - if (ret) { - spin_unlock_irqrestore(&device_domain_lock, flags); - return NULL; - } - list_add(&info->link, &domain->devices); - spin_unlock_irqrestore(&device_domain_lock, flags); - - /* PASID table is mandatory for a PCI device in scalable mode. */ - if (sm_supported(iommu) && !dev_is_real_dma_subdevice(dev)) { - ret = intel_pasid_alloc_table(dev); - if (ret) { - dev_err(dev, "PASID table allocation failed\n"); - dmar_remove_one_dev_info(dev); - return NULL; - } - - /* Setup the PASID entry for requests without PASID: */ - spin_lock_irqsave(&iommu->lock, flags); - if (hw_pass_through && domain_type_is_si(domain)) - ret = intel_pasid_setup_pass_through(iommu, domain, - dev, PASID_RID2PASID); - else if (domain_use_first_level(domain)) - ret = domain_setup_first_level(iommu, domain, dev, - PASID_RID2PASID); - else - ret = intel_pasid_setup_second_level(iommu, domain, - dev, PASID_RID2PASID); - spin_unlock_irqrestore(&iommu->lock, flags); - if (ret) { - dev_err(dev, "Setup RID2PASID failed\n"); - dmar_remove_one_dev_info(dev); - return NULL; - } - } - - if (dev && domain_context_mapping(domain, dev)) { - dev_err(dev, "Domain context map failed\n"); - dmar_remove_one_dev_info(dev); - return NULL; - } - - return domain; -} - static int iommu_domain_identity_map(struct dmar_domain *domain, unsigned long first_vpfn, unsigned long last_vpfn) @@ -2607,17 +2521,62 @@ static int __init si_domain_init(int hw) static int domain_add_dev_info(struct dmar_domain *domain, struct device *dev) { - struct dmar_domain *ndomain; + struct device_domain_info *info = dev_iommu_priv_get(dev); struct intel_iommu *iommu; + unsigned long flags; u8 bus, devfn; + int ret; iommu = device_to_iommu(dev, &bus, &devfn); if (!iommu) return -ENODEV; - ndomain = dmar_insert_one_dev_info(iommu, bus, devfn, dev, domain); - if (ndomain != domain) - return -EBUSY; + spin_lock_irqsave(&device_domain_lock, flags); + info->domain = domain; + spin_lock(&iommu->lock); + ret = domain_attach_iommu(domain, iommu); + spin_unlock(&iommu->lock); + if (ret) { + spin_unlock_irqrestore(&device_domain_lock, flags); + return ret; + } + list_add(&info->link, &domain->devices); + spin_unlock_irqrestore(&device_domain_lock, flags); + + /* PASID table is mandatory for a PCI device in scalable mode. */ + if (sm_supported(iommu) && !dev_is_real_dma_subdevice(dev)) { + ret = intel_pasid_alloc_table(dev); + if (ret) { + dev_err(dev, "PASID table allocation failed\n"); + dmar_remove_one_dev_info(dev); + return ret; + } + + /* Setup the PASID entry for requests without PASID: */ + spin_lock_irqsave(&iommu->lock, flags); + if (hw_pass_through && domain_type_is_si(domain)) + ret = intel_pasid_setup_pass_through(iommu, domain, + dev, PASID_RID2PASID); + else if (domain_use_first_level(domain)) + ret = domain_setup_first_level(iommu, domain, dev, + PASID_RID2PASID); + else + ret = intel_pasid_setup_second_level(iommu, domain, + dev, PASID_RID2PASID); + spin_unlock_irqrestore(&iommu->lock, flags); + if (ret) { + dev_err(dev, "Setup RID2PASID failed\n"); + dmar_remove_one_dev_info(dev); + return ret; + } + } + + ret = domain_context_mapping(domain, dev); + if (ret) { + dev_err(dev, "Domain context map failed\n"); + dmar_remove_one_dev_info(dev); + return ret; + } return 0; } @@ -3607,12 +3566,7 @@ static int intel_iommu_add(struct dmar_drhd_unit *dmaru) iommu->name); return -ENXIO; } - if (!ecap_sc_support(iommu->ecap) && - domain_update_iommu_snooping(iommu)) { - pr_warn("%s: Doesn't support snooping.\n", - iommu->name); - return -ENXIO; - } + sp = domain_update_iommu_superpage(NULL, iommu) - 1; if (sp >= 0 && !(cap_super_page_val(iommu->cap) & (1 << sp))) { pr_warn("%s: Doesn't support large page.\n", @@ -4304,7 +4258,6 @@ static int md_domain_init(struct dmar_domain *domain, int guest_width) domain->agaw = width_to_agaw(adjust_width); domain->iommu_coherency = false; - domain->iommu_snooping = false; domain->iommu_superpage = 0; domain->max_addr = 0; @@ -4369,6 +4322,9 @@ static int prepare_domain_attach_device(struct iommu_domain *domain, if (!iommu) return -ENODEV; + if (dmar_domain->force_snooping && !ecap_sc_support(iommu->ecap)) + return -EOPNOTSUPP; + /* check if this iommu agaw is sufficient for max mapped address */ addr_width = agaw_to_width(iommu->agaw); if (addr_width > cap_mgaw(iommu->cap)) @@ -4443,7 +4399,7 @@ static int intel_iommu_map(struct iommu_domain *domain, prot |= DMA_PTE_READ; if (iommu_prot & IOMMU_WRITE) prot |= DMA_PTE_WRITE; - if ((iommu_prot & IOMMU_CACHE) && dmar_domain->iommu_snooping) + if (dmar_domain->set_pte_snp) prot |= DMA_PTE_SNP; max_addr = iova + size; @@ -4566,12 +4522,71 @@ static phys_addr_t intel_iommu_iova_to_phys(struct iommu_domain *domain, return phys; } +static bool domain_support_force_snooping(struct dmar_domain *domain) +{ + struct device_domain_info *info; + bool support = true; + + assert_spin_locked(&device_domain_lock); + list_for_each_entry(info, &domain->devices, link) { + if (!ecap_sc_support(info->iommu->ecap)) { + support = false; + break; + } + } + + return support; +} + +static void domain_set_force_snooping(struct dmar_domain *domain) +{ + struct device_domain_info *info; + + assert_spin_locked(&device_domain_lock); + + /* + * Second level page table supports per-PTE snoop control. The + * iommu_map() interface will handle this by setting SNP bit. + */ + if (!domain_use_first_level(domain)) { + domain->set_pte_snp = true; + return; + } + + list_for_each_entry(info, &domain->devices, link) + intel_pasid_setup_page_snoop_control(info->iommu, info->dev, + PASID_RID2PASID); +} + +static bool intel_iommu_enforce_cache_coherency(struct iommu_domain *domain) +{ + struct dmar_domain *dmar_domain = to_dmar_domain(domain); + unsigned long flags; + + if (dmar_domain->force_snooping) + return true; + + spin_lock_irqsave(&device_domain_lock, flags); + if (!domain_support_force_snooping(dmar_domain)) { + spin_unlock_irqrestore(&device_domain_lock, flags); + return false; + } + + domain_set_force_snooping(dmar_domain); + dmar_domain->force_snooping = true; + spin_unlock_irqrestore(&device_domain_lock, flags); + + return true; +} + static bool intel_iommu_capable(enum iommu_cap cap) { if (cap == IOMMU_CAP_CACHE_COHERENCY) - return domain_update_iommu_snooping(NULL); + return true; if (cap == IOMMU_CAP_INTR_REMAP) return irq_remapping_enabled == 1; + if (cap == IOMMU_CAP_PRE_BOOT_PROTECTION) + return dmar_platform_optin(); return false; } @@ -4919,6 +4934,7 @@ const struct iommu_ops intel_iommu_ops = { .iotlb_sync = intel_iommu_tlb_sync, .iova_to_phys = intel_iommu_iova_to_phys, .free = intel_iommu_domain_free, + .enforce_cache_coherency = intel_iommu_enforce_cache_coherency, } }; diff --git a/drivers/iommu/intel/pasid.c b/drivers/iommu/intel/pasid.c index f8d215d85695b286a0ce469e1bf32ec90e97fa02..cb4c1d0cf25c0bbbaea3694efa879208aa6f0f6b 100644 --- a/drivers/iommu/intel/pasid.c +++ b/drivers/iommu/intel/pasid.c @@ -710,9 +710,6 @@ int intel_pasid_setup_second_level(struct intel_iommu *iommu, pasid_set_fault_enable(pte); pasid_set_page_snoop(pte, !!ecap_smpwc(iommu->ecap)); - if (domain->domain.type == IOMMU_DOMAIN_UNMANAGED) - pasid_set_pgsnp(pte); - /* * Since it is a second level only translation setup, we should * set SRE bit as well (addresses are expected to be GPAs). @@ -762,3 +759,45 @@ int intel_pasid_setup_pass_through(struct intel_iommu *iommu, return 0; } + +/* + * Set the page snoop control for a pasid entry which has been set up. + */ +void intel_pasid_setup_page_snoop_control(struct intel_iommu *iommu, + struct device *dev, u32 pasid) +{ + struct pasid_entry *pte; + u16 did; + + spin_lock(&iommu->lock); + pte = intel_pasid_get_entry(dev, pasid); + if (WARN_ON(!pte || !pasid_pte_is_present(pte))) { + spin_unlock(&iommu->lock); + return; + } + + pasid_set_pgsnp(pte); + did = pasid_get_domain_id(pte); + spin_unlock(&iommu->lock); + + if (!ecap_coherent(iommu->ecap)) + clflush_cache_range(pte, sizeof(*pte)); + + /* + * VT-d spec 3.4 table23 states guides for cache invalidation: + * + * - PASID-selective-within-Domain PASID-cache invalidation + * - PASID-selective PASID-based IOTLB invalidation + * - If (pasid is RID_PASID) + * - Global Device-TLB invalidation to affected functions + * Else + * - PASID-based Device-TLB invalidation (with S=1 and + * Addr[63:12]=0x7FFFFFFF_FFFFF) to affected functions + */ + pasid_cache_invalidation_with_pasid(iommu, did, pasid); + qi_flush_piotlb(iommu, did, pasid, 0, -1, 0); + + /* Device IOTLB doesn't need to be flushed in caching mode. */ + if (!cap_caching_mode(iommu->cap)) + devtlb_invalidation_with_pasid(iommu, dev, pasid); +} diff --git a/drivers/iommu/intel/pasid.h b/drivers/iommu/intel/pasid.h index ab4408c824a5a14d532288d7935b4b9b3491eb89..583ea67fc7836065392240bc9e2103557c7cf21f 100644 --- a/drivers/iommu/intel/pasid.h +++ b/drivers/iommu/intel/pasid.h @@ -123,4 +123,6 @@ void intel_pasid_tear_down_entry(struct intel_iommu *iommu, bool fault_ignore); int vcmd_alloc_pasid(struct intel_iommu *iommu, u32 *pasid); void vcmd_free_pasid(struct intel_iommu *iommu, u32 pasid); +void intel_pasid_setup_page_snoop_control(struct intel_iommu *iommu, + struct device *dev, u32 pasid); #endif /* __INTEL_PASID_H */ diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index 857d4c2fd1a206a0a944f3acf5e6ad79f4c9f21b..847ad47a2dfd38f49085c07b9113130db30733b4 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include @@ -40,14 +39,16 @@ struct iommu_group { struct kobject *devices_kobj; struct list_head devices; struct mutex mutex; - struct blocking_notifier_head notifier; void *iommu_data; void (*iommu_data_release)(void *iommu_data); char *name; int id; struct iommu_domain *default_domain; + struct iommu_domain *blocking_domain; struct iommu_domain *domain; struct list_head entry; + unsigned int owner_cnt; + void *owner; }; struct group_device { @@ -82,8 +83,8 @@ static int __iommu_attach_device(struct iommu_domain *domain, struct device *dev); static int __iommu_attach_group(struct iommu_domain *domain, struct iommu_group *group); -static void __iommu_detach_group(struct iommu_domain *domain, - struct iommu_group *group); +static int __iommu_group_set_domain(struct iommu_group *group, + struct iommu_domain *new_domain); static int iommu_create_device_direct_mappings(struct iommu_group *group, struct device *dev); static struct iommu_group *iommu_group_get_for_dev(struct device *dev); @@ -294,7 +295,11 @@ int iommu_probe_device(struct device *dev) mutex_lock(&group->mutex); iommu_alloc_default_domain(group, dev); - if (group->default_domain) { + /* + * If device joined an existing group which has been claimed, don't + * attach the default domain. + */ + if (group->default_domain && !group->owner) { ret = __iommu_attach_device(group->default_domain, dev); if (ret) { mutex_unlock(&group->mutex); @@ -599,6 +604,8 @@ static void iommu_group_release(struct kobject *kobj) if (group->default_domain) iommu_domain_free(group->default_domain); + if (group->blocking_domain) + iommu_domain_free(group->blocking_domain); kfree(group->name); kfree(group); @@ -633,7 +640,6 @@ struct iommu_group *iommu_group_alloc(void) mutex_init(&group->mutex); INIT_LIST_HEAD(&group->devices); INIT_LIST_HEAD(&group->entry); - BLOCKING_INIT_NOTIFIER_HEAD(&group->notifier); ret = ida_simple_get(&iommu_group_ida, 0, 0, GFP_KERNEL); if (ret < 0) { @@ -906,10 +912,6 @@ rename: if (ret) goto err_put_group; - /* Notify any listeners about change to group. */ - blocking_notifier_call_chain(&group->notifier, - IOMMU_GROUP_NOTIFY_ADD_DEVICE, dev); - trace_add_device_to_group(group->id, dev); dev_info(dev, "Adding to iommu group %d\n", group->id); @@ -951,10 +953,6 @@ void iommu_group_remove_device(struct device *dev) dev_info(dev, "Removing from iommu group %d\n", group->id); - /* Pre-notify listeners that a device is being removed. */ - blocking_notifier_call_chain(&group->notifier, - IOMMU_GROUP_NOTIFY_DEL_DEVICE, dev); - mutex_lock(&group->mutex); list_for_each_entry(tmp_device, &group->devices, list) { if (tmp_device->dev == dev) { @@ -1076,36 +1074,6 @@ void iommu_group_put(struct iommu_group *group) } EXPORT_SYMBOL_GPL(iommu_group_put); -/** - * iommu_group_register_notifier - Register a notifier for group changes - * @group: the group to watch - * @nb: notifier block to signal - * - * This function allows iommu group users to track changes in a group. - * See include/linux/iommu.h for actions sent via this notifier. Caller - * should hold a reference to the group throughout notifier registration. - */ -int iommu_group_register_notifier(struct iommu_group *group, - struct notifier_block *nb) -{ - return blocking_notifier_chain_register(&group->notifier, nb); -} -EXPORT_SYMBOL_GPL(iommu_group_register_notifier); - -/** - * iommu_group_unregister_notifier - Unregister a notifier - * @group: the group to watch - * @nb: notifier block to signal - * - * Unregister a previously registered group notifier block. - */ -int iommu_group_unregister_notifier(struct iommu_group *group, - struct notifier_block *nb) -{ - return blocking_notifier_chain_unregister(&group->notifier, nb); -} -EXPORT_SYMBOL_GPL(iommu_group_unregister_notifier); - /** * iommu_register_device_fault_handler() - Register a device fault handler * @dev: the device @@ -1651,14 +1619,8 @@ static int remove_iommu_group(struct device *dev, void *data) static int iommu_bus_notifier(struct notifier_block *nb, unsigned long action, void *data) { - unsigned long group_action = 0; struct device *dev = data; - struct iommu_group *group; - /* - * ADD/DEL call into iommu driver ops if provided, which may - * result in ADD/DEL notifiers to group->notifier - */ if (action == BUS_NOTIFY_ADD_DEVICE) { int ret; @@ -1669,34 +1631,6 @@ static int iommu_bus_notifier(struct notifier_block *nb, return NOTIFY_OK; } - /* - * Remaining BUS_NOTIFYs get filtered and republished to the - * group, if anyone is listening - */ - group = iommu_group_get(dev); - if (!group) - return 0; - - switch (action) { - case BUS_NOTIFY_BIND_DRIVER: - group_action = IOMMU_GROUP_NOTIFY_BIND_DRIVER; - break; - case BUS_NOTIFY_BOUND_DRIVER: - group_action = IOMMU_GROUP_NOTIFY_BOUND_DRIVER; - break; - case BUS_NOTIFY_UNBIND_DRIVER: - group_action = IOMMU_GROUP_NOTIFY_UNBIND_DRIVER; - break; - case BUS_NOTIFY_UNBOUND_DRIVER: - group_action = IOMMU_GROUP_NOTIFY_UNBOUND_DRIVER; - break; - } - - if (group_action) - blocking_notifier_call_chain(&group->notifier, - group_action, dev); - - iommu_group_put(group); return 0; } @@ -1913,6 +1847,29 @@ bool iommu_present(struct bus_type *bus) } EXPORT_SYMBOL_GPL(iommu_present); +/** + * device_iommu_capable() - check for a general IOMMU capability + * @dev: device to which the capability would be relevant, if available + * @cap: IOMMU capability + * + * Return: true if an IOMMU is present and supports the given capability + * for the given device, otherwise false. + */ +bool device_iommu_capable(struct device *dev, enum iommu_cap cap) +{ + const struct iommu_ops *ops; + + if (!dev->iommu || !dev->iommu->iommu_dev) + return false; + + ops = dev_iommu_ops(dev); + if (!ops->capable) + return false; + + return ops->capable(cap); +} +EXPORT_SYMBOL_GPL(device_iommu_capable); + bool iommu_capable(struct bus_type *bus, enum iommu_cap cap) { if (!bus->iommu_ops || !bus->iommu_ops->capable) @@ -1983,6 +1940,24 @@ void iommu_domain_free(struct iommu_domain *domain) } EXPORT_SYMBOL_GPL(iommu_domain_free); +/* + * Put the group's domain back to the appropriate core-owned domain - either the + * standard kernel-mode DMA configuration or an all-DMA-blocked domain. + */ +static void __iommu_group_set_core_domain(struct iommu_group *group) +{ + struct iommu_domain *new_domain; + int ret; + + if (group->owner) + new_domain = group->blocking_domain; + else + new_domain = group->default_domain; + + ret = __iommu_group_set_domain(group, new_domain); + WARN(ret, "iommu driver failed to attach the default/blocking domain"); +} + static int __iommu_attach_device(struct iommu_domain *domain, struct device *dev) { @@ -2039,9 +2014,6 @@ static void __iommu_detach_device(struct iommu_domain *domain, if (iommu_is_attach_deferred(dev)) return; - if (unlikely(domain->ops->detach_dev == NULL)) - return; - domain->ops->detach_dev(domain, dev); trace_detach_device_from_domain(dev); } @@ -2055,12 +2027,10 @@ void iommu_detach_device(struct iommu_domain *domain, struct device *dev) return; mutex_lock(&group->mutex); - if (iommu_group_device_count(group) != 1) { - WARN_ON(1); + if (WARN_ON(domain != group->domain) || + WARN_ON(iommu_group_device_count(group) != 1)) goto out_unlock; - } - - __iommu_detach_group(domain, group); + __iommu_group_set_core_domain(group); out_unlock: mutex_unlock(&group->mutex); @@ -2116,7 +2086,8 @@ static int __iommu_attach_group(struct iommu_domain *domain, { int ret; - if (group->default_domain && group->domain != group->default_domain) + if (group->domain && group->domain != group->default_domain && + group->domain != group->blocking_domain) return -EBUSY; ret = __iommu_group_for_each_dev(group, domain, @@ -2148,34 +2119,49 @@ static int iommu_group_do_detach_device(struct device *dev, void *data) return 0; } -static void __iommu_detach_group(struct iommu_domain *domain, - struct iommu_group *group) +static int __iommu_group_set_domain(struct iommu_group *group, + struct iommu_domain *new_domain) { int ret; - if (!group->default_domain) { - __iommu_group_for_each_dev(group, domain, + if (group->domain == new_domain) + return 0; + + /* + * New drivers should support default domains and so the detach_dev() op + * will never be called. Otherwise the NULL domain represents some + * platform specific behavior. + */ + if (!new_domain) { + if (WARN_ON(!group->domain->ops->detach_dev)) + return -EINVAL; + __iommu_group_for_each_dev(group, group->domain, iommu_group_do_detach_device); group->domain = NULL; - return; + return 0; } - if (group->domain == group->default_domain) - return; - - /* Detach by re-attaching to the default domain */ - ret = __iommu_group_for_each_dev(group, group->default_domain, + /* + * Changing the domain is done by calling attach_dev() on the new + * domain. This switch does not have to be atomic and DMA can be + * discarded during the transition. DMA must only be able to access + * either new_domain or group->domain, never something else. + * + * Note that this is called in error unwind paths, attaching to a + * domain that has already been attached cannot fail. + */ + ret = __iommu_group_for_each_dev(group, new_domain, iommu_group_do_attach_device); - if (ret != 0) - WARN_ON(1); - else - group->domain = group->default_domain; + if (ret) + return ret; + group->domain = new_domain; + return 0; } void iommu_detach_group(struct iommu_domain *domain, struct iommu_group *group) { mutex_lock(&group->mutex); - __iommu_detach_group(domain, group); + __iommu_group_set_core_domain(group); mutex_unlock(&group->mutex); } EXPORT_SYMBOL_GPL(iommu_detach_group); @@ -3102,3 +3088,167 @@ out: return ret; } + +/** + * iommu_device_use_default_domain() - Device driver wants to handle device + * DMA through the kernel DMA API. + * @dev: The device. + * + * The device driver about to bind @dev wants to do DMA through the kernel + * DMA API. Return 0 if it is allowed, otherwise an error. + */ +int iommu_device_use_default_domain(struct device *dev) +{ + struct iommu_group *group = iommu_group_get(dev); + int ret = 0; + + if (!group) + return 0; + + mutex_lock(&group->mutex); + if (group->owner_cnt) { + if (group->domain != group->default_domain || + group->owner) { + ret = -EBUSY; + goto unlock_out; + } + } + + group->owner_cnt++; + +unlock_out: + mutex_unlock(&group->mutex); + iommu_group_put(group); + + return ret; +} + +/** + * iommu_device_unuse_default_domain() - Device driver stops handling device + * DMA through the kernel DMA API. + * @dev: The device. + * + * The device driver doesn't want to do DMA through kernel DMA API anymore. + * It must be called after iommu_device_use_default_domain(). + */ +void iommu_device_unuse_default_domain(struct device *dev) +{ + struct iommu_group *group = iommu_group_get(dev); + + if (!group) + return; + + mutex_lock(&group->mutex); + if (!WARN_ON(!group->owner_cnt)) + group->owner_cnt--; + + mutex_unlock(&group->mutex); + iommu_group_put(group); +} + +static int __iommu_group_alloc_blocking_domain(struct iommu_group *group) +{ + struct group_device *dev = + list_first_entry(&group->devices, struct group_device, list); + + if (group->blocking_domain) + return 0; + + group->blocking_domain = + __iommu_domain_alloc(dev->dev->bus, IOMMU_DOMAIN_BLOCKED); + if (!group->blocking_domain) { + /* + * For drivers that do not yet understand IOMMU_DOMAIN_BLOCKED + * create an empty domain instead. + */ + group->blocking_domain = __iommu_domain_alloc( + dev->dev->bus, IOMMU_DOMAIN_UNMANAGED); + if (!group->blocking_domain) + return -EINVAL; + } + return 0; +} + +/** + * iommu_group_claim_dma_owner() - Set DMA ownership of a group + * @group: The group. + * @owner: Caller specified pointer. Used for exclusive ownership. + * + * This is to support backward compatibility for vfio which manages + * the dma ownership in iommu_group level. New invocations on this + * interface should be prohibited. + */ +int iommu_group_claim_dma_owner(struct iommu_group *group, void *owner) +{ + int ret = 0; + + mutex_lock(&group->mutex); + if (group->owner_cnt) { + ret = -EPERM; + goto unlock_out; + } else { + if (group->domain && group->domain != group->default_domain) { + ret = -EBUSY; + goto unlock_out; + } + + ret = __iommu_group_alloc_blocking_domain(group); + if (ret) + goto unlock_out; + + ret = __iommu_group_set_domain(group, group->blocking_domain); + if (ret) + goto unlock_out; + group->owner = owner; + } + + group->owner_cnt++; +unlock_out: + mutex_unlock(&group->mutex); + + return ret; +} +EXPORT_SYMBOL_GPL(iommu_group_claim_dma_owner); + +/** + * iommu_group_release_dma_owner() - Release DMA ownership of a group + * @group: The group. + * + * Release the DMA ownership claimed by iommu_group_claim_dma_owner(). + */ +void iommu_group_release_dma_owner(struct iommu_group *group) +{ + int ret; + + mutex_lock(&group->mutex); + if (WARN_ON(!group->owner_cnt || !group->owner)) + goto unlock_out; + + group->owner_cnt = 0; + group->owner = NULL; + ret = __iommu_group_set_domain(group, group->default_domain); + WARN(ret, "iommu driver failed to attach the default domain"); + +unlock_out: + mutex_unlock(&group->mutex); +} +EXPORT_SYMBOL_GPL(iommu_group_release_dma_owner); + +/** + * iommu_group_dma_owner_claimed() - Query group dma ownership status + * @group: The group. + * + * This provides status query on a given group. It is racy and only for + * non-binding status reporting. + */ +bool iommu_group_dma_owner_claimed(struct iommu_group *group) +{ + unsigned int user; + + mutex_lock(&group->mutex); + user = group->owner_cnt; + mutex_unlock(&group->mutex); + + return user; +} +EXPORT_SYMBOL_GPL(iommu_group_dma_owner_claimed); diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c index 50f57624610f63fd4124343e2b2b495a7abcee35..f09aedfdd462bd15c414bf8e85857c56780c30a4 100644 --- a/drivers/iommu/msm_iommu.c +++ b/drivers/iommu/msm_iommu.c @@ -583,7 +583,7 @@ static void print_ctx_regs(void __iomem *base, int ctx) GET_SCTLR(base, ctx), GET_ACTLR(base, ctx)); } -static void insert_iommu_master(struct device *dev, +static int insert_iommu_master(struct device *dev, struct msm_iommu_dev **iommu, struct of_phandle_args *spec) { @@ -592,6 +592,10 @@ static void insert_iommu_master(struct device *dev, if (list_empty(&(*iommu)->ctx_list)) { master = kzalloc(sizeof(*master), GFP_ATOMIC); + if (!master) { + dev_err(dev, "Failed to allocate iommu_master\n"); + return -ENOMEM; + } master->of_node = dev->of_node; list_add(&master->list, &(*iommu)->ctx_list); dev_iommu_priv_set(dev, master); @@ -601,30 +605,34 @@ static void insert_iommu_master(struct device *dev, if (master->mids[sid] == spec->args[0]) { dev_warn(dev, "Stream ID 0x%hx repeated; ignoring\n", sid); - return; + return 0; } master->mids[master->num_mids++] = spec->args[0]; + return 0; } static int qcom_iommu_of_xlate(struct device *dev, struct of_phandle_args *spec) { - struct msm_iommu_dev *iommu; + struct msm_iommu_dev *iommu = NULL, *iter; unsigned long flags; int ret = 0; spin_lock_irqsave(&msm_iommu_lock, flags); - list_for_each_entry(iommu, &qcom_iommu_devices, dev_node) - if (iommu->dev->of_node == spec->np) + list_for_each_entry(iter, &qcom_iommu_devices, dev_node) { + if (iter->dev->of_node == spec->np) { + iommu = iter; break; + } + } - if (!iommu || iommu->dev->of_node != spec->np) { + if (!iommu) { ret = -ENODEV; goto fail; } - insert_iommu_master(dev, &iommu, spec); + ret = insert_iommu_master(dev, &iommu, spec); fail: spin_unlock_irqrestore(&msm_iommu_lock, flags); diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index 6fd75a60abd6781b4bf10df1571e045d78fc035a..bb9dd92c9898d3ea34ecec811937c8311b663762 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -14,12 +14,14 @@ #include #include #include +#include #include #include #include #include #include #include +#include #include #include #include @@ -29,7 +31,7 @@ #include #include -#include "mtk_iommu.h" +#include #define REG_MMU_PT_BASE_ADDR 0x000 #define MMU_PT_ADDR_MASK GENMASK(31, 7) @@ -51,6 +53,8 @@ #define F_MMU_STANDARD_AXI_MODE_MASK (BIT(3) | BIT(19)) #define REG_MMU_DCM_DIS 0x050 +#define F_MMU_DCM BIT(8) + #define REG_MMU_WR_LEN_CTRL 0x054 #define F_MMU_WR_THROT_DIS_MASK (BIT(5) | BIT(21)) @@ -103,10 +107,15 @@ #define REG_MMU1_INT_ID 0x154 #define F_MMU_INT_ID_COMM_ID(a) (((a) >> 9) & 0x7) #define F_MMU_INT_ID_SUB_COMM_ID(a) (((a) >> 7) & 0x3) +#define F_MMU_INT_ID_COMM_ID_EXT(a) (((a) >> 10) & 0x7) +#define F_MMU_INT_ID_SUB_COMM_ID_EXT(a) (((a) >> 7) & 0x7) #define F_MMU_INT_ID_LARB_ID(a) (((a) >> 7) & 0x7) #define F_MMU_INT_ID_PORT_ID(a) (((a) >> 2) & 0x1f) #define MTK_PROTECT_PA_ALIGN 256 +#define MTK_IOMMU_BANK_SZ 0x1000 + +#define PERICFG_IOMMU_1 0x714 #define HAS_4GB_MODE BIT(0) /* HW will use the EMI clock if there isn't the "bclk". */ @@ -114,25 +123,147 @@ #define HAS_VLD_PA_RNG BIT(2) #define RESET_AXI BIT(3) #define OUT_ORDER_WR_EN BIT(4) -#define HAS_SUB_COMM BIT(5) -#define WR_THROT_EN BIT(6) -#define HAS_LEGACY_IVRP_PADDR BIT(7) -#define IOVA_34_EN BIT(8) +#define HAS_SUB_COMM_2BITS BIT(5) +#define HAS_SUB_COMM_3BITS BIT(6) +#define WR_THROT_EN BIT(7) +#define HAS_LEGACY_IVRP_PADDR BIT(8) +#define IOVA_34_EN BIT(9) +#define SHARE_PGTABLE BIT(10) /* 2 HW share pgtable */ +#define DCM_DISABLE BIT(11) +#define STD_AXI_MODE BIT(12) /* For non MM iommu */ +/* 2 bits: iommu type */ +#define MTK_IOMMU_TYPE_MM (0x0 << 13) +#define MTK_IOMMU_TYPE_INFRA (0x1 << 13) +#define MTK_IOMMU_TYPE_MASK (0x3 << 13) +/* PM and clock always on. e.g. infra iommu */ +#define PM_CLK_AO BIT(15) +#define IFA_IOMMU_PCIE_SUPPORT BIT(16) + +#define MTK_IOMMU_HAS_FLAG_MASK(pdata, _x, mask) \ + ((((pdata)->flags) & (mask)) == (_x)) + +#define MTK_IOMMU_HAS_FLAG(pdata, _x) MTK_IOMMU_HAS_FLAG_MASK(pdata, _x, _x) +#define MTK_IOMMU_IS_TYPE(pdata, _x) MTK_IOMMU_HAS_FLAG_MASK(pdata, _x,\ + MTK_IOMMU_TYPE_MASK) + +#define MTK_INVALID_LARBID MTK_LARB_NR_MAX + +#define MTK_LARB_COM_MAX 8 +#define MTK_LARB_SUBCOM_MAX 8 + +#define MTK_IOMMU_GROUP_MAX 8 +#define MTK_IOMMU_BANK_MAX 5 + +enum mtk_iommu_plat { + M4U_MT2712, + M4U_MT6779, + M4U_MT8167, + M4U_MT8173, + M4U_MT8183, + M4U_MT8186, + M4U_MT8192, + M4U_MT8195, +}; + +struct mtk_iommu_iova_region { + dma_addr_t iova_base; + unsigned long long size; +}; + +struct mtk_iommu_suspend_reg { + u32 misc_ctrl; + u32 dcm_dis; + u32 ctrl_reg; + u32 vld_pa_rng; + u32 wr_len_ctrl; + + u32 int_control[MTK_IOMMU_BANK_MAX]; + u32 int_main_control[MTK_IOMMU_BANK_MAX]; + u32 ivrp_paddr[MTK_IOMMU_BANK_MAX]; +}; + +struct mtk_iommu_plat_data { + enum mtk_iommu_plat m4u_plat; + u32 flags; + u32 inv_sel_reg; + + char *pericfg_comp_str; + struct list_head *hw_list; + unsigned int iova_region_nr; + const struct mtk_iommu_iova_region *iova_region; + + u8 banks_num; + bool banks_enable[MTK_IOMMU_BANK_MAX]; + unsigned int banks_portmsk[MTK_IOMMU_BANK_MAX]; + unsigned char larbid_remap[MTK_LARB_COM_MAX][MTK_LARB_SUBCOM_MAX]; +}; + +struct mtk_iommu_bank_data { + void __iomem *base; + int irq; + u8 id; + struct device *parent_dev; + struct mtk_iommu_data *parent_data; + spinlock_t tlb_lock; /* lock for tlb range flush */ + struct mtk_iommu_domain *m4u_dom; /* Each bank has a domain */ +}; + +struct mtk_iommu_data { + struct device *dev; + struct clk *bclk; + phys_addr_t protect_base; /* protect memory base */ + struct mtk_iommu_suspend_reg reg; + struct iommu_group *m4u_group[MTK_IOMMU_GROUP_MAX]; + bool enable_4GB; -#define MTK_IOMMU_HAS_FLAG(pdata, _x) \ - ((((pdata)->flags) & (_x)) == (_x)) + struct iommu_device iommu; + const struct mtk_iommu_plat_data *plat_data; + struct device *smicomm_dev; + + struct mtk_iommu_bank_data *bank; + + struct dma_iommu_mapping *mapping; /* For mtk_iommu_v1.c */ + struct regmap *pericfg; + + struct mutex mutex; /* Protect m4u_group/m4u_dom above */ + + /* + * In the sharing pgtable case, list data->list to the global list like m4ulist. + * In the non-sharing pgtable case, list data->list to the itself hw_list_head. + */ + struct list_head *hw_list; + struct list_head hw_list_head; + struct list_head list; + struct mtk_smi_larb_iommu larb_imu[MTK_LARB_NR_MAX]; +}; struct mtk_iommu_domain { struct io_pgtable_cfg cfg; struct io_pgtable_ops *iop; - struct mtk_iommu_data *data; + struct mtk_iommu_bank_data *bank; struct iommu_domain domain; + + struct mutex mutex; /* Protect "data" in this structure */ }; +static int mtk_iommu_bind(struct device *dev) +{ + struct mtk_iommu_data *data = dev_get_drvdata(dev); + + return component_bind_all(dev, &data->larb_imu); +} + +static void mtk_iommu_unbind(struct device *dev) +{ + struct mtk_iommu_data *data = dev_get_drvdata(dev); + + component_unbind_all(dev, &data->larb_imu); +} + static const struct iommu_ops mtk_iommu_ops; -static int mtk_iommu_hw_init(const struct mtk_iommu_data *data); +static int mtk_iommu_hw_init(const struct mtk_iommu_data *data, unsigned int bankid); #define MTK_IOMMU_TLB_ADDR(iova) ({ \ dma_addr_t _addr = iova; \ @@ -165,42 +296,28 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data *data); static LIST_HEAD(m4ulist); /* List all the M4U HWs */ -#define for_each_m4u(data) list_for_each_entry(data, &m4ulist, list) - -struct mtk_iommu_iova_region { - dma_addr_t iova_base; - unsigned long long size; -}; +#define for_each_m4u(data, head) list_for_each_entry(data, head, list) static const struct mtk_iommu_iova_region single_domain[] = { {.iova_base = 0, .size = SZ_4G}, }; static const struct mtk_iommu_iova_region mt8192_multi_dom[] = { - { .iova_base = 0x0, .size = SZ_4G}, /* disp: 0 ~ 4G */ + { .iova_base = 0x0, .size = SZ_4G}, /* 0 ~ 4G */ #if IS_ENABLED(CONFIG_ARCH_DMA_ADDR_T_64BIT) - { .iova_base = SZ_4G, .size = SZ_4G}, /* vdec: 4G ~ 8G */ - { .iova_base = SZ_4G * 2, .size = SZ_4G}, /* CAM/MDP: 8G ~ 12G */ + { .iova_base = SZ_4G, .size = SZ_4G}, /* 4G ~ 8G */ + { .iova_base = SZ_4G * 2, .size = SZ_4G}, /* 8G ~ 12G */ + { .iova_base = SZ_4G * 3, .size = SZ_4G}, /* 12G ~ 16G */ + { .iova_base = 0x240000000ULL, .size = 0x4000000}, /* CCU0 */ { .iova_base = 0x244000000ULL, .size = 0x4000000}, /* CCU1 */ #endif }; -/* - * There may be 1 or 2 M4U HWs, But we always expect they are in the same domain - * for the performance. - * - * Here always return the mtk_iommu_data of the first probed M4U where the - * iommu domain information is recorded. - */ -static struct mtk_iommu_data *mtk_iommu_get_m4u_data(void) +/* If 2 M4U share a domain(use the same hwlist), Put the corresponding info in first data.*/ +static struct mtk_iommu_data *mtk_iommu_get_frst_data(struct list_head *hwlist) { - struct mtk_iommu_data *data; - - for_each_m4u(data) - return data; - - return NULL; + return list_first_entry(hwlist, struct mtk_iommu_data, list); } static struct mtk_iommu_domain *to_mtk_domain(struct iommu_domain *dom) @@ -210,46 +327,72 @@ static struct mtk_iommu_domain *to_mtk_domain(struct iommu_domain *dom) static void mtk_iommu_tlb_flush_all(struct mtk_iommu_data *data) { + /* Tlb flush all always is in bank0. */ + struct mtk_iommu_bank_data *bank = &data->bank[0]; + void __iomem *base = bank->base; unsigned long flags; - spin_lock_irqsave(&data->tlb_lock, flags); - writel_relaxed(F_INVLD_EN1 | F_INVLD_EN0, - data->base + data->plat_data->inv_sel_reg); - writel_relaxed(F_ALL_INVLD, data->base + REG_MMU_INVALIDATE); + spin_lock_irqsave(&bank->tlb_lock, flags); + writel_relaxed(F_INVLD_EN1 | F_INVLD_EN0, base + data->plat_data->inv_sel_reg); + writel_relaxed(F_ALL_INVLD, base + REG_MMU_INVALIDATE); wmb(); /* Make sure the tlb flush all done */ - spin_unlock_irqrestore(&data->tlb_lock, flags); + spin_unlock_irqrestore(&bank->tlb_lock, flags); } static void mtk_iommu_tlb_flush_range_sync(unsigned long iova, size_t size, - size_t granule, - struct mtk_iommu_data *data) + struct mtk_iommu_bank_data *bank) { + struct list_head *head = bank->parent_data->hw_list; + struct mtk_iommu_bank_data *curbank; + struct mtk_iommu_data *data; + bool check_pm_status; unsigned long flags; + void __iomem *base; int ret; u32 tmp; - for_each_m4u(data) { - if (pm_runtime_get_if_in_use(data->dev) <= 0) - continue; + for_each_m4u(data, head) { + /* + * To avoid resume the iommu device frequently when the iommu device + * is not active, it doesn't always call pm_runtime_get here, then tlb + * flush depends on the tlb flush all in the runtime resume. + * + * There are 2 special cases: + * + * Case1: The iommu dev doesn't have power domain but has bclk. This case + * should also avoid the tlb flush while the dev is not active to mute + * the tlb timeout log. like mt8173. + * + * Case2: The power/clock of infra iommu is always on, and it doesn't + * have the device link with the master devices. This case should avoid + * the PM status check. + */ + check_pm_status = !MTK_IOMMU_HAS_FLAG(data->plat_data, PM_CLK_AO); - spin_lock_irqsave(&data->tlb_lock, flags); + if (check_pm_status) { + if (pm_runtime_get_if_in_use(data->dev) <= 0) + continue; + } + + curbank = &data->bank[bank->id]; + base = curbank->base; + + spin_lock_irqsave(&curbank->tlb_lock, flags); writel_relaxed(F_INVLD_EN1 | F_INVLD_EN0, - data->base + data->plat_data->inv_sel_reg); + base + data->plat_data->inv_sel_reg); - writel_relaxed(MTK_IOMMU_TLB_ADDR(iova), - data->base + REG_MMU_INVLD_START_A); + writel_relaxed(MTK_IOMMU_TLB_ADDR(iova), base + REG_MMU_INVLD_START_A); writel_relaxed(MTK_IOMMU_TLB_ADDR(iova + size - 1), - data->base + REG_MMU_INVLD_END_A); - writel_relaxed(F_MMU_INV_RANGE, - data->base + REG_MMU_INVALIDATE); + base + REG_MMU_INVLD_END_A); + writel_relaxed(F_MMU_INV_RANGE, base + REG_MMU_INVALIDATE); /* tlb sync */ - ret = readl_poll_timeout_atomic(data->base + REG_MMU_CPE_DONE, + ret = readl_poll_timeout_atomic(base + REG_MMU_CPE_DONE, tmp, tmp != 0, 10, 1000); /* Clear the CPE status */ - writel_relaxed(0, data->base + REG_MMU_CPE_DONE); - spin_unlock_irqrestore(&data->tlb_lock, flags); + writel_relaxed(0, base + REG_MMU_CPE_DONE); + spin_unlock_irqrestore(&curbank->tlb_lock, flags); if (ret) { dev_warn(data->dev, @@ -257,70 +400,103 @@ static void mtk_iommu_tlb_flush_range_sync(unsigned long iova, size_t size, mtk_iommu_tlb_flush_all(data); } - pm_runtime_put(data->dev); + if (check_pm_status) + pm_runtime_put(data->dev); } } static irqreturn_t mtk_iommu_isr(int irq, void *dev_id) { - struct mtk_iommu_data *data = dev_id; - struct mtk_iommu_domain *dom = data->m4u_dom; - unsigned int fault_larb, fault_port, sub_comm = 0; + struct mtk_iommu_bank_data *bank = dev_id; + struct mtk_iommu_data *data = bank->parent_data; + struct mtk_iommu_domain *dom = bank->m4u_dom; + unsigned int fault_larb = MTK_INVALID_LARBID, fault_port = 0, sub_comm = 0; u32 int_state, regval, va34_32, pa34_32; + const struct mtk_iommu_plat_data *plat_data = data->plat_data; + void __iomem *base = bank->base; u64 fault_iova, fault_pa; bool layer, write; /* Read error info from registers */ - int_state = readl_relaxed(data->base + REG_MMU_FAULT_ST1); + int_state = readl_relaxed(base + REG_MMU_FAULT_ST1); if (int_state & F_REG_MMU0_FAULT_MASK) { - regval = readl_relaxed(data->base + REG_MMU0_INT_ID); - fault_iova = readl_relaxed(data->base + REG_MMU0_FAULT_VA); - fault_pa = readl_relaxed(data->base + REG_MMU0_INVLD_PA); + regval = readl_relaxed(base + REG_MMU0_INT_ID); + fault_iova = readl_relaxed(base + REG_MMU0_FAULT_VA); + fault_pa = readl_relaxed(base + REG_MMU0_INVLD_PA); } else { - regval = readl_relaxed(data->base + REG_MMU1_INT_ID); - fault_iova = readl_relaxed(data->base + REG_MMU1_FAULT_VA); - fault_pa = readl_relaxed(data->base + REG_MMU1_INVLD_PA); + regval = readl_relaxed(base + REG_MMU1_INT_ID); + fault_iova = readl_relaxed(base + REG_MMU1_FAULT_VA); + fault_pa = readl_relaxed(base + REG_MMU1_INVLD_PA); } layer = fault_iova & F_MMU_FAULT_VA_LAYER_BIT; write = fault_iova & F_MMU_FAULT_VA_WRITE_BIT; - if (MTK_IOMMU_HAS_FLAG(data->plat_data, IOVA_34_EN)) { + if (MTK_IOMMU_HAS_FLAG(plat_data, IOVA_34_EN)) { va34_32 = FIELD_GET(F_MMU_INVAL_VA_34_32_MASK, fault_iova); - pa34_32 = FIELD_GET(F_MMU_INVAL_PA_34_32_MASK, fault_iova); fault_iova = fault_iova & F_MMU_INVAL_VA_31_12_MASK; fault_iova |= (u64)va34_32 << 32; - fault_pa |= (u64)pa34_32 << 32; } - - fault_port = F_MMU_INT_ID_PORT_ID(regval); - if (MTK_IOMMU_HAS_FLAG(data->plat_data, HAS_SUB_COMM)) { - fault_larb = F_MMU_INT_ID_COMM_ID(regval); - sub_comm = F_MMU_INT_ID_SUB_COMM_ID(regval); - } else { - fault_larb = F_MMU_INT_ID_LARB_ID(regval); + pa34_32 = FIELD_GET(F_MMU_INVAL_PA_34_32_MASK, fault_iova); + fault_pa |= (u64)pa34_32 << 32; + + if (MTK_IOMMU_IS_TYPE(plat_data, MTK_IOMMU_TYPE_MM)) { + fault_port = F_MMU_INT_ID_PORT_ID(regval); + if (MTK_IOMMU_HAS_FLAG(plat_data, HAS_SUB_COMM_2BITS)) { + fault_larb = F_MMU_INT_ID_COMM_ID(regval); + sub_comm = F_MMU_INT_ID_SUB_COMM_ID(regval); + } else if (MTK_IOMMU_HAS_FLAG(plat_data, HAS_SUB_COMM_3BITS)) { + fault_larb = F_MMU_INT_ID_COMM_ID_EXT(regval); + sub_comm = F_MMU_INT_ID_SUB_COMM_ID_EXT(regval); + } else { + fault_larb = F_MMU_INT_ID_LARB_ID(regval); + } + fault_larb = data->plat_data->larbid_remap[fault_larb][sub_comm]; } - fault_larb = data->plat_data->larbid_remap[fault_larb][sub_comm]; - if (report_iommu_fault(&dom->domain, data->dev, fault_iova, + if (report_iommu_fault(&dom->domain, bank->parent_dev, fault_iova, write ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ)) { dev_err_ratelimited( - data->dev, - "fault type=0x%x iova=0x%llx pa=0x%llx larb=%d port=%d layer=%d %s\n", - int_state, fault_iova, fault_pa, fault_larb, fault_port, + bank->parent_dev, + "fault type=0x%x iova=0x%llx pa=0x%llx master=0x%x(larb=%d port=%d) layer=%d %s\n", + int_state, fault_iova, fault_pa, regval, fault_larb, fault_port, layer, write ? "write" : "read"); } /* Interrupt clear */ - regval = readl_relaxed(data->base + REG_MMU_INT_CONTROL0); + regval = readl_relaxed(base + REG_MMU_INT_CONTROL0); regval |= F_INT_CLR_BIT; - writel_relaxed(regval, data->base + REG_MMU_INT_CONTROL0); + writel_relaxed(regval, base + REG_MMU_INT_CONTROL0); mtk_iommu_tlb_flush_all(data); return IRQ_HANDLED; } -static int mtk_iommu_get_domain_id(struct device *dev, - const struct mtk_iommu_plat_data *plat_data) +static unsigned int mtk_iommu_get_bank_id(struct device *dev, + const struct mtk_iommu_plat_data *plat_data) +{ + struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev); + unsigned int i, portmsk = 0, bankid = 0; + + if (plat_data->banks_num == 1) + return bankid; + + for (i = 0; i < fwspec->num_ids; i++) + portmsk |= BIT(MTK_M4U_TO_PORT(fwspec->ids[i])); + + for (i = 0; i < plat_data->banks_num && i < MTK_IOMMU_BANK_MAX; i++) { + if (!plat_data->banks_enable[i]) + continue; + + if (portmsk & plat_data->banks_portmsk[i]) { + bankid = i; + break; + } + } + return bankid; /* default is 0 */ +} + +static int mtk_iommu_get_iova_region_id(struct device *dev, + const struct mtk_iommu_plat_data *plat_data) { const struct mtk_iommu_iova_region *rgn = plat_data->iova_region; const struct bus_dma_region *dma_rgn = dev->dma_range_map; @@ -349,46 +525,65 @@ static int mtk_iommu_get_domain_id(struct device *dev, return -EINVAL; } -static void mtk_iommu_config(struct mtk_iommu_data *data, struct device *dev, - bool enable, unsigned int domid) +static int mtk_iommu_config(struct mtk_iommu_data *data, struct device *dev, + bool enable, unsigned int regionid) { struct mtk_smi_larb_iommu *larb_mmu; unsigned int larbid, portid; struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev); const struct mtk_iommu_iova_region *region; - int i; + u32 peri_mmuen, peri_mmuen_msk; + int i, ret = 0; for (i = 0; i < fwspec->num_ids; ++i) { larbid = MTK_M4U_TO_LARB(fwspec->ids[i]); portid = MTK_M4U_TO_PORT(fwspec->ids[i]); - larb_mmu = &data->larb_imu[larbid]; - - region = data->plat_data->iova_region + domid; - larb_mmu->bank[portid] = upper_32_bits(region->iova_base); - - dev_dbg(dev, "%s iommu for larb(%s) port %d dom %d bank %d.\n", - enable ? "enable" : "disable", dev_name(larb_mmu->dev), - portid, domid, larb_mmu->bank[portid]); - - if (enable) - larb_mmu->mmu |= MTK_SMI_MMU_EN(portid); - else - larb_mmu->mmu &= ~MTK_SMI_MMU_EN(portid); + if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_MM)) { + larb_mmu = &data->larb_imu[larbid]; + + region = data->plat_data->iova_region + regionid; + larb_mmu->bank[portid] = upper_32_bits(region->iova_base); + + dev_dbg(dev, "%s iommu for larb(%s) port %d region %d rgn-bank %d.\n", + enable ? "enable" : "disable", dev_name(larb_mmu->dev), + portid, regionid, larb_mmu->bank[portid]); + + if (enable) + larb_mmu->mmu |= MTK_SMI_MMU_EN(portid); + else + larb_mmu->mmu &= ~MTK_SMI_MMU_EN(portid); + } else if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_INFRA)) { + peri_mmuen_msk = BIT(portid); + /* PCI dev has only one output id, enable the next writing bit for PCIe */ + if (dev_is_pci(dev)) + peri_mmuen_msk |= BIT(portid + 1); + + peri_mmuen = enable ? peri_mmuen_msk : 0; + ret = regmap_update_bits(data->pericfg, PERICFG_IOMMU_1, + peri_mmuen_msk, peri_mmuen); + if (ret) + dev_err(dev, "%s iommu(%s) inframaster 0x%x fail(%d).\n", + enable ? "enable" : "disable", + dev_name(data->dev), peri_mmuen_msk, ret); + } } + return ret; } static int mtk_iommu_domain_finalise(struct mtk_iommu_domain *dom, struct mtk_iommu_data *data, - unsigned int domid) + unsigned int region_id) { const struct mtk_iommu_iova_region *region; - - /* Use the exist domain as there is only one pgtable here. */ - if (data->m4u_dom) { - dom->iop = data->m4u_dom->iop; - dom->cfg = data->m4u_dom->cfg; - dom->domain.pgsize_bitmap = data->m4u_dom->cfg.pgsize_bitmap; + struct mtk_iommu_domain *m4u_dom; + + /* Always use bank0 in sharing pgtable case */ + m4u_dom = data->bank[0].m4u_dom; + if (m4u_dom) { + dom->iop = m4u_dom->iop; + dom->cfg = m4u_dom->cfg; + dom->domain.pgsize_bitmap = m4u_dom->cfg.pgsize_bitmap; goto update_iova_region; } @@ -417,7 +612,7 @@ static int mtk_iommu_domain_finalise(struct mtk_iommu_domain *dom, update_iova_region: /* Update the iova region for this domain */ - region = data->plat_data->iova_region + domid; + region = data->plat_data->iova_region + region_id; dom->domain.geometry.aperture_start = region->iova_base; dom->domain.geometry.aperture_end = region->iova_base + region->size - 1; dom->domain.geometry.force_aperture = true; @@ -428,12 +623,13 @@ static struct iommu_domain *mtk_iommu_domain_alloc(unsigned type) { struct mtk_iommu_domain *dom; - if (type != IOMMU_DOMAIN_DMA) + if (type != IOMMU_DOMAIN_DMA && type != IOMMU_DOMAIN_UNMANAGED) return NULL; dom = kzalloc(sizeof(*dom), GFP_KERNEL); if (!dom) return NULL; + mutex_init(&dom->mutex); return &dom->domain; } @@ -446,40 +642,60 @@ static void mtk_iommu_domain_free(struct iommu_domain *domain) static int mtk_iommu_attach_device(struct iommu_domain *domain, struct device *dev) { - struct mtk_iommu_data *data = dev_iommu_priv_get(dev); + struct mtk_iommu_data *data = dev_iommu_priv_get(dev), *frstdata; struct mtk_iommu_domain *dom = to_mtk_domain(domain); + struct list_head *hw_list = data->hw_list; struct device *m4udev = data->dev; - int ret, domid; + struct mtk_iommu_bank_data *bank; + unsigned int bankid; + int ret, region_id; - domid = mtk_iommu_get_domain_id(dev, data->plat_data); - if (domid < 0) - return domid; + region_id = mtk_iommu_get_iova_region_id(dev, data->plat_data); + if (region_id < 0) + return region_id; - if (!dom->data) { - if (mtk_iommu_domain_finalise(dom, data, domid)) + bankid = mtk_iommu_get_bank_id(dev, data->plat_data); + mutex_lock(&dom->mutex); + if (!dom->bank) { + /* Data is in the frstdata in sharing pgtable case. */ + frstdata = mtk_iommu_get_frst_data(hw_list); + + ret = mtk_iommu_domain_finalise(dom, frstdata, region_id); + if (ret) { + mutex_unlock(&dom->mutex); return -ENODEV; - dom->data = data; + } + dom->bank = &data->bank[bankid]; } + mutex_unlock(&dom->mutex); - if (!data->m4u_dom) { /* Initialize the M4U HW */ + mutex_lock(&data->mutex); + bank = &data->bank[bankid]; + if (!bank->m4u_dom) { /* Initialize the M4U HW for each a BANK */ ret = pm_runtime_resume_and_get(m4udev); - if (ret < 0) - return ret; + if (ret < 0) { + dev_err(m4udev, "pm get fail(%d) in attach.\n", ret); + goto err_unlock; + } - ret = mtk_iommu_hw_init(data); + ret = mtk_iommu_hw_init(data, bankid); if (ret) { pm_runtime_put(m4udev); - return ret; + goto err_unlock; } - data->m4u_dom = dom; + bank->m4u_dom = dom; writel(dom->cfg.arm_v7s_cfg.ttbr & MMU_PT_ADDR_MASK, - data->base + REG_MMU_PT_BASE_ADDR); + bank->base + REG_MMU_PT_BASE_ADDR); pm_runtime_put(m4udev); } + mutex_unlock(&data->mutex); - mtk_iommu_config(data, dev, true, domid); - return 0; + return mtk_iommu_config(data, dev, true, region_id); + +err_unlock: + mutex_unlock(&data->mutex); + return ret; } static void mtk_iommu_detach_device(struct iommu_domain *domain, @@ -496,7 +712,7 @@ static int mtk_iommu_map(struct iommu_domain *domain, unsigned long iova, struct mtk_iommu_domain *dom = to_mtk_domain(domain); /* The "4GB mode" M4U physically can not use the lower remap of Dram. */ - if (dom->data->enable_4GB) + if (dom->bank->parent_data->enable_4GB) paddr |= BIT_ULL(32); /* Synchronize with the tlb_lock */ @@ -517,7 +733,7 @@ static void mtk_iommu_flush_iotlb_all(struct iommu_domain *domain) { struct mtk_iommu_domain *dom = to_mtk_domain(domain); - mtk_iommu_tlb_flush_all(dom->data); + mtk_iommu_tlb_flush_all(dom->bank->parent_data); } static void mtk_iommu_iotlb_sync(struct iommu_domain *domain, @@ -526,8 +742,7 @@ static void mtk_iommu_iotlb_sync(struct iommu_domain *domain, struct mtk_iommu_domain *dom = to_mtk_domain(domain); size_t length = gather->end - gather->start + 1; - mtk_iommu_tlb_flush_range_sync(gather->start, length, gather->pgsize, - dom->data); + mtk_iommu_tlb_flush_range_sync(gather->start, length, dom->bank); } static void mtk_iommu_sync_map(struct iommu_domain *domain, unsigned long iova, @@ -535,7 +750,7 @@ static void mtk_iommu_sync_map(struct iommu_domain *domain, unsigned long iova, { struct mtk_iommu_domain *dom = to_mtk_domain(domain); - mtk_iommu_tlb_flush_range_sync(iova, size, size, dom->data); + mtk_iommu_tlb_flush_range_sync(iova, size, dom->bank); } static phys_addr_t mtk_iommu_iova_to_phys(struct iommu_domain *domain, @@ -546,7 +761,7 @@ static phys_addr_t mtk_iommu_iova_to_phys(struct iommu_domain *domain, pa = dom->iop->iova_to_phys(dom->iop, iova); if (IS_ENABLED(CONFIG_PHYS_ADDR_T_64BIT) && - dom->data->enable_4GB && + dom->bank->parent_data->enable_4GB && pa >= MTK_IOMMU_4GB_MODE_REMAP_BASE) pa &= ~BIT_ULL(32); @@ -566,12 +781,18 @@ static struct iommu_device *mtk_iommu_probe_device(struct device *dev) data = dev_iommu_priv_get(dev); + if (!MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_MM)) + return &data->iommu; + /* * Link the consumer device with the smi-larb device(supplier). * The device that connects with each a larb is a independent HW. * All the ports in each a device should be in the same larbs. */ larbid = MTK_M4U_TO_LARB(fwspec->ids[0]); + if (larbid >= MTK_LARB_NR_MAX) + return ERR_PTR(-EINVAL); + for (i = 1; i < fwspec->num_ids; i++) { larbidx = MTK_M4U_TO_LARB(fwspec->ids[i]); if (larbid != larbidx) { @@ -581,6 +802,9 @@ static struct iommu_device *mtk_iommu_probe_device(struct device *dev) } } larbdev = data->larb_imu[larbid].dev; + if (!larbdev) + return ERR_PTR(-EINVAL); + link = device_link_add(dev, larbdev, DL_FLAG_PM_RUNTIME | DL_FLAG_STATELESS); if (!link) @@ -599,34 +823,55 @@ static void mtk_iommu_release_device(struct device *dev) return; data = dev_iommu_priv_get(dev); - larbid = MTK_M4U_TO_LARB(fwspec->ids[0]); - larbdev = data->larb_imu[larbid].dev; - device_link_remove(dev, larbdev); + if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_MM)) { + larbid = MTK_M4U_TO_LARB(fwspec->ids[0]); + larbdev = data->larb_imu[larbid].dev; + device_link_remove(dev, larbdev); + } iommu_fwspec_free(dev); } +static int mtk_iommu_get_group_id(struct device *dev, const struct mtk_iommu_plat_data *plat_data) +{ + unsigned int bankid; + + /* + * If the bank function is enabled, each bank is a iommu group/domain. + * Otherwise, each iova region is a iommu group/domain. + */ + bankid = mtk_iommu_get_bank_id(dev, plat_data); + if (bankid) + return bankid; + + return mtk_iommu_get_iova_region_id(dev, plat_data); +} + static struct iommu_group *mtk_iommu_device_group(struct device *dev) { - struct mtk_iommu_data *data = mtk_iommu_get_m4u_data(); + struct mtk_iommu_data *c_data = dev_iommu_priv_get(dev), *data; + struct list_head *hw_list = c_data->hw_list; struct iommu_group *group; - int domid; + int groupid; + data = mtk_iommu_get_frst_data(hw_list); if (!data) return ERR_PTR(-ENODEV); - domid = mtk_iommu_get_domain_id(dev, data->plat_data); - if (domid < 0) - return ERR_PTR(domid); + groupid = mtk_iommu_get_group_id(dev, data->plat_data); + if (groupid < 0) + return ERR_PTR(groupid); - group = data->m4u_group[domid]; + mutex_lock(&data->mutex); + group = data->m4u_group[groupid]; if (!group) { group = iommu_group_alloc(); if (!IS_ERR(group)) - data->m4u_group[domid] = group; + data->m4u_group[groupid] = group; } else { iommu_group_ref_get(group); } + mutex_unlock(&data->mutex); return group; } @@ -656,14 +901,14 @@ static void mtk_iommu_get_resv_regions(struct device *dev, struct list_head *head) { struct mtk_iommu_data *data = dev_iommu_priv_get(dev); - unsigned int domid = mtk_iommu_get_domain_id(dev, data->plat_data), i; + unsigned int regionid = mtk_iommu_get_iova_region_id(dev, data->plat_data), i; const struct mtk_iommu_iova_region *resv, *curdom; struct iommu_resv_region *region; int prot = IOMMU_WRITE | IOMMU_READ; - if ((int)domid < 0) + if ((int)regionid < 0) return; - curdom = data->plat_data->iova_region + domid; + curdom = data->plat_data->iova_region + regionid; for (i = 0; i < data->plat_data->iova_region_nr; i++) { resv = data->plat_data->iova_region + i; @@ -704,42 +949,24 @@ static const struct iommu_ops mtk_iommu_ops = { } }; -static int mtk_iommu_hw_init(const struct mtk_iommu_data *data) +static int mtk_iommu_hw_init(const struct mtk_iommu_data *data, unsigned int bankid) { + const struct mtk_iommu_bank_data *bankx = &data->bank[bankid]; + const struct mtk_iommu_bank_data *bank0 = &data->bank[0]; u32 regval; + /* + * Global control settings are in bank0. May re-init these global registers + * since no sure if there is bank0 consumers. + */ if (data->plat_data->m4u_plat == M4U_MT8173) { regval = F_MMU_PREFETCH_RT_REPLACE_MOD | F_MMU_TF_PROT_TO_PROGRAM_ADDR_MT8173; } else { - regval = readl_relaxed(data->base + REG_MMU_CTRL_REG); + regval = readl_relaxed(bank0->base + REG_MMU_CTRL_REG); regval |= F_MMU_TF_PROT_TO_PROGRAM_ADDR; } - writel_relaxed(regval, data->base + REG_MMU_CTRL_REG); - - regval = F_L2_MULIT_HIT_EN | - F_TABLE_WALK_FAULT_INT_EN | - F_PREETCH_FIFO_OVERFLOW_INT_EN | - F_MISS_FIFO_OVERFLOW_INT_EN | - F_PREFETCH_FIFO_ERR_INT_EN | - F_MISS_FIFO_ERR_INT_EN; - writel_relaxed(regval, data->base + REG_MMU_INT_CONTROL0); - - regval = F_INT_TRANSLATION_FAULT | - F_INT_MAIN_MULTI_HIT_FAULT | - F_INT_INVALID_PA_FAULT | - F_INT_ENTRY_REPLACEMENT_FAULT | - F_INT_TLB_MISS_FAULT | - F_INT_MISS_TRANSACTION_FIFO_FAULT | - F_INT_PRETETCH_TRANSATION_FIFO_FAULT; - writel_relaxed(regval, data->base + REG_MMU_INT_MAIN_CONTROL); - - if (MTK_IOMMU_HAS_FLAG(data->plat_data, HAS_LEGACY_IVRP_PADDR)) - regval = (data->protect_base >> 1) | (data->enable_4GB << 31); - else - regval = lower_32_bits(data->protect_base) | - upper_32_bits(data->protect_base); - writel_relaxed(regval, data->base + REG_MMU_IVRP_PADDR); + writel_relaxed(regval, bank0->base + REG_MMU_CTRL_REG); if (data->enable_4GB && MTK_IOMMU_HAS_FLAG(data->plat_data, HAS_VLD_PA_RNG)) { @@ -748,31 +975,61 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data *data) * 0x1_0000_0000 to 0x1_ffff_ffff. here record bit[32:30]. */ regval = F_MMU_VLD_PA_RNG(7, 4); - writel_relaxed(regval, data->base + REG_MMU_VLD_PA_RNG); + writel_relaxed(regval, bank0->base + REG_MMU_VLD_PA_RNG); } - writel_relaxed(0, data->base + REG_MMU_DCM_DIS); + if (MTK_IOMMU_HAS_FLAG(data->plat_data, DCM_DISABLE)) + writel_relaxed(F_MMU_DCM, bank0->base + REG_MMU_DCM_DIS); + else + writel_relaxed(0, bank0->base + REG_MMU_DCM_DIS); + if (MTK_IOMMU_HAS_FLAG(data->plat_data, WR_THROT_EN)) { /* write command throttling mode */ - regval = readl_relaxed(data->base + REG_MMU_WR_LEN_CTRL); + regval = readl_relaxed(bank0->base + REG_MMU_WR_LEN_CTRL); regval &= ~F_MMU_WR_THROT_DIS_MASK; - writel_relaxed(regval, data->base + REG_MMU_WR_LEN_CTRL); + writel_relaxed(regval, bank0->base + REG_MMU_WR_LEN_CTRL); } if (MTK_IOMMU_HAS_FLAG(data->plat_data, RESET_AXI)) { /* The register is called STANDARD_AXI_MODE in this case */ regval = 0; } else { - regval = readl_relaxed(data->base + REG_MMU_MISC_CTRL); - regval &= ~F_MMU_STANDARD_AXI_MODE_MASK; + regval = readl_relaxed(bank0->base + REG_MMU_MISC_CTRL); + if (!MTK_IOMMU_HAS_FLAG(data->plat_data, STD_AXI_MODE)) + regval &= ~F_MMU_STANDARD_AXI_MODE_MASK; if (MTK_IOMMU_HAS_FLAG(data->plat_data, OUT_ORDER_WR_EN)) regval &= ~F_MMU_IN_ORDER_WR_EN_MASK; } - writel_relaxed(regval, data->base + REG_MMU_MISC_CTRL); + writel_relaxed(regval, bank0->base + REG_MMU_MISC_CTRL); - if (devm_request_irq(data->dev, data->irq, mtk_iommu_isr, 0, - dev_name(data->dev), (void *)data)) { - writel_relaxed(0, data->base + REG_MMU_PT_BASE_ADDR); - dev_err(data->dev, "Failed @ IRQ-%d Request\n", data->irq); + /* Independent settings for each bank */ + regval = F_L2_MULIT_HIT_EN | + F_TABLE_WALK_FAULT_INT_EN | + F_PREETCH_FIFO_OVERFLOW_INT_EN | + F_MISS_FIFO_OVERFLOW_INT_EN | + F_PREFETCH_FIFO_ERR_INT_EN | + F_MISS_FIFO_ERR_INT_EN; + writel_relaxed(regval, bankx->base + REG_MMU_INT_CONTROL0); + + regval = F_INT_TRANSLATION_FAULT | + F_INT_MAIN_MULTI_HIT_FAULT | + F_INT_INVALID_PA_FAULT | + F_INT_ENTRY_REPLACEMENT_FAULT | + F_INT_TLB_MISS_FAULT | + F_INT_MISS_TRANSACTION_FIFO_FAULT | + F_INT_PRETETCH_TRANSATION_FIFO_FAULT; + writel_relaxed(regval, bankx->base + REG_MMU_INT_MAIN_CONTROL); + + if (MTK_IOMMU_HAS_FLAG(data->plat_data, HAS_LEGACY_IVRP_PADDR)) + regval = (data->protect_base >> 1) | (data->enable_4GB << 31); + else + regval = lower_32_bits(data->protect_base) | + upper_32_bits(data->protect_base); + writel_relaxed(regval, bankx->base + REG_MMU_IVRP_PADDR); + + if (devm_request_irq(bankx->parent_dev, bankx->irq, mtk_iommu_isr, 0, + dev_name(bankx->parent_dev), (void *)bankx)) { + writel_relaxed(0, bankx->base + REG_MMU_PT_BASE_ADDR); + dev_err(bankx->parent_dev, "Failed @ IRQ-%d Request\n", bankx->irq); return -ENODEV; } @@ -784,21 +1041,91 @@ static const struct component_master_ops mtk_iommu_com_ops = { .unbind = mtk_iommu_unbind, }; +static int mtk_iommu_mm_dts_parse(struct device *dev, struct component_match **match, + struct mtk_iommu_data *data) +{ + struct device_node *larbnode, *smicomm_node, *smi_subcomm_node; + struct platform_device *plarbdev; + struct device_link *link; + int i, larb_nr, ret; + + larb_nr = of_count_phandle_with_args(dev->of_node, "mediatek,larbs", NULL); + if (larb_nr < 0) + return larb_nr; + + for (i = 0; i < larb_nr; i++) { + u32 id; + + larbnode = of_parse_phandle(dev->of_node, "mediatek,larbs", i); + if (!larbnode) + return -EINVAL; + + if (!of_device_is_available(larbnode)) { + of_node_put(larbnode); + continue; + } + + ret = of_property_read_u32(larbnode, "mediatek,larb-id", &id); + if (ret)/* The id is consecutive if there is no this property */ + id = i; + + plarbdev = of_find_device_by_node(larbnode); + if (!plarbdev) { + of_node_put(larbnode); + return -ENODEV; + } + if (!plarbdev->dev.driver) { + of_node_put(larbnode); + return -EPROBE_DEFER; + } + data->larb_imu[id].dev = &plarbdev->dev; + + component_match_add_release(dev, match, component_release_of, + component_compare_of, larbnode); + } + + /* Get smi-(sub)-common dev from the last larb. */ + smi_subcomm_node = of_parse_phandle(larbnode, "mediatek,smi", 0); + if (!smi_subcomm_node) + return -EINVAL; + + /* + * It may have two level smi-common. the node is smi-sub-common if it + * has a new mediatek,smi property. otherwise it is smi-commmon. + */ + smicomm_node = of_parse_phandle(smi_subcomm_node, "mediatek,smi", 0); + if (smicomm_node) + of_node_put(smi_subcomm_node); + else + smicomm_node = smi_subcomm_node; + + plarbdev = of_find_device_by_node(smicomm_node); + of_node_put(smicomm_node); + data->smicomm_dev = &plarbdev->dev; + + link = device_link_add(data->smicomm_dev, dev, + DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME); + if (!link) { + dev_err(dev, "Unable to link %s.\n", dev_name(data->smicomm_dev)); + return -EINVAL; + } + return 0; +} + static int mtk_iommu_probe(struct platform_device *pdev) { struct mtk_iommu_data *data; struct device *dev = &pdev->dev; - struct device_node *larbnode, *smicomm_node; - struct platform_device *plarbdev; - struct device_link *link; struct resource *res; resource_size_t ioaddr; struct component_match *match = NULL; struct regmap *infracfg; void *protect; - int i, larb_nr, ret; + int ret, banks_num, i = 0; u32 val; char *p; + struct mtk_iommu_bank_data *bank; + void __iomem *base; data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); if (!data) @@ -835,15 +1162,36 @@ static int mtk_iommu_probe(struct platform_device *pdev) data->enable_4GB = !!(val & F_DDR_4GB_SUPPORT_EN); } + banks_num = data->plat_data->banks_num; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - data->base = devm_ioremap_resource(dev, res); - if (IS_ERR(data->base)) - return PTR_ERR(data->base); + if (resource_size(res) < banks_num * MTK_IOMMU_BANK_SZ) { + dev_err(dev, "banknr %d. res %pR is not enough.\n", banks_num, res); + return -EINVAL; + } + base = devm_ioremap_resource(dev, res); + if (IS_ERR(base)) + return PTR_ERR(base); ioaddr = res->start; - data->irq = platform_get_irq(pdev, 0); - if (data->irq < 0) - return data->irq; + data->bank = devm_kmalloc(dev, banks_num * sizeof(*data->bank), GFP_KERNEL); + if (!data->bank) + return -ENOMEM; + + do { + if (!data->plat_data->banks_enable[i]) + continue; + bank = &data->bank[i]; + bank->id = i; + bank->base = base + i * MTK_IOMMU_BANK_SZ; + bank->m4u_dom = NULL; + + bank->irq = platform_get_irq(pdev, i); + if (bank->irq < 0) + return bank->irq; + bank->parent_dev = dev; + bank->parent_data = data; + spin_lock_init(&bank->tlb_lock); + } while (++i < banks_num); if (MTK_IOMMU_HAS_FLAG(data->plat_data, HAS_BCLK)) { data->bclk = devm_clk_get(dev, "bclk"); @@ -851,62 +1199,27 @@ static int mtk_iommu_probe(struct platform_device *pdev) return PTR_ERR(data->bclk); } - larb_nr = of_count_phandle_with_args(dev->of_node, - "mediatek,larbs", NULL); - if (larb_nr < 0) - return larb_nr; - - for (i = 0; i < larb_nr; i++) { - u32 id; - - larbnode = of_parse_phandle(dev->of_node, "mediatek,larbs", i); - if (!larbnode) - return -EINVAL; - - if (!of_device_is_available(larbnode)) { - of_node_put(larbnode); - continue; - } - - ret = of_property_read_u32(larbnode, "mediatek,larb-id", &id); - if (ret)/* The id is consecutive if there is no this property */ - id = i; + pm_runtime_enable(dev); - plarbdev = of_find_device_by_node(larbnode); - if (!plarbdev) { - of_node_put(larbnode); - return -ENODEV; + if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_MM)) { + ret = mtk_iommu_mm_dts_parse(dev, &match, data); + if (ret) { + dev_err(dev, "mm dts parse fail(%d).", ret); + goto out_runtime_disable; } - if (!plarbdev->dev.driver) { - of_node_put(larbnode); - return -EPROBE_DEFER; + } else if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_INFRA) && + data->plat_data->pericfg_comp_str) { + infracfg = syscon_regmap_lookup_by_compatible(data->plat_data->pericfg_comp_str); + if (IS_ERR(infracfg)) { + ret = PTR_ERR(infracfg); + goto out_runtime_disable; } - data->larb_imu[id].dev = &plarbdev->dev; - - component_match_add_release(dev, &match, component_release_of, - component_compare_of, larbnode); - } - - /* Get smi-common dev from the last larb. */ - smicomm_node = of_parse_phandle(larbnode, "mediatek,smi", 0); - if (!smicomm_node) - return -EINVAL; - - plarbdev = of_find_device_by_node(smicomm_node); - of_node_put(smicomm_node); - data->smicomm_dev = &plarbdev->dev; - - pm_runtime_enable(dev); - link = device_link_add(data->smicomm_dev, dev, - DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME); - if (!link) { - dev_err(dev, "Unable to link %s.\n", dev_name(data->smicomm_dev)); - ret = -EINVAL; - goto out_runtime_disable; + data->pericfg = infracfg; } platform_set_drvdata(pdev, data); + mutex_init(&data->mutex); ret = iommu_device_sysfs_add(&data->iommu, dev, NULL, "mtk-iommu.%pa", &ioaddr); @@ -917,8 +1230,14 @@ static int mtk_iommu_probe(struct platform_device *pdev) if (ret) goto out_sysfs_remove; - spin_lock_init(&data->tlb_lock); - list_add_tail(&data->list, &m4ulist); + if (MTK_IOMMU_HAS_FLAG(data->plat_data, SHARE_PGTABLE)) { + list_add_tail(&data->list, data->plat_data->hw_list); + data->hw_list = data->plat_data->hw_list; + } else { + INIT_LIST_HEAD(&data->hw_list_head); + list_add_tail(&data->list, &data->hw_list_head); + data->hw_list = &data->hw_list_head; + } if (!iommu_present(&platform_bus_type)) { ret = bus_set_iommu(&platform_bus_type, &mtk_iommu_ops); @@ -926,9 +1245,20 @@ static int mtk_iommu_probe(struct platform_device *pdev) goto out_list_del; } - ret = component_master_add_with_match(dev, &mtk_iommu_com_ops, match); - if (ret) - goto out_bus_set_null; + if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_MM)) { + ret = component_master_add_with_match(dev, &mtk_iommu_com_ops, match); + if (ret) + goto out_bus_set_null; + } else if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_INFRA) && + MTK_IOMMU_HAS_FLAG(data->plat_data, IFA_IOMMU_PCIE_SUPPORT)) { +#ifdef CONFIG_PCI + if (!iommu_present(&pci_bus_type)) { + ret = bus_set_iommu(&pci_bus_type, &mtk_iommu_ops); + if (ret) /* PCIe fail don't affect platform_bus. */ + goto out_list_del; + } +#endif + } return ret; out_bus_set_null: @@ -939,7 +1269,8 @@ out_list_del: out_sysfs_remove: iommu_device_sysfs_remove(&data->iommu); out_link_remove: - device_link_remove(data->smicomm_dev, dev); + if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_MM)) + device_link_remove(data->smicomm_dev, dev); out_runtime_disable: pm_runtime_disable(dev); return ret; @@ -948,18 +1279,30 @@ out_runtime_disable: static int mtk_iommu_remove(struct platform_device *pdev) { struct mtk_iommu_data *data = platform_get_drvdata(pdev); + struct mtk_iommu_bank_data *bank; + int i; iommu_device_sysfs_remove(&data->iommu); iommu_device_unregister(&data->iommu); - if (iommu_present(&platform_bus_type)) - bus_set_iommu(&platform_bus_type, NULL); + list_del(&data->list); - clk_disable_unprepare(data->bclk); - device_link_remove(data->smicomm_dev, &pdev->dev); + if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_MM)) { + device_link_remove(data->smicomm_dev, &pdev->dev); + component_master_del(&pdev->dev, &mtk_iommu_com_ops); + } else if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_INFRA) && + MTK_IOMMU_HAS_FLAG(data->plat_data, IFA_IOMMU_PCIE_SUPPORT)) { +#ifdef CONFIG_PCI + bus_set_iommu(&pci_bus_type, NULL); +#endif + } pm_runtime_disable(&pdev->dev); - devm_free_irq(&pdev->dev, data->irq, data); - component_master_del(&pdev->dev, &mtk_iommu_com_ops); + for (i = 0; i < data->plat_data->banks_num; i++) { + bank = &data->bank[i]; + if (!bank->m4u_dom) + continue; + devm_free_irq(&pdev->dev, bank->irq, bank); + } return 0; } @@ -967,16 +1310,23 @@ static int __maybe_unused mtk_iommu_runtime_suspend(struct device *dev) { struct mtk_iommu_data *data = dev_get_drvdata(dev); struct mtk_iommu_suspend_reg *reg = &data->reg; - void __iomem *base = data->base; + void __iomem *base; + int i = 0; + base = data->bank[i].base; reg->wr_len_ctrl = readl_relaxed(base + REG_MMU_WR_LEN_CTRL); reg->misc_ctrl = readl_relaxed(base + REG_MMU_MISC_CTRL); reg->dcm_dis = readl_relaxed(base + REG_MMU_DCM_DIS); reg->ctrl_reg = readl_relaxed(base + REG_MMU_CTRL_REG); - reg->int_control0 = readl_relaxed(base + REG_MMU_INT_CONTROL0); - reg->int_main_control = readl_relaxed(base + REG_MMU_INT_MAIN_CONTROL); - reg->ivrp_paddr = readl_relaxed(base + REG_MMU_IVRP_PADDR); reg->vld_pa_rng = readl_relaxed(base + REG_MMU_VLD_PA_RNG); + do { + if (!data->plat_data->banks_enable[i]) + continue; + base = data->bank[i].base; + reg->int_control[i] = readl_relaxed(base + REG_MMU_INT_CONTROL0); + reg->int_main_control[i] = readl_relaxed(base + REG_MMU_INT_MAIN_CONTROL); + reg->ivrp_paddr[i] = readl_relaxed(base + REG_MMU_IVRP_PADDR); + } while (++i < data->plat_data->banks_num); clk_disable_unprepare(data->bclk); return 0; } @@ -985,9 +1335,9 @@ static int __maybe_unused mtk_iommu_runtime_resume(struct device *dev) { struct mtk_iommu_data *data = dev_get_drvdata(dev); struct mtk_iommu_suspend_reg *reg = &data->reg; - struct mtk_iommu_domain *m4u_dom = data->m4u_dom; - void __iomem *base = data->base; - int ret; + struct mtk_iommu_domain *m4u_dom; + void __iomem *base; + int ret, i = 0; ret = clk_prepare_enable(data->bclk); if (ret) { @@ -999,18 +1349,26 @@ static int __maybe_unused mtk_iommu_runtime_resume(struct device *dev) * Uppon first resume, only enable the clk and return, since the values of the * registers are not yet set. */ - if (!m4u_dom) + if (!reg->wr_len_ctrl) return 0; + base = data->bank[i].base; writel_relaxed(reg->wr_len_ctrl, base + REG_MMU_WR_LEN_CTRL); writel_relaxed(reg->misc_ctrl, base + REG_MMU_MISC_CTRL); writel_relaxed(reg->dcm_dis, base + REG_MMU_DCM_DIS); writel_relaxed(reg->ctrl_reg, base + REG_MMU_CTRL_REG); - writel_relaxed(reg->int_control0, base + REG_MMU_INT_CONTROL0); - writel_relaxed(reg->int_main_control, base + REG_MMU_INT_MAIN_CONTROL); - writel_relaxed(reg->ivrp_paddr, base + REG_MMU_IVRP_PADDR); writel_relaxed(reg->vld_pa_rng, base + REG_MMU_VLD_PA_RNG); - writel(m4u_dom->cfg.arm_v7s_cfg.ttbr & MMU_PT_ADDR_MASK, base + REG_MMU_PT_BASE_ADDR); + do { + m4u_dom = data->bank[i].m4u_dom; + if (!data->plat_data->banks_enable[i] || !m4u_dom) + continue; + base = data->bank[i].base; + writel_relaxed(reg->int_control[i], base + REG_MMU_INT_CONTROL0); + writel_relaxed(reg->int_main_control[i], base + REG_MMU_INT_MAIN_CONTROL); + writel_relaxed(reg->ivrp_paddr[i], base + REG_MMU_IVRP_PADDR); + writel(m4u_dom->cfg.arm_v7s_cfg.ttbr & MMU_PT_ADDR_MASK, + base + REG_MMU_PT_BASE_ADDR); + } while (++i < data->plat_data->banks_num); /* * Users may allocate dma buffer before they call pm_runtime_get, @@ -1029,17 +1387,24 @@ static const struct dev_pm_ops mtk_iommu_pm_ops = { static const struct mtk_iommu_plat_data mt2712_data = { .m4u_plat = M4U_MT2712, - .flags = HAS_4GB_MODE | HAS_BCLK | HAS_VLD_PA_RNG, + .flags = HAS_4GB_MODE | HAS_BCLK | HAS_VLD_PA_RNG | SHARE_PGTABLE | + MTK_IOMMU_TYPE_MM, + .hw_list = &m4ulist, .inv_sel_reg = REG_MMU_INV_SEL_GEN1, .iova_region = single_domain, + .banks_num = 1, + .banks_enable = {true}, .iova_region_nr = ARRAY_SIZE(single_domain), .larbid_remap = {{0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}}, }; static const struct mtk_iommu_plat_data mt6779_data = { .m4u_plat = M4U_MT6779, - .flags = HAS_SUB_COMM | OUT_ORDER_WR_EN | WR_THROT_EN, + .flags = HAS_SUB_COMM_2BITS | OUT_ORDER_WR_EN | WR_THROT_EN | + MTK_IOMMU_TYPE_MM, .inv_sel_reg = REG_MMU_INV_SEL_GEN2, + .banks_num = 1, + .banks_enable = {true}, .iova_region = single_domain, .iova_region_nr = ARRAY_SIZE(single_domain), .larbid_remap = {{0}, {1}, {2}, {3}, {5}, {7, 8}, {10}, {9}}, @@ -1047,8 +1412,10 @@ static const struct mtk_iommu_plat_data mt6779_data = { static const struct mtk_iommu_plat_data mt8167_data = { .m4u_plat = M4U_MT8167, - .flags = RESET_AXI | HAS_LEGACY_IVRP_PADDR, + .flags = RESET_AXI | HAS_LEGACY_IVRP_PADDR | MTK_IOMMU_TYPE_MM, .inv_sel_reg = REG_MMU_INV_SEL_GEN1, + .banks_num = 1, + .banks_enable = {true}, .iova_region = single_domain, .iova_region_nr = ARRAY_SIZE(single_domain), .larbid_remap = {{0}, {1}, {2}}, /* Linear mapping. */ @@ -1057,8 +1424,10 @@ static const struct mtk_iommu_plat_data mt8167_data = { static const struct mtk_iommu_plat_data mt8173_data = { .m4u_plat = M4U_MT8173, .flags = HAS_4GB_MODE | HAS_BCLK | RESET_AXI | - HAS_LEGACY_IVRP_PADDR, + HAS_LEGACY_IVRP_PADDR | MTK_IOMMU_TYPE_MM, .inv_sel_reg = REG_MMU_INV_SEL_GEN1, + .banks_num = 1, + .banks_enable = {true}, .iova_region = single_domain, .iova_region_nr = ARRAY_SIZE(single_domain), .larbid_remap = {{0}, {1}, {2}, {3}, {4}, {5}}, /* Linear mapping. */ @@ -1066,31 +1435,100 @@ static const struct mtk_iommu_plat_data mt8173_data = { static const struct mtk_iommu_plat_data mt8183_data = { .m4u_plat = M4U_MT8183, - .flags = RESET_AXI, + .flags = RESET_AXI | MTK_IOMMU_TYPE_MM, .inv_sel_reg = REG_MMU_INV_SEL_GEN1, + .banks_num = 1, + .banks_enable = {true}, .iova_region = single_domain, .iova_region_nr = ARRAY_SIZE(single_domain), .larbid_remap = {{0}, {4}, {5}, {6}, {7}, {2}, {3}, {1}}, }; +static const struct mtk_iommu_plat_data mt8186_data_mm = { + .m4u_plat = M4U_MT8186, + .flags = HAS_BCLK | HAS_SUB_COMM_2BITS | OUT_ORDER_WR_EN | + WR_THROT_EN | IOVA_34_EN | MTK_IOMMU_TYPE_MM, + .larbid_remap = {{0}, {1, MTK_INVALID_LARBID, 8}, {4}, {7}, {2}, {9, 11, 19, 20}, + {MTK_INVALID_LARBID, 14, 16}, + {MTK_INVALID_LARBID, 13, MTK_INVALID_LARBID, 17}}, + .inv_sel_reg = REG_MMU_INV_SEL_GEN2, + .banks_num = 1, + .banks_enable = {true}, + .iova_region = mt8192_multi_dom, + .iova_region_nr = ARRAY_SIZE(mt8192_multi_dom), +}; + static const struct mtk_iommu_plat_data mt8192_data = { .m4u_plat = M4U_MT8192, - .flags = HAS_BCLK | HAS_SUB_COMM | OUT_ORDER_WR_EN | - WR_THROT_EN | IOVA_34_EN, + .flags = HAS_BCLK | HAS_SUB_COMM_2BITS | OUT_ORDER_WR_EN | + WR_THROT_EN | IOVA_34_EN | MTK_IOMMU_TYPE_MM, .inv_sel_reg = REG_MMU_INV_SEL_GEN2, + .banks_num = 1, + .banks_enable = {true}, .iova_region = mt8192_multi_dom, .iova_region_nr = ARRAY_SIZE(mt8192_multi_dom), .larbid_remap = {{0}, {1}, {4, 5}, {7}, {2}, {9, 11, 19, 20}, {0, 14, 16}, {0, 13, 18, 17}}, }; +static const struct mtk_iommu_plat_data mt8195_data_infra = { + .m4u_plat = M4U_MT8195, + .flags = WR_THROT_EN | DCM_DISABLE | STD_AXI_MODE | PM_CLK_AO | + MTK_IOMMU_TYPE_INFRA | IFA_IOMMU_PCIE_SUPPORT, + .pericfg_comp_str = "mediatek,mt8195-pericfg_ao", + .inv_sel_reg = REG_MMU_INV_SEL_GEN2, + .banks_num = 5, + .banks_enable = {true, false, false, false, true}, + .banks_portmsk = {[0] = GENMASK(19, 16), /* PCIe */ + [4] = GENMASK(31, 20), /* USB */ + }, + .iova_region = single_domain, + .iova_region_nr = ARRAY_SIZE(single_domain), +}; + +static const struct mtk_iommu_plat_data mt8195_data_vdo = { + .m4u_plat = M4U_MT8195, + .flags = HAS_BCLK | HAS_SUB_COMM_2BITS | OUT_ORDER_WR_EN | + WR_THROT_EN | IOVA_34_EN | SHARE_PGTABLE | MTK_IOMMU_TYPE_MM, + .hw_list = &m4ulist, + .inv_sel_reg = REG_MMU_INV_SEL_GEN2, + .banks_num = 1, + .banks_enable = {true}, + .iova_region = mt8192_multi_dom, + .iova_region_nr = ARRAY_SIZE(mt8192_multi_dom), + .larbid_remap = {{2, 0}, {21}, {24}, {7}, {19}, {9, 10, 11}, + {13, 17, 15/* 17b */, 25}, {5}}, +}; + +static const struct mtk_iommu_plat_data mt8195_data_vpp = { + .m4u_plat = M4U_MT8195, + .flags = HAS_BCLK | HAS_SUB_COMM_3BITS | OUT_ORDER_WR_EN | + WR_THROT_EN | IOVA_34_EN | SHARE_PGTABLE | MTK_IOMMU_TYPE_MM, + .hw_list = &m4ulist, + .inv_sel_reg = REG_MMU_INV_SEL_GEN2, + .banks_num = 1, + .banks_enable = {true}, + .iova_region = mt8192_multi_dom, + .iova_region_nr = ARRAY_SIZE(mt8192_multi_dom), + .larbid_remap = {{1}, {3}, + {22, MTK_INVALID_LARBID, MTK_INVALID_LARBID, MTK_INVALID_LARBID, 23}, + {8}, {20}, {12}, + /* 16: 16a; 29: 16b; 30: CCUtop0; 31: CCUtop1 */ + {14, 16, 29, 26, 30, 31, 18}, + {4, MTK_INVALID_LARBID, MTK_INVALID_LARBID, MTK_INVALID_LARBID, 6}}, +}; + static const struct of_device_id mtk_iommu_of_ids[] = { { .compatible = "mediatek,mt2712-m4u", .data = &mt2712_data}, { .compatible = "mediatek,mt6779-m4u", .data = &mt6779_data}, { .compatible = "mediatek,mt8167-m4u", .data = &mt8167_data}, { .compatible = "mediatek,mt8173-m4u", .data = &mt8173_data}, { .compatible = "mediatek,mt8183-m4u", .data = &mt8183_data}, + { .compatible = "mediatek,mt8186-iommu-mm", .data = &mt8186_data_mm}, /* mm: m4u */ { .compatible = "mediatek,mt8192-m4u", .data = &mt8192_data}, + { .compatible = "mediatek,mt8195-iommu-infra", .data = &mt8195_data_infra}, + { .compatible = "mediatek,mt8195-iommu-vdo", .data = &mt8195_data_vdo}, + { .compatible = "mediatek,mt8195-iommu-vpp", .data = &mt8195_data_vpp}, {} }; diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h deleted file mode 100644 index b742432220c5ff4d4994dab7fa4ca58e91c53239..0000000000000000000000000000000000000000 --- a/drivers/iommu/mtk_iommu.h +++ /dev/null @@ -1,101 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (c) 2015-2016 MediaTek Inc. - * Author: Honghui Zhang - */ - -#ifndef _MTK_IOMMU_H_ -#define _MTK_IOMMU_H_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define MTK_LARB_COM_MAX 8 -#define MTK_LARB_SUBCOM_MAX 4 - -#define MTK_IOMMU_GROUP_MAX 8 - -struct mtk_iommu_suspend_reg { - union { - u32 standard_axi_mode;/* v1 */ - u32 misc_ctrl;/* v2 */ - }; - u32 dcm_dis; - u32 ctrl_reg; - u32 int_control0; - u32 int_main_control; - u32 ivrp_paddr; - u32 vld_pa_rng; - u32 wr_len_ctrl; -}; - -enum mtk_iommu_plat { - M4U_MT2701, - M4U_MT2712, - M4U_MT6779, - M4U_MT8167, - M4U_MT8173, - M4U_MT8183, - M4U_MT8192, -}; - -struct mtk_iommu_iova_region; - -struct mtk_iommu_plat_data { - enum mtk_iommu_plat m4u_plat; - u32 flags; - u32 inv_sel_reg; - - unsigned int iova_region_nr; - const struct mtk_iommu_iova_region *iova_region; - unsigned char larbid_remap[MTK_LARB_COM_MAX][MTK_LARB_SUBCOM_MAX]; -}; - -struct mtk_iommu_domain; - -struct mtk_iommu_data { - void __iomem *base; - int irq; - struct device *dev; - struct clk *bclk; - phys_addr_t protect_base; /* protect memory base */ - struct mtk_iommu_suspend_reg reg; - struct mtk_iommu_domain *m4u_dom; - struct iommu_group *m4u_group[MTK_IOMMU_GROUP_MAX]; - bool enable_4GB; - spinlock_t tlb_lock; /* lock for tlb range flush */ - - struct iommu_device iommu; - const struct mtk_iommu_plat_data *plat_data; - struct device *smicomm_dev; - - struct dma_iommu_mapping *mapping; /* For mtk_iommu_v1.c */ - - struct list_head list; - struct mtk_smi_larb_iommu larb_imu[MTK_LARB_NR_MAX]; -}; - -static inline int mtk_iommu_bind(struct device *dev) -{ - struct mtk_iommu_data *data = dev_get_drvdata(dev); - - return component_bind_all(dev, &data->larb_imu); -} - -static inline void mtk_iommu_unbind(struct device *dev) -{ - struct mtk_iommu_data *data = dev_get_drvdata(dev); - - component_unbind_all(dev, &data->larb_imu); -} - -#endif diff --git a/drivers/iommu/mtk_iommu_v1.c b/drivers/iommu/mtk_iommu_v1.c index ecff800656e6b6c7b8cd679af188fcc4c588ae0e..e1cb51b9866c38bd1a2176b6b7b35f46c9b4f963 100644 --- a/drivers/iommu/mtk_iommu_v1.c +++ b/drivers/iommu/mtk_iommu_v1.c @@ -7,7 +7,6 @@ * * Based on driver/iommu/mtk_iommu.c */ -#include #include #include #include @@ -28,10 +27,9 @@ #include #include #include -#include +#include #include #include -#include "mtk_iommu.h" #define REG_MMU_PT_BASE_ADDR 0x000 @@ -80,6 +78,7 @@ /* MTK generation one iommu HW only support 4K size mapping */ #define MT2701_IOMMU_PAGE_SHIFT 12 #define MT2701_IOMMU_PAGE_SIZE (1UL << MT2701_IOMMU_PAGE_SHIFT) +#define MT2701_LARB_NR_MAX 3 /* * MTK m4u support 4GB iova address space, and only support 4K page @@ -87,17 +86,53 @@ */ #define M2701_IOMMU_PGT_SIZE SZ_4M -struct mtk_iommu_domain { +struct mtk_iommu_v1_suspend_reg { + u32 standard_axi_mode; + u32 dcm_dis; + u32 ctrl_reg; + u32 int_control0; +}; + +struct mtk_iommu_v1_data { + void __iomem *base; + int irq; + struct device *dev; + struct clk *bclk; + phys_addr_t protect_base; /* protect memory base */ + struct mtk_iommu_v1_domain *m4u_dom; + + struct iommu_device iommu; + struct dma_iommu_mapping *mapping; + struct mtk_smi_larb_iommu larb_imu[MTK_LARB_NR_MAX]; + + struct mtk_iommu_v1_suspend_reg reg; +}; + +struct mtk_iommu_v1_domain { spinlock_t pgtlock; /* lock for page table */ struct iommu_domain domain; u32 *pgt_va; dma_addr_t pgt_pa; - struct mtk_iommu_data *data; + struct mtk_iommu_v1_data *data; }; -static struct mtk_iommu_domain *to_mtk_domain(struct iommu_domain *dom) +static int mtk_iommu_v1_bind(struct device *dev) +{ + struct mtk_iommu_v1_data *data = dev_get_drvdata(dev); + + return component_bind_all(dev, &data->larb_imu); +} + +static void mtk_iommu_v1_unbind(struct device *dev) +{ + struct mtk_iommu_v1_data *data = dev_get_drvdata(dev); + + component_unbind_all(dev, &data->larb_imu); +} + +static struct mtk_iommu_v1_domain *to_mtk_domain(struct iommu_domain *dom) { - return container_of(dom, struct mtk_iommu_domain, domain); + return container_of(dom, struct mtk_iommu_v1_domain, domain); } static const int mt2701_m4u_in_larb[] = { @@ -123,7 +158,7 @@ static inline int mt2701_m4u_to_port(int id) return id - mt2701_m4u_in_larb[larb]; } -static void mtk_iommu_tlb_flush_all(struct mtk_iommu_data *data) +static void mtk_iommu_v1_tlb_flush_all(struct mtk_iommu_v1_data *data) { writel_relaxed(F_INVLD_EN1 | F_INVLD_EN0, data->base + REG_MMU_INV_SEL); @@ -131,8 +166,8 @@ static void mtk_iommu_tlb_flush_all(struct mtk_iommu_data *data) wmb(); /* Make sure the tlb flush all done */ } -static void mtk_iommu_tlb_flush_range(struct mtk_iommu_data *data, - unsigned long iova, size_t size) +static void mtk_iommu_v1_tlb_flush_range(struct mtk_iommu_v1_data *data, + unsigned long iova, size_t size) { int ret; u32 tmp; @@ -150,16 +185,16 @@ static void mtk_iommu_tlb_flush_range(struct mtk_iommu_data *data, if (ret) { dev_warn(data->dev, "Partial TLB flush timed out, falling back to full flush\n"); - mtk_iommu_tlb_flush_all(data); + mtk_iommu_v1_tlb_flush_all(data); } /* Clear the CPE status */ writel_relaxed(0, data->base + REG_MMU_CPE_DONE); } -static irqreturn_t mtk_iommu_isr(int irq, void *dev_id) +static irqreturn_t mtk_iommu_v1_isr(int irq, void *dev_id) { - struct mtk_iommu_data *data = dev_id; - struct mtk_iommu_domain *dom = data->m4u_dom; + struct mtk_iommu_v1_data *data = dev_id; + struct mtk_iommu_v1_domain *dom = data->m4u_dom; u32 int_state, regval, fault_iova, fault_pa; unsigned int fault_larb, fault_port; @@ -189,13 +224,13 @@ static irqreturn_t mtk_iommu_isr(int irq, void *dev_id) regval |= F_INT_CLR_BIT; writel_relaxed(regval, data->base + REG_MMU_INT_CONTROL); - mtk_iommu_tlb_flush_all(data); + mtk_iommu_v1_tlb_flush_all(data); return IRQ_HANDLED; } -static void mtk_iommu_config(struct mtk_iommu_data *data, - struct device *dev, bool enable) +static void mtk_iommu_v1_config(struct mtk_iommu_v1_data *data, + struct device *dev, bool enable) { struct mtk_smi_larb_iommu *larb_mmu; unsigned int larbid, portid; @@ -217,9 +252,9 @@ static void mtk_iommu_config(struct mtk_iommu_data *data, } } -static int mtk_iommu_domain_finalise(struct mtk_iommu_data *data) +static int mtk_iommu_v1_domain_finalise(struct mtk_iommu_v1_data *data) { - struct mtk_iommu_domain *dom = data->m4u_dom; + struct mtk_iommu_v1_domain *dom = data->m4u_dom; spin_lock_init(&dom->pgtlock); @@ -235,9 +270,9 @@ static int mtk_iommu_domain_finalise(struct mtk_iommu_data *data) return 0; } -static struct iommu_domain *mtk_iommu_domain_alloc(unsigned type) +static struct iommu_domain *mtk_iommu_v1_domain_alloc(unsigned type) { - struct mtk_iommu_domain *dom; + struct mtk_iommu_v1_domain *dom; if (type != IOMMU_DOMAIN_UNMANAGED) return NULL; @@ -249,21 +284,20 @@ static struct iommu_domain *mtk_iommu_domain_alloc(unsigned type) return &dom->domain; } -static void mtk_iommu_domain_free(struct iommu_domain *domain) +static void mtk_iommu_v1_domain_free(struct iommu_domain *domain) { - struct mtk_iommu_domain *dom = to_mtk_domain(domain); - struct mtk_iommu_data *data = dom->data; + struct mtk_iommu_v1_domain *dom = to_mtk_domain(domain); + struct mtk_iommu_v1_data *data = dom->data; dma_free_coherent(data->dev, M2701_IOMMU_PGT_SIZE, dom->pgt_va, dom->pgt_pa); kfree(to_mtk_domain(domain)); } -static int mtk_iommu_attach_device(struct iommu_domain *domain, - struct device *dev) +static int mtk_iommu_v1_attach_device(struct iommu_domain *domain, struct device *dev) { - struct mtk_iommu_data *data = dev_iommu_priv_get(dev); - struct mtk_iommu_domain *dom = to_mtk_domain(domain); + struct mtk_iommu_v1_data *data = dev_iommu_priv_get(dev); + struct mtk_iommu_v1_domain *dom = to_mtk_domain(domain); struct dma_iommu_mapping *mtk_mapping; int ret; @@ -274,29 +308,28 @@ static int mtk_iommu_attach_device(struct iommu_domain *domain, if (!data->m4u_dom) { data->m4u_dom = dom; - ret = mtk_iommu_domain_finalise(data); + ret = mtk_iommu_v1_domain_finalise(data); if (ret) { data->m4u_dom = NULL; return ret; } } - mtk_iommu_config(data, dev, true); + mtk_iommu_v1_config(data, dev, true); return 0; } -static void mtk_iommu_detach_device(struct iommu_domain *domain, - struct device *dev) +static void mtk_iommu_v1_detach_device(struct iommu_domain *domain, struct device *dev) { - struct mtk_iommu_data *data = dev_iommu_priv_get(dev); + struct mtk_iommu_v1_data *data = dev_iommu_priv_get(dev); - mtk_iommu_config(data, dev, false); + mtk_iommu_v1_config(data, dev, false); } -static int mtk_iommu_map(struct iommu_domain *domain, unsigned long iova, - phys_addr_t paddr, size_t size, int prot, gfp_t gfp) +static int mtk_iommu_v1_map(struct iommu_domain *domain, unsigned long iova, + phys_addr_t paddr, size_t size, int prot, gfp_t gfp) { - struct mtk_iommu_domain *dom = to_mtk_domain(domain); + struct mtk_iommu_v1_domain *dom = to_mtk_domain(domain); unsigned int page_num = size >> MT2701_IOMMU_PAGE_SHIFT; unsigned long flags; unsigned int i; @@ -317,16 +350,15 @@ static int mtk_iommu_map(struct iommu_domain *domain, unsigned long iova, spin_unlock_irqrestore(&dom->pgtlock, flags); - mtk_iommu_tlb_flush_range(dom->data, iova, size); + mtk_iommu_v1_tlb_flush_range(dom->data, iova, size); return map_size == size ? 0 : -EEXIST; } -static size_t mtk_iommu_unmap(struct iommu_domain *domain, - unsigned long iova, size_t size, - struct iommu_iotlb_gather *gather) +static size_t mtk_iommu_v1_unmap(struct iommu_domain *domain, unsigned long iova, + size_t size, struct iommu_iotlb_gather *gather) { - struct mtk_iommu_domain *dom = to_mtk_domain(domain); + struct mtk_iommu_v1_domain *dom = to_mtk_domain(domain); unsigned long flags; u32 *pgt_base_iova = dom->pgt_va + (iova >> MT2701_IOMMU_PAGE_SHIFT); unsigned int page_num = size >> MT2701_IOMMU_PAGE_SHIFT; @@ -335,15 +367,14 @@ static size_t mtk_iommu_unmap(struct iommu_domain *domain, memset(pgt_base_iova, 0, page_num * sizeof(u32)); spin_unlock_irqrestore(&dom->pgtlock, flags); - mtk_iommu_tlb_flush_range(dom->data, iova, size); + mtk_iommu_v1_tlb_flush_range(dom->data, iova, size); return size; } -static phys_addr_t mtk_iommu_iova_to_phys(struct iommu_domain *domain, - dma_addr_t iova) +static phys_addr_t mtk_iommu_v1_iova_to_phys(struct iommu_domain *domain, dma_addr_t iova) { - struct mtk_iommu_domain *dom = to_mtk_domain(domain); + struct mtk_iommu_v1_domain *dom = to_mtk_domain(domain); unsigned long flags; phys_addr_t pa; @@ -355,17 +386,16 @@ static phys_addr_t mtk_iommu_iova_to_phys(struct iommu_domain *domain, return pa; } -static const struct iommu_ops mtk_iommu_ops; +static const struct iommu_ops mtk_iommu_v1_ops; /* * MTK generation one iommu HW only support one iommu domain, and all the client * sharing the same iova address space. */ -static int mtk_iommu_create_mapping(struct device *dev, - struct of_phandle_args *args) +static int mtk_iommu_v1_create_mapping(struct device *dev, struct of_phandle_args *args) { struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev); - struct mtk_iommu_data *data; + struct mtk_iommu_v1_data *data; struct platform_device *m4updev; struct dma_iommu_mapping *mtk_mapping; int ret; @@ -377,11 +407,11 @@ static int mtk_iommu_create_mapping(struct device *dev, } if (!fwspec) { - ret = iommu_fwspec_init(dev, &args->np->fwnode, &mtk_iommu_ops); + ret = iommu_fwspec_init(dev, &args->np->fwnode, &mtk_iommu_v1_ops); if (ret) return ret; fwspec = dev_iommu_fwspec_get(dev); - } else if (dev_iommu_fwspec_get(dev)->ops != &mtk_iommu_ops) { + } else if (dev_iommu_fwspec_get(dev)->ops != &mtk_iommu_v1_ops) { return -EINVAL; } @@ -413,16 +443,16 @@ static int mtk_iommu_create_mapping(struct device *dev, return 0; } -static int mtk_iommu_def_domain_type(struct device *dev) +static int mtk_iommu_v1_def_domain_type(struct device *dev) { return IOMMU_DOMAIN_UNMANAGED; } -static struct iommu_device *mtk_iommu_probe_device(struct device *dev) +static struct iommu_device *mtk_iommu_v1_probe_device(struct device *dev) { struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev); struct of_phandle_args iommu_spec; - struct mtk_iommu_data *data; + struct mtk_iommu_v1_data *data; int err, idx = 0, larbid, larbidx; struct device_link *link; struct device *larbdev; @@ -440,7 +470,7 @@ static struct iommu_device *mtk_iommu_probe_device(struct device *dev) "#iommu-cells", idx, &iommu_spec)) { - err = mtk_iommu_create_mapping(dev, &iommu_spec); + err = mtk_iommu_v1_create_mapping(dev, &iommu_spec); of_node_put(iommu_spec.np); if (err) return ERR_PTR(err); @@ -450,13 +480,16 @@ static struct iommu_device *mtk_iommu_probe_device(struct device *dev) idx++; } - if (!fwspec || fwspec->ops != &mtk_iommu_ops) + if (!fwspec || fwspec->ops != &mtk_iommu_v1_ops) return ERR_PTR(-ENODEV); /* Not a iommu client device */ data = dev_iommu_priv_get(dev); /* Link the consumer device with the smi-larb device(supplier) */ larbid = mt2701_m4u_to_larb(fwspec->ids[0]); + if (larbid >= MT2701_LARB_NR_MAX) + return ERR_PTR(-EINVAL); + for (idx = 1; idx < fwspec->num_ids; idx++) { larbidx = mt2701_m4u_to_larb(fwspec->ids[idx]); if (larbid != larbidx) { @@ -467,6 +500,9 @@ static struct iommu_device *mtk_iommu_probe_device(struct device *dev) } larbdev = data->larb_imu[larbid].dev; + if (!larbdev) + return ERR_PTR(-EINVAL); + link = device_link_add(dev, larbdev, DL_FLAG_PM_RUNTIME | DL_FLAG_STATELESS); if (!link) @@ -475,10 +511,10 @@ static struct iommu_device *mtk_iommu_probe_device(struct device *dev) return &data->iommu; } -static void mtk_iommu_probe_finalize(struct device *dev) +static void mtk_iommu_v1_probe_finalize(struct device *dev) { struct dma_iommu_mapping *mtk_mapping; - struct mtk_iommu_data *data; + struct mtk_iommu_v1_data *data; int err; data = dev_iommu_priv_get(dev); @@ -489,14 +525,14 @@ static void mtk_iommu_probe_finalize(struct device *dev) dev_err(dev, "Can't create IOMMU mapping - DMA-OPS will not work\n"); } -static void mtk_iommu_release_device(struct device *dev) +static void mtk_iommu_v1_release_device(struct device *dev) { struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev); - struct mtk_iommu_data *data; + struct mtk_iommu_v1_data *data; struct device *larbdev; unsigned int larbid; - if (!fwspec || fwspec->ops != &mtk_iommu_ops) + if (!fwspec || fwspec->ops != &mtk_iommu_v1_ops) return; data = dev_iommu_priv_get(dev); @@ -507,7 +543,7 @@ static void mtk_iommu_release_device(struct device *dev) iommu_fwspec_free(dev); } -static int mtk_iommu_hw_init(const struct mtk_iommu_data *data) +static int mtk_iommu_v1_hw_init(const struct mtk_iommu_v1_data *data) { u32 regval; int ret; @@ -537,7 +573,7 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data *data) writel_relaxed(F_MMU_DCM_ON, data->base + REG_MMU_DCM); - if (devm_request_irq(data->dev, data->irq, mtk_iommu_isr, 0, + if (devm_request_irq(data->dev, data->irq, mtk_iommu_v1_isr, 0, dev_name(data->dev), (void *)data)) { writel_relaxed(0, data->base + REG_MMU_PT_BASE_ADDR); clk_disable_unprepare(data->bclk); @@ -548,39 +584,39 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data *data) return 0; } -static const struct iommu_ops mtk_iommu_ops = { - .domain_alloc = mtk_iommu_domain_alloc, - .probe_device = mtk_iommu_probe_device, - .probe_finalize = mtk_iommu_probe_finalize, - .release_device = mtk_iommu_release_device, - .def_domain_type = mtk_iommu_def_domain_type, +static const struct iommu_ops mtk_iommu_v1_ops = { + .domain_alloc = mtk_iommu_v1_domain_alloc, + .probe_device = mtk_iommu_v1_probe_device, + .probe_finalize = mtk_iommu_v1_probe_finalize, + .release_device = mtk_iommu_v1_release_device, + .def_domain_type = mtk_iommu_v1_def_domain_type, .device_group = generic_device_group, .pgsize_bitmap = ~0UL << MT2701_IOMMU_PAGE_SHIFT, .owner = THIS_MODULE, .default_domain_ops = &(const struct iommu_domain_ops) { - .attach_dev = mtk_iommu_attach_device, - .detach_dev = mtk_iommu_detach_device, - .map = mtk_iommu_map, - .unmap = mtk_iommu_unmap, - .iova_to_phys = mtk_iommu_iova_to_phys, - .free = mtk_iommu_domain_free, + .attach_dev = mtk_iommu_v1_attach_device, + .detach_dev = mtk_iommu_v1_detach_device, + .map = mtk_iommu_v1_map, + .unmap = mtk_iommu_v1_unmap, + .iova_to_phys = mtk_iommu_v1_iova_to_phys, + .free = mtk_iommu_v1_domain_free, } }; -static const struct of_device_id mtk_iommu_of_ids[] = { +static const struct of_device_id mtk_iommu_v1_of_ids[] = { { .compatible = "mediatek,mt2701-m4u", }, {} }; -static const struct component_master_ops mtk_iommu_com_ops = { - .bind = mtk_iommu_bind, - .unbind = mtk_iommu_unbind, +static const struct component_master_ops mtk_iommu_v1_com_ops = { + .bind = mtk_iommu_v1_bind, + .unbind = mtk_iommu_v1_unbind, }; -static int mtk_iommu_probe(struct platform_device *pdev) +static int mtk_iommu_v1_probe(struct platform_device *pdev) { - struct mtk_iommu_data *data; struct device *dev = &pdev->dev; + struct mtk_iommu_v1_data *data; struct resource *res; struct component_match *match = NULL; void *protect; @@ -647,7 +683,7 @@ static int mtk_iommu_probe(struct platform_device *pdev) platform_set_drvdata(pdev, data); - ret = mtk_iommu_hw_init(data); + ret = mtk_iommu_v1_hw_init(data); if (ret) return ret; @@ -656,17 +692,17 @@ static int mtk_iommu_probe(struct platform_device *pdev) if (ret) return ret; - ret = iommu_device_register(&data->iommu, &mtk_iommu_ops, dev); + ret = iommu_device_register(&data->iommu, &mtk_iommu_v1_ops, dev); if (ret) goto out_sysfs_remove; if (!iommu_present(&platform_bus_type)) { - ret = bus_set_iommu(&platform_bus_type, &mtk_iommu_ops); + ret = bus_set_iommu(&platform_bus_type, &mtk_iommu_v1_ops); if (ret) goto out_dev_unreg; } - ret = component_master_add_with_match(dev, &mtk_iommu_com_ops, match); + ret = component_master_add_with_match(dev, &mtk_iommu_v1_com_ops, match); if (ret) goto out_bus_set_null; return ret; @@ -680,9 +716,9 @@ out_sysfs_remove: return ret; } -static int mtk_iommu_remove(struct platform_device *pdev) +static int mtk_iommu_v1_remove(struct platform_device *pdev) { - struct mtk_iommu_data *data = platform_get_drvdata(pdev); + struct mtk_iommu_v1_data *data = platform_get_drvdata(pdev); iommu_device_sysfs_remove(&data->iommu); iommu_device_unregister(&data->iommu); @@ -692,14 +728,14 @@ static int mtk_iommu_remove(struct platform_device *pdev) clk_disable_unprepare(data->bclk); devm_free_irq(&pdev->dev, data->irq, data); - component_master_del(&pdev->dev, &mtk_iommu_com_ops); + component_master_del(&pdev->dev, &mtk_iommu_v1_com_ops); return 0; } -static int __maybe_unused mtk_iommu_suspend(struct device *dev) +static int __maybe_unused mtk_iommu_v1_suspend(struct device *dev) { - struct mtk_iommu_data *data = dev_get_drvdata(dev); - struct mtk_iommu_suspend_reg *reg = &data->reg; + struct mtk_iommu_v1_data *data = dev_get_drvdata(dev); + struct mtk_iommu_v1_suspend_reg *reg = &data->reg; void __iomem *base = data->base; reg->standard_axi_mode = readl_relaxed(base + @@ -710,10 +746,10 @@ static int __maybe_unused mtk_iommu_suspend(struct device *dev) return 0; } -static int __maybe_unused mtk_iommu_resume(struct device *dev) +static int __maybe_unused mtk_iommu_v1_resume(struct device *dev) { - struct mtk_iommu_data *data = dev_get_drvdata(dev); - struct mtk_iommu_suspend_reg *reg = &data->reg; + struct mtk_iommu_v1_data *data = dev_get_drvdata(dev); + struct mtk_iommu_v1_suspend_reg *reg = &data->reg; void __iomem *base = data->base; writel_relaxed(data->m4u_dom->pgt_pa, base + REG_MMU_PT_BASE_ADDR); @@ -726,20 +762,20 @@ static int __maybe_unused mtk_iommu_resume(struct device *dev) return 0; } -static const struct dev_pm_ops mtk_iommu_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(mtk_iommu_suspend, mtk_iommu_resume) +static const struct dev_pm_ops mtk_iommu_v1_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(mtk_iommu_v1_suspend, mtk_iommu_v1_resume) }; -static struct platform_driver mtk_iommu_driver = { - .probe = mtk_iommu_probe, - .remove = mtk_iommu_remove, +static struct platform_driver mtk_iommu_v1_driver = { + .probe = mtk_iommu_v1_probe, + .remove = mtk_iommu_v1_remove, .driver = { .name = "mtk-iommu-v1", - .of_match_table = mtk_iommu_of_ids, - .pm = &mtk_iommu_pm_ops, + .of_match_table = mtk_iommu_v1_of_ids, + .pm = &mtk_iommu_v1_pm_ops, } }; -module_platform_driver(mtk_iommu_driver); +module_platform_driver(mtk_iommu_v1_driver); MODULE_DESCRIPTION("IOMMU API for MediaTek M4U v1 implementations"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/iommu/s390-iommu.c b/drivers/iommu/s390-iommu.c index 3833e86c6e7b8a82ae83985a6dcec34a85f9c1a3..c898bcbbce118f1509802ee74dadbd87025c52a1 100644 --- a/drivers/iommu/s390-iommu.c +++ b/drivers/iommu/s390-iommu.c @@ -99,7 +99,7 @@ static int s390_iommu_attach_device(struct iommu_domain *domain, if (!domain_device) return -ENOMEM; - if (zdev->dma_table) { + if (zdev->dma_table && !zdev->s390_domain) { cc = zpci_dma_exit_device(zdev); if (cc) { rc = -EIO; @@ -107,6 +107,9 @@ static int s390_iommu_attach_device(struct iommu_domain *domain, } } + if (zdev->s390_domain) + zpci_unregister_ioat(zdev, 0); + zdev->dma_table = s390_domain->dma_table; cc = zpci_register_ioat(zdev, 0, zdev->start_dma, zdev->end_dma, virt_to_phys(zdev->dma_table)); @@ -136,7 +139,13 @@ static int s390_iommu_attach_device(struct iommu_domain *domain, return 0; out_restore: - zpci_dma_init_device(zdev); + if (!zdev->s390_domain) { + zpci_dma_init_device(zdev); + } else { + zdev->dma_table = zdev->s390_domain->dma_table; + zpci_register_ioat(zdev, 0, zdev->start_dma, zdev->end_dma, + virt_to_phys(zdev->dma_table)); + } out_free: kfree(domain_device); @@ -167,7 +176,7 @@ static void s390_iommu_detach_device(struct iommu_domain *domain, } spin_unlock_irqrestore(&s390_domain->list_lock, flags); - if (found) { + if (found && (zdev->s390_domain == s390_domain)) { zdev->s390_domain = NULL; zpci_unregister_ioat(zdev, 0); zpci_dma_init_device(zdev); diff --git a/drivers/macintosh/Kconfig b/drivers/macintosh/Kconfig index 5cdc361da37cb0995eb58b6bdfa450c25f8fe12a..539a2ed4e13dc03deb43f52f32132608023ed98d 100644 --- a/drivers/macintosh/Kconfig +++ b/drivers/macintosh/Kconfig @@ -44,6 +44,7 @@ config ADB_IOP config ADB_CUDA bool "Support for Cuda/Egret based Macs and PowerMacs" depends on (ADB || PPC_PMAC) && !PPC_PMAC64 + select RTC_LIB help This provides support for Cuda/Egret based Macintosh and Power Macintosh systems. This includes most m68k based Macs, @@ -57,6 +58,7 @@ config ADB_CUDA config ADB_PMU bool "Support for PMU based PowerMacs and PowerBooks" depends on PPC_PMAC || MAC + select RTC_LIB help On PowerBooks, iBooks, and recent iMacs and Power Macintoshes, the PMU is an embedded microprocessor whose primary function is to @@ -67,6 +69,10 @@ config ADB_PMU this device; you should do so if your machine is one of those mentioned above. +config ADB_PMU_EVENT + def_bool y + depends on ADB_PMU && INPUT=y + config ADB_PMU_LED bool "Support for the Power/iBook front LED" depends on PPC_PMAC && ADB_PMU diff --git a/drivers/macintosh/Makefile b/drivers/macintosh/Makefile index 49819b1b6f2010d5f0c057036a432f191f8e9367..712edcb3e0b0819665099ce023b32de83951726d 100644 --- a/drivers/macintosh/Makefile +++ b/drivers/macintosh/Makefile @@ -12,7 +12,8 @@ obj-$(CONFIG_MAC_EMUMOUSEBTN) += mac_hid.o obj-$(CONFIG_INPUT_ADBHID) += adbhid.o obj-$(CONFIG_ANSLCD) += ans-lcd.o -obj-$(CONFIG_ADB_PMU) += via-pmu.o via-pmu-event.o +obj-$(CONFIG_ADB_PMU) += via-pmu.o +obj-$(CONFIG_ADB_PMU_EVENT) += via-pmu-event.o obj-$(CONFIG_ADB_PMU_LED) += via-pmu-led.o obj-$(CONFIG_PMAC_BACKLIGHT) += via-pmu-backlight.o obj-$(CONFIG_ADB_CUDA) += via-cuda.o diff --git a/drivers/macintosh/adb.c b/drivers/macintosh/adb.c index 73b39618903977bed1c4d92c93fecd0680653c8c..439fab4eaa850a171626252cb473b45c14964fe8 100644 --- a/drivers/macintosh/adb.c +++ b/drivers/macintosh/adb.c @@ -38,10 +38,10 @@ #include #include #include +#include #include #ifdef CONFIG_PPC -#include #include #endif diff --git a/drivers/macintosh/adbhid.c b/drivers/macintosh/adbhid.c index 994ba5cb367898060076cdd52a47d043f9380a00..b2fe7a3dc47134a358c11e5a25e9f01fedc85d9c 100644 --- a/drivers/macintosh/adbhid.c +++ b/drivers/macintosh/adbhid.c @@ -789,7 +789,8 @@ adbhid_input_register(int id, int default_id, int original_handler_id, switch (default_id) { case ADB_KEYBOARD: - hid->keycode = kmalloc(sizeof(adb_to_linux_keycodes), GFP_KERNEL); + hid->keycode = kmemdup(adb_to_linux_keycodes, + sizeof(adb_to_linux_keycodes), GFP_KERNEL); if (!hid->keycode) { err = -ENOMEM; goto fail; @@ -797,8 +798,6 @@ adbhid_input_register(int id, int default_id, int original_handler_id, sprintf(hid->name, "ADB keyboard"); - memcpy(hid->keycode, adb_to_linux_keycodes, sizeof(adb_to_linux_keycodes)); - switch (original_handler_id) { default: keyboard_type = ""; @@ -817,9 +816,7 @@ adbhid_input_register(int id, int default_id, int original_handler_id, case 0xC4: case 0xC7: keyboard_type = "ISO, swapping keys"; input_dev->id.version = ADB_KEYBOARD_ISO; - i = hid->keycode[10]; - hid->keycode[10] = hid->keycode[50]; - hid->keycode[50] = i; + swap(hid->keycode[10], hid->keycode[50]); break; case 0x12: case 0x15: case 0x16: case 0x17: case 0x1A: diff --git a/drivers/macintosh/ams/ams-core.c b/drivers/macintosh/ams/ams-core.c index 01eeb2336d1a1a5159b0a4b39416c76e01a2c0d6..877e8cb2312834719870c0c120c680861d774b47 100644 --- a/drivers/macintosh/ams/ams-core.c +++ b/drivers/macintosh/ams/ams-core.c @@ -50,7 +50,7 @@ static ssize_t ams_show_current(struct device *dev, ams_sensors(&x, &y, &z); mutex_unlock(&ams_info.lock); - return snprintf(buf, PAGE_SIZE, "%d %d %d\n", x, y, z); + return sysfs_emit(buf, "%d %d %d\n", x, y, z); } static DEVICE_ATTR(current, S_IRUGO, ams_show_current, NULL); diff --git a/drivers/macintosh/ams/ams-i2c.c b/drivers/macintosh/ams/ams-i2c.c index 21271b2e9259e048d37169bbe3838362d45688ad..d2f0cde6f9c742325417b4abf1dbabedea424afe 100644 --- a/drivers/macintosh/ams/ams-i2c.c +++ b/drivers/macintosh/ams/ams-i2c.c @@ -256,8 +256,6 @@ static void ams_i2c_exit(void) int __init ams_i2c_init(struct device_node *np) { - int result; - /* Set implementation stuff */ ams_info.of_node = np; ams_info.exit = ams_i2c_exit; @@ -266,7 +264,5 @@ int __init ams_i2c_init(struct device_node *np) ams_info.clear_irq = ams_i2c_clear_irq; ams_info.bustype = BUS_I2C; - result = i2c_add_driver(&ams_i2c_driver); - - return result; + return i2c_add_driver(&ams_i2c_driver); } diff --git a/drivers/macintosh/ans-lcd.c b/drivers/macintosh/ans-lcd.c index b4821c751d04c444ac9078dd703aadb0dd427b91..fa904b24a600a4b0754372ad0220accb732fc128 100644 --- a/drivers/macintosh/ans-lcd.c +++ b/drivers/macintosh/ans-lcd.c @@ -11,10 +11,10 @@ #include #include #include +#include #include #include -#include #include #include "ans-lcd.h" diff --git a/drivers/macintosh/macio-adb.c b/drivers/macintosh/macio-adb.c index dc634c2932fd358917a511de0fd008182a392bbe..9b63bd2551c632a4893f2be9332b5e11a03d4e85 100644 --- a/drivers/macintosh/macio-adb.c +++ b/drivers/macintosh/macio-adb.c @@ -9,8 +9,11 @@ #include #include #include -#include +#include +#include +#include #include + #include #include #include diff --git a/drivers/macintosh/macio_asic.c b/drivers/macintosh/macio_asic.c index 1943a007e2d55b14e1816d4baebcbc89a2bcfa0d..1ec1e5984563fd2bef6ab9e62b7248d2a8a36a70 100644 --- a/drivers/macintosh/macio_asic.c +++ b/drivers/macintosh/macio_asic.c @@ -20,13 +20,14 @@ #include #include #include +#include #include +#include #include #include #include #include -#include #undef DEBUG @@ -472,7 +473,7 @@ static void macio_pci_add_devices(struct macio_chip *chip) root_res = &rdev->resource[0]; /* First scan 1st level */ - for (np = NULL; (np = of_get_next_child(pnode, np)) != NULL;) { + for_each_child_of_node(pnode, np) { if (macio_skip_device(np)) continue; of_node_get(np); @@ -489,7 +490,7 @@ static void macio_pci_add_devices(struct macio_chip *chip) /* Add media bay devices if any */ if (mbdev) { pnode = mbdev->ofdev.dev.of_node; - for (np = NULL; (np = of_get_next_child(pnode, np)) != NULL;) { + for_each_child_of_node(pnode, np) { if (macio_skip_device(np)) continue; of_node_get(np); @@ -502,7 +503,7 @@ static void macio_pci_add_devices(struct macio_chip *chip) /* Add serial ports if any */ if (sdev) { pnode = sdev->ofdev.dev.of_node; - for (np = NULL; (np = of_get_next_child(pnode, np)) != NULL;) { + for_each_child_of_node(pnode, np) { if (macio_skip_device(np)) continue; of_node_get(np); diff --git a/drivers/macintosh/macio_sysfs.c b/drivers/macintosh/macio_sysfs.c index 27f5eefc508f4afbe240d4d96c9aaf1d4ab191d1..2bbe359b26d91ae29e9342efb60f607f51ebbc82 100644 --- a/drivers/macintosh/macio_sysfs.c +++ b/drivers/macintosh/macio_sysfs.c @@ -1,5 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 #include +#include +#include #include #include diff --git a/drivers/macintosh/mediabay.c b/drivers/macintosh/mediabay.c index b17660c022eb247acb7140ade656faa6fdb66388..36070c6586d138fc9bb088bef52a2def52e87185 100644 --- a/drivers/macintosh/mediabay.c +++ b/drivers/macintosh/mediabay.c @@ -17,7 +17,7 @@ #include #include #include -#include + #include #include #include diff --git a/drivers/macintosh/rack-meter.c b/drivers/macintosh/rack-meter.c index 60311e8d6240d8bfa02f0a710e9eba4b8c9702e3..c28893e41a8bed5019f053cc68f9e7d862af73bf 100644 --- a/drivers/macintosh/rack-meter.c +++ b/drivers/macintosh/rack-meter.c @@ -27,7 +27,6 @@ #include #include -#include #include #include #include diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c index a4fbc3fc713d8ccfc3bcd55a9f36b21393ca7df9..b495bfa7789625ad5d7bf9101ae2d45167b843e2 100644 --- a/drivers/macintosh/smu.c +++ b/drivers/macintosh/smu.c @@ -41,7 +41,6 @@ #include #include -#include #include #include #include @@ -1087,7 +1086,7 @@ static int smu_open(struct inode *inode, struct file *file) unsigned long flags; pp = kzalloc(sizeof(struct smu_private), GFP_KERNEL); - if (pp == 0) + if (!pp) return -ENOMEM; spin_lock_init(&pp->lock); pp->mode = smu_file_commands; @@ -1254,7 +1253,7 @@ static __poll_t smu_fpoll(struct file *file, poll_table *wait) __poll_t mask = 0; unsigned long flags; - if (pp == 0) + if (!pp) return 0; if (pp->mode == smu_file_commands) { @@ -1277,7 +1276,7 @@ static int smu_release(struct inode *inode, struct file *file) unsigned long flags; unsigned int busy; - if (pp == 0) + if (!pp) return 0; file->private_data = NULL; diff --git a/drivers/macintosh/therm_adt746x.c b/drivers/macintosh/therm_adt746x.c index 7e218437730ce4145d419798bec9f0be06c4e619..e604cbc91763d20329875014f6acca3fdc56e066 100644 --- a/drivers/macintosh/therm_adt746x.c +++ b/drivers/macintosh/therm_adt746x.c @@ -27,7 +27,6 @@ #include #include -#include #include #include #include diff --git a/drivers/macintosh/therm_windtunnel.c b/drivers/macintosh/therm_windtunnel.c index f55f6adf5e5ff77de90dcee8160a4853e58437b0..9226b74fa08f63601727e127e8a54c13f0c86f94 100644 --- a/drivers/macintosh/therm_windtunnel.c +++ b/drivers/macintosh/therm_windtunnel.c @@ -38,7 +38,6 @@ #include #include -#include #include #include #include diff --git a/drivers/macintosh/via-cuda.c b/drivers/macintosh/via-cuda.c index 3d0d0b9d471d4da2b101db59d88a79e60dba3ea7..5071289063f0395187116b024e78a9e06427f6f5 100644 --- a/drivers/macintosh/via-cuda.c +++ b/drivers/macintosh/via-cuda.c @@ -18,8 +18,10 @@ #include #include #include +#include +#include + #ifdef CONFIG_PPC -#include #include #include #else @@ -237,10 +239,10 @@ int __init find_via_cuda(void) const u32 *reg; int err; - if (vias != 0) + if (vias) return 1; vias = of_find_node_by_name(NULL, "via-cuda"); - if (vias == 0) + if (!vias) return 0; reg = of_get_property(vias, "reg", NULL); @@ -518,7 +520,7 @@ cuda_write(struct adb_request *req) req->reply_len = 0; spin_lock_irqsave(&cuda_lock, flags); - if (current_req != 0) { + if (current_req) { last_req->next = req; last_req = req; } else { diff --git a/drivers/macintosh/via-pmu-backlight.c b/drivers/macintosh/via-pmu-backlight.c index 50ada02ae75d7deb4d9bd4af53b93d262653de73..2194016122d2f4a739b699ad679a560a072c4529 100644 --- a/drivers/macintosh/via-pmu-backlight.c +++ b/drivers/macintosh/via-pmu-backlight.c @@ -12,7 +12,6 @@ #include #include #include -#include #define MAX_PMU_LEVEL 0xFF diff --git a/drivers/macintosh/via-pmu-led.c b/drivers/macintosh/via-pmu-led.c index ae067ab2373d75de9140c04718848508ce605861..a4fb16d7db3c11faef51b8f37c937ec0acacd5df 100644 --- a/drivers/macintosh/via-pmu-led.c +++ b/drivers/macintosh/via-pmu-led.c @@ -25,7 +25,7 @@ #include #include #include -#include +#include static spinlock_t pmu_blink_lock; static struct adb_request pmu_blink_req; diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c index 4b98bc26a94b564a116952536642f97ea7ca69eb..49657962d89206d554b4d2eed4303b4353e09d75 100644 --- a/drivers/macintosh/via-pmu.c +++ b/drivers/macintosh/via-pmu.c @@ -59,7 +59,6 @@ #include #include #include -#include #include #include #include @@ -161,7 +160,7 @@ static unsigned char __iomem *gpio_reg; static int gpio_irq = 0; static int gpio_irq_enabled = -1; static volatile int pmu_suspended; -static spinlock_t pmu_lock; +static DEFINE_SPINLOCK(pmu_lock); static u8 pmu_intr_mask; static int pmu_version; static int drop_interrupts; @@ -305,8 +304,6 @@ int __init find_via_pmu(void) goto fail; } - spin_lock_init(&pmu_lock); - pmu_has_adb = 1; pmu_intr_mask = PMU_INT_PCEJECT | @@ -388,8 +385,6 @@ int __init find_via_pmu(void) pmu_kind = PMU_UNKNOWN; - spin_lock_init(&pmu_lock); - pmu_has_adb = 1; pmu_intr_mask = PMU_INT_PCEJECT | @@ -1459,7 +1454,7 @@ next: pmu_pass_intr(data, len); /* len == 6 is probably a bad check. But how do I * know what PMU versions send what events here? */ - if (len == 6) { + if (IS_ENABLED(CONFIG_ADB_PMU_EVENT) && len == 6) { via_pmu_event(PMU_EVT_POWER, !!(data[1]&8)); via_pmu_event(PMU_EVT_LID, data[1]&1); } diff --git a/drivers/macintosh/windfarm_ad7417_sensor.c b/drivers/macintosh/windfarm_ad7417_sensor.c index e7dec328c7cfdffeede1bf04b701ac9bca899301..6ad6441abcbcc8e8ffbb06928da1fefe7fda1704 100644 --- a/drivers/macintosh/windfarm_ad7417_sensor.c +++ b/drivers/macintosh/windfarm_ad7417_sensor.c @@ -13,7 +13,7 @@ #include #include #include -#include + #include #include #include diff --git a/drivers/macintosh/windfarm_core.c b/drivers/macintosh/windfarm_core.c index 07f91ec1f960e4fc7d217147934bf4b9792771fa..5307b1e34261d3d135416d430983ab3c048b7d37 100644 --- a/drivers/macintosh/windfarm_core.c +++ b/drivers/macintosh/windfarm_core.c @@ -35,8 +35,6 @@ #include #include -#include - #include "windfarm.h" #define VERSION "0.2" diff --git a/drivers/macintosh/windfarm_cpufreq_clamp.c b/drivers/macintosh/windfarm_cpufreq_clamp.c index 7b726f00f1834d1cd4aa544090215ad9562e4c08..28d18ef22bbbb0073102e23d3815018e3fee5872 100644 --- a/drivers/macintosh/windfarm_cpufreq_clamp.c +++ b/drivers/macintosh/windfarm_cpufreq_clamp.c @@ -10,8 +10,6 @@ #include #include -#include - #include "windfarm.h" #define VERSION "0.3" diff --git a/drivers/macintosh/windfarm_fcu_controls.c b/drivers/macintosh/windfarm_fcu_controls.c index 2470e5a725c812f5342cdf40fd88aab61a5ca414..82e7b2005ae78c9bbdaf1ece10df4bef33306339 100644 --- a/drivers/macintosh/windfarm_fcu_controls.c +++ b/drivers/macintosh/windfarm_fcu_controls.c @@ -14,7 +14,7 @@ #include #include #include -#include + #include #include #include diff --git a/drivers/macintosh/windfarm_lm75_sensor.c b/drivers/macintosh/windfarm_lm75_sensor.c index 29f48c2028b6ddf8879abc9bcb65882a43ca9d05..eb7e7f0bd21905898bb62cc7f3d1b189ff63b02c 100644 --- a/drivers/macintosh/windfarm_lm75_sensor.c +++ b/drivers/macintosh/windfarm_lm75_sensor.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/macintosh/windfarm_lm87_sensor.c b/drivers/macintosh/windfarm_lm87_sensor.c index 9fab0b47cd3dd2500c8d1c3c0b72aa21603e31a6..807efdde86bc5f03ebd1b46f073d51223acf08f3 100644 --- a/drivers/macintosh/windfarm_lm87_sensor.c +++ b/drivers/macintosh/windfarm_lm87_sensor.c @@ -13,7 +13,7 @@ #include #include #include -#include + #include #include #include diff --git a/drivers/macintosh/windfarm_max6690_sensor.c b/drivers/macintosh/windfarm_max6690_sensor.c index 1e7b03d44ad975413a8086f12a5ff0b95d339d90..55ee417fb878981843967e05ab15be987357b5f6 100644 --- a/drivers/macintosh/windfarm_max6690_sensor.c +++ b/drivers/macintosh/windfarm_max6690_sensor.c @@ -10,7 +10,7 @@ #include #include #include -#include + #include #include "windfarm.h" diff --git a/drivers/macintosh/windfarm_mpu.h b/drivers/macintosh/windfarm_mpu.h index 157ce6e3f32e235b379f8834868e9f740bb20fb3..b5ce347d12d4ac1d49faa6dd5571c665c3015642 100644 --- a/drivers/macintosh/windfarm_mpu.h +++ b/drivers/macintosh/windfarm_mpu.h @@ -8,6 +8,8 @@ #ifndef __WINDFARM_MPU_H #define __WINDFARM_MPU_H +#include + typedef unsigned short fu16; typedef int fs32; typedef short fs16; diff --git a/drivers/macintosh/windfarm_pm112.c b/drivers/macintosh/windfarm_pm112.c index e8377ce0a95af8b1d4f116bf08dc1a3508f60965..d1dec314ae305948668a5216ca9d80982973ec91 100644 --- a/drivers/macintosh/windfarm_pm112.c +++ b/drivers/macintosh/windfarm_pm112.c @@ -12,7 +12,9 @@ #include #include #include -#include +#include +#include + #include #include "windfarm.h" diff --git a/drivers/macintosh/windfarm_pm121.c b/drivers/macintosh/windfarm_pm121.c index ba1ec6fc11d21138d0434b35e0b74227278ebf43..36312f163aac8efb002148372f730a5e3d496b3c 100644 --- a/drivers/macintosh/windfarm_pm121.c +++ b/drivers/macintosh/windfarm_pm121.c @@ -201,7 +201,8 @@ #include #include #include -#include +#include + #include #include #include diff --git a/drivers/macintosh/windfarm_pm72.c b/drivers/macintosh/windfarm_pm72.c index e81746b87cff68e0c4ab3ced219823a65adaefc6..e21f973551cc25206687861323ab219948774a39 100644 --- a/drivers/macintosh/windfarm_pm72.c +++ b/drivers/macintosh/windfarm_pm72.c @@ -11,7 +11,7 @@ #include #include #include -#include + #include #include "windfarm.h" diff --git a/drivers/macintosh/windfarm_pm81.c b/drivers/macintosh/windfarm_pm81.c index 82c67a4ee5f7cecb5740635704736b96230f9cd2..e0f4743f21cc618f3e34ae186d2256088a002065 100644 --- a/drivers/macintosh/windfarm_pm81.c +++ b/drivers/macintosh/windfarm_pm81.c @@ -102,7 +102,8 @@ #include #include #include -#include +#include + #include #include #include diff --git a/drivers/macintosh/windfarm_pm91.c b/drivers/macintosh/windfarm_pm91.c index 3f346af9e3f7985a89a83c3b337b2f570a798318..c8535855360d1fbd43756952da03888f489705c7 100644 --- a/drivers/macintosh/windfarm_pm91.c +++ b/drivers/macintosh/windfarm_pm91.c @@ -37,7 +37,8 @@ #include #include #include -#include +#include + #include #include #include diff --git a/drivers/macintosh/windfarm_rm31.c b/drivers/macintosh/windfarm_rm31.c index 7acd1684c451ddfb316677d4c956cad775983f6c..e9eb7fdde48c1f6fb07df32e678fab72d54a030c 100644 --- a/drivers/macintosh/windfarm_rm31.c +++ b/drivers/macintosh/windfarm_rm31.c @@ -11,7 +11,7 @@ #include #include #include -#include + #include #include "windfarm.h" diff --git a/drivers/macintosh/windfarm_smu_controls.c b/drivers/macintosh/windfarm_smu_controls.c index 75966052819a0f236f702c908b64d3c61e81aa46..e9957ad49a2af21c4f953daadce9021585a2429a 100644 --- a/drivers/macintosh/windfarm_smu_controls.c +++ b/drivers/macintosh/windfarm_smu_controls.c @@ -14,7 +14,8 @@ #include #include #include -#include +#include + #include #include #include diff --git a/drivers/macintosh/windfarm_smu_sat.c b/drivers/macintosh/windfarm_smu_sat.c index e46e1153a0b4354d6d43f28136bdf8f4050a6fc2..5ade627eaa788d231be2d6b2606c0ed3e4538584 100644 --- a/drivers/macintosh/windfarm_smu_sat.c +++ b/drivers/macintosh/windfarm_smu_sat.c @@ -13,7 +13,7 @@ #include #include #include -#include + #include #include diff --git a/drivers/macintosh/windfarm_smu_sensors.c b/drivers/macintosh/windfarm_smu_sensors.c index c8706cfb83fd8e96845c84c2c42cc675df702823..00c6fe25fcba0cd2385803bb75b3a4ff8f41b83b 100644 --- a/drivers/macintosh/windfarm_smu_sensors.c +++ b/drivers/macintosh/windfarm_smu_sensors.c @@ -14,7 +14,8 @@ #include #include #include -#include +#include + #include #include #include diff --git a/drivers/md/dm-linear.c b/drivers/md/dm-linear.c index 0a6abbbe3745274e5118b0ee89fdce62b86247ab..3212ef6aa81bb515dac745f6fa349e472b5b42b0 100644 --- a/drivers/md/dm-linear.c +++ b/drivers/md/dm-linear.c @@ -165,11 +165,12 @@ static struct dax_device *linear_dax_pgoff(struct dm_target *ti, pgoff_t *pgoff) } static long linear_dax_direct_access(struct dm_target *ti, pgoff_t pgoff, - long nr_pages, void **kaddr, pfn_t *pfn) + long nr_pages, enum dax_access_mode mode, void **kaddr, + pfn_t *pfn) { struct dax_device *dax_dev = linear_dax_pgoff(ti, &pgoff); - return dax_direct_access(dax_dev, pgoff, nr_pages, kaddr, pfn); + return dax_direct_access(dax_dev, pgoff, nr_pages, mode, kaddr, pfn); } static int linear_dax_zero_page_range(struct dm_target *ti, pgoff_t pgoff, @@ -180,9 +181,18 @@ static int linear_dax_zero_page_range(struct dm_target *ti, pgoff_t pgoff, return dax_zero_page_range(dax_dev, pgoff, nr_pages); } +static size_t linear_dax_recovery_write(struct dm_target *ti, pgoff_t pgoff, + void *addr, size_t bytes, struct iov_iter *i) +{ + struct dax_device *dax_dev = linear_dax_pgoff(ti, &pgoff); + + return dax_recovery_write(dax_dev, pgoff, addr, bytes, i); +} + #else #define linear_dax_direct_access NULL #define linear_dax_zero_page_range NULL +#define linear_dax_recovery_write NULL #endif static struct target_type linear_target = { @@ -200,6 +210,7 @@ static struct target_type linear_target = { .iterate_devices = linear_iterate_devices, .direct_access = linear_dax_direct_access, .dax_zero_page_range = linear_dax_zero_page_range, + .dax_recovery_write = linear_dax_recovery_write, }; int __init dm_linear_init(void) diff --git a/drivers/md/dm-log-writes.c b/drivers/md/dm-log-writes.c index e194226c89e54082e9c010a395ff9b624aa365bb..20fd688f72e7c0cd9cabd92c740fedcfd1235730 100644 --- a/drivers/md/dm-log-writes.c +++ b/drivers/md/dm-log-writes.c @@ -888,11 +888,12 @@ static struct dax_device *log_writes_dax_pgoff(struct dm_target *ti, } static long log_writes_dax_direct_access(struct dm_target *ti, pgoff_t pgoff, - long nr_pages, void **kaddr, pfn_t *pfn) + long nr_pages, enum dax_access_mode mode, void **kaddr, + pfn_t *pfn) { struct dax_device *dax_dev = log_writes_dax_pgoff(ti, &pgoff); - return dax_direct_access(dax_dev, pgoff, nr_pages, kaddr, pfn); + return dax_direct_access(dax_dev, pgoff, nr_pages, mode, kaddr, pfn); } static int log_writes_dax_zero_page_range(struct dm_target *ti, pgoff_t pgoff, @@ -903,9 +904,18 @@ static int log_writes_dax_zero_page_range(struct dm_target *ti, pgoff_t pgoff, return dax_zero_page_range(dax_dev, pgoff, nr_pages << PAGE_SHIFT); } +static size_t log_writes_dax_recovery_write(struct dm_target *ti, + pgoff_t pgoff, void *addr, size_t bytes, struct iov_iter *i) +{ + struct dax_device *dax_dev = log_writes_dax_pgoff(ti, &pgoff); + + return dax_recovery_write(dax_dev, pgoff, addr, bytes, i); +} + #else #define log_writes_dax_direct_access NULL #define log_writes_dax_zero_page_range NULL +#define log_writes_dax_recovery_write NULL #endif static struct target_type log_writes_target = { @@ -923,6 +933,7 @@ static struct target_type log_writes_target = { .io_hints = log_writes_io_hints, .direct_access = log_writes_dax_direct_access, .dax_zero_page_range = log_writes_dax_zero_page_range, + .dax_recovery_write = log_writes_dax_recovery_write, }; static int __init dm_log_writes_init(void) diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c index c81d331d1afe98e2fe371e2ca33c408b9e3e2299..baa085cc67bdefbe4317b8840f3eaca136a344da 100644 --- a/drivers/md/dm-stripe.c +++ b/drivers/md/dm-stripe.c @@ -315,11 +315,12 @@ static struct dax_device *stripe_dax_pgoff(struct dm_target *ti, pgoff_t *pgoff) } static long stripe_dax_direct_access(struct dm_target *ti, pgoff_t pgoff, - long nr_pages, void **kaddr, pfn_t *pfn) + long nr_pages, enum dax_access_mode mode, void **kaddr, + pfn_t *pfn) { struct dax_device *dax_dev = stripe_dax_pgoff(ti, &pgoff); - return dax_direct_access(dax_dev, pgoff, nr_pages, kaddr, pfn); + return dax_direct_access(dax_dev, pgoff, nr_pages, mode, kaddr, pfn); } static int stripe_dax_zero_page_range(struct dm_target *ti, pgoff_t pgoff, @@ -330,9 +331,18 @@ static int stripe_dax_zero_page_range(struct dm_target *ti, pgoff_t pgoff, return dax_zero_page_range(dax_dev, pgoff, nr_pages); } +static size_t stripe_dax_recovery_write(struct dm_target *ti, pgoff_t pgoff, + void *addr, size_t bytes, struct iov_iter *i) +{ + struct dax_device *dax_dev = stripe_dax_pgoff(ti, &pgoff); + + return dax_recovery_write(dax_dev, pgoff, addr, bytes, i); +} + #else #define stripe_dax_direct_access NULL #define stripe_dax_zero_page_range NULL +#define stripe_dax_recovery_write NULL #endif /* @@ -469,6 +479,7 @@ static struct target_type stripe_target = { .io_hints = stripe_io_hints, .direct_access = stripe_dax_direct_access, .dax_zero_page_range = stripe_dax_zero_page_range, + .dax_recovery_write = stripe_dax_recovery_write, }; int __init dm_stripe_init(void) diff --git a/drivers/md/dm-target.c b/drivers/md/dm-target.c index 64dd0b34fcf490cee3779e179e9b8c7c543b7e53..8cd5184e62f0663731337273ce590451b59a4c54 100644 --- a/drivers/md/dm-target.c +++ b/drivers/md/dm-target.c @@ -10,6 +10,7 @@ #include #include #include +#include #define DM_MSG_PREFIX "target" @@ -142,7 +143,8 @@ static void io_err_release_clone_rq(struct request *clone, } static long io_err_dax_direct_access(struct dm_target *ti, pgoff_t pgoff, - long nr_pages, void **kaddr, pfn_t *pfn) + long nr_pages, enum dax_access_mode mode, void **kaddr, + pfn_t *pfn) { return -EIO; } diff --git a/drivers/md/dm-writecache.c b/drivers/md/dm-writecache.c index 5630b470ba429be4c6c046612ebeb921da46258d..d74c5a7a0ab496f5a1154548de8cacc64e5ecc6b 100644 --- a/drivers/md/dm-writecache.c +++ b/drivers/md/dm-writecache.c @@ -286,7 +286,8 @@ static int persistent_memory_claim(struct dm_writecache *wc) id = dax_read_lock(); - da = dax_direct_access(wc->ssd_dev->dax_dev, offset, p, &wc->memory_map, &pfn); + da = dax_direct_access(wc->ssd_dev->dax_dev, offset, p, DAX_ACCESS, + &wc->memory_map, &pfn); if (da < 0) { wc->memory_map = NULL; r = da; @@ -308,8 +309,8 @@ static int persistent_memory_claim(struct dm_writecache *wc) i = 0; do { long daa; - daa = dax_direct_access(wc->ssd_dev->dax_dev, offset + i, p - i, - NULL, &pfn); + daa = dax_direct_access(wc->ssd_dev->dax_dev, offset + i, + p - i, DAX_ACCESS, NULL, &pfn); if (daa <= 0) { r = daa ? daa : -EINVAL; goto err3; diff --git a/drivers/md/dm.c b/drivers/md/dm.c index d62f1354ecbfed062acf9d464c6ccf93a89eee42..dfb0a551bd880e9da428c8c28ee9a8822278ed09 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -1143,7 +1143,8 @@ static struct dm_target *dm_dax_get_live_target(struct mapped_device *md, } static long dm_dax_direct_access(struct dax_device *dax_dev, pgoff_t pgoff, - long nr_pages, void **kaddr, pfn_t *pfn) + long nr_pages, enum dax_access_mode mode, void **kaddr, + pfn_t *pfn) { struct mapped_device *md = dax_get_private(dax_dev); sector_t sector = pgoff * PAGE_SECTORS; @@ -1161,7 +1162,7 @@ static long dm_dax_direct_access(struct dax_device *dax_dev, pgoff_t pgoff, if (len < 1) goto out; nr_pages = min(len, nr_pages); - ret = ti->type->direct_access(ti, pgoff, nr_pages, kaddr, pfn); + ret = ti->type->direct_access(ti, pgoff, nr_pages, mode, kaddr, pfn); out: dm_put_live_table(md, srcu_idx); @@ -1196,6 +1197,25 @@ static int dm_dax_zero_page_range(struct dax_device *dax_dev, pgoff_t pgoff, return ret; } +static size_t dm_dax_recovery_write(struct dax_device *dax_dev, pgoff_t pgoff, + void *addr, size_t bytes, struct iov_iter *i) +{ + struct mapped_device *md = dax_get_private(dax_dev); + sector_t sector = pgoff * PAGE_SECTORS; + struct dm_target *ti; + int srcu_idx; + long ret = 0; + + ti = dm_dax_get_live_target(md, sector, &srcu_idx); + if (!ti || !ti->type->dax_recovery_write) + goto out; + + ret = ti->type->dax_recovery_write(ti, pgoff, addr, bytes, i); +out: + dm_put_live_table(md, srcu_idx); + return ret; +} + /* * A target may call dm_accept_partial_bio only from the map routine. It is * allowed for all bio types except REQ_PREFLUSH, REQ_OP_ZONE_* zone management @@ -3231,6 +3251,7 @@ static const struct block_device_operations dm_rq_blk_dops = { static const struct dax_operations dm_dax_ops = { .direct_access = dm_dax_direct_access, .zero_page_range = dm_dax_zero_page_range, + .recovery_write = dm_dax_recovery_write, }; /* diff --git a/drivers/memory/emif.c b/drivers/memory/emif.c index 6c2a421b86e3349830f404bddce0438e115decba..f305643209f03bc8dd58dde7ea3b722fa2c46dc6 100644 --- a/drivers/memory/emif.c +++ b/drivers/memory/emif.c @@ -630,7 +630,7 @@ static irqreturn_t emif_threaded_isr(int irq, void *dev_id) dev_emerg(emif->dev, "SDRAM temperature exceeds operating limit.. Needs shut down!!!\n"); /* If we have Power OFF ability, use it, else try restarting */ - if (pm_power_off) { + if (kernel_can_power_off()) { kernel_power_off(); } else { WARN(1, "FIXME: NO pm_power_off!!! trying restart\n"); diff --git a/drivers/mfd/cros_ec_dev.c b/drivers/mfd/cros_ec_dev.c index 546feef851abb5e7abc63c820322f0878220117b..596731caf4079f2d1a1d9d818de4362372cf7dc8 100644 --- a/drivers/mfd/cros_ec_dev.c +++ b/drivers/mfd/cros_ec_dev.c @@ -114,6 +114,9 @@ static const struct mfd_cell cros_ec_platform_cells[] = { { .name = "cros-ec-chardev", }, { .name = "cros-ec-debugfs", }, { .name = "cros-ec-sysfs", }, +}; + +static const struct mfd_cell cros_ec_pchg_cells[] = { { .name = "cros-ec-pchg", }, }; @@ -137,6 +140,7 @@ static int ec_device_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct cros_ec_platform *ec_platform = dev_get_platdata(dev); struct cros_ec_dev *ec = kzalloc(sizeof(*ec), GFP_KERNEL); + struct ec_response_pchg_count pchg_count; int i; if (!ec) @@ -242,6 +246,21 @@ static int ec_device_probe(struct platform_device *pdev) } } + /* + * The PCHG device cannot be detected by sending EC_FEATURE_GET_CMD, but + * it can be detected by querying the number of peripheral chargers. + */ + retval = cros_ec_command(ec->ec_dev, 0, EC_CMD_PCHG_COUNT, NULL, 0, + &pchg_count, sizeof(pchg_count)); + if (retval >= 0 && pchg_count.port_count) { + retval = mfd_add_hotplug_devices(ec->dev, + cros_ec_pchg_cells, + ARRAY_SIZE(cros_ec_pchg_cells)); + if (retval) + dev_warn(ec->dev, "failed to add pchg: %d\n", + retval); + } + /* * The following subdevices cannot be detected by sending the * EC_FEATURE_GET_CMD to the Embedded Controller device. diff --git a/drivers/mfd/davinci_voicecodec.c b/drivers/mfd/davinci_voicecodec.c index e5c8bc998eb4e4fb558a2437408f7d491077c42f..965820481f1e11909da5a4327962c9837b551e4e 100644 --- a/drivers/mfd/davinci_voicecodec.c +++ b/drivers/mfd/davinci_voicecodec.c @@ -46,14 +46,12 @@ static int __init davinci_vc_probe(struct platform_device *pdev) } clk_enable(davinci_vc->clk); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - - fifo_base = (dma_addr_t)res->start; - davinci_vc->base = devm_ioremap_resource(&pdev->dev, res); + davinci_vc->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); if (IS_ERR(davinci_vc->base)) { ret = PTR_ERR(davinci_vc->base); goto fail; } + fifo_base = (dma_addr_t)res->start; davinci_vc->regmap = devm_regmap_init_mmio(&pdev->dev, davinci_vc->base, diff --git a/drivers/mfd/hi655x-pmic.c b/drivers/mfd/hi655x-pmic.c index 6909d075d017c28788f24dc66f3b735786d2698f..a58e42ddcd0c0fc277e9f446c1d5e1326b1688c9 100644 --- a/drivers/mfd/hi655x-pmic.c +++ b/drivers/mfd/hi655x-pmic.c @@ -9,14 +9,13 @@ * Fei Wang */ -#include #include #include #include #include #include #include -#include +#include #include #include #include @@ -94,7 +93,6 @@ static int hi655x_pmic_probe(struct platform_device *pdev) int ret; struct hi655x_pmic *pmic; struct device *dev = &pdev->dev; - struct device_node *np = dev->of_node; void __iomem *base; pmic = devm_kzalloc(dev, sizeof(*pmic), GFP_KERNEL); @@ -120,21 +118,12 @@ static int hi655x_pmic_probe(struct platform_device *pdev) hi655x_local_irq_clear(pmic->regmap); - pmic->gpio = of_get_named_gpio(np, "pmic-gpios", 0); - if (!gpio_is_valid(pmic->gpio)) { - dev_err(dev, "Failed to get the pmic-gpios\n"); - return -ENODEV; - } - - ret = devm_gpio_request_one(dev, pmic->gpio, GPIOF_IN, - "hi655x_pmic_irq"); - if (ret < 0) { - dev_err(dev, "Failed to request gpio %d ret = %d\n", - pmic->gpio, ret); - return ret; - } + pmic->gpio = devm_gpiod_get_optional(dev, "pmic", GPIOD_IN); + if (IS_ERR(pmic->gpio)) + return dev_err_probe(dev, PTR_ERR(pmic->gpio), + "Failed to request hi655x pmic-gpio"); - ret = regmap_add_irq_chip(pmic->regmap, gpio_to_irq(pmic->gpio), + ret = regmap_add_irq_chip(pmic->regmap, gpiod_to_irq(pmic->gpio), IRQF_TRIGGER_LOW | IRQF_NO_SUSPEND, 0, &hi655x_irq_chip, &pmic->irq_data); if (ret) { @@ -149,7 +138,7 @@ static int hi655x_pmic_probe(struct platform_device *pdev) regmap_irq_get_domain(pmic->irq_data)); if (ret) { dev_err(dev, "Failed to register device %d\n", ret); - regmap_del_irq_chip(gpio_to_irq(pmic->gpio), pmic->irq_data); + regmap_del_irq_chip(gpiod_to_irq(pmic->gpio), pmic->irq_data); return ret; } @@ -160,7 +149,7 @@ static int hi655x_pmic_remove(struct platform_device *pdev) { struct hi655x_pmic *pmic = platform_get_drvdata(pdev); - regmap_del_irq_chip(gpio_to_irq(pmic->gpio), pmic->irq_data); + regmap_del_irq_chip(gpiod_to_irq(pmic->gpio), pmic->irq_data); mfd_remove_devices(&pdev->dev); return 0; } diff --git a/drivers/mfd/intel-lpss-pci.c b/drivers/mfd/intel-lpss-pci.c index 962ee14c62ddf41b80b1197413b8875fccf7b73a..f7950d2197df97db6eb2ea5d38b98c1e317afd58 100644 --- a/drivers/mfd/intel-lpss-pci.c +++ b/drivers/mfd/intel-lpss-pci.c @@ -319,6 +319,8 @@ static const struct pci_device_id intel_lpss_pci_ids[] = { { PCI_VDEVICE(INTEL, 0x51c5), (kernel_ulong_t)&bxt_i2c_info }, { PCI_VDEVICE(INTEL, 0x51c6), (kernel_ulong_t)&bxt_i2c_info }, { PCI_VDEVICE(INTEL, 0x51c7), (kernel_ulong_t)&bxt_uart_info }, + { PCI_VDEVICE(INTEL, 0x51d8), (kernel_ulong_t)&bxt_i2c_info }, + { PCI_VDEVICE(INTEL, 0x51d9), (kernel_ulong_t)&bxt_i2c_info }, { PCI_VDEVICE(INTEL, 0x51e8), (kernel_ulong_t)&bxt_i2c_info }, { PCI_VDEVICE(INTEL, 0x51e9), (kernel_ulong_t)&bxt_i2c_info }, { PCI_VDEVICE(INTEL, 0x51ea), (kernel_ulong_t)&bxt_i2c_info }, diff --git a/drivers/mfd/ipaq-micro.c b/drivers/mfd/ipaq-micro.c index e92eeeb67a98a025667bc537345fd5102cf1bac4..4cd5ecc722112bf5af86500eef730320ac475c4c 100644 --- a/drivers/mfd/ipaq-micro.c +++ b/drivers/mfd/ipaq-micro.c @@ -403,7 +403,7 @@ static int __init micro_probe(struct platform_device *pdev) micro_reset_comm(micro); irq = platform_get_irq(pdev, 0); - if (!irq) + if (irq < 0) return -EINVAL; ret = devm_request_irq(&pdev->dev, irq, micro_serial_isr, IRQF_SHARED, "ipaq-micro", diff --git a/drivers/mfd/mt6397-core.c b/drivers/mfd/mt6397-core.c index bddb40054b9e9ca6bd8030366af35b5b681847b0..1a368ad08f5838f817d8e4cd309b48808114ca26 100644 --- a/drivers/mfd/mt6397-core.c +++ b/drivers/mfd/mt6397-core.c @@ -54,6 +54,13 @@ static const struct resource mt6358_keys_resources[] = { DEFINE_RES_IRQ_NAMED(MT6358_IRQ_HOMEKEY_R, "homekey_r"), }; +static const struct resource mt6359_keys_resources[] = { + DEFINE_RES_IRQ_NAMED(MT6359_IRQ_PWRKEY, "powerkey"), + DEFINE_RES_IRQ_NAMED(MT6359_IRQ_HOMEKEY, "homekey"), + DEFINE_RES_IRQ_NAMED(MT6359_IRQ_PWRKEY_R, "powerkey_r"), + DEFINE_RES_IRQ_NAMED(MT6359_IRQ_HOMEKEY_R, "homekey_r"), +}; + static const struct resource mt6323_keys_resources[] = { DEFINE_RES_IRQ_NAMED(MT6323_IRQ_STATUS_PWRKEY, "powerkey"), DEFINE_RES_IRQ_NAMED(MT6323_IRQ_STATUS_FCHRKEY, "homekey"), @@ -122,6 +129,12 @@ static const struct mfd_cell mt6359_devs[] = { .of_compatible = "mediatek,mt6358-rtc", }, { .name = "mt6359-sound", }, + { + .name = "mtk-pmic-keys", + .num_resources = ARRAY_SIZE(mt6359_keys_resources), + .resources = mt6359_keys_resources, + .of_compatible = "mediatek,mt6359-keys" + }, }; static const struct mfd_cell mt6397_devs[] = { diff --git a/drivers/mfd/rt4831.c b/drivers/mfd/rt4831.c index b169781ac6756aac5cc3d46749de1f222742761b..fb3bd788a3eb2a8f0d93a111f8305a5ace6a2667 100644 --- a/drivers/mfd/rt4831.c +++ b/drivers/mfd/rt4831.c @@ -90,9 +90,14 @@ static int rt4831_probe(struct i2c_client *client) static int rt4831_remove(struct i2c_client *client) { struct regmap *regmap = dev_get_regmap(&client->dev, NULL); + int ret; /* Disable WLED and DSV outputs */ - return regmap_update_bits(regmap, RT4831_REG_ENABLE, RT4831_RESET_MASK, RT4831_RESET_MASK); + ret = regmap_update_bits(regmap, RT4831_REG_ENABLE, RT4831_RESET_MASK, RT4831_RESET_MASK); + if (ret) + dev_warn(&client->dev, "Failed to disable outputs (%pe)\n", ERR_PTR(ret)); + + return 0; } static const struct of_device_id __maybe_unused rt4831_of_match[] = { diff --git a/drivers/mfd/sprd-sc27xx-spi.c b/drivers/mfd/sprd-sc27xx-spi.c index 55d2c31bdfb205e50a5d2d9967cbd277f5a399d2..d05a47c5187f9298a2d9a35c6da9578f74e9f9d7 100644 --- a/drivers/mfd/sprd-sc27xx-spi.c +++ b/drivers/mfd/sprd-sc27xx-spi.c @@ -240,13 +240,14 @@ static int sprd_pmic_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(sprd_pmic_pm_ops, sprd_pmic_suspend, sprd_pmic_resume); static const struct of_device_id sprd_pmic_match[] = { - { .compatible = "sprd,sc2731", .data = &sc2731_data }, { .compatible = "sprd,sc2730", .data = &sc2730_data }, + { .compatible = "sprd,sc2731", .data = &sc2731_data }, {}, }; MODULE_DEVICE_TABLE(of, sprd_pmic_match); static const struct spi_device_id sprd_pmic_spi_ids[] = { + { .name = "sc2730", .driver_data = (unsigned long)&sc2730_data }, { .name = "sc2731", .driver_data = (unsigned long)&sc2731_data }, {}, }; diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c index 289b556dede28eb80d0cc27a300c5e87b8740953..bd6659cf3bc036fa399c5a8a58c4bcb95aeb4379 100644 --- a/drivers/mfd/twl-core.c +++ b/drivers/mfd/twl-core.c @@ -1036,15 +1036,11 @@ static void clocks_init(struct device *dev, static int twl_remove(struct i2c_client *client) { unsigned i, num_slaves; - int status; if (twl_class_is_4030()) - status = twl4030_exit_irq(); + twl4030_exit_irq(); else - status = twl6030_exit_irq(); - - if (status < 0) - return status; + twl6030_exit_irq(); num_slaves = twl_get_num_slaves(); for (i = 0; i < num_slaves; i++) { diff --git a/drivers/mfd/twl-core.h b/drivers/mfd/twl-core.h index 6f96c2009a9f491f485e9752b647575bb9f42b37..b4bf6a233bd0cc9a7b6e915bae2ad66af64a9897 100644 --- a/drivers/mfd/twl-core.h +++ b/drivers/mfd/twl-core.h @@ -3,9 +3,9 @@ #define __TWL_CORE_H__ extern int twl6030_init_irq(struct device *dev, int irq_num); -extern int twl6030_exit_irq(void); +extern void twl6030_exit_irq(void); extern int twl4030_init_irq(struct device *dev, int irq_num); -extern int twl4030_exit_irq(void); +extern void twl4030_exit_irq(void); extern int twl4030_init_chip_irq(const char *chip); #endif /* __TWL_CORE_H__ */ diff --git a/drivers/mfd/twl4030-irq.c b/drivers/mfd/twl4030-irq.c index ab417438d1faa4c8f3734ddad4b4c01a2dffa595..4f576f0160a94ee7f34b70863b361dee33357907 100644 --- a/drivers/mfd/twl4030-irq.c +++ b/drivers/mfd/twl4030-irq.c @@ -753,14 +753,11 @@ fail: return status; } -int twl4030_exit_irq(void) +void twl4030_exit_irq(void) { /* FIXME undo twl_init_irq() */ - if (twl4030_irq_base) { + if (twl4030_irq_base) pr_err("twl4030: can't yet clean up IRQs?\n"); - return -ENOSYS; - } - return 0; } int twl4030_init_chip_irq(const char *chip) diff --git a/drivers/mfd/twl6030-irq.c b/drivers/mfd/twl6030-irq.c index 97af6c2a6007b70cb357ca7b043a7594ed1122b8..3c03681c124c044ae942aee5ccb223ce70ded8bc 100644 --- a/drivers/mfd/twl6030-irq.c +++ b/drivers/mfd/twl6030-irq.c @@ -438,7 +438,7 @@ fail_irq: return status; } -int twl6030_exit_irq(void) +void twl6030_exit_irq(void) { if (twl6030_irq && twl6030_irq->twl_irq) { unregister_pm_notifier(&twl6030_irq->pm_nb); @@ -453,6 +453,5 @@ int twl6030_exit_irq(void) * in this module. */ } - return 0; } diff --git a/drivers/misc/cxl/api.c b/drivers/misc/cxl/api.c index b493de962153ba627af0e3b7dd3f059d5620e91e..d85c5653086357f5e11762d53901e0fdecf8d963 100644 --- a/drivers/misc/cxl/api.c +++ b/drivers/misc/cxl/api.c @@ -12,6 +12,7 @@ #include #include #include +#include #include "cxl.h" diff --git a/drivers/misc/cxl/cxl.h b/drivers/misc/cxl/cxl.h index 5dc0f6093f9d92aa267c1f733cc39c848900c3f2..7a6dd91987fd869ce1bee6f8b570f7e06a9c7e34 100644 --- a/drivers/misc/cxl/cxl.h +++ b/drivers/misc/cxl/cxl.h @@ -25,6 +25,8 @@ extern uint cxl_verbose; +struct property; + #define CXL_TIMEOUT 5 /* diff --git a/drivers/misc/cxl/cxllib.c b/drivers/misc/cxl/cxllib.c index 53b9198564269c6ffb6e647a1cc1c54bda833cff..e5fe0a171472fe99d7450347cb47ba3168bd9527 100644 --- a/drivers/misc/cxl/cxllib.c +++ b/drivers/misc/cxl/cxllib.c @@ -5,6 +5,7 @@ #include #include +#include #include #include diff --git a/drivers/misc/cxl/flash.c b/drivers/misc/cxl/flash.c index 5b93ff51d82a545088d8a9c83bc133bb0fe177e3..eee9decc121ed4467d233f13eb92bb1012661cc7 100644 --- a/drivers/misc/cxl/flash.c +++ b/drivers/misc/cxl/flash.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include "cxl.h" diff --git a/drivers/misc/cxl/guest.c b/drivers/misc/cxl/guest.c index 9d485c9e3fff0de8b373292f9c5fff8435e70afa..3321c014913c3a2093dbb3696f8277b1a78de6cc 100644 --- a/drivers/misc/cxl/guest.c +++ b/drivers/misc/cxl/guest.c @@ -6,6 +6,8 @@ #include #include #include +#include +#include #include "cxl.h" #include "hcalls.h" diff --git a/drivers/misc/cxl/irq.c b/drivers/misc/cxl/irq.c index 4cb829d5d873cae0bade953f7b12b759662c664d..5f0e2dcebb3494b6298694ae2a486b77f1905075 100644 --- a/drivers/misc/cxl/irq.c +++ b/drivers/misc/cxl/irq.c @@ -4,6 +4,7 @@ */ #include +#include #include #include #include diff --git a/drivers/misc/cxl/main.c b/drivers/misc/cxl/main.c index 43b312d06e3efc1cecd1d4a67ff49c5c45004b6a..c1fbf6f588f7af8f2c1e8094b08ea1cc3fd3dfcb 100644 --- a/drivers/misc/cxl/main.c +++ b/drivers/misc/cxl/main.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include diff --git a/drivers/misc/cxl/native.c b/drivers/misc/cxl/native.c index 1a7f228360416de9e72ee024dc6dd76f42ab35bd..50b0c44bb8d70eaecd68c1c6a3cdd2484245cd2e 100644 --- a/drivers/misc/cxl/native.c +++ b/drivers/misc/cxl/native.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include diff --git a/drivers/misc/ocxl/afu_irq.c b/drivers/misc/ocxl/afu_irq.c index ecdcfae025b7b35995e42ba6335dc1a9f0076ef3..a06920b7e049a76a79b09d005f5889fd6e5d71a7 100644 --- a/drivers/misc/ocxl/afu_irq.c +++ b/drivers/misc/ocxl/afu_irq.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0+ // Copyright 2017 IBM Corp. #include +#include #include #include #include "ocxl_internal.h" diff --git a/drivers/misc/ocxl/file.c b/drivers/misc/ocxl/file.c index d881f5e40ad9edb5f07ebdca9dccf00c9df263c7..6777c419a8da2a3ac3d24bd11da7da28ae7e9d3e 100644 --- a/drivers/misc/ocxl/file.c +++ b/drivers/misc/ocxl/file.c @@ -556,7 +556,9 @@ int ocxl_file_register_afu(struct ocxl_afu *afu) err_unregister: ocxl_sysfs_unregister_afu(info); // safe to call even if register failed + free_minor(info); device_unregister(&info->dev); + return rc; err_put: ocxl_afu_put(afu); free_minor(info); diff --git a/drivers/misc/ocxl/link.c b/drivers/misc/ocxl/link.c index 9670d02c927f036b19ae69b9105f77ad4641881f..4cf4c55a5f0063a573b9e3d6cc2d1b853831755f 100644 --- a/drivers/misc/ocxl/link.c +++ b/drivers/misc/ocxl/link.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index af6c3c329076fe85fc24a35c22a79caf6f7795d1..d6144978e32d5d977b65a4cf8c3f0f9cef4f34b1 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -508,7 +508,7 @@ config MMC_OMAP_HS config MMC_WBSD tristate "Winbond W83L51xD SD/MMC Card Interface support" - depends on ISA_DMA_API && !M68K + depends on ISA_DMA_API help This selects the Winbond(R) W83L51xD Secure digital and Multimedia card Interface. diff --git a/drivers/nvdimm/btt_devs.c b/drivers/nvdimm/btt_devs.c index e5a58520d39827a17f32802090618810094798c8..fabbb31f2c35db326de8554a41c062ba51c039de 100644 --- a/drivers/nvdimm/btt_devs.c +++ b/drivers/nvdimm/btt_devs.c @@ -50,14 +50,14 @@ static ssize_t sector_size_store(struct device *dev, struct nd_btt *nd_btt = to_nd_btt(dev); ssize_t rc; - nd_device_lock(dev); + device_lock(dev); nvdimm_bus_lock(dev); rc = nd_size_select_store(dev, buf, &nd_btt->lbasize, btt_lbasize_supported); dev_dbg(dev, "result: %zd wrote: %s%s", rc, buf, buf[len - 1] == '\n' ? "" : "\n"); nvdimm_bus_unlock(dev); - nd_device_unlock(dev); + device_unlock(dev); return rc ? rc : len; } @@ -79,11 +79,11 @@ static ssize_t uuid_store(struct device *dev, struct nd_btt *nd_btt = to_nd_btt(dev); ssize_t rc; - nd_device_lock(dev); + device_lock(dev); rc = nd_uuid_store(dev, &nd_btt->uuid, buf, len); dev_dbg(dev, "result: %zd wrote: %s%s", rc, buf, buf[len - 1] == '\n' ? "" : "\n"); - nd_device_unlock(dev); + device_unlock(dev); return rc ? rc : len; } @@ -108,13 +108,13 @@ static ssize_t namespace_store(struct device *dev, struct nd_btt *nd_btt = to_nd_btt(dev); ssize_t rc; - nd_device_lock(dev); + device_lock(dev); nvdimm_bus_lock(dev); rc = nd_namespace_store(dev, &nd_btt->ndns, buf, len); dev_dbg(dev, "result: %zd wrote: %s%s", rc, buf, buf[len - 1] == '\n' ? "" : "\n"); nvdimm_bus_unlock(dev); - nd_device_unlock(dev); + device_unlock(dev); return rc; } @@ -126,14 +126,14 @@ static ssize_t size_show(struct device *dev, struct nd_btt *nd_btt = to_nd_btt(dev); ssize_t rc; - nd_device_lock(dev); + device_lock(dev); if (dev->driver) rc = sprintf(buf, "%llu\n", nd_btt->size); else { /* no size to convey if the btt instance is disabled */ rc = -ENXIO; } - nd_device_unlock(dev); + device_unlock(dev); return rc; } @@ -178,6 +178,8 @@ bool is_nd_btt(struct device *dev) } EXPORT_SYMBOL(is_nd_btt); +static struct lock_class_key nvdimm_btt_key; + static struct device *__nd_btt_create(struct nd_region *nd_region, unsigned long lbasize, uuid_t *uuid, struct nd_namespace_common *ndns) @@ -205,6 +207,7 @@ static struct device *__nd_btt_create(struct nd_region *nd_region, dev->parent = &nd_region->dev; dev->type = &nd_btt_device_type; device_initialize(&nd_btt->dev); + lockdep_set_class(&nd_btt->dev.mutex, &nvdimm_btt_key); if (ndns && !__nd_attach_ndns(&nd_btt->dev, ndns, &nd_btt->ndns)) { dev_dbg(&ndns->dev, "failed, already claimed by %s\n", dev_name(ndns->claim)); @@ -225,7 +228,7 @@ struct device *nd_btt_create(struct nd_region *nd_region) { struct device *dev = __nd_btt_create(nd_region, 0, NULL, NULL); - __nd_device_register(dev); + nd_device_register(dev); return dev; } @@ -324,7 +327,7 @@ static int __nd_btt_probe(struct nd_btt *nd_btt, if (!nd_btt->uuid) return -ENOMEM; - __nd_device_register(&nd_btt->dev); + nd_device_register(&nd_btt->dev); return 0; } diff --git a/drivers/nvdimm/bus.c b/drivers/nvdimm/bus.c index 7b0d1443217a3cda30764432789b5a42c41e7721..a4fc17db707c9b99afcbad8342f093a55516d6ea 100644 --- a/drivers/nvdimm/bus.c +++ b/drivers/nvdimm/bus.c @@ -88,10 +88,7 @@ static int nvdimm_bus_probe(struct device *dev) dev->driver->name, dev_name(dev)); nvdimm_bus_probe_start(nvdimm_bus); - debug_nvdimm_lock(dev); rc = nd_drv->probe(dev); - debug_nvdimm_unlock(dev); - if ((rc == 0 || rc == -EOPNOTSUPP) && dev->parent && is_nd_region(dev->parent)) nd_region_advance_seeds(to_nd_region(dev->parent), dev); @@ -111,11 +108,8 @@ static void nvdimm_bus_remove(struct device *dev) struct module *provider = to_bus_provider(dev); struct nvdimm_bus *nvdimm_bus = walk_to_nvdimm_bus(dev); - if (nd_drv->remove) { - debug_nvdimm_lock(dev); + if (nd_drv->remove) nd_drv->remove(dev); - debug_nvdimm_unlock(dev); - } dev_dbg(&nvdimm_bus->dev, "%s.remove(%s)\n", dev->driver->name, dev_name(dev)); @@ -139,7 +133,7 @@ static void nvdimm_bus_shutdown(struct device *dev) void nd_device_notify(struct device *dev, enum nvdimm_event event) { - nd_device_lock(dev); + device_lock(dev); if (dev->driver) { struct nd_device_driver *nd_drv; @@ -147,7 +141,7 @@ void nd_device_notify(struct device *dev, enum nvdimm_event event) if (nd_drv->notify) nd_drv->notify(dev, event); } - nd_device_unlock(dev); + device_unlock(dev); } EXPORT_SYMBOL(nd_device_notify); @@ -334,6 +328,8 @@ struct nvdimm_bus *nvdimm_to_bus(struct nvdimm *nvdimm) } EXPORT_SYMBOL_GPL(nvdimm_to_bus); +static struct lock_class_key nvdimm_bus_key; + struct nvdimm_bus *nvdimm_bus_register(struct device *parent, struct nvdimm_bus_descriptor *nd_desc) { @@ -360,6 +356,7 @@ struct nvdimm_bus *nvdimm_bus_register(struct device *parent, nvdimm_bus->dev.bus = &nvdimm_bus_type; nvdimm_bus->dev.of_node = nd_desc->of_node; device_initialize(&nvdimm_bus->dev); + lockdep_set_class(&nvdimm_bus->dev.mutex, &nvdimm_bus_key); device_set_pm_not_required(&nvdimm_bus->dev); rc = dev_set_name(&nvdimm_bus->dev, "ndbus%d", nvdimm_bus->id); if (rc) @@ -511,7 +508,7 @@ static void nd_async_device_unregister(void *d, async_cookie_t cookie) put_device(dev); } -void __nd_device_register(struct device *dev) +void nd_device_register(struct device *dev) { if (!dev) return; @@ -537,12 +534,6 @@ void __nd_device_register(struct device *dev) async_schedule_dev_domain(nd_async_device_register, dev, &nd_async_domain); } - -void nd_device_register(struct device *dev) -{ - device_initialize(dev); - __nd_device_register(dev); -} EXPORT_SYMBOL(nd_device_register); void nd_device_unregister(struct device *dev, enum nd_async_mode mode) @@ -572,9 +563,9 @@ void nd_device_unregister(struct device *dev, enum nd_async_mode mode) * or otherwise let the async path handle it if the * unregistration was already queued. */ - nd_device_lock(dev); + device_lock(dev); killed = kill_device(dev); - nd_device_unlock(dev); + device_unlock(dev); if (!killed) return; @@ -724,6 +715,8 @@ static void ndctl_release(struct device *dev) kfree(dev); } +static struct lock_class_key nvdimm_ndctl_key; + int nvdimm_bus_create_ndctl(struct nvdimm_bus *nvdimm_bus) { dev_t devt = MKDEV(nvdimm_bus_major, nvdimm_bus->id); @@ -734,6 +727,7 @@ int nvdimm_bus_create_ndctl(struct nvdimm_bus *nvdimm_bus) if (!dev) return -ENOMEM; device_initialize(dev); + lockdep_set_class(&dev->mutex, &nvdimm_ndctl_key); device_set_pm_not_required(dev); dev->class = nd_class; dev->parent = &nvdimm_bus->dev; @@ -930,10 +924,10 @@ void wait_nvdimm_bus_probe_idle(struct device *dev) if (nvdimm_bus->probe_active == 0) break; nvdimm_bus_unlock(dev); - nd_device_unlock(dev); + device_unlock(dev); wait_event(nvdimm_bus->wait, nvdimm_bus->probe_active == 0); - nd_device_lock(dev); + device_lock(dev); nvdimm_bus_lock(dev); } while (true); } @@ -1167,7 +1161,7 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, struct nvdimm *nvdimm, goto out; } - nd_device_lock(dev); + device_lock(dev); nvdimm_bus_lock(dev); rc = nd_cmd_clear_to_send(nvdimm_bus, nvdimm, func, buf); if (rc) @@ -1189,7 +1183,7 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, struct nvdimm *nvdimm, out_unlock: nvdimm_bus_unlock(dev); - nd_device_unlock(dev); + device_unlock(dev); out: kfree(in_env); kfree(out_env); diff --git a/drivers/nvdimm/core.c b/drivers/nvdimm/core.c index 69a03358817f1c9a78d7b695d34183b7776d0fb4..d91799b71d23a3d8bb0d71505224eb94fc4f338a 100644 --- a/drivers/nvdimm/core.c +++ b/drivers/nvdimm/core.c @@ -215,7 +215,7 @@ EXPORT_SYMBOL_GPL(to_nvdimm_bus_dev); * * Enforce that uuids can only be changed while the device is disabled * (driver detached) - * LOCKING: expects nd_device_lock() is held on entry + * LOCKING: expects device_lock() is held on entry */ int nd_uuid_store(struct device *dev, uuid_t **uuid_out, const char *buf, size_t len) @@ -316,15 +316,15 @@ static DEVICE_ATTR_RO(provider); static int flush_namespaces(struct device *dev, void *data) { - nd_device_lock(dev); - nd_device_unlock(dev); + device_lock(dev); + device_unlock(dev); return 0; } static int flush_regions_dimms(struct device *dev, void *data) { - nd_device_lock(dev); - nd_device_unlock(dev); + device_lock(dev); + device_unlock(dev); device_for_each_child(dev, NULL, flush_namespaces); return 0; } @@ -368,9 +368,7 @@ static ssize_t capability_show(struct device *dev, if (!nd_desc->fw_ops) return -EOPNOTSUPP; - nvdimm_bus_lock(dev); cap = nd_desc->fw_ops->capability(nd_desc); - nvdimm_bus_unlock(dev); switch (cap) { case NVDIMM_FWA_CAP_QUIESCE: @@ -395,10 +393,8 @@ static ssize_t activate_show(struct device *dev, if (!nd_desc->fw_ops) return -EOPNOTSUPP; - nvdimm_bus_lock(dev); cap = nd_desc->fw_ops->capability(nd_desc); state = nd_desc->fw_ops->activate_state(nd_desc); - nvdimm_bus_unlock(dev); if (cap < NVDIMM_FWA_CAP_QUIESCE) return -EOPNOTSUPP; @@ -443,7 +439,6 @@ static ssize_t activate_store(struct device *dev, else return -EINVAL; - nvdimm_bus_lock(dev); state = nd_desc->fw_ops->activate_state(nd_desc); switch (state) { @@ -461,7 +456,6 @@ static ssize_t activate_store(struct device *dev, default: rc = -ENXIO; } - nvdimm_bus_unlock(dev); if (rc == 0) rc = len; @@ -484,10 +478,7 @@ static umode_t nvdimm_bus_firmware_visible(struct kobject *kobj, struct attribut if (!nd_desc->fw_ops) return 0; - nvdimm_bus_lock(dev); cap = nd_desc->fw_ops->capability(nd_desc); - nvdimm_bus_unlock(dev); - if (cap < NVDIMM_FWA_CAP_QUIESCE) return 0; diff --git a/drivers/nvdimm/dax_devs.c b/drivers/nvdimm/dax_devs.c index 99965077bac4f83fab28b7083b1031fc0ed4534a..7f4a9d28b67023a401d7648d7917d101d4825785 100644 --- a/drivers/nvdimm/dax_devs.c +++ b/drivers/nvdimm/dax_devs.c @@ -80,7 +80,7 @@ struct device *nd_dax_create(struct nd_region *nd_region) nd_dax = nd_dax_alloc(nd_region); if (nd_dax) dev = nd_pfn_devinit(&nd_dax->nd_pfn, NULL); - __nd_device_register(dev); + nd_device_register(dev); return dev; } @@ -119,7 +119,7 @@ int nd_dax_probe(struct device *dev, struct nd_namespace_common *ndns) nd_detach_ndns(dax_dev, &nd_pfn->ndns); put_device(dax_dev); } else - __nd_device_register(dax_dev); + nd_device_register(dax_dev); return rc; } diff --git a/drivers/nvdimm/dimm_devs.c b/drivers/nvdimm/dimm_devs.c index ee507eed42b530119c03507326587b092bb6da5c..c7c9805774911f434332b9a722cbffcacc86ac23 100644 --- a/drivers/nvdimm/dimm_devs.c +++ b/drivers/nvdimm/dimm_devs.c @@ -341,9 +341,9 @@ static ssize_t available_slots_show(struct device *dev, { ssize_t rc; - nd_device_lock(dev); + device_lock(dev); rc = __available_slots_show(dev_get_drvdata(dev), buf); - nd_device_unlock(dev); + device_unlock(dev); return rc; } @@ -386,12 +386,12 @@ static ssize_t security_store(struct device *dev, * done while probing is idle and the DIMM is not in active use * in any region. */ - nd_device_lock(dev); + device_lock(dev); nvdimm_bus_lock(dev); wait_nvdimm_bus_probe_idle(dev); rc = nvdimm_security_store(dev, buf, len); nvdimm_bus_unlock(dev); - nd_device_unlock(dev); + device_unlock(dev); return rc; } @@ -570,6 +570,8 @@ bool is_nvdimm(struct device *dev) return dev->type == &nvdimm_device_type; } +static struct lock_class_key nvdimm_key; + struct nvdimm *__nvdimm_create(struct nvdimm_bus *nvdimm_bus, void *provider_data, const struct attribute_group **groups, unsigned long flags, unsigned long cmd_mask, int num_flush, @@ -613,6 +615,8 @@ struct nvdimm *__nvdimm_create(struct nvdimm_bus *nvdimm_bus, /* get security state and extended (master) state */ nvdimm->sec.flags = nvdimm_security_flags(nvdimm, NVDIMM_USER); nvdimm->sec.ext_flags = nvdimm_security_flags(nvdimm, NVDIMM_MASTER); + device_initialize(dev); + lockdep_set_class(&dev->mutex, &nvdimm_key); nd_device_register(dev); return nvdimm; diff --git a/drivers/nvdimm/namespace_devs.c b/drivers/nvdimm/namespace_devs.c index 62b83b2e26e3f3c7d6c9b502cef5841f29432658..bf4f5c09d9b1b3685eb359b64733335d729061fc 100644 --- a/drivers/nvdimm/namespace_devs.c +++ b/drivers/nvdimm/namespace_devs.c @@ -264,7 +264,7 @@ static ssize_t alt_name_store(struct device *dev, struct nd_region *nd_region = to_nd_region(dev->parent); ssize_t rc; - nd_device_lock(dev); + device_lock(dev); nvdimm_bus_lock(dev); wait_nvdimm_bus_probe_idle(dev); rc = __alt_name_store(dev, buf, len); @@ -272,7 +272,7 @@ static ssize_t alt_name_store(struct device *dev, rc = nd_namespace_label_update(nd_region, dev); dev_dbg(dev, "%s(%zd)\n", rc < 0 ? "fail " : "", rc); nvdimm_bus_unlock(dev); - nd_device_unlock(dev); + device_unlock(dev); return rc < 0 ? rc : len; } @@ -846,7 +846,7 @@ static ssize_t size_store(struct device *dev, if (rc) return rc; - nd_device_lock(dev); + device_lock(dev); nvdimm_bus_lock(dev); wait_nvdimm_bus_probe_idle(dev); rc = __size_store(dev, val); @@ -868,7 +868,7 @@ static ssize_t size_store(struct device *dev, dev_dbg(dev, "%llx %s (%d)\n", val, rc < 0 ? "fail" : "success", rc); nvdimm_bus_unlock(dev); - nd_device_unlock(dev); + device_unlock(dev); return rc < 0 ? rc : len; } @@ -1043,7 +1043,7 @@ static ssize_t uuid_store(struct device *dev, } else return -ENXIO; - nd_device_lock(dev); + device_lock(dev); nvdimm_bus_lock(dev); wait_nvdimm_bus_probe_idle(dev); if (to_ndns(dev)->claim) @@ -1059,7 +1059,7 @@ static ssize_t uuid_store(struct device *dev, dev_dbg(dev, "result: %zd wrote: %s%s", rc, buf, buf[len - 1] == '\n' ? "" : "\n"); nvdimm_bus_unlock(dev); - nd_device_unlock(dev); + device_unlock(dev); return rc < 0 ? rc : len; } @@ -1118,7 +1118,7 @@ static ssize_t sector_size_store(struct device *dev, } else return -ENXIO; - nd_device_lock(dev); + device_lock(dev); nvdimm_bus_lock(dev); if (to_ndns(dev)->claim) rc = -EBUSY; @@ -1129,7 +1129,7 @@ static ssize_t sector_size_store(struct device *dev, dev_dbg(dev, "result: %zd %s: %s%s", rc, rc < 0 ? "tried" : "wrote", buf, buf[len - 1] == '\n' ? "" : "\n"); nvdimm_bus_unlock(dev); - nd_device_unlock(dev); + device_unlock(dev); return rc ? rc : len; } @@ -1239,9 +1239,9 @@ static ssize_t holder_show(struct device *dev, struct nd_namespace_common *ndns = to_ndns(dev); ssize_t rc; - nd_device_lock(dev); + device_lock(dev); rc = sprintf(buf, "%s\n", ndns->claim ? dev_name(ndns->claim) : ""); - nd_device_unlock(dev); + device_unlock(dev); return rc; } @@ -1278,7 +1278,7 @@ static ssize_t holder_class_store(struct device *dev, struct nd_region *nd_region = to_nd_region(dev->parent); int rc; - nd_device_lock(dev); + device_lock(dev); nvdimm_bus_lock(dev); wait_nvdimm_bus_probe_idle(dev); rc = __holder_class_store(dev, buf); @@ -1286,7 +1286,7 @@ static ssize_t holder_class_store(struct device *dev, rc = nd_namespace_label_update(nd_region, dev); dev_dbg(dev, "%s(%d)\n", rc < 0 ? "fail " : "", rc); nvdimm_bus_unlock(dev); - nd_device_unlock(dev); + device_unlock(dev); return rc < 0 ? rc : len; } @@ -1297,7 +1297,7 @@ static ssize_t holder_class_show(struct device *dev, struct nd_namespace_common *ndns = to_ndns(dev); ssize_t rc; - nd_device_lock(dev); + device_lock(dev); if (ndns->claim_class == NVDIMM_CCLASS_NONE) rc = sprintf(buf, "\n"); else if ((ndns->claim_class == NVDIMM_CCLASS_BTT) || @@ -1309,7 +1309,7 @@ static ssize_t holder_class_show(struct device *dev, rc = sprintf(buf, "dax\n"); else rc = sprintf(buf, "\n"); - nd_device_unlock(dev); + device_unlock(dev); return rc; } @@ -1323,7 +1323,7 @@ static ssize_t mode_show(struct device *dev, char *mode; ssize_t rc; - nd_device_lock(dev); + device_lock(dev); claim = ndns->claim; if (claim && is_nd_btt(claim)) mode = "safe"; @@ -1336,7 +1336,7 @@ static ssize_t mode_show(struct device *dev, else mode = "raw"; rc = sprintf(buf, "%s\n", mode); - nd_device_unlock(dev); + device_unlock(dev); return rc; } @@ -1456,8 +1456,8 @@ struct nd_namespace_common *nvdimm_namespace_common_probe(struct device *dev) * Flush any in-progess probes / removals in the driver * for the raw personality of this namespace. */ - nd_device_lock(&ndns->dev); - nd_device_unlock(&ndns->dev); + device_lock(&ndns->dev); + device_unlock(&ndns->dev); if (ndns->dev.driver) { dev_dbg(&ndns->dev, "is active, can't bind %s\n", dev_name(dev)); @@ -1830,6 +1830,8 @@ static struct device *nd_namespace_pmem_create(struct nd_region *nd_region) return dev; } +static struct lock_class_key nvdimm_namespace_key; + void nd_region_create_ns_seed(struct nd_region *nd_region) { WARN_ON(!is_nvdimm_bus_locked(&nd_region->dev)); @@ -1845,8 +1847,12 @@ void nd_region_create_ns_seed(struct nd_region *nd_region) */ if (!nd_region->ns_seed) dev_err(&nd_region->dev, "failed to create namespace\n"); - else + else { + device_initialize(nd_region->ns_seed); + lockdep_set_class(&nd_region->ns_seed->mutex, + &nvdimm_namespace_key); nd_device_register(nd_region->ns_seed); + } } void nd_region_create_dax_seed(struct nd_region *nd_region) @@ -2200,6 +2206,8 @@ int nd_region_register_namespaces(struct nd_region *nd_region, int *err) if (id < 0) break; dev_set_name(dev, "namespace%d.%d", nd_region->id, id); + device_initialize(dev); + lockdep_set_class(&dev->mutex, &nvdimm_namespace_key); nd_device_register(dev); } if (i) diff --git a/drivers/nvdimm/nd-core.h b/drivers/nvdimm/nd-core.h index 448f9dcb4bb7d706585c9a702dbd3c69010cda9a..cc86ee09d7c081172d1257363e51a301378de684 100644 --- a/drivers/nvdimm/nd-core.h +++ b/drivers/nvdimm/nd-core.h @@ -106,7 +106,7 @@ void nd_region_create_dax_seed(struct nd_region *nd_region); int nvdimm_bus_create_ndctl(struct nvdimm_bus *nvdimm_bus); void nvdimm_bus_destroy_ndctl(struct nvdimm_bus *nvdimm_bus); void nd_synchronize(void); -void __nd_device_register(struct device *dev); +void nd_device_register(struct device *dev); struct nd_label_id; char *nd_label_gen_id(struct nd_label_id *label_id, const uuid_t *uuid, u32 flags); @@ -161,70 +161,4 @@ static inline void devm_nsio_disable(struct device *dev, { } #endif - -#ifdef CONFIG_PROVE_NVDIMM_LOCKING -extern struct class *nd_class; - -enum { - LOCK_BUS, - LOCK_NDCTL, - LOCK_REGION, - LOCK_DIMM = LOCK_REGION, - LOCK_NAMESPACE, - LOCK_CLAIM, -}; - -static inline void debug_nvdimm_lock(struct device *dev) -{ - if (is_nd_region(dev)) - mutex_lock_nested(&dev->lockdep_mutex, LOCK_REGION); - else if (is_nvdimm(dev)) - mutex_lock_nested(&dev->lockdep_mutex, LOCK_DIMM); - else if (is_nd_btt(dev) || is_nd_pfn(dev) || is_nd_dax(dev)) - mutex_lock_nested(&dev->lockdep_mutex, LOCK_CLAIM); - else if (dev->parent && (is_nd_region(dev->parent))) - mutex_lock_nested(&dev->lockdep_mutex, LOCK_NAMESPACE); - else if (is_nvdimm_bus(dev)) - mutex_lock_nested(&dev->lockdep_mutex, LOCK_BUS); - else if (dev->class && dev->class == nd_class) - mutex_lock_nested(&dev->lockdep_mutex, LOCK_NDCTL); - else - dev_WARN(dev, "unknown lock level\n"); -} - -static inline void debug_nvdimm_unlock(struct device *dev) -{ - mutex_unlock(&dev->lockdep_mutex); -} - -static inline void nd_device_lock(struct device *dev) -{ - device_lock(dev); - debug_nvdimm_lock(dev); -} - -static inline void nd_device_unlock(struct device *dev) -{ - debug_nvdimm_unlock(dev); - device_unlock(dev); -} -#else -static inline void nd_device_lock(struct device *dev) -{ - device_lock(dev); -} - -static inline void nd_device_unlock(struct device *dev) -{ - device_unlock(dev); -} - -static inline void debug_nvdimm_lock(struct device *dev) -{ -} - -static inline void debug_nvdimm_unlock(struct device *dev) -{ -} -#endif #endif /* __ND_CORE_H__ */ diff --git a/drivers/nvdimm/pfn_devs.c b/drivers/nvdimm/pfn_devs.c index c31e184bfa45e923208ec8158d146cf3759fa09a..0e92ab4b32833a45ab3a60f8ef3cc3607f5a40e1 100644 --- a/drivers/nvdimm/pfn_devs.c +++ b/drivers/nvdimm/pfn_devs.c @@ -55,7 +55,7 @@ static ssize_t mode_store(struct device *dev, struct nd_pfn *nd_pfn = to_nd_pfn_safe(dev); ssize_t rc = 0; - nd_device_lock(dev); + device_lock(dev); nvdimm_bus_lock(dev); if (dev->driver) rc = -EBUSY; @@ -77,7 +77,7 @@ static ssize_t mode_store(struct device *dev, dev_dbg(dev, "result: %zd wrote: %s%s", rc, buf, buf[len - 1] == '\n' ? "" : "\n"); nvdimm_bus_unlock(dev); - nd_device_unlock(dev); + device_unlock(dev); return rc ? rc : len; } @@ -123,14 +123,14 @@ static ssize_t align_store(struct device *dev, unsigned long aligns[MAX_NVDIMM_ALIGN] = { [0] = 0, }; ssize_t rc; - nd_device_lock(dev); + device_lock(dev); nvdimm_bus_lock(dev); rc = nd_size_select_store(dev, buf, &nd_pfn->align, nd_pfn_supported_alignments(aligns)); dev_dbg(dev, "result: %zd wrote: %s%s", rc, buf, buf[len - 1] == '\n' ? "" : "\n"); nvdimm_bus_unlock(dev); - nd_device_unlock(dev); + device_unlock(dev); return rc ? rc : len; } @@ -152,11 +152,11 @@ static ssize_t uuid_store(struct device *dev, struct nd_pfn *nd_pfn = to_nd_pfn_safe(dev); ssize_t rc; - nd_device_lock(dev); + device_lock(dev); rc = nd_uuid_store(dev, &nd_pfn->uuid, buf, len); dev_dbg(dev, "result: %zd wrote: %s%s", rc, buf, buf[len - 1] == '\n' ? "" : "\n"); - nd_device_unlock(dev); + device_unlock(dev); return rc ? rc : len; } @@ -181,13 +181,13 @@ static ssize_t namespace_store(struct device *dev, struct nd_pfn *nd_pfn = to_nd_pfn_safe(dev); ssize_t rc; - nd_device_lock(dev); + device_lock(dev); nvdimm_bus_lock(dev); rc = nd_namespace_store(dev, &nd_pfn->ndns, buf, len); dev_dbg(dev, "result: %zd wrote: %s%s", rc, buf, buf[len - 1] == '\n' ? "" : "\n"); nvdimm_bus_unlock(dev); - nd_device_unlock(dev); + device_unlock(dev); return rc; } @@ -199,7 +199,7 @@ static ssize_t resource_show(struct device *dev, struct nd_pfn *nd_pfn = to_nd_pfn_safe(dev); ssize_t rc; - nd_device_lock(dev); + device_lock(dev); if (dev->driver) { struct nd_pfn_sb *pfn_sb = nd_pfn->pfn_sb; u64 offset = __le64_to_cpu(pfn_sb->dataoff); @@ -213,7 +213,7 @@ static ssize_t resource_show(struct device *dev, /* no address to convey if the pfn instance is disabled */ rc = -ENXIO; } - nd_device_unlock(dev); + device_unlock(dev); return rc; } @@ -225,7 +225,7 @@ static ssize_t size_show(struct device *dev, struct nd_pfn *nd_pfn = to_nd_pfn_safe(dev); ssize_t rc; - nd_device_lock(dev); + device_lock(dev); if (dev->driver) { struct nd_pfn_sb *pfn_sb = nd_pfn->pfn_sb; u64 offset = __le64_to_cpu(pfn_sb->dataoff); @@ -241,7 +241,7 @@ static ssize_t size_show(struct device *dev, /* no size to convey if the pfn instance is disabled */ rc = -ENXIO; } - nd_device_unlock(dev); + device_unlock(dev); return rc; } @@ -291,6 +291,8 @@ bool is_nd_pfn(struct device *dev) } EXPORT_SYMBOL(is_nd_pfn); +static struct lock_class_key nvdimm_pfn_key; + struct device *nd_pfn_devinit(struct nd_pfn *nd_pfn, struct nd_namespace_common *ndns) { @@ -303,6 +305,7 @@ struct device *nd_pfn_devinit(struct nd_pfn *nd_pfn, nd_pfn->align = nd_pfn_default_alignment(); dev = &nd_pfn->dev; device_initialize(&nd_pfn->dev); + lockdep_set_class(&nd_pfn->dev.mutex, &nvdimm_pfn_key); if (ndns && !__nd_attach_ndns(&nd_pfn->dev, ndns, &nd_pfn->ndns)) { dev_dbg(&ndns->dev, "failed, already claimed by %s\n", dev_name(ndns->claim)); @@ -346,7 +349,7 @@ struct device *nd_pfn_create(struct nd_region *nd_region) nd_pfn = nd_pfn_alloc(nd_region); dev = nd_pfn_devinit(nd_pfn, NULL); - __nd_device_register(dev); + nd_device_register(dev); return dev; } @@ -643,7 +646,7 @@ int nd_pfn_probe(struct device *dev, struct nd_namespace_common *ndns) nd_detach_ndns(pfn_dev, &nd_pfn->ndns); put_device(pfn_dev); } else - __nd_device_register(pfn_dev); + nd_device_register(pfn_dev); return rc; } diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c index 58d95242a836b07e45d71c8aea8a141bf68511a4..629d10fcf53b2c0e828e6b9641189562b105b293 100644 --- a/drivers/nvdimm/pmem.c +++ b/drivers/nvdimm/pmem.c @@ -45,9 +45,25 @@ static struct nd_region *to_region(struct pmem_device *pmem) return to_nd_region(to_dev(pmem)->parent); } -static void hwpoison_clear(struct pmem_device *pmem, - phys_addr_t phys, unsigned int len) +static phys_addr_t to_phys(struct pmem_device *pmem, phys_addr_t offset) { + return pmem->phys_addr + offset; +} + +static sector_t to_sect(struct pmem_device *pmem, phys_addr_t offset) +{ + return (offset - pmem->data_offset) >> SECTOR_SHIFT; +} + +static phys_addr_t to_offset(struct pmem_device *pmem, sector_t sector) +{ + return (sector << SECTOR_SHIFT) + pmem->data_offset; +} + +static void pmem_mkpage_present(struct pmem_device *pmem, phys_addr_t offset, + unsigned int len) +{ + phys_addr_t phys = to_phys(pmem, offset); unsigned long pfn_start, pfn_end, pfn; /* only pmem in the linear map supports HWPoison */ @@ -69,33 +85,40 @@ static void hwpoison_clear(struct pmem_device *pmem, } } -static blk_status_t pmem_clear_poison(struct pmem_device *pmem, - phys_addr_t offset, unsigned int len) +static void pmem_clear_bb(struct pmem_device *pmem, sector_t sector, long blks) { - struct device *dev = to_dev(pmem); - sector_t sector; - long cleared; - blk_status_t rc = BLK_STS_OK; + if (blks == 0) + return; + badblocks_clear(&pmem->bb, sector, blks); + if (pmem->bb_state) + sysfs_notify_dirent(pmem->bb_state); +} - sector = (offset - pmem->data_offset) / 512; +static long __pmem_clear_poison(struct pmem_device *pmem, + phys_addr_t offset, unsigned int len) +{ + phys_addr_t phys = to_phys(pmem, offset); + long cleared = nvdimm_clear_poison(to_dev(pmem), phys, len); - cleared = nvdimm_clear_poison(dev, pmem->phys_addr + offset, len); - if (cleared < len) - rc = BLK_STS_IOERR; - if (cleared > 0 && cleared / 512) { - hwpoison_clear(pmem, pmem->phys_addr + offset, cleared); - cleared /= 512; - dev_dbg(dev, "%#llx clear %ld sector%s\n", - (unsigned long long) sector, cleared, - cleared > 1 ? "s" : ""); - badblocks_clear(&pmem->bb, sector, cleared); - if (pmem->bb_state) - sysfs_notify_dirent(pmem->bb_state); + if (cleared > 0) { + pmem_mkpage_present(pmem, offset, cleared); + arch_invalidate_pmem(pmem->virt_addr + offset, len); } + return cleared; +} + +static blk_status_t pmem_clear_poison(struct pmem_device *pmem, + phys_addr_t offset, unsigned int len) +{ + long cleared = __pmem_clear_poison(pmem, offset, len); - arch_invalidate_pmem(pmem->virt_addr + offset, len); + if (cleared < 0) + return BLK_STS_IOERR; - return rc; + pmem_clear_bb(pmem, to_sect(pmem, offset), cleared >> SECTOR_SHIFT); + if (cleared < len) + return BLK_STS_IOERR; + return BLK_STS_OK; } static void write_pmem(void *pmem_addr, struct page *page, @@ -143,7 +166,7 @@ static blk_status_t pmem_do_read(struct pmem_device *pmem, sector_t sector, unsigned int len) { blk_status_t rc; - phys_addr_t pmem_off = sector * 512 + pmem->data_offset; + phys_addr_t pmem_off = to_offset(pmem, sector); void *pmem_addr = pmem->virt_addr + pmem_off; if (unlikely(is_bad_pmem(&pmem->bb, sector, len))) @@ -158,36 +181,20 @@ static blk_status_t pmem_do_write(struct pmem_device *pmem, struct page *page, unsigned int page_off, sector_t sector, unsigned int len) { - blk_status_t rc = BLK_STS_OK; - bool bad_pmem = false; - phys_addr_t pmem_off = sector * 512 + pmem->data_offset; + phys_addr_t pmem_off = to_offset(pmem, sector); void *pmem_addr = pmem->virt_addr + pmem_off; - if (unlikely(is_bad_pmem(&pmem->bb, sector, len))) - bad_pmem = true; + if (unlikely(is_bad_pmem(&pmem->bb, sector, len))) { + blk_status_t rc = pmem_clear_poison(pmem, pmem_off, len); + + if (rc != BLK_STS_OK) + return rc; + } - /* - * Note that we write the data both before and after - * clearing poison. The write before clear poison - * handles situations where the latest written data is - * preserved and the clear poison operation simply marks - * the address range as valid without changing the data. - * In this case application software can assume that an - * interrupted write will either return the new good - * data or an error. - * - * However, if pmem_clear_poison() leaves the data in an - * indeterminate state we need to perform the write - * after clear poison. - */ flush_dcache_page(page); write_pmem(pmem_addr, page, page_off, len); - if (unlikely(bad_pmem)) { - rc = pmem_clear_poison(pmem, pmem_off, len); - write_pmem(pmem_addr, page, page_off, len); - } - return rc; + return BLK_STS_OK; } static void pmem_submit_bio(struct bio *bio) @@ -255,24 +262,47 @@ static int pmem_rw_page(struct block_device *bdev, sector_t sector, /* see "strong" declaration in tools/testing/nvdimm/pmem-dax.c */ __weak long __pmem_direct_access(struct pmem_device *pmem, pgoff_t pgoff, - long nr_pages, void **kaddr, pfn_t *pfn) + long nr_pages, enum dax_access_mode mode, void **kaddr, + pfn_t *pfn) { resource_size_t offset = PFN_PHYS(pgoff) + pmem->data_offset; - - if (unlikely(is_bad_pmem(&pmem->bb, PFN_PHYS(pgoff) / 512, - PFN_PHYS(nr_pages)))) - return -EIO; + sector_t sector = PFN_PHYS(pgoff) >> SECTOR_SHIFT; + unsigned int num = PFN_PHYS(nr_pages) >> SECTOR_SHIFT; + struct badblocks *bb = &pmem->bb; + sector_t first_bad; + int num_bad; if (kaddr) *kaddr = pmem->virt_addr + offset; if (pfn) *pfn = phys_to_pfn_t(pmem->phys_addr + offset, pmem->pfn_flags); + if (bb->count && + badblocks_check(bb, sector, num, &first_bad, &num_bad)) { + long actual_nr; + + if (mode != DAX_RECOVERY_WRITE) + return -EIO; + + /* + * Set the recovery stride is set to kernel page size because + * the underlying driver and firmware clear poison functions + * don't appear to handle large chunk(such as 2MiB) reliably. + */ + actual_nr = PHYS_PFN( + PAGE_ALIGN((first_bad - sector) << SECTOR_SHIFT)); + dev_dbg(pmem->bb.dev, "start sector(%llu), nr_pages(%ld), first_bad(%llu), actual_nr(%ld)\n", + sector, nr_pages, first_bad, actual_nr); + if (actual_nr) + return actual_nr; + return 1; + } + /* - * If badblocks are present, limit known good range to the - * requested range. + * If badblocks are present but not in the range, limit known good range + * to the requested range. */ - if (unlikely(pmem->bb.count)) + if (bb->count) return nr_pages; return PHYS_PFN(pmem->size - pmem->pfn_pad - offset); } @@ -294,16 +324,73 @@ static int pmem_dax_zero_page_range(struct dax_device *dax_dev, pgoff_t pgoff, } static long pmem_dax_direct_access(struct dax_device *dax_dev, - pgoff_t pgoff, long nr_pages, void **kaddr, pfn_t *pfn) + pgoff_t pgoff, long nr_pages, enum dax_access_mode mode, + void **kaddr, pfn_t *pfn) +{ + struct pmem_device *pmem = dax_get_private(dax_dev); + + return __pmem_direct_access(pmem, pgoff, nr_pages, mode, kaddr, pfn); +} + +/* + * The recovery write thread started out as a normal pwrite thread and + * when the filesystem was told about potential media error in the + * range, filesystem turns the normal pwrite to a dax_recovery_write. + * + * The recovery write consists of clearing media poison, clearing page + * HWPoison bit, reenable page-wide read-write permission, flush the + * caches and finally write. A competing pread thread will be held + * off during the recovery process since data read back might not be + * valid, and this is achieved by clearing the badblock records after + * the recovery write is complete. Competing recovery write threads + * are already serialized by writer lock held by dax_iomap_rw(). + */ +static size_t pmem_recovery_write(struct dax_device *dax_dev, pgoff_t pgoff, + void *addr, size_t bytes, struct iov_iter *i) { struct pmem_device *pmem = dax_get_private(dax_dev); + size_t olen, len, off; + phys_addr_t pmem_off; + struct device *dev = pmem->bb.dev; + long cleared; + + off = offset_in_page(addr); + len = PFN_PHYS(PFN_UP(off + bytes)); + if (!is_bad_pmem(&pmem->bb, PFN_PHYS(pgoff) >> SECTOR_SHIFT, len)) + return _copy_from_iter_flushcache(addr, bytes, i); + + /* + * Not page-aligned range cannot be recovered. This should not + * happen unless something else went wrong. + */ + if (off || !PAGE_ALIGNED(bytes)) { + dev_dbg(dev, "Found poison, but addr(%p) or bytes(%#zx) not page aligned\n", + addr, bytes); + return 0; + } + + pmem_off = PFN_PHYS(pgoff) + pmem->data_offset; + cleared = __pmem_clear_poison(pmem, pmem_off, len); + if (cleared > 0 && cleared < len) { + dev_dbg(dev, "poison cleared only %ld out of %zu bytes\n", + cleared, len); + return 0; + } + if (cleared < 0) { + dev_dbg(dev, "poison clear failed: %ld\n", cleared); + return 0; + } + + olen = _copy_from_iter_flushcache(addr, bytes, i); + pmem_clear_bb(pmem, to_sect(pmem, pmem_off), cleared >> SECTOR_SHIFT); - return __pmem_direct_access(pmem, pgoff, nr_pages, kaddr, pfn); + return olen; } static const struct dax_operations pmem_dax_ops = { .direct_access = pmem_dax_direct_access, .zero_page_range = pmem_dax_zero_page_range, + .recovery_write = pmem_recovery_write, }; static ssize_t write_cache_show(struct device *dev, @@ -573,7 +660,7 @@ static void nd_pmem_remove(struct device *dev) nvdimm_namespace_detach_btt(to_nd_btt(dev)); else { /* - * Note, this assumes nd_device_lock() context to not + * Note, this assumes device_lock() context to not * race nd_pmem_notify() */ sysfs_put(pmem->bb_state); diff --git a/drivers/nvdimm/pmem.h b/drivers/nvdimm/pmem.h index 1f51a23614299b14be825981963b3464d7f79be8..392b0b38acb97c0a87d8464b0fbcf85b5a2fffa0 100644 --- a/drivers/nvdimm/pmem.h +++ b/drivers/nvdimm/pmem.h @@ -8,6 +8,8 @@ #include #include +enum dax_access_mode; + /* this definition is in it's own header for tools/testing/nvdimm to consume */ struct pmem_device { /* One contiguous memory region per device */ @@ -28,7 +30,8 @@ struct pmem_device { }; long __pmem_direct_access(struct pmem_device *pmem, pgoff_t pgoff, - long nr_pages, void **kaddr, pfn_t *pfn); + long nr_pages, enum dax_access_mode mode, void **kaddr, + pfn_t *pfn); #ifdef CONFIG_MEMORY_FAILURE static inline bool test_and_clear_pmem_poison(struct page *page) diff --git a/drivers/nvdimm/region.c b/drivers/nvdimm/region.c index 188560b1c110de6cba1b9175c249c593539e6dea..390123d293ea18f8e1a80215710ff2d94c0420a0 100644 --- a/drivers/nvdimm/region.c +++ b/drivers/nvdimm/region.c @@ -95,7 +95,7 @@ static void nd_region_remove(struct device *dev) nvdimm_bus_unlock(dev); /* - * Note, this assumes nd_device_lock() context to not race + * Note, this assumes device_lock() context to not race * nd_region_notify() */ sysfs_put(nd_region->bb_state); diff --git a/drivers/nvdimm/region_devs.c b/drivers/nvdimm/region_devs.c index 0cb274c2b508b30229431fed9e250cb5b41bcf4f..d976260eca7ad85b2b32447ad1fe103734834b3e 100644 --- a/drivers/nvdimm/region_devs.c +++ b/drivers/nvdimm/region_devs.c @@ -279,7 +279,7 @@ static ssize_t set_cookie_show(struct device *dev, * the v1.1 namespace label cookie definition. To read all this * data we need to wait for probing to settle. */ - nd_device_lock(dev); + device_lock(dev); nvdimm_bus_lock(dev); wait_nvdimm_bus_probe_idle(dev); if (nd_region->ndr_mappings) { @@ -296,7 +296,7 @@ static ssize_t set_cookie_show(struct device *dev, } } nvdimm_bus_unlock(dev); - nd_device_unlock(dev); + device_unlock(dev); if (rc) return rc; @@ -353,12 +353,12 @@ static ssize_t available_size_show(struct device *dev, * memory nvdimm_bus_lock() is dropped, but that's userspace's * problem to not race itself. */ - nd_device_lock(dev); + device_lock(dev); nvdimm_bus_lock(dev); wait_nvdimm_bus_probe_idle(dev); available = nd_region_available_dpa(nd_region); nvdimm_bus_unlock(dev); - nd_device_unlock(dev); + device_unlock(dev); return sprintf(buf, "%llu\n", available); } @@ -370,12 +370,12 @@ static ssize_t max_available_extent_show(struct device *dev, struct nd_region *nd_region = to_nd_region(dev); unsigned long long available = 0; - nd_device_lock(dev); + device_lock(dev); nvdimm_bus_lock(dev); wait_nvdimm_bus_probe_idle(dev); available = nd_region_allocatable_dpa(nd_region); nvdimm_bus_unlock(dev); - nd_device_unlock(dev); + device_unlock(dev); return sprintf(buf, "%llu\n", available); } @@ -549,12 +549,12 @@ static ssize_t region_badblocks_show(struct device *dev, struct nd_region *nd_region = to_nd_region(dev); ssize_t rc; - nd_device_lock(dev); + device_lock(dev); if (dev->driver) rc = badblocks_show(&nd_region->bb, buf, 0); else rc = -ENXIO; - nd_device_unlock(dev); + device_unlock(dev); return rc; } @@ -949,6 +949,8 @@ static unsigned long default_align(struct nd_region *nd_region) return align; } +static struct lock_class_key nvdimm_region_key; + static struct nd_region *nd_region_create(struct nvdimm_bus *nvdimm_bus, struct nd_region_desc *ndr_desc, const struct device_type *dev_type, const char *caller) @@ -1035,6 +1037,8 @@ static struct nd_region *nd_region_create(struct nvdimm_bus *nvdimm_bus, else nd_region->flush = NULL; + device_initialize(dev); + lockdep_set_class(&dev->mutex, &nvdimm_region_key); nd_device_register(dev); return nd_region; diff --git a/drivers/nvdimm/security.c b/drivers/nvdimm/security.c index 4b80150e4afa742533400b7e39f9aa8cd5ac88e7..b5aa55c61461621138fd110873ce94cb889f70ee 100644 --- a/drivers/nvdimm/security.c +++ b/drivers/nvdimm/security.c @@ -379,11 +379,6 @@ static int security_overwrite(struct nvdimm *nvdimm, unsigned int keyid) || !nvdimm->sec.flags) return -EOPNOTSUPP; - if (dev->driver == NULL) { - dev_dbg(dev, "Unable to overwrite while DIMM active.\n"); - return -EINVAL; - } - rc = check_security_state(nvdimm); if (rc) return rc; diff --git a/drivers/opp/core.c b/drivers/opp/core.c index 7404072522982e53c6da07a8a87c283d40b2a415..84063eaebb91d1e7ce9db1725a1b2088d7ad5787 100644 --- a/drivers/opp/core.c +++ b/drivers/opp/core.c @@ -456,103 +456,6 @@ struct dev_pm_opp *dev_pm_opp_find_freq_exact(struct device *dev, } EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_exact); -/** - * dev_pm_opp_find_level_exact() - search for an exact level - * @dev: device for which we do this operation - * @level: level to search for - * - * Return: Searches for exact match in the opp table and returns pointer to the - * matching opp if found, else returns ERR_PTR in case of error and should - * be handled using IS_ERR. Error return values can be: - * EINVAL: for bad pointer - * ERANGE: no match found for search - * ENODEV: if device not found in list of registered devices - * - * The callers are required to call dev_pm_opp_put() for the returned OPP after - * use. - */ -struct dev_pm_opp *dev_pm_opp_find_level_exact(struct device *dev, - unsigned int level) -{ - struct opp_table *opp_table; - struct dev_pm_opp *temp_opp, *opp = ERR_PTR(-ERANGE); - - opp_table = _find_opp_table(dev); - if (IS_ERR(opp_table)) { - int r = PTR_ERR(opp_table); - - dev_err(dev, "%s: OPP table not found (%d)\n", __func__, r); - return ERR_PTR(r); - } - - mutex_lock(&opp_table->lock); - - list_for_each_entry(temp_opp, &opp_table->opp_list, node) { - if (temp_opp->level == level) { - opp = temp_opp; - - /* Increment the reference count of OPP */ - dev_pm_opp_get(opp); - break; - } - } - - mutex_unlock(&opp_table->lock); - dev_pm_opp_put_opp_table(opp_table); - - return opp; -} -EXPORT_SYMBOL_GPL(dev_pm_opp_find_level_exact); - -/** - * dev_pm_opp_find_level_ceil() - search for an rounded up level - * @dev: device for which we do this operation - * @level: level to search for - * - * Return: Searches for rounded up match in the opp table and returns pointer - * to the matching opp if found, else returns ERR_PTR in case of error and - * should be handled using IS_ERR. Error return values can be: - * EINVAL: for bad pointer - * ERANGE: no match found for search - * ENODEV: if device not found in list of registered devices - * - * The callers are required to call dev_pm_opp_put() for the returned OPP after - * use. - */ -struct dev_pm_opp *dev_pm_opp_find_level_ceil(struct device *dev, - unsigned int *level) -{ - struct opp_table *opp_table; - struct dev_pm_opp *temp_opp, *opp = ERR_PTR(-ERANGE); - - opp_table = _find_opp_table(dev); - if (IS_ERR(opp_table)) { - int r = PTR_ERR(opp_table); - - dev_err(dev, "%s: OPP table not found (%d)\n", __func__, r); - return ERR_PTR(r); - } - - mutex_lock(&opp_table->lock); - - list_for_each_entry(temp_opp, &opp_table->opp_list, node) { - if (temp_opp->available && temp_opp->level >= *level) { - opp = temp_opp; - *level = opp->level; - - /* Increment the reference count of OPP */ - dev_pm_opp_get(opp); - break; - } - } - - mutex_unlock(&opp_table->lock); - dev_pm_opp_put_opp_table(opp_table); - - return opp; -} -EXPORT_SYMBOL_GPL(dev_pm_opp_find_level_ceil); - static noinline struct dev_pm_opp *_find_freq_ceil(struct opp_table *opp_table, unsigned long *freq) { @@ -729,6 +632,223 @@ struct dev_pm_opp *dev_pm_opp_find_freq_ceil_by_volt(struct device *dev, } EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_ceil_by_volt); +/** + * dev_pm_opp_find_level_exact() - search for an exact level + * @dev: device for which we do this operation + * @level: level to search for + * + * Return: Searches for exact match in the opp table and returns pointer to the + * matching opp if found, else returns ERR_PTR in case of error and should + * be handled using IS_ERR. Error return values can be: + * EINVAL: for bad pointer + * ERANGE: no match found for search + * ENODEV: if device not found in list of registered devices + * + * The callers are required to call dev_pm_opp_put() for the returned OPP after + * use. + */ +struct dev_pm_opp *dev_pm_opp_find_level_exact(struct device *dev, + unsigned int level) +{ + struct opp_table *opp_table; + struct dev_pm_opp *temp_opp, *opp = ERR_PTR(-ERANGE); + + opp_table = _find_opp_table(dev); + if (IS_ERR(opp_table)) { + int r = PTR_ERR(opp_table); + + dev_err(dev, "%s: OPP table not found (%d)\n", __func__, r); + return ERR_PTR(r); + } + + mutex_lock(&opp_table->lock); + + list_for_each_entry(temp_opp, &opp_table->opp_list, node) { + if (temp_opp->level == level) { + opp = temp_opp; + + /* Increment the reference count of OPP */ + dev_pm_opp_get(opp); + break; + } + } + + mutex_unlock(&opp_table->lock); + dev_pm_opp_put_opp_table(opp_table); + + return opp; +} +EXPORT_SYMBOL_GPL(dev_pm_opp_find_level_exact); + +/** + * dev_pm_opp_find_level_ceil() - search for an rounded up level + * @dev: device for which we do this operation + * @level: level to search for + * + * Return: Searches for rounded up match in the opp table and returns pointer + * to the matching opp if found, else returns ERR_PTR in case of error and + * should be handled using IS_ERR. Error return values can be: + * EINVAL: for bad pointer + * ERANGE: no match found for search + * ENODEV: if device not found in list of registered devices + * + * The callers are required to call dev_pm_opp_put() for the returned OPP after + * use. + */ +struct dev_pm_opp *dev_pm_opp_find_level_ceil(struct device *dev, + unsigned int *level) +{ + struct opp_table *opp_table; + struct dev_pm_opp *temp_opp, *opp = ERR_PTR(-ERANGE); + + opp_table = _find_opp_table(dev); + if (IS_ERR(opp_table)) { + int r = PTR_ERR(opp_table); + + dev_err(dev, "%s: OPP table not found (%d)\n", __func__, r); + return ERR_PTR(r); + } + + mutex_lock(&opp_table->lock); + + list_for_each_entry(temp_opp, &opp_table->opp_list, node) { + if (temp_opp->available && temp_opp->level >= *level) { + opp = temp_opp; + *level = opp->level; + + /* Increment the reference count of OPP */ + dev_pm_opp_get(opp); + break; + } + } + + mutex_unlock(&opp_table->lock); + dev_pm_opp_put_opp_table(opp_table); + + return opp; +} +EXPORT_SYMBOL_GPL(dev_pm_opp_find_level_ceil); + +/** + * dev_pm_opp_find_bw_ceil() - Search for a rounded ceil bandwidth + * @dev: device for which we do this operation + * @freq: start bandwidth + * @index: which bandwidth to compare, in case of OPPs with several values + * + * Search for the matching floor *available* OPP from a starting bandwidth + * for a device. + * + * Return: matching *opp and refreshes *bw accordingly, else returns + * ERR_PTR in case of error and should be handled using IS_ERR. Error return + * values can be: + * EINVAL: for bad pointer + * ERANGE: no match found for search + * ENODEV: if device not found in list of registered devices + * + * The callers are required to call dev_pm_opp_put() for the returned OPP after + * use. + */ +struct dev_pm_opp *dev_pm_opp_find_bw_ceil(struct device *dev, + unsigned int *bw, int index) +{ + struct opp_table *opp_table; + struct dev_pm_opp *temp_opp, *opp = ERR_PTR(-ERANGE); + + if (!dev || !bw) { + dev_err(dev, "%s: Invalid argument bw=%p\n", __func__, bw); + return ERR_PTR(-EINVAL); + } + + opp_table = _find_opp_table(dev); + if (IS_ERR(opp_table)) + return ERR_CAST(opp_table); + + if (index >= opp_table->path_count) + return ERR_PTR(-EINVAL); + + mutex_lock(&opp_table->lock); + + list_for_each_entry(temp_opp, &opp_table->opp_list, node) { + if (temp_opp->available && temp_opp->bandwidth) { + if (temp_opp->bandwidth[index].peak >= *bw) { + opp = temp_opp; + *bw = opp->bandwidth[index].peak; + + /* Increment the reference count of OPP */ + dev_pm_opp_get(opp); + break; + } + } + } + + mutex_unlock(&opp_table->lock); + dev_pm_opp_put_opp_table(opp_table); + + return opp; +} +EXPORT_SYMBOL_GPL(dev_pm_opp_find_bw_ceil); + +/** + * dev_pm_opp_find_bw_floor() - Search for a rounded floor bandwidth + * @dev: device for which we do this operation + * @freq: start bandwidth + * @index: which bandwidth to compare, in case of OPPs with several values + * + * Search for the matching floor *available* OPP from a starting bandwidth + * for a device. + * + * Return: matching *opp and refreshes *bw accordingly, else returns + * ERR_PTR in case of error and should be handled using IS_ERR. Error return + * values can be: + * EINVAL: for bad pointer + * ERANGE: no match found for search + * ENODEV: if device not found in list of registered devices + * + * The callers are required to call dev_pm_opp_put() for the returned OPP after + * use. + */ +struct dev_pm_opp *dev_pm_opp_find_bw_floor(struct device *dev, + unsigned int *bw, int index) +{ + struct opp_table *opp_table; + struct dev_pm_opp *temp_opp, *opp = ERR_PTR(-ERANGE); + + if (!dev || !bw) { + dev_err(dev, "%s: Invalid argument bw=%p\n", __func__, bw); + return ERR_PTR(-EINVAL); + } + + opp_table = _find_opp_table(dev); + if (IS_ERR(opp_table)) + return ERR_CAST(opp_table); + + if (index >= opp_table->path_count) + return ERR_PTR(-EINVAL); + + mutex_lock(&opp_table->lock); + + list_for_each_entry(temp_opp, &opp_table->opp_list, node) { + if (temp_opp->available && temp_opp->bandwidth) { + /* go to the next node, before choosing prev */ + if (temp_opp->bandwidth[index].peak > *bw) + break; + opp = temp_opp; + } + } + + /* Increment the reference count of OPP */ + if (!IS_ERR(opp)) + dev_pm_opp_get(opp); + mutex_unlock(&opp_table->lock); + dev_pm_opp_put_opp_table(opp_table); + + if (!IS_ERR(opp)) + *bw = opp->bandwidth[index].peak; + + return opp; +} +EXPORT_SYMBOL_GPL(dev_pm_opp_find_bw_floor); + static int _set_opp_voltage(struct device *dev, struct regulator *reg, struct dev_pm_opp_supply *supply) { @@ -1486,9 +1606,8 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_put); */ void dev_pm_opp_remove(struct device *dev, unsigned long freq) { - struct dev_pm_opp *opp; + struct dev_pm_opp *opp = NULL, *iter; struct opp_table *opp_table; - bool found = false; opp_table = _find_opp_table(dev); if (IS_ERR(opp_table)) @@ -1496,16 +1615,16 @@ void dev_pm_opp_remove(struct device *dev, unsigned long freq) mutex_lock(&opp_table->lock); - list_for_each_entry(opp, &opp_table->opp_list, node) { - if (opp->rate == freq) { - found = true; + list_for_each_entry(iter, &opp_table->opp_list, node) { + if (iter->rate == freq) { + opp = iter; break; } } mutex_unlock(&opp_table->lock); - if (found) { + if (opp) { dev_pm_opp_put(opp); /* Drop the reference taken by dev_pm_opp_add() */ @@ -2019,10 +2138,9 @@ struct opp_table *dev_pm_opp_set_regulators(struct device *dev, for (i = 0; i < count; i++) { reg = regulator_get_optional(dev, names[i]); if (IS_ERR(reg)) { - ret = PTR_ERR(reg); - if (ret != -EPROBE_DEFER) - dev_err(dev, "%s: no regulator (%s) found: %d\n", - __func__, names[i], ret); + ret = dev_err_probe(dev, PTR_ERR(reg), + "%s: no regulator (%s) found\n", + __func__, names[i]); goto free_regulators; } @@ -2168,11 +2286,8 @@ struct opp_table *dev_pm_opp_set_clkname(struct device *dev, const char *name) /* Find clk for the device */ opp_table->clk = clk_get(dev, name); if (IS_ERR(opp_table->clk)) { - ret = PTR_ERR(opp_table->clk); - if (ret != -EPROBE_DEFER) { - dev_err(dev, "%s: Couldn't find clock: %d\n", __func__, - ret); - } + ret = dev_err_probe(dev, PTR_ERR(opp_table->clk), + "%s: Couldn't find clock\n", __func__); goto err; } diff --git a/drivers/opp/debugfs.c b/drivers/opp/debugfs.c index 3fcc1f97f2d107dbfdc9b5f3e767028d5bc9aa91..1b6e5c55c3edb5b2ee937eff0a8e67767450d202 100644 --- a/drivers/opp/debugfs.c +++ b/drivers/opp/debugfs.c @@ -195,14 +195,18 @@ void opp_debug_register(struct opp_device *opp_dev, struct opp_table *opp_table) static void opp_migrate_dentry(struct opp_device *opp_dev, struct opp_table *opp_table) { - struct opp_device *new_dev; + struct opp_device *new_dev = NULL, *iter; const struct device *dev; struct dentry *dentry; /* Look for next opp-dev */ - list_for_each_entry(new_dev, &opp_table->dev_list, node) - if (new_dev != opp_dev) + list_for_each_entry(iter, &opp_table->dev_list, node) + if (iter != opp_dev) { + new_dev = iter; break; + } + + BUG_ON(!new_dev); /* new_dev is guaranteed to be valid here */ dev = new_dev->dev; diff --git a/drivers/opp/of.c b/drivers/opp/of.c index 485ea980bde7d65841297a2c99c0acb51f1011ab..30394929d700e0abde673178ba890885ac7f7424 100644 --- a/drivers/opp/of.c +++ b/drivers/opp/of.c @@ -437,11 +437,11 @@ static int _bandwidth_supported(struct device *dev, struct opp_table *opp_table) /* Checking only first OPP is sufficient */ np = of_get_next_available_child(opp_np, NULL); + of_node_put(opp_np); if (!np) { dev_err(dev, "OPP table empty\n"); return -EINVAL; } - of_node_put(opp_np); prop = of_find_property(np, "opp-peak-kBps", NULL); of_node_put(np); diff --git a/drivers/pci/controller/pci-hyperv.c b/drivers/pci/controller/pci-hyperv.c index d270a204324e9cc556de9715b6d9470b28694583..db814f7b93baa1a9d84388858abb4a04f523561b 100644 --- a/drivers/pci/controller/pci-hyperv.c +++ b/drivers/pci/controller/pci-hyperv.c @@ -91,6 +91,13 @@ static enum pci_protocol_version_t pci_protocol_versions[] = { /* space for 32bit serial number as string */ #define SLOT_NAME_SIZE 11 +/* + * Size of requestor for VMbus; the value is based on the observation + * that having more than one request outstanding is 'rare', and so 64 + * should be generous in ensuring that we don't ever run out. + */ +#define HV_PCI_RQSTOR_SIZE 64 + /* * Message Types */ @@ -604,17 +611,19 @@ static unsigned int hv_msi_get_int_vector(struct irq_data *data) return cfg->vector; } -static void hv_set_msi_entry_from_desc(union hv_msi_entry *msi_entry, - struct msi_desc *msi_desc) -{ - msi_entry->address.as_uint32 = msi_desc->msg.address_lo; - msi_entry->data.as_uint32 = msi_desc->msg.data; -} - static int hv_msi_prepare(struct irq_domain *domain, struct device *dev, int nvec, msi_alloc_info_t *info) { - return pci_msi_prepare(domain, dev, nvec, info); + int ret = pci_msi_prepare(domain, dev, nvec, info); + + /* + * By using the interrupt remapper in the hypervisor IOMMU, contiguous + * CPU vectors is not needed for multi-MSI + */ + if (info->type == X86_IRQ_ALLOC_TYPE_PCI_MSI) + info->flags &= ~X86_IRQ_ALLOC_CONTIGUOUS_VECTORS; + + return ret; } /** @@ -631,6 +640,7 @@ static void hv_arch_irq_unmask(struct irq_data *data) { struct msi_desc *msi_desc = irq_data_get_msi_desc(data); struct hv_retarget_device_interrupt *params; + struct tran_int_desc *int_desc; struct hv_pcibus_device *hbus; struct cpumask *dest; cpumask_var_t tmp; @@ -645,6 +655,7 @@ static void hv_arch_irq_unmask(struct irq_data *data) pdev = msi_desc_to_pci_dev(msi_desc); pbus = pdev->bus; hbus = container_of(pbus->sysdata, struct hv_pcibus_device, sysdata); + int_desc = data->chip_data; spin_lock_irqsave(&hbus->retarget_msi_interrupt_lock, flags); @@ -652,7 +663,8 @@ static void hv_arch_irq_unmask(struct irq_data *data) memset(params, 0, sizeof(*params)); params->partition_id = HV_PARTITION_ID_SELF; params->int_entry.source = HV_INTERRUPT_SOURCE_MSI; - hv_set_msi_entry_from_desc(¶ms->int_entry.msi_entry, msi_desc); + params->int_entry.msi_entry.address.as_uint32 = int_desc->address & 0xffffffff; + params->int_entry.msi_entry.data.as_uint32 = int_desc->data; params->device_id = (hbus->hdev->dev_instance.b[5] << 24) | (hbus->hdev->dev_instance.b[4] << 16) | (hbus->hdev->dev_instance.b[7] << 8) | @@ -969,11 +981,7 @@ static void hv_pci_generic_compl(void *context, struct pci_response *resp, { struct hv_pci_compl *comp_pkt = context; - if (resp_packet_size >= offsetofend(struct pci_response, status)) - comp_pkt->completion_status = resp->status; - else - comp_pkt->completion_status = -1; - + comp_pkt->completion_status = resp->status; complete(&comp_pkt->host_event); } @@ -1513,6 +1521,10 @@ static void hv_int_desc_free(struct hv_pci_dev *hpdev, u8 buffer[sizeof(struct pci_delete_interrupt)]; } ctxt; + if (!int_desc->vector_count) { + kfree(int_desc); + return; + } memset(&ctxt, 0, sizeof(ctxt)); int_pkt = (struct pci_delete_interrupt *)&ctxt.pkt.message; int_pkt->message_type.type = @@ -1520,7 +1532,7 @@ static void hv_int_desc_free(struct hv_pci_dev *hpdev, int_pkt->wslot.slot = hpdev->desc.win_slot.slot; int_pkt->int_desc = *int_desc; vmbus_sendpacket(hpdev->hbus->hdev->channel, int_pkt, sizeof(*int_pkt), - (unsigned long)&ctxt.pkt, VM_PKT_DATA_INBAND, 0); + 0, VM_PKT_DATA_INBAND, 0); kfree(int_desc); } @@ -1590,19 +1602,24 @@ static void hv_pci_compose_compl(void *context, struct pci_response *resp, struct pci_create_int_response *int_resp = (struct pci_create_int_response *)resp; + if (resp_packet_size < sizeof(*int_resp)) { + comp_pkt->comp_pkt.completion_status = -1; + goto out; + } comp_pkt->comp_pkt.completion_status = resp->status; comp_pkt->int_desc = int_resp->int_desc; +out: complete(&comp_pkt->comp_pkt.host_event); } static u32 hv_compose_msi_req_v1( struct pci_create_interrupt *int_pkt, struct cpumask *affinity, - u32 slot, u8 vector) + u32 slot, u8 vector, u8 vector_count) { int_pkt->message_type.type = PCI_CREATE_INTERRUPT_MESSAGE; int_pkt->wslot.slot = slot; int_pkt->int_desc.vector = vector; - int_pkt->int_desc.vector_count = 1; + int_pkt->int_desc.vector_count = vector_count; int_pkt->int_desc.delivery_mode = DELIVERY_MODE; /* @@ -1625,14 +1642,14 @@ static int hv_compose_msi_req_get_cpu(struct cpumask *affinity) static u32 hv_compose_msi_req_v2( struct pci_create_interrupt2 *int_pkt, struct cpumask *affinity, - u32 slot, u8 vector) + u32 slot, u8 vector, u8 vector_count) { int cpu; int_pkt->message_type.type = PCI_CREATE_INTERRUPT_MESSAGE2; int_pkt->wslot.slot = slot; int_pkt->int_desc.vector = vector; - int_pkt->int_desc.vector_count = 1; + int_pkt->int_desc.vector_count = vector_count; int_pkt->int_desc.delivery_mode = DELIVERY_MODE; cpu = hv_compose_msi_req_get_cpu(affinity); int_pkt->int_desc.processor_array[0] = @@ -1644,7 +1661,7 @@ static u32 hv_compose_msi_req_v2( static u32 hv_compose_msi_req_v3( struct pci_create_interrupt3 *int_pkt, struct cpumask *affinity, - u32 slot, u32 vector) + u32 slot, u32 vector, u8 vector_count) { int cpu; @@ -1652,7 +1669,7 @@ static u32 hv_compose_msi_req_v3( int_pkt->wslot.slot = slot; int_pkt->int_desc.vector = vector; int_pkt->int_desc.reserved = 0; - int_pkt->int_desc.vector_count = 1; + int_pkt->int_desc.vector_count = vector_count; int_pkt->int_desc.delivery_mode = DELIVERY_MODE; cpu = hv_compose_msi_req_get_cpu(affinity); int_pkt->int_desc.processor_array[0] = @@ -1683,6 +1700,8 @@ static void hv_compose_msi_msg(struct irq_data *data, struct msi_msg *msg) struct cpumask *dest; struct compose_comp_ctxt comp; struct tran_int_desc *int_desc; + struct msi_desc *msi_desc; + u8 vector, vector_count; struct { struct pci_packet pci_pkt; union { @@ -1691,11 +1710,21 @@ static void hv_compose_msi_msg(struct irq_data *data, struct msi_msg *msg) struct pci_create_interrupt3 v3; } int_pkts; } __packed ctxt; - + u64 trans_id; u32 size; int ret; - pdev = msi_desc_to_pci_dev(irq_data_get_msi_desc(data)); + /* Reuse the previous allocation */ + if (data->chip_data) { + int_desc = data->chip_data; + msg->address_hi = int_desc->address >> 32; + msg->address_lo = int_desc->address & 0xffffffff; + msg->data = int_desc->data; + return; + } + + msi_desc = irq_data_get_msi_desc(data); + pdev = msi_desc_to_pci_dev(msi_desc); dest = irq_data_get_effective_affinity_mask(data); pbus = pdev->bus; hbus = container_of(pbus->sysdata, struct hv_pcibus_device, sysdata); @@ -1704,17 +1733,40 @@ static void hv_compose_msi_msg(struct irq_data *data, struct msi_msg *msg) if (!hpdev) goto return_null_message; - /* Free any previous message that might have already been composed. */ - if (data->chip_data) { - int_desc = data->chip_data; - data->chip_data = NULL; - hv_int_desc_free(hpdev, int_desc); - } - int_desc = kzalloc(sizeof(*int_desc), GFP_ATOMIC); if (!int_desc) goto drop_reference; + if (!msi_desc->pci.msi_attrib.is_msix && msi_desc->nvec_used > 1) { + /* + * If this is not the first MSI of Multi MSI, we already have + * a mapping. Can exit early. + */ + if (msi_desc->irq != data->irq) { + data->chip_data = int_desc; + int_desc->address = msi_desc->msg.address_lo | + (u64)msi_desc->msg.address_hi << 32; + int_desc->data = msi_desc->msg.data + + (data->irq - msi_desc->irq); + msg->address_hi = msi_desc->msg.address_hi; + msg->address_lo = msi_desc->msg.address_lo; + msg->data = int_desc->data; + put_pcichild(hpdev); + return; + } + /* + * The vector we select here is a dummy value. The correct + * value gets sent to the hypervisor in unmask(). This needs + * to be aligned with the count, and also not zero. Multi-msi + * is powers of 2 up to 32, so 32 will always work here. + */ + vector = 32; + vector_count = msi_desc->nvec_used; + } else { + vector = hv_msi_get_int_vector(data); + vector_count = 1; + } + memset(&ctxt, 0, sizeof(ctxt)); init_completion(&comp.comp_pkt.host_event); ctxt.pci_pkt.completion_func = hv_pci_compose_compl; @@ -1725,7 +1777,8 @@ static void hv_compose_msi_msg(struct irq_data *data, struct msi_msg *msg) size = hv_compose_msi_req_v1(&ctxt.int_pkts.v1, dest, hpdev->desc.win_slot.slot, - hv_msi_get_int_vector(data)); + vector, + vector_count); break; case PCI_PROTOCOL_VERSION_1_2: @@ -1733,14 +1786,16 @@ static void hv_compose_msi_msg(struct irq_data *data, struct msi_msg *msg) size = hv_compose_msi_req_v2(&ctxt.int_pkts.v2, dest, hpdev->desc.win_slot.slot, - hv_msi_get_int_vector(data)); + vector, + vector_count); break; case PCI_PROTOCOL_VERSION_1_4: size = hv_compose_msi_req_v3(&ctxt.int_pkts.v3, dest, hpdev->desc.win_slot.slot, - hv_msi_get_int_vector(data)); + vector, + vector_count); break; default: @@ -1753,10 +1808,10 @@ static void hv_compose_msi_msg(struct irq_data *data, struct msi_msg *msg) goto free_int_desc; } - ret = vmbus_sendpacket(hpdev->hbus->hdev->channel, &ctxt.int_pkts, - size, (unsigned long)&ctxt.pci_pkt, - VM_PKT_DATA_INBAND, - VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); + ret = vmbus_sendpacket_getid(hpdev->hbus->hdev->channel, &ctxt.int_pkts, + size, (unsigned long)&ctxt.pci_pkt, + &trans_id, VM_PKT_DATA_INBAND, + VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); if (ret) { dev_err(&hbus->hdev->device, "Sending request for interrupt failed: 0x%x", @@ -1835,6 +1890,15 @@ static void hv_compose_msi_msg(struct irq_data *data, struct msi_msg *msg) enable_tasklet: tasklet_enable(&channel->callback_event); + /* + * The completion packet on the stack becomes invalid after 'return'; + * remove the ID from the VMbus requestor if the identifier is still + * mapped to/associated with the packet. (The identifier could have + * been 're-used', i.e., already removed and (re-)mapped.) + * + * Cf. hv_pci_onchannelcallback(). + */ + vmbus_request_addr_match(channel, trans_id, (unsigned long)&ctxt.pci_pkt); free_int_desc: kfree(int_desc); drop_reference: @@ -2082,12 +2146,17 @@ static void prepopulate_bars(struct hv_pcibus_device *hbus) } } if (high_size <= 1 && low_size <= 1) { - /* Set the memory enable bit. */ - _hv_pcifront_read_config(hpdev, PCI_COMMAND, 2, - &command); - command |= PCI_COMMAND_MEMORY; - _hv_pcifront_write_config(hpdev, PCI_COMMAND, 2, - command); + /* + * No need to set the PCI_COMMAND_MEMORY bit as + * the core PCI driver doesn't require the bit + * to be pre-set. Actually here we intentionally + * keep the bit off so that the PCI BAR probing + * in the core PCI driver doesn't cause Hyper-V + * to unnecessarily unmap/map the virtual BARs + * from/to the physical BARs multiple times. + * This reduces the VM boot time significantly + * if the BAR sizes are huge. + */ break; } } @@ -2223,12 +2292,14 @@ static void q_resource_requirements(void *context, struct pci_response *resp, struct q_res_req_compl *completion = context; struct pci_q_res_req_response *q_res_req = (struct pci_q_res_req_response *)resp; + s32 status; int i; - if (resp->status < 0) { + status = (resp_packet_size < sizeof(*q_res_req)) ? -1 : resp->status; + if (status < 0) { dev_err(&completion->hpdev->hbus->hdev->device, "query resource requirements failed: %x\n", - resp->status); + status); } else { for (i = 0; i < PCI_STD_NUM_BARS; i++) { completion->hpdev->probed_bar[i] = @@ -2652,7 +2723,7 @@ static void hv_eject_device_work(struct work_struct *work) ejct_pkt->message_type.type = PCI_EJECTION_COMPLETE; ejct_pkt->wslot.slot = hpdev->desc.win_slot.slot; vmbus_sendpacket(hbus->hdev->channel, ejct_pkt, - sizeof(*ejct_pkt), (unsigned long)&ctxt.pkt, + sizeof(*ejct_pkt), 0, VM_PKT_DATA_INBAND, 0); /* For the get_pcichild() in hv_pci_eject_device() */ @@ -2699,8 +2770,9 @@ static void hv_pci_onchannelcallback(void *context) const int packet_size = 0x100; int ret; struct hv_pcibus_device *hbus = context; + struct vmbus_channel *chan = hbus->hdev->channel; u32 bytes_recvd; - u64 req_id; + u64 req_id, req_addr; struct vmpacket_descriptor *desc; unsigned char *buffer; int bufferlen = packet_size; @@ -2712,14 +2784,15 @@ static void hv_pci_onchannelcallback(void *context) struct pci_dev_inval_block *inval; struct pci_dev_incoming *dev_message; struct hv_pci_dev *hpdev; + unsigned long flags; buffer = kmalloc(bufferlen, GFP_ATOMIC); if (!buffer) return; while (1) { - ret = vmbus_recvpacket_raw(hbus->hdev->channel, buffer, - bufferlen, &bytes_recvd, &req_id); + ret = vmbus_recvpacket_raw(chan, buffer, bufferlen, + &bytes_recvd, &req_id); if (ret == -ENOBUFS) { kfree(buffer); @@ -2746,15 +2819,29 @@ static void hv_pci_onchannelcallback(void *context) switch (desc->type) { case VM_PKT_COMP: + lock_requestor(chan, flags); + req_addr = __vmbus_request_addr_match(chan, req_id, + VMBUS_RQST_ADDR_ANY); + if (req_addr == VMBUS_RQST_ERROR) { + unlock_requestor(chan, flags); + dev_err(&hbus->hdev->device, + "Invalid transaction ID %llx\n", + req_id); + break; + } + comp_packet = (struct pci_packet *)req_addr; + response = (struct pci_response *)buffer; /* - * The host is trusted, and thus it's safe to interpret - * this transaction ID as a pointer. + * Call ->completion_func() within the critical section to make + * sure that the packet pointer is still valid during the call: + * here 'valid' means that there's a task still waiting for the + * completion, and that the packet data is still on the waiting + * task's stack. Cf. hv_compose_msi_msg(). */ - comp_packet = (struct pci_packet *)req_id; - response = (struct pci_response *)buffer; comp_packet->completion_func(comp_packet->compl_ctxt, response, bytes_recvd); + unlock_requestor(chan, flags); break; case VM_PKT_DATA_INBAND: @@ -2764,7 +2851,8 @@ static void hv_pci_onchannelcallback(void *context) case PCI_BUS_RELATIONS: bus_rel = (struct pci_bus_relations *)buffer; - if (bytes_recvd < + if (bytes_recvd < sizeof(*bus_rel) || + bytes_recvd < struct_size(bus_rel, func, bus_rel->device_count)) { dev_err(&hbus->hdev->device, @@ -2778,7 +2866,8 @@ static void hv_pci_onchannelcallback(void *context) case PCI_BUS_RELATIONS2: bus_rel2 = (struct pci_bus_relations2 *)buffer; - if (bytes_recvd < + if (bytes_recvd < sizeof(*bus_rel2) || + bytes_recvd < struct_size(bus_rel2, func, bus_rel2->device_count)) { dev_err(&hbus->hdev->device, @@ -2792,6 +2881,11 @@ static void hv_pci_onchannelcallback(void *context) case PCI_EJECT: dev_message = (struct pci_dev_incoming *)buffer; + if (bytes_recvd < sizeof(*dev_message)) { + dev_err(&hbus->hdev->device, + "eject message too small\n"); + break; + } hpdev = get_pcichild_wslot(hbus, dev_message->wslot.slot); if (hpdev) { @@ -2803,6 +2897,11 @@ static void hv_pci_onchannelcallback(void *context) case PCI_INVALIDATE_BLOCK: inval = (struct pci_dev_inval_block *)buffer; + if (bytes_recvd < sizeof(*inval)) { + dev_err(&hbus->hdev->device, + "invalidate message too small\n"); + break; + } hpdev = get_pcichild_wslot(hbus, inval->wslot.slot); if (hpdev) { @@ -3431,6 +3530,10 @@ static int hv_pci_probe(struct hv_device *hdev, goto free_dom; } + hdev->channel->next_request_id_callback = vmbus_next_request_id; + hdev->channel->request_addr_callback = vmbus_request_addr; + hdev->channel->rqstor_size = HV_PCI_RQSTOR_SIZE; + ret = vmbus_open(hdev->channel, pci_ring_size, pci_ring_size, NULL, 0, hv_pci_onchannelcallback, hbus); if (ret) @@ -3561,6 +3664,7 @@ free_bus: static int hv_pci_bus_exit(struct hv_device *hdev, bool keep_devs) { struct hv_pcibus_device *hbus = hv_get_drvdata(hdev); + struct vmbus_channel *chan = hdev->channel; struct { struct pci_packet teardown_packet; u8 buffer[sizeof(struct pci_message)]; @@ -3568,13 +3672,14 @@ static int hv_pci_bus_exit(struct hv_device *hdev, bool keep_devs) struct hv_pci_compl comp_pkt; struct hv_pci_dev *hpdev, *tmp; unsigned long flags; + u64 trans_id; int ret; /* * After the host sends the RESCIND_CHANNEL message, it doesn't * access the per-channel ringbuffer any longer. */ - if (hdev->channel->rescind) + if (chan->rescind) return 0; if (!keep_devs) { @@ -3611,16 +3716,26 @@ static int hv_pci_bus_exit(struct hv_device *hdev, bool keep_devs) pkt.teardown_packet.compl_ctxt = &comp_pkt; pkt.teardown_packet.message[0].type = PCI_BUS_D0EXIT; - ret = vmbus_sendpacket(hdev->channel, &pkt.teardown_packet.message, - sizeof(struct pci_message), - (unsigned long)&pkt.teardown_packet, - VM_PKT_DATA_INBAND, - VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); + ret = vmbus_sendpacket_getid(chan, &pkt.teardown_packet.message, + sizeof(struct pci_message), + (unsigned long)&pkt.teardown_packet, + &trans_id, VM_PKT_DATA_INBAND, + VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); if (ret) return ret; - if (wait_for_completion_timeout(&comp_pkt.host_event, 10 * HZ) == 0) + if (wait_for_completion_timeout(&comp_pkt.host_event, 10 * HZ) == 0) { + /* + * The completion packet on the stack becomes invalid after + * 'return'; remove the ID from the VMbus requestor if the + * identifier is still mapped to/associated with the packet. + * + * Cf. hv_pci_onchannelcallback(). + */ + vmbus_request_addr_match(chan, trans_id, + (unsigned long)&pkt.teardown_packet); return -ETIMEDOUT; + } return 0; } @@ -3761,6 +3876,10 @@ static int hv_pci_resume(struct hv_device *hdev) hbus->state = hv_pcibus_init; + hdev->channel->next_request_id_callback = vmbus_next_request_id; + hdev->channel->request_addr_callback = vmbus_request_addr; + hdev->channel->rqstor_size = HV_PCI_RQSTOR_SIZE; + ret = vmbus_open(hdev->channel, pci_ring_size, pci_ring_size, NULL, 0, hv_pci_onchannelcallback, hbus); if (ret) diff --git a/drivers/pci/of.c b/drivers/pci/of.c index 6c1b81304665343edc37dbea468360bc261ad87a..196834ed44fe84595a696159dd42deb24ec42b71 100644 --- a/drivers/pci/of.c +++ b/drivers/pci/of.c @@ -369,7 +369,6 @@ static int devm_of_pci_get_host_bridge_resources(struct device *dev, dev_dbg(dev, "Parsing dma-ranges property...\n"); for_each_of_pci_range(&parser, &range) { - struct resource_entry *entry; /* * If we failed translation or got a zero-sized region * then skip this range @@ -393,12 +392,7 @@ static int devm_of_pci_get_host_bridge_resources(struct device *dev, goto failed; } - /* Keep the resource list sorted */ - resource_list_for_each_entry(entry, ib_resources) - if (entry->res->start > res->start) - break; - - pci_add_resource_offset(&entry->node, res, + pci_add_resource_offset(ib_resources, res, res->start - range.pci_addr); } diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 2f3b69adfc9eb771909d89c172b751345ec248e3..49238ddd39eec54a86873f2859963a80ab9568b9 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -20,6 +20,7 @@ #include #include #include +#include #include "pci.h" #include "pcie/portdrv.h" @@ -1620,6 +1621,7 @@ static int pci_bus_num_vf(struct device *dev) */ static int pci_dma_configure(struct device *dev) { + struct pci_driver *driver = to_pci_driver(dev->driver); struct device *bridge; int ret = 0; @@ -1635,9 +1637,24 @@ static int pci_dma_configure(struct device *dev) } pci_put_host_bridge_device(bridge); + + if (!ret && !driver->driver_managed_dma) { + ret = iommu_device_use_default_domain(dev); + if (ret) + arch_teardown_dma_ops(dev); + } + return ret; } +static void pci_dma_cleanup(struct device *dev) +{ + struct pci_driver *driver = to_pci_driver(dev->driver); + + if (!driver->driver_managed_dma) + iommu_device_unuse_default_domain(dev); +} + struct bus_type pci_bus_type = { .name = "pci", .match = pci_bus_match, @@ -1651,6 +1668,7 @@ struct bus_type pci_bus_type = { .pm = PCI_PM_OPS_PTR, .num_vf = pci_bus_num_vf, .dma_configure = pci_dma_configure, + .dma_cleanup = pci_dma_cleanup, }; EXPORT_SYMBOL(pci_bus_type); diff --git a/drivers/pci/pci-stub.c b/drivers/pci/pci-stub.c index e408099fea5257dfe3218282d138615d966ab2f0..d1f4c1ce7bd1b803176a46523c57fada8b984cc1 100644 --- a/drivers/pci/pci-stub.c +++ b/drivers/pci/pci-stub.c @@ -36,6 +36,7 @@ static struct pci_driver stub_driver = { .name = "pci-stub", .id_table = NULL, /* only dynamic id's */ .probe = pci_stub_probe, + .driver_managed_dma = true, }; static int __init pci_stub_init(void) diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c index 4b8801656ffbb8fdd3ac43d6b603e42b1a284976..7f8788a970ae18f1be9db6d7d2e863b0c82435bb 100644 --- a/drivers/pci/pcie/portdrv_pci.c +++ b/drivers/pci/pcie/portdrv_pci.c @@ -202,6 +202,8 @@ static struct pci_driver pcie_portdriver = { .err_handler = &pcie_portdrv_err_handler, + .driver_managed_dma = true, + .driver.pm = PCIE_PORTDRV_PM_OPS, }; diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c index 47e433e09c5ce319e97fe1384941d278c9d435ba..dad453054776806aa7a7a32e52fbe9ba30ccaf18 100644 --- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c +++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c @@ -358,6 +358,22 @@ static int bcm2835_gpio_direction_output(struct gpio_chip *chip, return 0; } +static int bcm2835_of_gpio_ranges_fallback(struct gpio_chip *gc, + struct device_node *np) +{ + struct pinctrl_dev *pctldev = of_pinctrl_get(np); + + of_node_put(np); + + if (!pctldev) + return 0; + + gpiochip_add_pin_range(gc, pinctrl_dev_get_devname(pctldev), 0, 0, + gc->ngpio); + + return 0; +} + static const struct gpio_chip bcm2835_gpio_chip = { .label = MODULE_NAME, .owner = THIS_MODULE, @@ -372,6 +388,7 @@ static const struct gpio_chip bcm2835_gpio_chip = { .base = -1, .ngpio = BCM2835_NUM_GPIOS, .can_sleep = false, + .of_gpio_ranges_fallback = bcm2835_of_gpio_ranges_fallback, }; static const struct gpio_chip bcm2711_gpio_chip = { @@ -388,6 +405,7 @@ static const struct gpio_chip bcm2711_gpio_chip = { .base = -1, .ngpio = BCM2711_NUM_GPIOS, .can_sleep = false, + .of_gpio_ranges_fallback = bcm2835_of_gpio_ranges_fallback, }; static void bcm2835_gpio_irq_handle_bank(struct bcm2835_pinctrl *pc, diff --git a/drivers/pinctrl/berlin/berlin-bg4ct.c b/drivers/pinctrl/berlin/berlin-bg4ct.c index 6a7fe929a68bd5bcca4558347c1f70fef39fc950..3026a3b3da2dd948209574732736f712ebc2beb5 100644 --- a/drivers/pinctrl/berlin/berlin-bg4ct.c +++ b/drivers/pinctrl/berlin/berlin-bg4ct.c @@ -460,8 +460,7 @@ static int berlin4ct_pinctrl_probe(struct platform_device *pdev) if (!rmconfig) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - base = devm_ioremap_resource(&pdev->dev, res); + base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); if (IS_ERR(base)) return PTR_ERR(base); diff --git a/drivers/pinctrl/freescale/Kconfig b/drivers/pinctrl/freescale/Kconfig index 453dc47f4fa4105dbaaff683d4e898bfee29ab35..d96b1130efd398db65573220a998540549eb0822 100644 --- a/drivers/pinctrl/freescale/Kconfig +++ b/drivers/pinctrl/freescale/Kconfig @@ -206,3 +206,10 @@ config PINCTRL_IMX23 config PINCTRL_IMX28 bool select PINCTRL_MXS + +config PINCTRL_IMXRT1170 + bool "IMXRT1170 pinctrl driver" + depends on ARCH_MXC + select PINCTRL_IMX + help + Say Y here to enable the imxrt1170 pinctrl driver diff --git a/drivers/pinctrl/freescale/Makefile b/drivers/pinctrl/freescale/Makefile index 9f5d1c090338b37f95bf9b04d341c23db6e8f977..647dff060477863cfc49c5fb6f2023cfe0e2d826 100644 --- a/drivers/pinctrl/freescale/Makefile +++ b/drivers/pinctrl/freescale/Makefile @@ -32,3 +32,4 @@ obj-$(CONFIG_PINCTRL_IMX23) += pinctrl-imx23.o obj-$(CONFIG_PINCTRL_IMX25) += pinctrl-imx25.o obj-$(CONFIG_PINCTRL_IMX28) += pinctrl-imx28.o obj-$(CONFIG_PINCTRL_IMXRT1050) += pinctrl-imxrt1050.o +obj-$(CONFIG_PINCTRL_IMXRT1170) += pinctrl-imxrt1170.o diff --git a/drivers/pinctrl/freescale/pinctrl-imxrt1170.c b/drivers/pinctrl/freescale/pinctrl-imxrt1170.c new file mode 100644 index 0000000000000000000000000000000000000000..5da1545fde919dee08243e3c45d9de7fab1ed847 --- /dev/null +++ b/drivers/pinctrl/freescale/pinctrl-imxrt1170.c @@ -0,0 +1,349 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2022 + * Author(s): Jesse Taube + */ + +#include +#include +#include +#include +#include + +#include "pinctrl-imx.h" + +enum imxrt1170_pads { + IMXRT1170_PAD_RESERVE0, + IMXRT1170_PAD_RESERVE1, + IMXRT1170_PAD_RESERVE2, + IMXRT1170_PAD_RESERVE3, + IMXRT1170_PAD_EMC_B1_00, + IMXRT1170_PAD_EMC_B1_01, + IMXRT1170_PAD_EMC_B1_02, + IMXRT1170_PAD_EMC_B1_03, + IMXRT1170_PAD_EMC_B1_04, + IMXRT1170_PAD_EMC_B1_05, + IMXRT1170_PAD_EMC_B1_06, + IMXRT1170_PAD_EMC_B1_07, + IMXRT1170_PAD_EMC_B1_08, + IMXRT1170_PAD_EMC_B1_09, + IMXRT1170_PAD_EMC_B1_10, + IMXRT1170_PAD_EMC_B1_11, + IMXRT1170_PAD_EMC_B1_12, + IMXRT1170_PAD_EMC_B1_13, + IMXRT1170_PAD_EMC_B1_14, + IMXRT1170_PAD_EMC_B1_15, + IMXRT1170_PAD_EMC_B1_16, + IMXRT1170_PAD_EMC_B1_17, + IMXRT1170_PAD_EMC_B1_18, + IMXRT1170_PAD_EMC_B1_19, + IMXRT1170_PAD_EMC_B1_20, + IMXRT1170_PAD_EMC_B1_21, + IMXRT1170_PAD_EMC_B1_22, + IMXRT1170_PAD_EMC_B1_23, + IMXRT1170_PAD_EMC_B1_24, + IMXRT1170_PAD_EMC_B1_25, + IMXRT1170_PAD_EMC_B1_26, + IMXRT1170_PAD_EMC_B1_27, + IMXRT1170_PAD_EMC_B1_28, + IMXRT1170_PAD_EMC_B1_29, + IMXRT1170_PAD_EMC_B1_30, + IMXRT1170_PAD_EMC_B1_31, + IMXRT1170_PAD_EMC_B1_32, + IMXRT1170_PAD_EMC_B1_33, + IMXRT1170_PAD_EMC_B1_34, + IMXRT1170_PAD_EMC_B1_35, + IMXRT1170_PAD_EMC_B1_36, + IMXRT1170_PAD_EMC_B1_37, + IMXRT1170_PAD_EMC_B1_38, + IMXRT1170_PAD_EMC_B1_39, + IMXRT1170_PAD_EMC_B1_40, + IMXRT1170_PAD_EMC_B1_41, + IMXRT1170_PAD_EMC_B2_00, + IMXRT1170_PAD_EMC_B2_01, + IMXRT1170_PAD_EMC_B2_02, + IMXRT1170_PAD_EMC_B2_03, + IMXRT1170_PAD_EMC_B2_04, + IMXRT1170_PAD_EMC_B2_05, + IMXRT1170_PAD_EMC_B2_06, + IMXRT1170_PAD_EMC_B2_07, + IMXRT1170_PAD_EMC_B2_08, + IMXRT1170_PAD_EMC_B2_09, + IMXRT1170_PAD_EMC_B2_10, + IMXRT1170_PAD_EMC_B2_11, + IMXRT1170_PAD_EMC_B2_12, + IMXRT1170_PAD_EMC_B2_13, + IMXRT1170_PAD_EMC_B2_14, + IMXRT1170_PAD_EMC_B2_15, + IMXRT1170_PAD_EMC_B2_16, + IMXRT1170_PAD_EMC_B2_17, + IMXRT1170_PAD_EMC_B2_18, + IMXRT1170_PAD_EMC_B2_19, + IMXRT1170_PAD_EMC_B2_20, + IMXRT1170_PAD_AD_00, + IMXRT1170_PAD_AD_01, + IMXRT1170_PAD_AD_02, + IMXRT1170_PAD_AD_03, + IMXRT1170_PAD_AD_04, + IMXRT1170_PAD_AD_05, + IMXRT1170_PAD_AD_06, + IMXRT1170_PAD_AD_07, + IMXRT1170_PAD_AD_08, + IMXRT1170_PAD_AD_09, + IMXRT1170_PAD_AD_10, + IMXRT1170_PAD_AD_11, + IMXRT1170_PAD_AD_12, + IMXRT1170_PAD_AD_13, + IMXRT1170_PAD_AD_14, + IMXRT1170_PAD_AD_15, + IMXRT1170_PAD_AD_16, + IMXRT1170_PAD_AD_17, + IMXRT1170_PAD_AD_18, + IMXRT1170_PAD_AD_19, + IMXRT1170_PAD_AD_20, + IMXRT1170_PAD_AD_21, + IMXRT1170_PAD_AD_22, + IMXRT1170_PAD_AD_23, + IMXRT1170_PAD_AD_24, + IMXRT1170_PAD_AD_25, + IMXRT1170_PAD_AD_26, + IMXRT1170_PAD_AD_27, + IMXRT1170_PAD_AD_28, + IMXRT1170_PAD_AD_29, + IMXRT1170_PAD_AD_30, + IMXRT1170_PAD_AD_31, + IMXRT1170_PAD_AD_32, + IMXRT1170_PAD_AD_33, + IMXRT1170_PAD_AD_34, + IMXRT1170_PAD_AD_35, + IMXRT1170_PAD_SD_B1_00, + IMXRT1170_PAD_SD_B1_01, + IMXRT1170_PAD_SD_B1_02, + IMXRT1170_PAD_SD_B1_03, + IMXRT1170_PAD_SD_B1_04, + IMXRT1170_PAD_SD_B1_05, + IMXRT1170_PAD_SD_B2_00, + IMXRT1170_PAD_SD_B2_01, + IMXRT1170_PAD_SD_B2_02, + IMXRT1170_PAD_SD_B2_03, + IMXRT1170_PAD_SD_B2_04, + IMXRT1170_PAD_SD_B2_05, + IMXRT1170_PAD_SD_B2_06, + IMXRT1170_PAD_SD_B2_07, + IMXRT1170_PAD_SD_B2_08, + IMXRT1170_PAD_SD_B2_09, + IMXRT1170_PAD_SD_B2_10, + IMXRT1170_PAD_SD_B2_11, + IMXRT1170_PAD_DISP_B1_00, + IMXRT1170_PAD_DISP_B1_01, + IMXRT1170_PAD_DISP_B1_02, + IMXRT1170_PAD_DISP_B1_03, + IMXRT1170_PAD_DISP_B1_04, + IMXRT1170_PAD_DISP_B1_05, + IMXRT1170_PAD_DISP_B1_06, + IMXRT1170_PAD_DISP_B1_07, + IMXRT1170_PAD_DISP_B1_08, + IMXRT1170_PAD_DISP_B1_09, + IMXRT1170_PAD_DISP_B1_10, + IMXRT1170_PAD_DISP_B1_11, + IMXRT1170_PAD_DISP_B2_00, + IMXRT1170_PAD_DISP_B2_01, + IMXRT1170_PAD_DISP_B2_02, + IMXRT1170_PAD_DISP_B2_03, + IMXRT1170_PAD_DISP_B2_04, + IMXRT1170_PAD_DISP_B2_05, + IMXRT1170_PAD_DISP_B2_06, + IMXRT1170_PAD_DISP_B2_07, + IMXRT1170_PAD_DISP_B2_08, + IMXRT1170_PAD_DISP_B2_09, + IMXRT1170_PAD_DISP_B2_10, + IMXRT1170_PAD_DISP_B2_11, + IMXRT1170_PAD_DISP_B2_12, + IMXRT1170_PAD_DISP_B2_13, + IMXRT1170_PAD_DISP_B2_14, + IMXRT1170_PAD_DISP_B2_15, +}; + +/* Pad names for the pinmux subsystem */ +static const struct pinctrl_pin_desc imxrt1170_pinctrl_pads[] = { + IMX_PINCTRL_PIN(IMXRT1170_PAD_RESERVE0), + IMX_PINCTRL_PIN(IMXRT1170_PAD_RESERVE1), + IMX_PINCTRL_PIN(IMXRT1170_PAD_RESERVE2), + IMX_PINCTRL_PIN(IMXRT1170_PAD_RESERVE3), + IMX_PINCTRL_PIN(IMXRT1170_PAD_EMC_B1_00), + IMX_PINCTRL_PIN(IMXRT1170_PAD_EMC_B1_01), + IMX_PINCTRL_PIN(IMXRT1170_PAD_EMC_B1_02), + IMX_PINCTRL_PIN(IMXRT1170_PAD_EMC_B1_03), + IMX_PINCTRL_PIN(IMXRT1170_PAD_EMC_B1_04), + IMX_PINCTRL_PIN(IMXRT1170_PAD_EMC_B1_05), + IMX_PINCTRL_PIN(IMXRT1170_PAD_EMC_B1_06), + IMX_PINCTRL_PIN(IMXRT1170_PAD_EMC_B1_07), + IMX_PINCTRL_PIN(IMXRT1170_PAD_EMC_B1_08), + IMX_PINCTRL_PIN(IMXRT1170_PAD_EMC_B1_09), + IMX_PINCTRL_PIN(IMXRT1170_PAD_EMC_B1_10), + IMX_PINCTRL_PIN(IMXRT1170_PAD_EMC_B1_11), + IMX_PINCTRL_PIN(IMXRT1170_PAD_EMC_B1_12), + IMX_PINCTRL_PIN(IMXRT1170_PAD_EMC_B1_13), + IMX_PINCTRL_PIN(IMXRT1170_PAD_EMC_B1_14), + IMX_PINCTRL_PIN(IMXRT1170_PAD_EMC_B1_15), + IMX_PINCTRL_PIN(IMXRT1170_PAD_EMC_B1_16), + IMX_PINCTRL_PIN(IMXRT1170_PAD_EMC_B1_17), + IMX_PINCTRL_PIN(IMXRT1170_PAD_EMC_B1_18), + IMX_PINCTRL_PIN(IMXRT1170_PAD_EMC_B1_19), + IMX_PINCTRL_PIN(IMXRT1170_PAD_EMC_B1_20), + IMX_PINCTRL_PIN(IMXRT1170_PAD_EMC_B1_21), + IMX_PINCTRL_PIN(IMXRT1170_PAD_EMC_B1_22), + IMX_PINCTRL_PIN(IMXRT1170_PAD_EMC_B1_23), + IMX_PINCTRL_PIN(IMXRT1170_PAD_EMC_B1_24), + IMX_PINCTRL_PIN(IMXRT1170_PAD_EMC_B1_25), + IMX_PINCTRL_PIN(IMXRT1170_PAD_EMC_B1_26), + IMX_PINCTRL_PIN(IMXRT1170_PAD_EMC_B1_27), + IMX_PINCTRL_PIN(IMXRT1170_PAD_EMC_B1_28), + IMX_PINCTRL_PIN(IMXRT1170_PAD_EMC_B1_29), + IMX_PINCTRL_PIN(IMXRT1170_PAD_EMC_B1_30), + IMX_PINCTRL_PIN(IMXRT1170_PAD_EMC_B1_31), + IMX_PINCTRL_PIN(IMXRT1170_PAD_EMC_B1_32), + IMX_PINCTRL_PIN(IMXRT1170_PAD_EMC_B1_33), + IMX_PINCTRL_PIN(IMXRT1170_PAD_EMC_B1_34), + IMX_PINCTRL_PIN(IMXRT1170_PAD_EMC_B1_35), + IMX_PINCTRL_PIN(IMXRT1170_PAD_EMC_B1_36), + IMX_PINCTRL_PIN(IMXRT1170_PAD_EMC_B1_37), + IMX_PINCTRL_PIN(IMXRT1170_PAD_EMC_B1_38), + IMX_PINCTRL_PIN(IMXRT1170_PAD_EMC_B1_39), + IMX_PINCTRL_PIN(IMXRT1170_PAD_EMC_B1_40), + IMX_PINCTRL_PIN(IMXRT1170_PAD_EMC_B1_41), + IMX_PINCTRL_PIN(IMXRT1170_PAD_EMC_B2_00), + IMX_PINCTRL_PIN(IMXRT1170_PAD_EMC_B2_01), + IMX_PINCTRL_PIN(IMXRT1170_PAD_EMC_B2_02), + IMX_PINCTRL_PIN(IMXRT1170_PAD_EMC_B2_03), + IMX_PINCTRL_PIN(IMXRT1170_PAD_EMC_B2_04), + IMX_PINCTRL_PIN(IMXRT1170_PAD_EMC_B2_05), + IMX_PINCTRL_PIN(IMXRT1170_PAD_EMC_B2_06), + IMX_PINCTRL_PIN(IMXRT1170_PAD_EMC_B2_07), + IMX_PINCTRL_PIN(IMXRT1170_PAD_EMC_B2_08), + IMX_PINCTRL_PIN(IMXRT1170_PAD_EMC_B2_09), + IMX_PINCTRL_PIN(IMXRT1170_PAD_EMC_B2_10), + IMX_PINCTRL_PIN(IMXRT1170_PAD_EMC_B2_11), + IMX_PINCTRL_PIN(IMXRT1170_PAD_EMC_B2_12), + IMX_PINCTRL_PIN(IMXRT1170_PAD_EMC_B2_13), + IMX_PINCTRL_PIN(IMXRT1170_PAD_EMC_B2_14), + IMX_PINCTRL_PIN(IMXRT1170_PAD_EMC_B2_15), + IMX_PINCTRL_PIN(IMXRT1170_PAD_EMC_B2_16), + IMX_PINCTRL_PIN(IMXRT1170_PAD_EMC_B2_17), + IMX_PINCTRL_PIN(IMXRT1170_PAD_EMC_B2_18), + IMX_PINCTRL_PIN(IMXRT1170_PAD_EMC_B2_19), + IMX_PINCTRL_PIN(IMXRT1170_PAD_EMC_B2_20), + IMX_PINCTRL_PIN(IMXRT1170_PAD_AD_00), + IMX_PINCTRL_PIN(IMXRT1170_PAD_AD_01), + IMX_PINCTRL_PIN(IMXRT1170_PAD_AD_02), + IMX_PINCTRL_PIN(IMXRT1170_PAD_AD_03), + IMX_PINCTRL_PIN(IMXRT1170_PAD_AD_04), + IMX_PINCTRL_PIN(IMXRT1170_PAD_AD_05), + IMX_PINCTRL_PIN(IMXRT1170_PAD_AD_06), + IMX_PINCTRL_PIN(IMXRT1170_PAD_AD_07), + IMX_PINCTRL_PIN(IMXRT1170_PAD_AD_08), + IMX_PINCTRL_PIN(IMXRT1170_PAD_AD_09), + IMX_PINCTRL_PIN(IMXRT1170_PAD_AD_10), + IMX_PINCTRL_PIN(IMXRT1170_PAD_AD_11), + IMX_PINCTRL_PIN(IMXRT1170_PAD_AD_12), + IMX_PINCTRL_PIN(IMXRT1170_PAD_AD_13), + IMX_PINCTRL_PIN(IMXRT1170_PAD_AD_14), + IMX_PINCTRL_PIN(IMXRT1170_PAD_AD_15), + IMX_PINCTRL_PIN(IMXRT1170_PAD_AD_16), + IMX_PINCTRL_PIN(IMXRT1170_PAD_AD_17), + IMX_PINCTRL_PIN(IMXRT1170_PAD_AD_18), + IMX_PINCTRL_PIN(IMXRT1170_PAD_AD_19), + IMX_PINCTRL_PIN(IMXRT1170_PAD_AD_20), + IMX_PINCTRL_PIN(IMXRT1170_PAD_AD_21), + IMX_PINCTRL_PIN(IMXRT1170_PAD_AD_22), + IMX_PINCTRL_PIN(IMXRT1170_PAD_AD_23), + IMX_PINCTRL_PIN(IMXRT1170_PAD_AD_24), + IMX_PINCTRL_PIN(IMXRT1170_PAD_AD_25), + IMX_PINCTRL_PIN(IMXRT1170_PAD_AD_26), + IMX_PINCTRL_PIN(IMXRT1170_PAD_AD_27), + IMX_PINCTRL_PIN(IMXRT1170_PAD_AD_28), + IMX_PINCTRL_PIN(IMXRT1170_PAD_AD_29), + IMX_PINCTRL_PIN(IMXRT1170_PAD_AD_30), + IMX_PINCTRL_PIN(IMXRT1170_PAD_AD_31), + IMX_PINCTRL_PIN(IMXRT1170_PAD_AD_32), + IMX_PINCTRL_PIN(IMXRT1170_PAD_AD_33), + IMX_PINCTRL_PIN(IMXRT1170_PAD_AD_34), + IMX_PINCTRL_PIN(IMXRT1170_PAD_AD_35), + IMX_PINCTRL_PIN(IMXRT1170_PAD_SD_B1_00), + IMX_PINCTRL_PIN(IMXRT1170_PAD_SD_B1_01), + IMX_PINCTRL_PIN(IMXRT1170_PAD_SD_B1_02), + IMX_PINCTRL_PIN(IMXRT1170_PAD_SD_B1_03), + IMX_PINCTRL_PIN(IMXRT1170_PAD_SD_B1_04), + IMX_PINCTRL_PIN(IMXRT1170_PAD_SD_B1_05), + IMX_PINCTRL_PIN(IMXRT1170_PAD_SD_B2_00), + IMX_PINCTRL_PIN(IMXRT1170_PAD_SD_B2_01), + IMX_PINCTRL_PIN(IMXRT1170_PAD_SD_B2_02), + IMX_PINCTRL_PIN(IMXRT1170_PAD_SD_B2_03), + IMX_PINCTRL_PIN(IMXRT1170_PAD_SD_B2_04), + IMX_PINCTRL_PIN(IMXRT1170_PAD_SD_B2_05), + IMX_PINCTRL_PIN(IMXRT1170_PAD_SD_B2_06), + IMX_PINCTRL_PIN(IMXRT1170_PAD_SD_B2_07), + IMX_PINCTRL_PIN(IMXRT1170_PAD_SD_B2_08), + IMX_PINCTRL_PIN(IMXRT1170_PAD_SD_B2_09), + IMX_PINCTRL_PIN(IMXRT1170_PAD_SD_B2_10), + IMX_PINCTRL_PIN(IMXRT1170_PAD_SD_B2_11), + IMX_PINCTRL_PIN(IMXRT1170_PAD_DISP_B1_00), + IMX_PINCTRL_PIN(IMXRT1170_PAD_DISP_B1_01), + IMX_PINCTRL_PIN(IMXRT1170_PAD_DISP_B1_02), + IMX_PINCTRL_PIN(IMXRT1170_PAD_DISP_B1_03), + IMX_PINCTRL_PIN(IMXRT1170_PAD_DISP_B1_04), + IMX_PINCTRL_PIN(IMXRT1170_PAD_DISP_B1_05), + IMX_PINCTRL_PIN(IMXRT1170_PAD_DISP_B1_06), + IMX_PINCTRL_PIN(IMXRT1170_PAD_DISP_B1_07), + IMX_PINCTRL_PIN(IMXRT1170_PAD_DISP_B1_08), + IMX_PINCTRL_PIN(IMXRT1170_PAD_DISP_B1_09), + IMX_PINCTRL_PIN(IMXRT1170_PAD_DISP_B1_10), + IMX_PINCTRL_PIN(IMXRT1170_PAD_DISP_B1_11), + IMX_PINCTRL_PIN(IMXRT1170_PAD_DISP_B2_00), + IMX_PINCTRL_PIN(IMXRT1170_PAD_DISP_B2_01), + IMX_PINCTRL_PIN(IMXRT1170_PAD_DISP_B2_02), + IMX_PINCTRL_PIN(IMXRT1170_PAD_DISP_B2_03), + IMX_PINCTRL_PIN(IMXRT1170_PAD_DISP_B2_04), + IMX_PINCTRL_PIN(IMXRT1170_PAD_DISP_B2_05), + IMX_PINCTRL_PIN(IMXRT1170_PAD_DISP_B2_06), + IMX_PINCTRL_PIN(IMXRT1170_PAD_DISP_B2_07), + IMX_PINCTRL_PIN(IMXRT1170_PAD_DISP_B2_08), + IMX_PINCTRL_PIN(IMXRT1170_PAD_DISP_B2_09), + IMX_PINCTRL_PIN(IMXRT1170_PAD_DISP_B2_10), + IMX_PINCTRL_PIN(IMXRT1170_PAD_DISP_B2_11), + IMX_PINCTRL_PIN(IMXRT1170_PAD_DISP_B2_12), + IMX_PINCTRL_PIN(IMXRT1170_PAD_DISP_B2_13), + IMX_PINCTRL_PIN(IMXRT1170_PAD_DISP_B2_14), + IMX_PINCTRL_PIN(IMXRT1170_PAD_DISP_B2_15), +}; + +static const struct imx_pinctrl_soc_info imxrt1170_pinctrl_info = { + .pins = imxrt1170_pinctrl_pads, + .npins = ARRAY_SIZE(imxrt1170_pinctrl_pads), + .gpr_compatible = "fsl,imxrt1170-iomuxc-gpr", +}; + +static const struct of_device_id imxrt1170_pinctrl_of_match[] = { + { .compatible = "fsl,imxrt1170-iomuxc", .data = &imxrt1170_pinctrl_info, }, + { /* sentinel */ } +}; + +static int imxrt1170_pinctrl_probe(struct platform_device *pdev) +{ + return imx_pinctrl_probe(pdev, &imxrt1170_pinctrl_info); +} + +static struct platform_driver imxrt1170_pinctrl_driver = { + .driver = { + .name = "imxrt1170-pinctrl", + .of_match_table = of_match_ptr(imxrt1170_pinctrl_of_match), + .suppress_bind_attrs = true, + }, + .probe = imxrt1170_pinctrl_probe, +}; + +static int __init imxrt1170_pinctrl_init(void) +{ + return platform_driver_register(&imxrt1170_pinctrl_driver); +} +arch_initcall(imxrt1170_pinctrl_init); diff --git a/drivers/pinctrl/intel/pinctrl-baytrail.c b/drivers/pinctrl/intel/pinctrl-baytrail.c index f89c9fcd4e1b2ad03caebed91cdf1cf4495ddc9d..31f8f271628c86c638b90510a2bcde246cf91edb 100644 --- a/drivers/pinctrl/intel/pinctrl-baytrail.c +++ b/drivers/pinctrl/intel/pinctrl-baytrail.c @@ -1350,15 +1350,15 @@ static void byt_irq_ack(struct irq_data *d) { struct gpio_chip *gc = irq_data_get_irq_chip_data(d); struct intel_pinctrl *vg = gpiochip_get_data(gc); - unsigned int offset = irqd_to_hwirq(d); + irq_hw_number_t hwirq = irqd_to_hwirq(d); void __iomem *reg; - reg = byt_gpio_reg(vg, offset, BYT_INT_STAT_REG); + reg = byt_gpio_reg(vg, hwirq, BYT_INT_STAT_REG); if (!reg) return; raw_spin_lock(&byt_lock); - writel(BIT(offset % 32), reg); + writel(BIT(hwirq % 32), reg); raw_spin_unlock(&byt_lock); } @@ -1366,20 +1366,24 @@ static void byt_irq_mask(struct irq_data *d) { struct gpio_chip *gc = irq_data_get_irq_chip_data(d); struct intel_pinctrl *vg = gpiochip_get_data(gc); + irq_hw_number_t hwirq = irqd_to_hwirq(d); - byt_gpio_clear_triggering(vg, irqd_to_hwirq(d)); + byt_gpio_clear_triggering(vg, hwirq); + gpiochip_disable_irq(gc, hwirq); } static void byt_irq_unmask(struct irq_data *d) { struct gpio_chip *gc = irq_data_get_irq_chip_data(d); struct intel_pinctrl *vg = gpiochip_get_data(gc); - unsigned int offset = irqd_to_hwirq(d); + irq_hw_number_t hwirq = irqd_to_hwirq(d); unsigned long flags; void __iomem *reg; u32 value; - reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG); + gpiochip_enable_irq(gc, hwirq); + + reg = byt_gpio_reg(vg, hwirq, BYT_CONF0_REG); if (!reg) return; @@ -1412,12 +1416,13 @@ static void byt_irq_unmask(struct irq_data *d) static int byt_irq_type(struct irq_data *d, unsigned int type) { struct intel_pinctrl *vg = gpiochip_get_data(irq_data_get_irq_chip_data(d)); - u32 offset = irqd_to_hwirq(d); + irq_hw_number_t hwirq = irqd_to_hwirq(d); u32 value; unsigned long flags; - void __iomem *reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG); + void __iomem *reg; - if (!reg || offset >= vg->chip.ngpio) + reg = byt_gpio_reg(vg, hwirq, BYT_CONF0_REG); + if (!reg) return -EINVAL; raw_spin_lock_irqsave(&byt_lock, flags); @@ -1447,6 +1452,16 @@ static int byt_irq_type(struct irq_data *d, unsigned int type) return 0; } +static const struct irq_chip byt_gpio_irq_chip = { + .name = "BYT-GPIO", + .irq_ack = byt_irq_ack, + .irq_mask = byt_irq_mask, + .irq_unmask = byt_irq_unmask, + .irq_set_type = byt_irq_type, + .flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_SET_TYPE_MASKED | IRQCHIP_IMMUTABLE, + GPIOCHIP_IRQ_RESOURCE_HELPERS, +}; + static void byt_gpio_irq_handler(struct irq_desc *desc) { struct irq_data *data = irq_desc_get_irq_data(desc); @@ -1633,15 +1648,8 @@ static int byt_gpio_probe(struct intel_pinctrl *vg) if (irq > 0) { struct gpio_irq_chip *girq; - vg->irqchip.name = "BYT-GPIO", - vg->irqchip.irq_ack = byt_irq_ack, - vg->irqchip.irq_mask = byt_irq_mask, - vg->irqchip.irq_unmask = byt_irq_unmask, - vg->irqchip.irq_set_type = byt_irq_type, - vg->irqchip.flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_SET_TYPE_MASKED, - girq = &gc->irq; - girq->chip = &vg->irqchip; + gpio_irq_chip_set_chip(girq, &byt_gpio_irq_chip); girq->init_hw = byt_gpio_irq_init_hw; girq->init_valid_mask = byt_init_irq_valid_mask; girq->parent_handler = byt_gpio_irq_handler; diff --git a/drivers/pinctrl/intel/pinctrl-broxton.c b/drivers/pinctrl/intel/pinctrl-broxton.c index 2be7e414f80323c95a9edb23a7b390cd463347c1..fb15cd10a32f6334c9223e1d00ef5498db493148 100644 --- a/drivers/pinctrl/intel/pinctrl-broxton.c +++ b/drivers/pinctrl/intel/pinctrl-broxton.c @@ -1035,4 +1035,5 @@ module_exit(bxt_pinctrl_exit); MODULE_AUTHOR("Mika Westerberg "); MODULE_DESCRIPTION("Intel Broxton SoC pinctrl/GPIO driver"); MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:apollolake-pinctrl"); MODULE_ALIAS("platform:broxton-pinctrl"); diff --git a/drivers/pinctrl/intel/pinctrl-cherryview.c b/drivers/pinctrl/intel/pinctrl-cherryview.c index 1d58182690767b694144367616eac428ef438f9d..26b2a425d201d2a977d086e6d1cb75c3983c9dc5 100644 --- a/drivers/pinctrl/intel/pinctrl-cherryview.c +++ b/drivers/pinctrl/intel/pinctrl-cherryview.c @@ -1242,12 +1242,12 @@ static void chv_gpio_irq_ack(struct irq_data *d) { struct gpio_chip *gc = irq_data_get_irq_chip_data(d); struct intel_pinctrl *pctrl = gpiochip_get_data(gc); - int pin = irqd_to_hwirq(d); + irq_hw_number_t hwirq = irqd_to_hwirq(d); u32 intr_line; raw_spin_lock(&chv_lock); - intr_line = chv_readl(pctrl, pin, CHV_PADCTRL0); + intr_line = chv_readl(pctrl, hwirq, CHV_PADCTRL0); intr_line &= CHV_PADCTRL0_INTSEL_MASK; intr_line >>= CHV_PADCTRL0_INTSEL_SHIFT; chv_pctrl_writel(pctrl, CHV_INTSTAT, BIT(intr_line)); @@ -1255,17 +1255,15 @@ static void chv_gpio_irq_ack(struct irq_data *d) raw_spin_unlock(&chv_lock); } -static void chv_gpio_irq_mask_unmask(struct irq_data *d, bool mask) +static void chv_gpio_irq_mask_unmask(struct gpio_chip *gc, irq_hw_number_t hwirq, bool mask) { - struct gpio_chip *gc = irq_data_get_irq_chip_data(d); struct intel_pinctrl *pctrl = gpiochip_get_data(gc); - int pin = irqd_to_hwirq(d); u32 value, intr_line; unsigned long flags; raw_spin_lock_irqsave(&chv_lock, flags); - intr_line = chv_readl(pctrl, pin, CHV_PADCTRL0); + intr_line = chv_readl(pctrl, hwirq, CHV_PADCTRL0); intr_line &= CHV_PADCTRL0_INTSEL_MASK; intr_line >>= CHV_PADCTRL0_INTSEL_SHIFT; @@ -1281,12 +1279,20 @@ static void chv_gpio_irq_mask_unmask(struct irq_data *d, bool mask) static void chv_gpio_irq_mask(struct irq_data *d) { - chv_gpio_irq_mask_unmask(d, true); + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + irq_hw_number_t hwirq = irqd_to_hwirq(d); + + chv_gpio_irq_mask_unmask(gc, hwirq, true); + gpiochip_disable_irq(gc, hwirq); } static void chv_gpio_irq_unmask(struct irq_data *d) { - chv_gpio_irq_mask_unmask(d, false); + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + irq_hw_number_t hwirq = irqd_to_hwirq(d); + + gpiochip_enable_irq(gc, hwirq); + chv_gpio_irq_mask_unmask(gc, hwirq, false); } static unsigned chv_gpio_irq_startup(struct irq_data *d) @@ -1306,17 +1312,17 @@ static unsigned chv_gpio_irq_startup(struct irq_data *d) struct intel_pinctrl *pctrl = gpiochip_get_data(gc); struct device *dev = pctrl->dev; struct intel_community_context *cctx = &pctrl->context.communities[0]; - unsigned int pin = irqd_to_hwirq(d); + irq_hw_number_t hwirq = irqd_to_hwirq(d); irq_flow_handler_t handler; unsigned long flags; u32 intsel, value; raw_spin_lock_irqsave(&chv_lock, flags); - intsel = chv_readl(pctrl, pin, CHV_PADCTRL0); + intsel = chv_readl(pctrl, hwirq, CHV_PADCTRL0); intsel &= CHV_PADCTRL0_INTSEL_MASK; intsel >>= CHV_PADCTRL0_INTSEL_SHIFT; - value = chv_readl(pctrl, pin, CHV_PADCTRL1); + value = chv_readl(pctrl, hwirq, CHV_PADCTRL1); if (value & CHV_PADCTRL1_INTWAKECFG_LEVEL) handler = handle_level_irq; else @@ -1324,9 +1330,9 @@ static unsigned chv_gpio_irq_startup(struct irq_data *d) if (cctx->intr_lines[intsel] == CHV_INVALID_HWIRQ) { irq_set_handler_locked(d, handler); - dev_dbg(dev, "using interrupt line %u for IRQ_TYPE_NONE on pin %u\n", - intsel, pin); - cctx->intr_lines[intsel] = pin; + dev_dbg(dev, "using interrupt line %u for IRQ_TYPE_NONE on pin %lu\n", + intsel, hwirq); + cctx->intr_lines[intsel] = hwirq; } raw_spin_unlock_irqrestore(&chv_lock, flags); } @@ -1392,14 +1398,14 @@ static int chv_gpio_irq_type(struct irq_data *d, unsigned int type) { struct gpio_chip *gc = irq_data_get_irq_chip_data(d); struct intel_pinctrl *pctrl = gpiochip_get_data(gc); - unsigned int pin = irqd_to_hwirq(d); + irq_hw_number_t hwirq = irqd_to_hwirq(d); unsigned long flags; u32 value; int ret; raw_spin_lock_irqsave(&chv_lock, flags); - ret = chv_gpio_set_intr_line(pctrl, pin); + ret = chv_gpio_set_intr_line(pctrl, hwirq); if (ret) goto out_unlock; @@ -1416,8 +1422,8 @@ static int chv_gpio_irq_type(struct irq_data *d, unsigned int type) * 2. If the pin cfg is not locked in BIOS: * Driver programs the IntWakeCfg bits and save the mapping. */ - if (!chv_pad_locked(pctrl, pin)) { - value = chv_readl(pctrl, pin, CHV_PADCTRL1); + if (!chv_pad_locked(pctrl, hwirq)) { + value = chv_readl(pctrl, hwirq, CHV_PADCTRL1); value &= ~CHV_PADCTRL1_INTWAKECFG_MASK; value &= ~CHV_PADCTRL1_INVRXTX_MASK; @@ -1434,7 +1440,7 @@ static int chv_gpio_irq_type(struct irq_data *d, unsigned int type) value |= CHV_PADCTRL1_INVRXTX_RXDATA; } - chv_writel(pctrl, pin, CHV_PADCTRL1, value); + chv_writel(pctrl, hwirq, CHV_PADCTRL1, value); } if (type & IRQ_TYPE_EDGE_BOTH) @@ -1448,6 +1454,17 @@ out_unlock: return ret; } +static const struct irq_chip chv_gpio_irq_chip = { + .name = "chv-gpio", + .irq_startup = chv_gpio_irq_startup, + .irq_ack = chv_gpio_irq_ack, + .irq_mask = chv_gpio_irq_mask, + .irq_unmask = chv_gpio_irq_unmask, + .irq_set_type = chv_gpio_irq_type, + .flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_IMMUTABLE, + GPIOCHIP_IRQ_RESOURCE_HELPERS, +}; + static void chv_gpio_irq_handler(struct irq_desc *desc) { struct gpio_chip *gc = irq_desc_get_handler_data(desc); @@ -1611,15 +1628,8 @@ static int chv_gpio_probe(struct intel_pinctrl *pctrl, int irq) chip->base = -1; pctrl->irq = irq; - pctrl->irqchip.name = "chv-gpio"; - pctrl->irqchip.irq_startup = chv_gpio_irq_startup; - pctrl->irqchip.irq_ack = chv_gpio_irq_ack; - pctrl->irqchip.irq_mask = chv_gpio_irq_mask; - pctrl->irqchip.irq_unmask = chv_gpio_irq_unmask; - pctrl->irqchip.irq_set_type = chv_gpio_irq_type; - pctrl->irqchip.flags = IRQCHIP_SKIP_SET_WAKE; - - chip->irq.chip = &pctrl->irqchip; + + gpio_irq_chip_set_chip(&chip->irq, &chv_gpio_irq_chip); chip->irq.init_hw = chv_gpio_irq_init_hw; chip->irq.parent_handler = chv_gpio_irq_handler; chip->irq.num_parents = 1; diff --git a/drivers/pinctrl/intel/pinctrl-intel.c b/drivers/pinctrl/intel/pinctrl-intel.c index 826d494f3cc66e66419e9d49f36de4c7e530a2a2..ffc045f7bf00b5970f37f5f9e3e2eaa398be00ab 100644 --- a/drivers/pinctrl/intel/pinctrl-intel.c +++ b/drivers/pinctrl/intel/pinctrl-intel.c @@ -858,6 +858,9 @@ static const struct pinctrl_desc intel_pinctrl_desc = { * When coming through gpiolib irqchip, the GPIO offset is not * automatically translated to pinctrl pin number. This function can be * used to find out the corresponding pinctrl pin. + * + * Return: a pin number and pointers to the community and pad group, which + * the pin belongs to, or negative error code if translation can't be done. */ static int intel_gpio_to_pin(struct intel_pinctrl *pctrl, unsigned int offset, const struct intel_community **community, @@ -899,6 +902,8 @@ static int intel_gpio_to_pin(struct intel_pinctrl *pctrl, unsigned int offset, * @pin: pin number * * Translate the pin number of pinctrl to GPIO offset + * + * Return: a GPIO offset, or negative error code if translation can't be done. */ static __maybe_unused int intel_pin_to_gpio(struct intel_pinctrl *pctrl, int pin) { @@ -1039,15 +1044,14 @@ static void intel_gpio_irq_ack(struct irq_data *d) } } -static void intel_gpio_irq_mask_unmask(struct irq_data *d, bool mask) +static void intel_gpio_irq_mask_unmask(struct gpio_chip *gc, irq_hw_number_t hwirq, bool mask) { - struct gpio_chip *gc = irq_data_get_irq_chip_data(d); struct intel_pinctrl *pctrl = gpiochip_get_data(gc); const struct intel_community *community; const struct intel_padgroup *padgrp; int pin; - pin = intel_gpio_to_pin(pctrl, irqd_to_hwirq(d), &community, &padgrp); + pin = intel_gpio_to_pin(pctrl, hwirq, &community, &padgrp); if (pin >= 0) { unsigned int gpp, gpp_offset; unsigned long flags; @@ -1077,12 +1081,20 @@ static void intel_gpio_irq_mask_unmask(struct irq_data *d, bool mask) static void intel_gpio_irq_mask(struct irq_data *d) { - intel_gpio_irq_mask_unmask(d, true); + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + irq_hw_number_t hwirq = irqd_to_hwirq(d); + + intel_gpio_irq_mask_unmask(gc, hwirq, true); + gpiochip_disable_irq(gc, hwirq); } static void intel_gpio_irq_unmask(struct irq_data *d) { - intel_gpio_irq_mask_unmask(d, false); + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + irq_hw_number_t hwirq = irqd_to_hwirq(d); + + gpiochip_enable_irq(gc, hwirq); + intel_gpio_irq_mask_unmask(gc, hwirq, false); } static int intel_gpio_irq_type(struct irq_data *d, unsigned int type) @@ -1157,6 +1169,17 @@ static int intel_gpio_irq_wake(struct irq_data *d, unsigned int on) return 0; } +static const struct irq_chip intel_gpio_irq_chip = { + .name = "intel-gpio", + .irq_ack = intel_gpio_irq_ack, + .irq_mask = intel_gpio_irq_mask, + .irq_unmask = intel_gpio_irq_unmask, + .irq_set_type = intel_gpio_irq_type, + .irq_set_wake = intel_gpio_irq_wake, + .flags = IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_IMMUTABLE, + GPIOCHIP_IRQ_RESOURCE_HELPERS, +}; + static int intel_gpio_community_irq_handler(struct intel_pinctrl *pctrl, const struct intel_community *community) { @@ -1319,15 +1342,6 @@ static int intel_gpio_probe(struct intel_pinctrl *pctrl, int irq) pctrl->chip.add_pin_ranges = intel_gpio_add_pin_ranges; pctrl->irq = irq; - /* Setup IRQ chip */ - pctrl->irqchip.name = dev_name(pctrl->dev); - pctrl->irqchip.irq_ack = intel_gpio_irq_ack; - pctrl->irqchip.irq_mask = intel_gpio_irq_mask; - pctrl->irqchip.irq_unmask = intel_gpio_irq_unmask; - pctrl->irqchip.irq_set_type = intel_gpio_irq_type; - pctrl->irqchip.irq_set_wake = intel_gpio_irq_wake; - pctrl->irqchip.flags = IRQCHIP_MASK_ON_SUSPEND; - /* * On some platforms several GPIO controllers share the same interrupt * line. @@ -1340,8 +1354,9 @@ static int intel_gpio_probe(struct intel_pinctrl *pctrl, int irq) return ret; } + /* Setup IRQ chip */ girq = &pctrl->chip.irq; - girq->chip = &pctrl->irqchip; + gpio_irq_chip_set_chip(girq, &intel_gpio_irq_chip); /* This will let us handle the IRQ in the driver */ girq->parent_handler = NULL; girq->num_parents = 0; diff --git a/drivers/pinctrl/intel/pinctrl-intel.h b/drivers/pinctrl/intel/pinctrl-intel.h index c4fef03b663f7b30fd018efde4d53711b1b8b108..710341bb67ccc484bf8e265636c612d70434095e 100644 --- a/drivers/pinctrl/intel/pinctrl-intel.h +++ b/drivers/pinctrl/intel/pinctrl-intel.h @@ -223,7 +223,6 @@ struct intel_pinctrl_context { * @pctldesc: Pin controller description * @pctldev: Pointer to the pin controller device * @chip: GPIO chip in this pin controller - * @irqchip: IRQ chip in this pin controller * @soc: SoC/PCH specific pin configuration data * @communities: All communities in this pin controller * @ncommunities: Number of communities in this pin controller @@ -236,7 +235,6 @@ struct intel_pinctrl { struct pinctrl_desc pctldesc; struct pinctrl_dev *pctldev; struct gpio_chip chip; - struct irq_chip irqchip; const struct intel_pinctrl_soc_data *soc; struct intel_community *communities; size_t ncommunities; diff --git a/drivers/pinctrl/intel/pinctrl-lynxpoint.c b/drivers/pinctrl/intel/pinctrl-lynxpoint.c index 561fa322b0b477e66ffaa1a25333f46f8e68384f..4fb39eb30902cbe1baad3c75bec0afaac9ffa403 100644 --- a/drivers/pinctrl/intel/pinctrl-lynxpoint.c +++ b/drivers/pinctrl/intel/pinctrl-lynxpoint.c @@ -663,7 +663,7 @@ static void lp_irq_ack(struct irq_data *d) { struct gpio_chip *gc = irq_data_get_irq_chip_data(d); struct intel_pinctrl *lg = gpiochip_get_data(gc); - u32 hwirq = irqd_to_hwirq(d); + irq_hw_number_t hwirq = irqd_to_hwirq(d); void __iomem *reg = lp_gpio_reg(&lg->chip, hwirq, LP_INT_STAT); unsigned long flags; @@ -684,10 +684,12 @@ static void lp_irq_enable(struct irq_data *d) { struct gpio_chip *gc = irq_data_get_irq_chip_data(d); struct intel_pinctrl *lg = gpiochip_get_data(gc); - u32 hwirq = irqd_to_hwirq(d); + irq_hw_number_t hwirq = irqd_to_hwirq(d); void __iomem *reg = lp_gpio_reg(&lg->chip, hwirq, LP_INT_ENABLE); unsigned long flags; + gpiochip_enable_irq(gc, hwirq); + raw_spin_lock_irqsave(&lg->lock, flags); iowrite32(ioread32(reg) | BIT(hwirq % 32), reg); raw_spin_unlock_irqrestore(&lg->lock, flags); @@ -697,30 +699,33 @@ static void lp_irq_disable(struct irq_data *d) { struct gpio_chip *gc = irq_data_get_irq_chip_data(d); struct intel_pinctrl *lg = gpiochip_get_data(gc); - u32 hwirq = irqd_to_hwirq(d); + irq_hw_number_t hwirq = irqd_to_hwirq(d); void __iomem *reg = lp_gpio_reg(&lg->chip, hwirq, LP_INT_ENABLE); unsigned long flags; raw_spin_lock_irqsave(&lg->lock, flags); iowrite32(ioread32(reg) & ~BIT(hwirq % 32), reg); raw_spin_unlock_irqrestore(&lg->lock, flags); + + gpiochip_disable_irq(gc, hwirq); } static int lp_irq_set_type(struct irq_data *d, unsigned int type) { struct gpio_chip *gc = irq_data_get_irq_chip_data(d); struct intel_pinctrl *lg = gpiochip_get_data(gc); - u32 hwirq = irqd_to_hwirq(d); - void __iomem *reg = lp_gpio_reg(&lg->chip, hwirq, LP_CONFIG1); + irq_hw_number_t hwirq = irqd_to_hwirq(d); unsigned long flags; + void __iomem *reg; u32 value; - if (hwirq >= lg->chip.ngpio) + reg = lp_gpio_reg(&lg->chip, hwirq, LP_CONFIG1); + if (!reg) return -EINVAL; /* Fail if BIOS reserved pin for ACPI use */ if (lp_gpio_acpi_use(lg, hwirq)) { - dev_err(lg->dev, "pin %u can't be used as IRQ\n", hwirq); + dev_err(lg->dev, "pin %lu can't be used as IRQ\n", hwirq); return -EBUSY; } @@ -755,7 +760,7 @@ static int lp_irq_set_type(struct irq_data *d, unsigned int type) return 0; } -static struct irq_chip lp_irqchip = { +static const struct irq_chip lp_irqchip = { .name = "LP-GPIO", .irq_ack = lp_irq_ack, .irq_mask = lp_irq_mask, @@ -763,7 +768,8 @@ static struct irq_chip lp_irqchip = { .irq_enable = lp_irq_enable, .irq_disable = lp_irq_disable, .irq_set_type = lp_irq_set_type, - .flags = IRQCHIP_SKIP_SET_WAKE, + .flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_IMMUTABLE, + GPIOCHIP_IRQ_RESOURCE_HELPERS, }; static int lp_gpio_irq_init_hw(struct gpio_chip *chip) @@ -884,7 +890,7 @@ static int lp_gpio_probe(struct platform_device *pdev) struct gpio_irq_chip *girq; girq = &gc->irq; - girq->chip = &lp_irqchip; + gpio_irq_chip_set_chip(girq, &lp_irqchip); girq->init_hw = lp_gpio_irq_init_hw; girq->parent_handler = lp_gpio_irq_handler; girq->num_parents = 1; diff --git a/drivers/pinctrl/mediatek/Kconfig b/drivers/pinctrl/mediatek/Kconfig index 40accd110c3d8fe74fad1b01ab0cada0ed94fe8a..1600a2c18eeefadf0862d44ed429efe38a014817 100644 --- a/drivers/pinctrl/mediatek/Kconfig +++ b/drivers/pinctrl/mediatek/Kconfig @@ -106,6 +106,13 @@ config PINCTRL_MT6779 In MTK platform, we support virtual gpio and use it to map specific eint which doesn't have real gpio pin. +config PINCTRL_MT6795 + bool "Mediatek MT6795 pin control" + depends on OF + depends on ARM64 || COMPILE_TEST + default ARM64 && ARCH_MEDIATEK + select PINCTRL_MTK_PARIS + config PINCTRL_MT6797 bool "Mediatek MT6797 pin control" depends on OF @@ -166,6 +173,7 @@ config PINCTRL_MT8195 bool "Mediatek MT8195 pin control" depends on OF depends on ARM64 || COMPILE_TEST + default ARM64 && ARCH_MEDIATEK select PINCTRL_MTK_PARIS config PINCTRL_MT8365 diff --git a/drivers/pinctrl/mediatek/Makefile b/drivers/pinctrl/mediatek/Makefile index 29018d6ad0def56e7206700cf930a5669e2cba84..c8f226ae36c943638f0afdeef1a8172a1756982f 100644 --- a/drivers/pinctrl/mediatek/Makefile +++ b/drivers/pinctrl/mediatek/Makefile @@ -13,6 +13,7 @@ obj-$(CONFIG_PINCTRL_MT8135) += pinctrl-mt8135.o obj-$(CONFIG_PINCTRL_MT8127) += pinctrl-mt8127.o obj-$(CONFIG_PINCTRL_MT6765) += pinctrl-mt6765.o obj-$(CONFIG_PINCTRL_MT6779) += pinctrl-mt6779.o +obj-$(CONFIG_PINCTRL_MT6795) += pinctrl-mt6795.o obj-$(CONFIG_PINCTRL_MT6797) += pinctrl-mt6797.o obj-$(CONFIG_PINCTRL_MT7622) += pinctrl-mt7622.o obj-$(CONFIG_PINCTRL_MT7623) += pinctrl-mt7623.o diff --git a/drivers/pinctrl/mediatek/pinctrl-mt6795.c b/drivers/pinctrl/mediatek/pinctrl-mt6795.c new file mode 100644 index 0000000000000000000000000000000000000000..f90152261a0f619ab162e54f6f436e42dd7da52b --- /dev/null +++ b/drivers/pinctrl/mediatek/pinctrl-mt6795.c @@ -0,0 +1,623 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2022 Collabora Ltd. + * Author: AngeloGioacchino Del Regno + */ + +#include "pinctrl-mtk-mt6795.h" +#include "pinctrl-paris.h" + +#define PIN_FIELD15(_s_pin, _e_pin, _s_addr, _x_addrs, _s_bit, _x_bits) \ + PIN_FIELD_CALC(_s_pin, _e_pin, 0, _s_addr, _x_addrs, _s_bit, \ + _x_bits, 15, 0) + +#define PIN_FIELD16(_s_pin, _e_pin, _s_addr, _x_addrs, _s_bit, _x_bits) \ + PIN_FIELD_CALC(_s_pin, _e_pin, 0, _s_addr, _x_addrs, _s_bit, \ + _x_bits, 16, 0) + +#define PINS_FIELD16(_s_pin, _e_pin, _s_addr, _x_addrs, _s_bit, _x_bits)\ + PIN_FIELD_CALC(_s_pin, _e_pin, 0, _s_addr, _x_addrs, _s_bit, \ + _x_bits, 16, 1) + +static const struct mtk_pin_field_calc mt6795_pin_dir_range[] = { + PIN_FIELD16(0, 196, 0x0, 0x10, 0, 1), +}; + +static const struct mtk_pin_field_calc mt6795_pin_pullen_range[] = { + PIN_FIELD16(0, 196, 0x100, 0x10, 0, 1), +}; + +static const struct mtk_pin_field_calc mt6795_pin_pullsel_range[] = { + PIN_FIELD16(0, 196, 0x200, 0x10, 0, 1), +}; + +static const struct mtk_pin_field_calc mt6795_pin_do_range[] = { + PIN_FIELD16(0, 196, 0x400, 0x10, 0, 1), +}; + +static const struct mtk_pin_field_calc mt6795_pin_di_range[] = { + PIN_FIELD16(0, 196, 0x500, 0x10, 0, 1), +}; + +static const struct mtk_pin_field_calc mt6795_pin_mode_range[] = { + PIN_FIELD15(0, 196, 0x600, 0x10, 0, 3), +}; + +static const struct mtk_pin_field_calc mt6795_pin_ies_range[] = { + PINS_FIELD16(0, 4, 0x900, 0x10, 1, 1), + PINS_FIELD16(5, 9, 0x900, 0x10, 2, 1), + PINS_FIELD16(10, 15, 0x900, 0x10, 10, 1), + PINS_FIELD16(16, 16, 0x900, 0x10, 2, 1), + PINS_FIELD16(17, 19, 0x910, 0x10, 3, 1), + PINS_FIELD16(20, 22, 0x910, 0x10, 4, 1), + PINS_FIELD16(23, 26, 0xce0, 0x10, 14, 1), + PINS_FIELD16(27, 27, 0xcc0, 0x10, 14, 1), + PINS_FIELD16(28, 28, 0xcd0, 0x10, 14, 1), + PINS_FIELD16(29, 32, 0x900, 0x10, 3, 1), + PINS_FIELD16(33, 33, 0x900, 0x10, 4, 1), + PINS_FIELD16(34, 36, 0x900, 0x10, 5, 1), + PINS_FIELD16(37, 38, 0x900, 0x10, 6, 1), + PINS_FIELD16(39, 39, 0x900, 0x10, 7, 1), + PINS_FIELD16(40, 40, 0x900, 0x10, 8, 1), + PINS_FIELD16(41, 42, 0x900, 0x10, 9, 1), + PINS_FIELD16(43, 46, 0x900, 0x10, 11, 1), + PINS_FIELD16(47, 61, 0x920, 0x10, 3, 1), + PINS_FIELD16(62, 66, 0x920, 0x10, 4, 1), + PINS_FIELD16(67, 67, 0x920, 0x10, 3, 1), + PINS_FIELD16(68, 72, 0x920, 0x10, 5, 1), + PINS_FIELD16(73, 77, 0x920, 0x10, 6, 1), + PINS_FIELD16(78, 91, 0x920, 0x10, 7, 1), + PINS_FIELD16(92, 92, 0x900, 0x10, 13, 1), + PINS_FIELD16(93, 95, 0x900, 0x10, 14, 1), + PINS_FIELD16(96, 99, 0x900, 0x10, 15, 1), + PINS_FIELD16(100, 103, 0xca0, 0x10, 14, 1), + PINS_FIELD16(104, 104, 0xc80, 0x10, 14, 1), + PINS_FIELD16(105, 105, 0xc90, 0x10, 14, 1), + PINS_FIELD16(106, 107, 0x910, 0x10, 0, 1), + PINS_FIELD16(108, 112, 0x910, 0x10, 1, 1), + PINS_FIELD16(113, 116, 0x910, 0x10, 2, 1), + PINS_FIELD16(117, 118, 0x910, 0x10, 5, 1), + PINS_FIELD16(119, 124, 0x910, 0x10, 6, 1), + PINS_FIELD16(125, 126, 0x910, 0x10, 7, 1), + PINS_FIELD16(129, 129, 0x910, 0x10, 8, 1), + PINS_FIELD16(130, 131, 0x910, 0x10, 9, 1), + PINS_FIELD16(132, 135, 0x910, 0x10, 8, 1), + PINS_FIELD16(136, 137, 0x910, 0x10, 7, 1), + PINS_FIELD16(154, 161, 0xc20, 0x10, 14, 1), + PINS_FIELD16(162, 162, 0xc10, 0x10, 14, 1), + PINS_FIELD16(163, 163, 0xc00, 0x10, 14, 1), + PINS_FIELD16(164, 164, 0xd10, 0x10, 14, 1), + PINS_FIELD16(165, 165, 0xd00, 0x10, 14, 1), + PINS_FIELD16(166, 169, 0x910, 0x10, 14, 1), + PINS_FIELD16(176, 179, 0x910, 0x10, 15, 1), + PINS_FIELD16(180, 180, 0x920, 0x10, 0, 1), + PINS_FIELD16(181, 184, 0x920, 0x10, 1, 1), + PINS_FIELD16(185, 191, 0x920, 0x10, 2, 1), + PINS_FIELD16(192, 192, 0x920, 0x10, 8, 1), + PINS_FIELD16(193, 194, 0x920, 0x10, 9, 1), + PINS_FIELD16(195, 196, 0x920, 0x10, 8, 1), +}; + +static const struct mtk_pin_field_calc mt6795_pin_smt_range[] = { + PINS_FIELD16(0, 4, 0x930, 0x10, 1, 1), + PINS_FIELD16(5, 9, 0x930, 0x10, 2, 1), + PINS_FIELD16(10, 15, 0x930, 0x10, 10, 1), + PINS_FIELD16(16, 16, 0x930, 0x10, 2, 1), + PINS_FIELD16(17, 19, 0x940, 0x10, 3, 1), + PINS_FIELD16(20, 22, 0x940, 0x10, 4, 1), + PINS_FIELD16(23, 26, 0xce0, 0x10, 13, 1), + PINS_FIELD16(27, 27, 0xcc0, 0x10, 13, 1), + PINS_FIELD16(28, 28, 0xcd0, 0x10, 13, 1), + PINS_FIELD16(29, 32, 0x930, 0x10, 3, 1), + PINS_FIELD16(33, 33, 0x930, 0x10, 4, 1), + PINS_FIELD16(34, 36, 0x930, 0x10, 5, 1), + PINS_FIELD16(37, 38, 0x930, 0x10, 6, 1), + PINS_FIELD16(39, 39, 0x930, 0x10, 7, 1), + PINS_FIELD16(40, 40, 0x930, 0x10, 8, 1), + PINS_FIELD16(41, 42, 0x930, 0x10, 9, 1), + PINS_FIELD16(43, 46, 0x930, 0x10, 11, 1), + PINS_FIELD16(47, 61, 0x950, 0x10, 3, 1), + PINS_FIELD16(62, 66, 0x950, 0x10, 4, 1), + PINS_FIELD16(67, 67, 0x950, 0x10, 3, 1), + PINS_FIELD16(68, 72, 0x950, 0x10, 5, 1), + PINS_FIELD16(73, 77, 0x950, 0x10, 6, 1), + PINS_FIELD16(78, 91, 0x950, 0x10, 7, 1), + PINS_FIELD16(92, 92, 0x930, 0x10, 13, 1), + PINS_FIELD16(93, 95, 0x930, 0x10, 14, 1), + PINS_FIELD16(96, 99, 0x930, 0x10, 15, 1), + PINS_FIELD16(100, 103, 0xca0, 0x10, 13, 1), + PINS_FIELD16(104, 104, 0xc80, 0x10, 13, 1), + PINS_FIELD16(105, 105, 0xc90, 0x10, 13, 1), + PINS_FIELD16(106, 107, 0x940, 0x10, 0, 1), + PINS_FIELD16(108, 112, 0x940, 0x10, 1, 1), + PINS_FIELD16(113, 116, 0x940, 0x10, 2, 1), + PINS_FIELD16(117, 118, 0x940, 0x10, 5, 1), + PINS_FIELD16(119, 124, 0x940, 0x10, 6, 1), + PINS_FIELD16(125, 126, 0x940, 0x10, 7, 1), + PINS_FIELD16(129, 129, 0x940, 0x10, 8, 1), + PINS_FIELD16(130, 131, 0x940, 0x10, 9, 1), + PINS_FIELD16(132, 135, 0x940, 0x10, 8, 1), + PINS_FIELD16(136, 137, 0x940, 0x10, 7, 1), + PINS_FIELD16(154, 161, 0xc20, 0x10, 13, 1), + PINS_FIELD16(162, 162, 0xc10, 0x10, 13, 1), + PINS_FIELD16(163, 163, 0xc00, 0x10, 13, 1), + PINS_FIELD16(164, 164, 0xd10, 0x10, 13, 1), + PINS_FIELD16(165, 165, 0xd00, 0x10, 13, 1), + PINS_FIELD16(166, 169, 0x940, 0x10, 14, 1), + PINS_FIELD16(176, 179, 0x940, 0x10, 15, 1), + PINS_FIELD16(180, 180, 0x950, 0x10, 0, 1), + PINS_FIELD16(181, 184, 0x950, 0x10, 1, 1), + PINS_FIELD16(185, 191, 0x950, 0x10, 2, 1), + PINS_FIELD16(192, 192, 0x950, 0x10, 8, 1), + PINS_FIELD16(193, 194, 0x950, 0x10, 9, 1), + PINS_FIELD16(195, 196, 0x950, 0x10, 8, 1), +}; + + +static const struct mtk_pin_field_calc mt6795_pin_pupd_range[] = { + /* KROW */ + PIN_FIELD16(119, 119, 0xe00, 0x10, 2, 1), /* KROW0 */ + PIN_FIELD16(120, 120, 0xe00, 0x10, 6, 1), /* KROW1 */ + PIN_FIELD16(121, 121, 0xe00, 0x10, 10, 1), /* KROW2 */ + PIN_FIELD16(122, 122, 0xe10, 0x10, 2, 1), /* KCOL0 */ + PIN_FIELD16(123, 123, 0xe10, 0x10, 6, 1), /* KCOL1 */ + PIN_FIELD16(124, 124, 0xe10, 0x10, 10, 1), /* KCOL2 */ + + /* DPI */ + PIN_FIELD16(138, 138, 0xd50, 0x10, 2, 1), /* CK */ + PIN_FIELD16(139, 139, 0xd60, 0x10, 1, 1), /* DE */ + PIN_FIELD16(140, 140, 0xd70, 0x10, 1, 1), /* data0 */ + PIN_FIELD16(141, 141, 0xd70, 0x10, 3, 1), /* data1 */ + PIN_FIELD16(142, 142, 0xd70, 0x10, 5, 1), /* data2 */ + PIN_FIELD16(143, 143, 0xd70, 0x10, 7, 1), /* data3 */ + PIN_FIELD16(144, 144, 0xd50, 0x10, 5, 1), /* data4 */ + PIN_FIELD16(145, 145, 0xd50, 0x10, 7, 1), /* data5 */ + PIN_FIELD16(146, 146, 0xd60, 0x10, 7, 1), /* data6 */ + PIN_FIELD16(147, 147, 0xed0, 0x10, 6, 1), /* data7 */ + PIN_FIELD16(148, 148, 0xed0, 0x10, 8, 1), /* data8 */ + PIN_FIELD16(149, 149, 0xed0, 0x10, 10, 1), /* data9 */ + PIN_FIELD16(150, 150, 0xed0, 0x10, 12, 1), /* data10 */ + PIN_FIELD16(151, 151, 0xed0, 0x10, 14, 1), /* data11 */ + PIN_FIELD16(152, 152, 0xd60, 0x10, 3, 1), /* hsync */ + PIN_FIELD16(153, 153, 0xd60, 0x10, 5, 1), /* vsync */ + + /* MSDC0 */ + PIN_FIELD16(154, 154, 0xc20, 0x10, 2, 1), /* DATA 0-7 */ + PIN_FIELD16(155, 155, 0xc20, 0x10, 2, 1), /* DATA 0-7 */ + PIN_FIELD16(156, 156, 0xc20, 0x10, 2, 1), /* DATA 0-7 */ + PIN_FIELD16(157, 157, 0xc20, 0x10, 2, 1), /* DATA 0-7 */ + PIN_FIELD16(158, 158, 0xc20, 0x10, 2, 1), /* DATA 0-7 */ + PIN_FIELD16(159, 159, 0xc20, 0x10, 2, 1), /* DATA 0-7 */ + PIN_FIELD16(160, 160, 0xc20, 0x10, 2, 1), /* DATA 0-7 */ + PIN_FIELD16(161, 161, 0xc20, 0x10, 2, 1), /* DATA 0-7 */ + PIN_FIELD16(162, 162, 0xc10, 0x10, 2, 1), /* CMD */ + PIN_FIELD16(163, 163, 0xc00, 0x10, 2, 1), /* CLK */ + PIN_FIELD16(164, 164, 0xd10, 0x10, 2, 1), /* DS */ + PIN_FIELD16(165, 165, 0xd00, 0x10, 2, 1), /* RST */ + + /* MSDC1 */ + PIN_FIELD16(170, 170, 0xc50, 0x10, 2, 1), /* CMD */ + PIN_FIELD16(171, 171, 0xd20, 0x10, 2, 1), /* DAT0 */ + PIN_FIELD16(172, 172, 0xd20, 0x10, 6, 1), /* DAT1 */ + PIN_FIELD16(173, 173, 0xd20, 0x10, 10, 1), /* DAT2 */ + PIN_FIELD16(174, 174, 0xd20, 0x10, 14, 1), /* DAT3 */ + PIN_FIELD16(175, 175, 0xc40, 0x10, 2, 1), /* CLK */ + + /* MSDC2 */ + PIN_FIELD16(100, 100, 0xd30, 0x10, 2, 1), /* DAT0 */ + PIN_FIELD16(101, 101, 0xd30, 0x10, 6, 1), /* DAT1 */ + PIN_FIELD16(102, 102, 0xd30, 0x10, 10, 1), /* DAT2 */ + PIN_FIELD16(103, 103, 0xd30, 0x10, 14, 1), /* DAT3 */ + PIN_FIELD16(104, 104, 0xc80, 0x10, 2, 1), /* CLK */ + PIN_FIELD16(105, 105, 0xc90, 0x10, 2, 1), /* CMD */ + + /* MSDC3 */ + PIN_FIELD16(23, 23, 0xd40, 0x10, 2, 1), /* DAT0 */ + PIN_FIELD16(24, 24, 0xd40, 0x10, 6, 5), /* DAT1 */ + PIN_FIELD16(25, 25, 0xd40, 0x10, 10, 9), /* DAT2 */ + PIN_FIELD16(26, 26, 0xd40, 0x10, 14, 13), /* DAT3 */ + PIN_FIELD16(27, 27, 0xcc0, 0x10, 2, 1), /* CLK */ + PIN_FIELD16(28, 28, 0xcd0, 0x10, 2, 1) /* CMD */ +}; + +static const struct mtk_pin_field_calc mt6795_pin_r0_range[] = { + PIN_FIELD16(23, 23, 0xd40, 0x10, 0, 1), + PIN_FIELD16(24, 24, 0xd40, 0x10, 4, 1), + PIN_FIELD16(25, 25, 0xd40, 0x10, 8, 1), + PIN_FIELD16(26, 26, 0xd40, 0x10, 12, 1), + PIN_FIELD16(27, 27, 0xcc0, 0x10, 0, 1), + PIN_FIELD16(28, 28, 0xcd0, 0x10, 0, 1), + PIN_FIELD16(100, 100, 0xd30, 0x10, 0, 1), + PIN_FIELD16(101, 101, 0xd30, 0x10, 4, 1), + PIN_FIELD16(102, 102, 0xd30, 0x10, 8, 1), + PIN_FIELD16(103, 103, 0xd30, 0x10, 12, 1), + PIN_FIELD16(104, 104, 0xc80, 0x10, 0, 1), + PIN_FIELD16(105, 105, 0xc90, 0x10, 0, 1), + PIN_FIELD16(119, 119, 0xe00, 0x10, 0, 1), + PIN_FIELD16(120, 120, 0xe00, 0x10, 4, 1), + PIN_FIELD16(121, 121, 0xe00, 0x10, 8, 1), + PIN_FIELD16(122, 122, 0xe10, 0x10, 0, 1), + PIN_FIELD16(123, 123, 0xe10, 0x10, 4, 1), + PIN_FIELD16(124, 124, 0xe10, 0x10, 8, 1), + PIN_FIELD16(138, 138, 0xd50, 0x10, 0, 1), + PIN_FIELD16(139, 139, 0xd60, 0x10, 0, 1), + PIN_FIELD16(140, 140, 0xd70, 0x10, 0, 1), + PIN_FIELD16(141, 141, 0xd70, 0x10, 1, 1), + PIN_FIELD16(142, 142, 0xd70, 0x10, 3, 1), + PIN_FIELD16(143, 143, 0xd70, 0x10, 5, 1), + PIN_FIELD16(144, 144, 0xd50, 0x10, 3, 1), + PIN_FIELD16(145, 145, 0xd50, 0x10, 5, 1), + PIN_FIELD16(146, 146, 0xd60, 0x10, 5, 1), + PIN_FIELD16(147, 147, 0xed0, 0x10, 4, 1), + PIN_FIELD16(148, 148, 0xed0, 0x10, 6, 1), + PIN_FIELD16(149, 149, 0xed0, 0x10, 8, 1), + PIN_FIELD16(150, 150, 0xed0, 0x10, 10, 1), + PIN_FIELD16(151, 151, 0xed0, 0x10, 12, 1), + PIN_FIELD16(152, 152, 0xd60, 0x10, 1, 1), + PIN_FIELD16(153, 153, 0xd60, 0x10, 3, 1), + PIN_FIELD16(154, 155, 0xc20, 0x10, 0, 1), + PIN_FIELD16(155, 156, 0xc20, 0x10, 0, 1), + PIN_FIELD16(156, 157, 0xc20, 0x10, 0, 1), + PIN_FIELD16(157, 158, 0xc20, 0x10, 0, 1), + PIN_FIELD16(158, 159, 0xc20, 0x10, 0, 1), + PIN_FIELD16(159, 160, 0xc20, 0x10, 0, 1), + PIN_FIELD16(160, 161, 0xc20, 0x10, 0, 1), + PIN_FIELD16(161, 161, 0xc20, 0x10, 0, 1), + PIN_FIELD16(162, 162, 0xc10, 0x10, 0, 1), + PIN_FIELD16(163, 163, 0xc00, 0x10, 0, 1), + PIN_FIELD16(164, 164, 0xd10, 0x10, 0, 1), + PIN_FIELD16(165, 165, 0xd00, 0x10, 0, 1), + PIN_FIELD16(170, 170, 0xc50, 0x10, 0, 1), + PIN_FIELD16(171, 171, 0xd20, 0x10, 0, 1), + PIN_FIELD16(172, 172, 0xd20, 0x10, 4, 1), + PIN_FIELD16(173, 173, 0xd20, 0x10, 8, 1), + PIN_FIELD16(174, 174, 0xd20, 0x10, 12, 1), + PIN_FIELD16(175, 175, 0xc40, 0x10, 0, 1), +}; + +static const struct mtk_pin_field_calc mt6795_pin_r1_range[] = { + PIN_FIELD16(23, 23, 0xd40, 0x10, 1, 1), + PIN_FIELD16(24, 24, 0xd40, 0x10, 5, 1), + PIN_FIELD16(25, 25, 0xd40, 0x10, 9, 1), + PIN_FIELD16(26, 26, 0xd40, 0x10, 13, 1), + PIN_FIELD16(27, 27, 0xcc0, 0x10, 1, 1), + PIN_FIELD16(28, 28, 0xcd0, 0x10, 1, 1), + PIN_FIELD16(100, 100, 0xd30, 0x10, 1, 1), + PIN_FIELD16(101, 101, 0xd30, 0x10, 5, 1), + PIN_FIELD16(102, 102, 0xd30, 0x10, 9, 1), + PIN_FIELD16(103, 103, 0xd30, 0x10, 13, 1), + PIN_FIELD16(104, 104, 0xc80, 0x10, 1, 1), + PIN_FIELD16(105, 105, 0xc90, 0x10, 1, 1), + PIN_FIELD16(119, 119, 0xe00, 0x10, 1, 1), + PIN_FIELD16(120, 120, 0xe00, 0x10, 5, 1), + PIN_FIELD16(121, 121, 0xe00, 0x10, 9, 1), + PIN_FIELD16(122, 122, 0xe10, 0x10, 1, 1), + PIN_FIELD16(123, 123, 0xe10, 0x10, 5, 1), + PIN_FIELD16(124, 124, 0xe10, 0x10, 9, 1), + PIN_FIELD16(138, 138, 0xd50, 0x10, 1, 1), + PIN_FIELD16(139, 139, 0xd60, 0x10, 0, 1), + PIN_FIELD16(140, 140, 0xd70, 0x10, 0, 1), + PIN_FIELD16(141, 141, 0xd70, 0x10, 2, 1), + PIN_FIELD16(142, 142, 0xd70, 0x10, 4, 1), + PIN_FIELD16(143, 143, 0xd70, 0x10, 6, 1), + PIN_FIELD16(144, 144, 0xd50, 0x10, 4, 1), + PIN_FIELD16(145, 145, 0xd50, 0x10, 6, 1), + PIN_FIELD16(146, 146, 0xd60, 0x10, 6, 1), + PIN_FIELD16(147, 147, 0xed0, 0x10, 5, 1), + PIN_FIELD16(148, 148, 0xed0, 0x10, 7, 1), + PIN_FIELD16(149, 149, 0xed0, 0x10, 9, 1), + PIN_FIELD16(150, 150, 0xed0, 0x10, 11, 1), + PIN_FIELD16(151, 151, 0xed0, 0x10, 13, 1), + PIN_FIELD16(152, 152, 0xd60, 0x10, 2, 1), + PIN_FIELD16(153, 153, 0xd60, 0x10, 4, 1), + PIN_FIELD16(154, 155, 0xc20, 0x10, 1, 1), + PIN_FIELD16(155, 156, 0xc20, 0x10, 1, 1), + PIN_FIELD16(156, 157, 0xc20, 0x10, 1, 1), + PIN_FIELD16(157, 158, 0xc20, 0x10, 1, 1), + PIN_FIELD16(158, 159, 0xc20, 0x10, 1, 1), + PIN_FIELD16(159, 160, 0xc20, 0x10, 1, 1), + PIN_FIELD16(160, 161, 0xc20, 0x10, 1, 1), + PIN_FIELD16(161, 161, 0xc20, 0x10, 1, 1), + PIN_FIELD16(162, 162, 0xc10, 0x10, 1, 1), + PIN_FIELD16(163, 163, 0xc00, 0x10, 1, 1), + PIN_FIELD16(164, 164, 0xd10, 0x10, 1, 1), + PIN_FIELD16(165, 165, 0xd00, 0x10, 1, 1), + PIN_FIELD16(170, 170, 0xc50, 0x10, 1, 1), + PIN_FIELD16(171, 171, 0xd20, 0x10, 1, 1), + PIN_FIELD16(172, 172, 0xd20, 0x10, 5, 1), + PIN_FIELD16(173, 173, 0xd20, 0x10, 9, 1), + PIN_FIELD16(174, 174, 0xd20, 0x10, 13, 1), + PIN_FIELD16(175, 175, 0xc40, 0x10, 1, 1), +}; + +static const struct mtk_pin_field_calc mt6795_pin_drv_range[] = { + PINS_FIELD16(0, 4, 0xb30, 0x10, 13, 2), + PINS_FIELD16(5, 9, 0xb30, 0x10, 1, 2), + PINS_FIELD16(10, 15, 0xb30, 0x10, 5, 2), + PIN_FIELD16(16, 16, 0xb30, 0x10, 1, 2), + PINS_FIELD16(17, 19, 0xb70, 0x10, 5, 2), + PINS_FIELD16(20, 22, 0xb70, 0x10, 9, 2), + PINS_FIELD16(23, 26, 0xce0, 0x10, 8, 2), + PIN_FIELD16(27, 27, 0xcc0, 0x10, 8, 2), + PIN_FIELD16(28, 28, 0xcd0, 0x10, 8, 2), + PINS_FIELD16(29, 32, 0xb80, 0x10, 13, 2), + PIN_FIELD16(33, 33, 0xb10, 0x10, 13, 2), + PINS_FIELD16(34, 36, 0xb10, 0x10, 9, 2), + PINS_FIELD16(37, 38, 0xb10, 0x10, 5, 2), + PIN_FIELD16(39, 39, 0xb20, 0x10, 1, 2), + PIN_FIELD16(40, 40, 0xb20, 0x10, 5, 2), + PINS_FIELD16(41, 42, 0xb20, 0x10, 9, 2), + PINS_FIELD16(47, 61, 0xb00, 0x10, 9, 2), + PINS_FIELD16(62, 66, 0xb70, 0x10, 1, 2), + PINS_FIELD16(67, 67, 0xb00, 0x10, 9, 2), + PINS_FIELD16(68, 72, 0xb60, 0x10, 13, 2), + PINS_FIELD16(73, 77, 0xb40, 0x10, 13, 2), + PIN_FIELD16(78, 78, 0xb00, 0x10, 12, 3), + PINS_FIELD16(79, 91, 0xb00, 0x10, 13, 2), + PIN_FIELD16(92, 92, 0xb60, 0x10, 5, 2), + PINS_FIELD16(93, 95, 0xb60, 0x10, 1, 2), + PINS_FIELD16(96, 99, 0xb80, 0x10, 9, 2), + PINS_FIELD16(100, 103, 0xca0, 0x10, 8, 2), + PIN_FIELD16(104, 104, 0xc80, 0x10, 8, 2), + PIN_FIELD16(105, 105, 0xc90, 0x10, 8, 2), + PINS_FIELD16(106, 107, 0xb50, 0x10, 9, 2), + PINS_FIELD16(108, 112, 0xb50, 0x10, 1, 2), + PINS_FIELD16(113, 116, 0xb80, 0x10, 5, 2), + PINS_FIELD16(117, 118, 0xb90, 0x10, 1, 2), + PINS_FIELD16(119, 124, 0xb50, 0x10, 5, 2), + PIN_FIELD16(127, 127, 0xb70, 0x10, 5, 2), + PIN_FIELD16(128, 128, 0xb70, 0x10, 9, 2), + PIN_FIELD16(129, 129, 0xb40, 0x10, 9, 2), + PINS_FIELD16(130, 131, 0xb40, 0x10, 13, 2), + PINS_FIELD16(132, 135, 0xb40, 0x10, 9, 2), + PIN_FIELD16(138, 138, 0xb50, 0x10, 8, 2), + PIN_FIELD16(139, 139, 0xb60, 0x10, 8, 2), + PINS_FIELD16(140, 151, 0xb70, 0x10, 8, 2), + PINS_FIELD16(152, 153, 0xb60, 0x10, 8, 2), + PINS_FIELD16(153, 153, 0xb60, 0x10, 8, 2), + PINS_FIELD16(154, 161, 0xc20, 0x10, 8, 2), + PIN_FIELD16(162, 162, 0xc10, 0x10, 8, 2), + PIN_FIELD16(163, 163, 0xc00, 0x10, 8, 2), + PIN_FIELD16(164, 164, 0xd10, 0x10, 8, 2), + PIN_FIELD16(165, 165, 0xd00, 0x10, 8, 2), + PINS_FIELD16(166, 169, 0xb80, 0x10, 1, 2), + PINS_FIELD16(170, 173, 0xc60, 0x10, 8, 2), + PIN_FIELD16(174, 174, 0xc40, 0x10, 8, 2), + PIN_FIELD16(175, 175, 0xc50, 0x10, 8, 2), + PINS_FIELD16(176, 179, 0xb70, 0x10, 13, 2), + PIN_FIELD16(180, 180, 0xb00, 0x10, 5, 2), + PINS_FIELD16(181, 184, 0xb00, 0x10, 1, 2), + PINS_FIELD16(185, 191, 0xb60, 0x10, 9, 2), + PIN_FIELD16(192, 192, 0xb40, 0x10, 1, 2), + PINS_FIELD16(193, 194, 0xb40, 0x10, 5, 2), + PINS_FIELD16(195, 196, 0xb40, 0x10, 1, 2), +}; + +static const struct mtk_pin_field_calc mt6795_pin_sr_range[] = { + PINS_FIELD16(0, 4, 0xb30, 0x10, 15, 1), + PINS_FIELD16(5, 9, 0xb30, 0x10, 3, 1), + PINS_FIELD16(10, 15, 0xb30, 0x10, 7, 1), + PIN_FIELD16(16, 16, 0xb30, 0x10, 5, 1), + PINS_FIELD16(23, 26, 0xce0, 0x10, 12, 1), + PIN_FIELD16(27, 27, 0xcc0, 0x10, 12, 1), + PIN_FIELD16(28, 28, 0xcd0, 0x10, 12, 1), + PINS_FIELD16(29, 32, 0xb80, 0x10, 15, 1), + PIN_FIELD16(33, 33, 0xb10, 0x10, 15, 1), + PINS_FIELD16(34, 36, 0xb10, 0x10, 11, 1), + PINS_FIELD16(37, 38, 0xb10, 0x10, 7, 1), + PIN_FIELD16(39, 39, 0xb20, 0x10, 3, 1), + PIN_FIELD16(40, 40, 0xb20, 0x10, 7, 1), + PINS_FIELD16(41, 42, 0xb20, 0x10, 11, 1), + PINS_FIELD16(47, 61, 0xb00, 0x10, 11, 1), + PINS_FIELD16(62, 66, 0xb70, 0x10, 3, 1), + PINS_FIELD16(67, 67, 0xb00, 0x10, 11, 1), + PINS_FIELD16(68, 72, 0xb60, 0x10, 15, 1), + PINS_FIELD16(73, 77, 0xb40, 0x10, 15, 1), + PIN_FIELD16(78, 78, 0xb00, 0x10, 15, 3), + PINS_FIELD16(79, 91, 0xb00, 0x10, 15, 1), + PIN_FIELD16(92, 92, 0xb60, 0x10, 7, 1), + PINS_FIELD16(93, 95, 0xb60, 0x10, 3, 1), + PINS_FIELD16(96, 99, 0xb80, 0x10, 11, 1), + PINS_FIELD16(100, 103, 0xca0, 0x10, 12, 1), + PIN_FIELD16(104, 104, 0xc80, 0x10, 12, 1), + PIN_FIELD16(105, 105, 0xc90, 0x10, 12, 1), + PINS_FIELD16(106, 107, 0xb50, 0x10, 11, 1), + PINS_FIELD16(108, 112, 0xb50, 0x10, 3, 1), + PINS_FIELD16(113, 116, 0xb80, 0x10, 7, 1), + PINS_FIELD16(117, 118, 0xb90, 0x10, 3, 1), + PINS_FIELD16(119, 124, 0xb50, 0x10, 7, 1), + PIN_FIELD16(127, 127, 0xb70, 0x10, 7, 1), + PIN_FIELD16(128, 128, 0xb70, 0x10, 11, 1), + PIN_FIELD16(129, 129, 0xb40, 0x10, 11, 1), + PINS_FIELD16(130, 131, 0xb40, 0x10, 15, 1), + PINS_FIELD16(132, 135, 0xb40, 0x10, 11, 1), + PIN_FIELD16(138, 138, 0xb50, 0x10, 12, 1), + PIN_FIELD16(139, 139, 0xb60, 0x10, 12, 1), + PINS_FIELD16(140, 151, 0xb70, 0x10, 12, 1), + PINS_FIELD16(152, 153, 0xb60, 0x10, 12, 1), + PINS_FIELD16(153, 153, 0xb60, 0x10, 12, 1), + PINS_FIELD16(154, 161, 0xc20, 0x10, 12, 1), + PIN_FIELD16(162, 162, 0xc10, 0x10, 12, 1), + PIN_FIELD16(163, 163, 0xc00, 0x10, 12, 1), + PIN_FIELD16(164, 164, 0xd10, 0x10, 12, 1), + PIN_FIELD16(165, 165, 0xd00, 0x10, 12, 1), + PINS_FIELD16(166, 169, 0xb80, 0x10, 3, 1), + PINS_FIELD16(170, 173, 0xc60, 0x10, 12, 1), + PIN_FIELD16(174, 174, 0xc40, 0x10, 12, 1), + PIN_FIELD16(175, 175, 0xc50, 0x10, 12, 1), + PINS_FIELD16(176, 179, 0xb70, 0x10, 15, 1), + PIN_FIELD16(180, 180, 0xb00, 0x10, 7, 1), + PINS_FIELD16(181, 184, 0xb00, 0x10, 3, 1), + PINS_FIELD16(185, 191, 0xb60, 0x10, 11, 1), + PIN_FIELD16(192, 192, 0xb40, 0x10, 3, 1), + PINS_FIELD16(193, 194, 0xb40, 0x10, 7, 1), + PINS_FIELD16(195, 196, 0xb40, 0x10, 3, 1), +}; + +static const struct mtk_pin_reg_calc mt6795_reg_cals[PINCTRL_PIN_REG_MAX] = { + [PINCTRL_PIN_REG_MODE] = MTK_RANGE(mt6795_pin_mode_range), + [PINCTRL_PIN_REG_DIR] = MTK_RANGE(mt6795_pin_dir_range), + [PINCTRL_PIN_REG_DI] = MTK_RANGE(mt6795_pin_di_range), + [PINCTRL_PIN_REG_DO] = MTK_RANGE(mt6795_pin_do_range), + [PINCTRL_PIN_REG_SR] = MTK_RANGE(mt6795_pin_sr_range), + [PINCTRL_PIN_REG_SMT] = MTK_RANGE(mt6795_pin_smt_range), + [PINCTRL_PIN_REG_DRV] = MTK_RANGE(mt6795_pin_drv_range), + [PINCTRL_PIN_REG_PUPD] = MTK_RANGE(mt6795_pin_pupd_range), + [PINCTRL_PIN_REG_R0] = MTK_RANGE(mt6795_pin_r0_range), + [PINCTRL_PIN_REG_R1] = MTK_RANGE(mt6795_pin_r1_range), + [PINCTRL_PIN_REG_IES] = MTK_RANGE(mt6795_pin_ies_range), + [PINCTRL_PIN_REG_PULLEN] = MTK_RANGE(mt6795_pin_pullen_range), + [PINCTRL_PIN_REG_PULLSEL] = MTK_RANGE(mt6795_pin_pullsel_range), +}; + +static const struct mtk_eint_hw mt6795_eint_hw = { + .port_mask = 7, + .ports = 7, + .ap_num = 224, + .db_cnt = 32, +}; + +static const unsigned int mt6795_pull_type[] = { + MTK_PULL_PULLSEL_TYPE,/*0*/ MTK_PULL_PULLSEL_TYPE,/*1*/ + MTK_PULL_PULLSEL_TYPE,/*2*/ MTK_PULL_PULLSEL_TYPE,/*3*/ + MTK_PULL_PULLSEL_TYPE,/*4*/ MTK_PULL_PULLSEL_TYPE,/*5*/ + MTK_PULL_PULLSEL_TYPE,/*6*/ MTK_PULL_PULLSEL_TYPE,/*7*/ + MTK_PULL_PULLSEL_TYPE,/*8*/ MTK_PULL_PULLSEL_TYPE,/*9*/ + MTK_PULL_PULLSEL_TYPE,/*10*/ MTK_PULL_PULLSEL_TYPE,/*11*/ + MTK_PULL_PULLSEL_TYPE,/*12*/ MTK_PULL_PULLSEL_TYPE,/*13*/ + MTK_PULL_PULLSEL_TYPE,/*14*/ MTK_PULL_PULLSEL_TYPE,/*15*/ + MTK_PULL_PULLSEL_TYPE,/*16*/ MTK_PULL_PULLSEL_TYPE,/*17*/ + MTK_PULL_PULLSEL_TYPE,/*18*/ MTK_PULL_PULLSEL_TYPE,/*19*/ + MTK_PULL_PULLSEL_TYPE,/*20*/ MTK_PULL_PULLSEL_TYPE,/*21*/ + MTK_PULL_PULLSEL_TYPE,/*22*/ MTK_PULL_PUPD_R1R0_TYPE,/*23*/ + MTK_PULL_PUPD_R1R0_TYPE,/*24*/ MTK_PULL_PUPD_R1R0_TYPE,/*25*/ + MTK_PULL_PUPD_R1R0_TYPE,/*26*/ MTK_PULL_PUPD_R1R0_TYPE,/*27*/ + MTK_PULL_PUPD_R1R0_TYPE,/*28*/ MTK_PULL_PULLSEL_TYPE,/*29*/ + MTK_PULL_PULLSEL_TYPE,/*30*/ MTK_PULL_PULLSEL_TYPE,/*31*/ + MTK_PULL_PULLSEL_TYPE,/*32*/ MTK_PULL_PULLSEL_TYPE,/*33*/ + MTK_PULL_PULLSEL_TYPE,/*34*/ MTK_PULL_PULLSEL_TYPE,/*35*/ + MTK_PULL_PULLSEL_TYPE,/*36*/ MTK_PULL_PULLSEL_TYPE,/*37*/ + MTK_PULL_PULLSEL_TYPE,/*38*/ MTK_PULL_PULLSEL_TYPE,/*39*/ + MTK_PULL_PULLSEL_TYPE,/*40*/ MTK_PULL_PULLSEL_TYPE,/*41*/ + MTK_PULL_PULLSEL_TYPE,/*42*/ MTK_PULL_PULLSEL_TYPE,/*43*/ + MTK_PULL_PULLSEL_TYPE,/*44*/ MTK_PULL_PULLSEL_TYPE,/*45*/ + MTK_PULL_PULLSEL_TYPE,/*46*/ MTK_PULL_PULLSEL_TYPE,/*47*/ + MTK_PULL_PULLSEL_TYPE,/*48*/ MTK_PULL_PULLSEL_TYPE,/*49*/ + MTK_PULL_PULLSEL_TYPE,/*50*/ MTK_PULL_PULLSEL_TYPE,/*51*/ + MTK_PULL_PULLSEL_TYPE,/*52*/ MTK_PULL_PULLSEL_TYPE,/*53*/ + MTK_PULL_PULLSEL_TYPE,/*54*/ MTK_PULL_PULLSEL_TYPE,/*55*/ + MTK_PULL_PULLSEL_TYPE,/*56*/ MTK_PULL_PULLSEL_TYPE,/*57*/ + MTK_PULL_PULLSEL_TYPE,/*58*/ MTK_PULL_PULLSEL_TYPE,/*59*/ + MTK_PULL_PULLSEL_TYPE,/*60*/ MTK_PULL_PULLSEL_TYPE,/*61*/ + MTK_PULL_PULLSEL_TYPE,/*62*/ MTK_PULL_PULLSEL_TYPE,/*63*/ + MTK_PULL_PULLSEL_TYPE,/*64*/ MTK_PULL_PULLSEL_TYPE,/*65*/ + MTK_PULL_PULLSEL_TYPE,/*66*/ MTK_PULL_PUPD_R1R0_TYPE,/*67*/ + MTK_PULL_PUPD_R1R0_TYPE,/*68*/ MTK_PULL_PUPD_R1R0_TYPE,/*69*/ + MTK_PULL_PUPD_R1R0_TYPE,/*70*/ MTK_PULL_PUPD_R1R0_TYPE,/*71*/ + MTK_PULL_PUPD_R1R0_TYPE,/*72*/ MTK_PULL_PUPD_R1R0_TYPE,/*73*/ + MTK_PULL_PUPD_R1R0_TYPE,/*74*/ MTK_PULL_PUPD_R1R0_TYPE,/*75*/ + MTK_PULL_PUPD_R1R0_TYPE,/*76*/ MTK_PULL_PUPD_R1R0_TYPE,/*77*/ + MTK_PULL_PUPD_R1R0_TYPE,/*78*/ MTK_PULL_PUPD_R1R0_TYPE,/*79*/ + MTK_PULL_PUPD_R1R0_TYPE,/*80*/ MTK_PULL_PUPD_R1R0_TYPE,/*81*/ + MTK_PULL_PUPD_R1R0_TYPE,/*82*/ MTK_PULL_PULLSEL_TYPE,/*83*/ + MTK_PULL_PUPD_R1R0_TYPE,/*84*/ MTK_PULL_PUPD_R1R0_TYPE,/*85*/ + MTK_PULL_PUPD_R1R0_TYPE,/*86*/ MTK_PULL_PUPD_R1R0_TYPE,/*87*/ + MTK_PULL_PUPD_R1R0_TYPE,/*88*/ MTK_PULL_PUPD_R1R0_TYPE,/*89*/ + MTK_PULL_PULLSEL_TYPE,/*90*/ MTK_PULL_PULLSEL_TYPE,/*91*/ + MTK_PULL_PULLSEL_TYPE,/*92*/ MTK_PULL_PULLSEL_TYPE,/*93*/ + MTK_PULL_PULLSEL_TYPE,/*94*/ MTK_PULL_PULLSEL_TYPE,/*95*/ + MTK_PULL_PULLSEL_TYPE,/*96*/ MTK_PULL_PULLSEL_TYPE,/*97*/ + MTK_PULL_PULLSEL_TYPE,/*98*/ MTK_PULL_PULLSEL_TYPE,/*99*/ + MTK_PULL_PUPD_R1R0_TYPE,/*100*/ MTK_PULL_PUPD_R1R0_TYPE,/*101*/ + MTK_PULL_PUPD_R1R0_TYPE,/*102*/ MTK_PULL_PUPD_R1R0_TYPE,/*103*/ + MTK_PULL_PUPD_R1R0_TYPE,/*104*/ MTK_PULL_PUPD_R1R0_TYPE,/*105*/ + MTK_PULL_PULLSEL_TYPE,/*106*/ MTK_PULL_PULLSEL_TYPE,/*107*/ + MTK_PULL_PULLSEL_TYPE,/*108*/ MTK_PULL_PULLSEL_TYPE,/*109*/ + MTK_PULL_PULLSEL_TYPE,/*110*/ MTK_PULL_PULLSEL_TYPE,/*111*/ + MTK_PULL_PULLSEL_TYPE,/*112*/ MTK_PULL_PULLSEL_TYPE,/*113*/ + MTK_PULL_PULLSEL_TYPE,/*114*/ MTK_PULL_PULLSEL_TYPE,/*115*/ + MTK_PULL_PULLSEL_TYPE,/*116*/ MTK_PULL_PULLSEL_TYPE,/*117*/ + MTK_PULL_PULLSEL_TYPE,/*118*/ MTK_PULL_PUPD_R1R0_TYPE,/*119*/ + MTK_PULL_PUPD_R1R0_TYPE,/*120*/ MTK_PULL_PUPD_R1R0_TYPE,/*121*/ + MTK_PULL_PUPD_R1R0_TYPE,/*122*/ MTK_PULL_PUPD_R1R0_TYPE,/*123*/ + MTK_PULL_PUPD_R1R0_TYPE,/*124*/ MTK_PULL_PULLSEL_TYPE,/*125*/ + MTK_PULL_PULLSEL_TYPE,/*126*/ MTK_PULL_PULLSEL_TYPE,/*127*/ + MTK_PULL_PULLSEL_TYPE,/*128*/ MTK_PULL_PULLSEL_TYPE,/*129*/ + MTK_PULL_PULLSEL_TYPE,/*130*/ MTK_PULL_PULLSEL_TYPE,/*131*/ + MTK_PULL_PULLSEL_TYPE,/*132*/ MTK_PULL_PULLSEL_TYPE,/*133*/ + MTK_PULL_PULLSEL_TYPE,/*134*/ MTK_PULL_PULLSEL_TYPE,/*135*/ + MTK_PULL_PULLSEL_TYPE,/*136*/ MTK_PULL_PULLSEL_TYPE,/*137*/ + MTK_PULL_PUPD_R1R0_TYPE,/*138*/ MTK_PULL_PUPD_R1R0_TYPE,/*139*/ + MTK_PULL_PUPD_R1R0_TYPE,/*140*/ MTK_PULL_PUPD_R1R0_TYPE,/*141*/ + MTK_PULL_PUPD_R1R0_TYPE,/*142*/ MTK_PULL_PUPD_R1R0_TYPE,/*143*/ + MTK_PULL_PUPD_R1R0_TYPE,/*144*/ MTK_PULL_PUPD_R1R0_TYPE,/*145*/ + MTK_PULL_PUPD_R1R0_TYPE,/*146*/ MTK_PULL_PUPD_R1R0_TYPE,/*147*/ + MTK_PULL_PUPD_R1R0_TYPE,/*148*/ MTK_PULL_PUPD_R1R0_TYPE,/*149*/ + MTK_PULL_PUPD_R1R0_TYPE,/*150*/ MTK_PULL_PUPD_R1R0_TYPE,/*151*/ + MTK_PULL_PUPD_R1R0_TYPE,/*152*/ MTK_PULL_PUPD_R1R0_TYPE,/*153*/ + MTK_PULL_PUPD_R1R0_TYPE,/*154*/ MTK_PULL_PUPD_R1R0_TYPE,/*155*/ + MTK_PULL_PUPD_R1R0_TYPE,/*156*/ MTK_PULL_PUPD_R1R0_TYPE,/*157*/ + MTK_PULL_PUPD_R1R0_TYPE,/*158*/ MTK_PULL_PUPD_R1R0_TYPE,/*159*/ + MTK_PULL_PUPD_R1R0_TYPE,/*160*/ MTK_PULL_PUPD_R1R0_TYPE,/*161*/ + MTK_PULL_PUPD_R1R0_TYPE,/*162*/ MTK_PULL_PUPD_R1R0_TYPE,/*163*/ + MTK_PULL_PUPD_R1R0_TYPE,/*164*/ MTK_PULL_PUPD_R1R0_TYPE,/*165*/ + MTK_PULL_PULLSEL_TYPE,/*166*/ MTK_PULL_PULLSEL_TYPE,/*167*/ + MTK_PULL_PULLSEL_TYPE,/*168*/ MTK_PULL_PULLSEL_TYPE,/*169*/ + MTK_PULL_PUPD_R1R0_TYPE,/*170*/ MTK_PULL_PUPD_R1R0_TYPE,/*171*/ + MTK_PULL_PUPD_R1R0_TYPE,/*172*/ MTK_PULL_PUPD_R1R0_TYPE,/*173*/ + MTK_PULL_PUPD_R1R0_TYPE,/*174*/ MTK_PULL_PUPD_R1R0_TYPE,/*175*/ + MTK_PULL_PULLSEL_TYPE,/*176*/ MTK_PULL_PULLSEL_TYPE,/*177*/ + MTK_PULL_PULLSEL_TYPE,/*178*/ MTK_PULL_PULLSEL_TYPE,/*179*/ + MTK_PULL_PULLSEL_TYPE,/*180*/ MTK_PULL_PULLSEL_TYPE,/*181*/ + MTK_PULL_PULLSEL_TYPE,/*182*/ MTK_PULL_PULLSEL_TYPE,/*183*/ + MTK_PULL_PULLSEL_TYPE,/*184*/ MTK_PULL_PULLSEL_TYPE,/*185*/ + MTK_PULL_PULLSEL_TYPE,/*186*/ MTK_PULL_PULLSEL_TYPE,/*187*/ + MTK_PULL_PULLSEL_TYPE,/*188*/ MTK_PULL_PULLSEL_TYPE,/*189*/ + MTK_PULL_PULLSEL_TYPE,/*190*/ MTK_PULL_PULLSEL_TYPE,/*191*/ + MTK_PULL_PULLSEL_TYPE,/*192*/ MTK_PULL_PULLSEL_TYPE,/*193*/ + MTK_PULL_PULLSEL_TYPE,/*194*/ MTK_PULL_PULLSEL_TYPE,/*195*/ + MTK_PULL_PULLSEL_TYPE,/*196*/ +}; + +static const struct mtk_pin_soc mt6795_data = { + .reg_cal = mt6795_reg_cals, + .pins = mtk_pins_mt6795, + .npins = ARRAY_SIZE(mtk_pins_mt6795), + .ngrps = ARRAY_SIZE(mtk_pins_mt6795), + .nfuncs = 8, + .eint_hw = &mt6795_eint_hw, + .gpio_m = 0, + .base_names = mtk_default_register_base_names, + .nbase_names = ARRAY_SIZE(mtk_default_register_base_names), + .pull_type = mt6795_pull_type, + .bias_disable_set = mtk_pinconf_bias_disable_set_rev1, + .bias_disable_get = mtk_pinconf_bias_disable_get_rev1, + .bias_set = mtk_pinconf_bias_set_rev1, + .bias_get = mtk_pinconf_bias_get_rev1, + .bias_set_combo = mtk_pinconf_bias_set_combo, + .bias_get_combo = mtk_pinconf_bias_get_combo, + .drive_set = mtk_pinconf_drive_set_rev1, + .drive_get = mtk_pinconf_drive_get_rev1, + .adv_pull_get = mtk_pinconf_adv_pull_get, + .adv_pull_set = mtk_pinconf_adv_pull_set, +}; + +static const struct of_device_id mt6795_pctrl_match[] = { + { .compatible = "mediatek,mt6795-pinctrl", .data = &mt6795_data }, + { } +}; + +static struct platform_driver mt6795_pinctrl_driver = { + .driver = { + .name = "mt6795-pinctrl", + .of_match_table = mt6795_pctrl_match, + .pm = &mtk_paris_pinctrl_pm_ops, + }, + .probe = mtk_paris_pinctrl_probe, +}; + +static int __init mtk_pinctrl_init(void) +{ + return platform_driver_register(&mt6795_pinctrl_driver); +} +arch_initcall(mtk_pinctrl_init); diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-mt6795.h b/drivers/pinctrl/mediatek/pinctrl-mtk-mt6795.h new file mode 100644 index 0000000000000000000000000000000000000000..f639bd8591160e8e63ad7e6dcadb6c911c442e67 --- /dev/null +++ b/drivers/pinctrl/mediatek/pinctrl-mtk-mt6795.h @@ -0,0 +1,1698 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2022 Collabora Ltd. + * Author: AngeloGioacchino Del Regno + */ + +#ifndef __PINCTRL_MTK_MT6795_H +#define __PINCTRL_MTK_MT6795_H + +#include "pinctrl-paris.h" + +static const struct mtk_pin_desc mtk_pins_mt6795[] = { + MTK_PIN( + 0, "GPIO0", + MTK_EINT_FUNCTION(0, 0), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO0"), + MTK_FUNCTION(1, "IRDA_PDN"), + MTK_FUNCTION(2, "I2S1_WS"), + MTK_FUNCTION(4, "TDD_TMS"), + MTK_FUNCTION(5, "UTXD0") + ), + MTK_PIN( + 1, "GPIO1", + MTK_EINT_FUNCTION(0, 1), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO1"), + MTK_FUNCTION(1, "IRDA_RXD"), + MTK_FUNCTION(2, "I2S1_BCK"), + MTK_FUNCTION(3, "SDA4"), + MTK_FUNCTION(4, "TDD_TCK"), + MTK_FUNCTION(5, "URXD0") + ), + MTK_PIN( + 2, "GPIO2", + MTK_EINT_FUNCTION(0, 2), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO2"), + MTK_FUNCTION(1, "IRDA_TXD"), + MTK_FUNCTION(2, "I2S1_MCK"), + MTK_FUNCTION(3, "SCL4"), + MTK_FUNCTION(4, "TDD_TDI"), + MTK_FUNCTION(5, "UTXD3") + ), + MTK_PIN( + 3, "GPIO3", + MTK_EINT_FUNCTION(0, 3), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO3"), + MTK_FUNCTION(1, "DSI1_TE"), + MTK_FUNCTION(2, "I2S1_DO_1"), + MTK_FUNCTION(3, "SDA3"), + MTK_FUNCTION(4, "TDD_TDO"), + MTK_FUNCTION(5, "URXD3") + ), + MTK_PIN( + 4, "GPIO4", + MTK_EINT_FUNCTION(0, 4), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO4"), + MTK_FUNCTION(1, "DISP_PWM1"), + MTK_FUNCTION(2, "I2S1_DO_2"), + MTK_FUNCTION(3, "SCL3"), + MTK_FUNCTION(4, "TDD_TRSTN") + ), + MTK_PIN( + 5, "GPIO5", + MTK_EINT_FUNCTION(0, 5), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO5"), + MTK_FUNCTION(1, "PCM1_CLK"), + MTK_FUNCTION(2, "I2S2_WS"), + MTK_FUNCTION(3, "SPI_CK_3"), + MTK_FUNCTION(4, "LTE_MD32_JTAG_TMS"), + MTK_FUNCTION(5, "AP_MD32_JTAG_TMS") + ), + MTK_PIN( + 6, "GPIO6", + MTK_EINT_FUNCTION(0, 6), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO6"), + MTK_FUNCTION(1, "PCM1_SYNC"), + MTK_FUNCTION(2, "I2S2_BCK"), + MTK_FUNCTION(3, "SPI_MI_3"), + MTK_FUNCTION(4, "LTE_MD32_JTAG_TCK"), + MTK_FUNCTION(5, "AP_MD32_JTAG_TCK") + ), + MTK_PIN( + 7, "GPIO7", + MTK_EINT_FUNCTION(0, 7), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO7"), + MTK_FUNCTION(1, "PCM1_DI"), + MTK_FUNCTION(2, "I2S2_DI_1"), + MTK_FUNCTION(3, "SPI_MO_3"), + MTK_FUNCTION(4, "LTE_MD32_JTAG_TDI"), + MTK_FUNCTION(5, "AP_MD32_JTAG_TDI") + ), + MTK_PIN( + 8, "GPIO8", + MTK_EINT_FUNCTION(0, 8), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO8"), + MTK_FUNCTION(1, "PCM1_DO"), + MTK_FUNCTION(2, "I2S2_DI_2"), + MTK_FUNCTION(3, "SPI_CS_3"), + MTK_FUNCTION(4, "LTE_MD32_JTAG_TDO"), + MTK_FUNCTION(5, "AP_MD32_JTAG_TDO") + ), + MTK_PIN( + 9, "GPIO9", + MTK_EINT_FUNCTION(0, 9), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO9"), + MTK_FUNCTION(1, "USB_DRVVBUS"), + MTK_FUNCTION(2, "I2S2_MCK"), + MTK_FUNCTION(4, "LTE_MD32_JTAG_TRST"), + MTK_FUNCTION(5, "AP_MD32_JTAG_TRST") + ), + MTK_PIN( + 10, "GPIO10", + MTK_EINT_FUNCTION(0, 10), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO10"), + MTK_FUNCTION(2, "I2S0_WS") + ), + MTK_PIN( + 11, "GPIO11", + MTK_EINT_FUNCTION(0, 11), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO11"), + MTK_FUNCTION(2, "I2S0_BCK") + ), + MTK_PIN( + 12, "GPIO12", + MTK_EINT_FUNCTION(0, 12), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO12"), + MTK_FUNCTION(2, "I2S0_MCK") + ), + MTK_PIN( + 13, "GPIO13", + MTK_EINT_FUNCTION(0, 13), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO13"), + MTK_FUNCTION(2, "I2S0_DO") + ), + MTK_PIN( + 14, "GPIO14", + MTK_EINT_FUNCTION(0, 14), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO14"), + MTK_FUNCTION(2, "I2S0_DI"), + MTK_FUNCTION(3, "DISP_PWM1"), + MTK_FUNCTION(4, "PWM4"), + MTK_FUNCTION(5, "IRDA_RXD"), + MTK_FUNCTION(6, "I2S1_BCK") + ), + MTK_PIN( + 15, "GPIO15", + MTK_EINT_FUNCTION(0, 15), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO15"), + MTK_FUNCTION(2, "DSI1_TE"), + MTK_FUNCTION(3, "USB_DRVVBUS"), + MTK_FUNCTION(4, "PWM5"), + MTK_FUNCTION(5, "IRDA_TXD"), + MTK_FUNCTION(6, "I2S1_MCK") + ), + MTK_PIN( + 16, "GPIO16", + MTK_EINT_FUNCTION(0, 16), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO16"), + MTK_FUNCTION(1, "IDDIG"), + MTK_FUNCTION(2, "FLASH"), + MTK_FUNCTION(3, "EXT_FRAME_SYNC"), + MTK_FUNCTION(4, "PWM5") + ), + MTK_PIN( + 17, "GPIO17", + MTK_EINT_FUNCTION(0, 17), + DRV_GRP0, + MTK_FUNCTION(0, "GPIO17"), + MTK_FUNCTION(1, "SIM1_SCLK"), + MTK_FUNCTION(2, "SIM2_SCLK") + ), + MTK_PIN( + 18, "GPIO18", + MTK_EINT_FUNCTION(0, 18), + DRV_GRP0, + MTK_FUNCTION(0, "GPIO18"), + MTK_FUNCTION(1, "SIM1_SRST"), + MTK_FUNCTION(2, "SIM2_SRST") + ), + MTK_PIN( + 19, "GPIO19", + MTK_EINT_FUNCTION(0, 19), + DRV_GRP0, + MTK_FUNCTION(0, "GPIO19"), + MTK_FUNCTION(1, "SIM1_SDAT"), + MTK_FUNCTION(2, "SIM2_SDAT") + ), + MTK_PIN( + 20, "GPIO20", + MTK_EINT_FUNCTION(0, 20), + DRV_GRP0, + MTK_FUNCTION(0, "GPIO20"), + MTK_FUNCTION(1, "SIM2_SCLK"), + MTK_FUNCTION(2, "SIM1_SCLK") + ), + MTK_PIN( + 21, "GPIO21", + MTK_EINT_FUNCTION(0, 21), + DRV_GRP0, + MTK_FUNCTION(0, "GPIO21"), + MTK_FUNCTION(1, "SIM2_SRST"), + MTK_FUNCTION(2, "SIM1_SRST") + ), + MTK_PIN( + 22, "GPIO22", + MTK_EINT_FUNCTION(0, 22), + DRV_GRP0, + MTK_FUNCTION(0, "GPIO22"), + MTK_FUNCTION(1, "SIM2_SDAT"), + MTK_FUNCTION(2, "SIM1_SDAT") + ), + MTK_PIN( + 23, "GPIO23", + MTK_EINT_FUNCTION(0, 23), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO23"), + MTK_FUNCTION(1, "MSDC3_DAT0") + ), + MTK_PIN( + 24, "GPIO24", + MTK_EINT_FUNCTION(0, 24), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO24"), + MTK_FUNCTION(1, "MSDC3_DAT1") + ), + MTK_PIN( + 25, "GPIO25", + MTK_EINT_FUNCTION(0, 25), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO25"), + MTK_FUNCTION(1, "MSDC3_DAT2") + ), + MTK_PIN( + 26, "GPIO26", + MTK_EINT_FUNCTION(0, 26), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO26"), + MTK_FUNCTION(1, "MSDC3_DAT3") + ), + MTK_PIN( + 27, "GPIO27", + MTK_EINT_FUNCTION(0, 27), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO27"), + MTK_FUNCTION(1, "MSDC3_CLK") + ), + MTK_PIN( + 28, "GPIO28", + MTK_EINT_FUNCTION(0, 28), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO28"), + MTK_FUNCTION(1, "MSDC3_CMD") + ), + MTK_PIN( + 29, "GPIO29", + MTK_EINT_FUNCTION(0, 29), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO29"), + MTK_FUNCTION(1, "PTA_RXD"), + MTK_FUNCTION(2, "UCTS2") + ), + MTK_PIN( + 30, "GPIO30", + MTK_EINT_FUNCTION(0, 30), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO30"), + MTK_FUNCTION(1, "PTA_TXD"), + MTK_FUNCTION(2, "URTS2") + ), + MTK_PIN( + 31, "GPIO31", + MTK_EINT_FUNCTION(0, 31), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO31"), + MTK_FUNCTION(1, "URXD2"), + MTK_FUNCTION(2, "UTXD2") + ), + MTK_PIN( + 32, "GPIO32", + MTK_EINT_FUNCTION(0, 32), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO32"), + MTK_FUNCTION(1, "UTXD2"), + MTK_FUNCTION(2, "URXD2") + ), + MTK_PIN( + 33, "GPIO33", + MTK_EINT_FUNCTION(0, 33), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO33"), + MTK_FUNCTION(1, "MRG_CLK"), + MTK_FUNCTION(2, "PCM0_CLK") + ), + MTK_PIN( + 34, "GPIO34", + MTK_EINT_FUNCTION(0, 34), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO34"), + MTK_FUNCTION(1, "MRG_DI"), + MTK_FUNCTION(2, "PCM0_DI") + ), + MTK_PIN( + 35, "GPIO35", + MTK_EINT_FUNCTION(0, 35), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO35"), + MTK_FUNCTION(1, "MRG_DO"), + MTK_FUNCTION(2, "PCM0_DO") + ), + MTK_PIN( + 36, "GPIO36", + MTK_EINT_FUNCTION(0, 36), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO36"), + MTK_FUNCTION(1, "MRG_SYNC"), + MTK_FUNCTION(2, "PCM0_SYNC") + ), + MTK_PIN( + 37, "GPIO37", + MTK_EINT_FUNCTION(0, 37), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO37"), + MTK_FUNCTION(1, "GPS_SYNC") + ), + MTK_PIN( + 38, "GPIO38", + MTK_EINT_FUNCTION(0, 38), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO38"), + MTK_FUNCTION(1, "DAIRSTB") + ), + MTK_PIN( + 39, "GPIO39", + MTK_EINT_FUNCTION(0, 39), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO39"), + MTK_FUNCTION(1, "CM2MCLK") + ), + MTK_PIN( + 40, "GPIO40", + MTK_EINT_FUNCTION(0, 40), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO40"), + MTK_FUNCTION(1, "CM3MCLK"), + MTK_FUNCTION(2, "IRDA_PDN"), + MTK_FUNCTION(3, "PWM6"), + MTK_FUNCTION(4, "I2S1_WS") + ), + MTK_PIN( + 41, "GPIO41", + MTK_EINT_FUNCTION(0, 41), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO41"), + MTK_FUNCTION(1, "CMPCLK"), + MTK_FUNCTION(2, "CMCSK"), + MTK_FUNCTION(3, "FLASH") + ), + MTK_PIN( + 42, "GPIO42", + MTK_EINT_FUNCTION(0, 42), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO42"), + MTK_FUNCTION(1, "CMMCLK") + ), + MTK_PIN( + 43, "GPIO43", + MTK_EINT_FUNCTION(0, 43), + DRV_FIXED, + MTK_FUNCTION(0, "GPIO43"), + MTK_FUNCTION(1, "SDA2") + ), + MTK_PIN( + 44, "GPIO44", + MTK_EINT_FUNCTION(0, 44), + DRV_FIXED, + MTK_FUNCTION(0, "GPIO44"), + MTK_FUNCTION(1, "SCL2") + ), + MTK_PIN( + 45, "GPIO45", + MTK_EINT_FUNCTION(0, 45), + DRV_FIXED, + MTK_FUNCTION(0, "GPIO45"), + MTK_FUNCTION(1, "SDA0") + ), + MTK_PIN( + 46, "GPIO46", + MTK_EINT_FUNCTION(0, 46), + DRV_FIXED, + MTK_FUNCTION(0, "GPIO46"), + MTK_FUNCTION(1, "SCL0") + ), + MTK_PIN( + 47, "GPIO47", + MTK_EINT_FUNCTION(0, 47), + DRV_GRP0, + MTK_FUNCTION(0, "GPIO47"), + MTK_FUNCTION(1, "BPI_BUS0") + ), + MTK_PIN( + 48, "GPIO48", + MTK_EINT_FUNCTION(0, 48), + DRV_GRP0, + MTK_FUNCTION(0, "GPIO48"), + MTK_FUNCTION(1, "BPI_BUS1") + ), + MTK_PIN( + 49, "GPIO49", + MTK_EINT_FUNCTION(0, 49), + DRV_GRP0, + MTK_FUNCTION(0, "GPIO49"), + MTK_FUNCTION(1, "BPI_BUS2") + ), + MTK_PIN( + 50, "GPIO50", + MTK_EINT_FUNCTION(0, 50), + DRV_GRP0, + MTK_FUNCTION(0, "GPIO50"), + MTK_FUNCTION(1, "BPI_BUS3") + ), + MTK_PIN( + 51, "GPIO51", + MTK_EINT_FUNCTION(0, 51), + DRV_GRP0, + MTK_FUNCTION(0, "GPIO51"), + MTK_FUNCTION(1, "BPI_BUS4") + ), + MTK_PIN( + 52, "GPIO52", + MTK_EINT_FUNCTION(0, 52), + DRV_GRP0, + MTK_FUNCTION(0, "GPIO52"), + MTK_FUNCTION(1, "BPI_BUS5") + ), + MTK_PIN( + 53, "GPIO53", + MTK_EINT_FUNCTION(0, 53), + DRV_GRP0, + MTK_FUNCTION(0, "GPIO53"), + MTK_FUNCTION(1, "BPI_BUS6") + ), + MTK_PIN( + 54, "GPIO54", + MTK_EINT_FUNCTION(0, 54), + DRV_GRP0, + MTK_FUNCTION(0, "GPIO54"), + MTK_FUNCTION(1, "BPI_BUS7") + ), + MTK_PIN( + 55, "GPIO55", + MTK_EINT_FUNCTION(0, 55), + DRV_GRP0, + MTK_FUNCTION(0, "GPIO55"), + MTK_FUNCTION(1, "BPI_BUS8") + ), + MTK_PIN( + 56, "GPIO56", + MTK_EINT_FUNCTION(0, 56), + DRV_GRP0, + MTK_FUNCTION(0, "GPIO56"), + MTK_FUNCTION(1, "BPI_BUS9") + ), + MTK_PIN( + 57, "GPIO57", + MTK_EINT_FUNCTION(0, 57), + DRV_GRP0, + MTK_FUNCTION(0, "GPIO57"), + MTK_FUNCTION(1, "BPI_BUS10") + ), + MTK_PIN( + 58, "GPIO58", + MTK_EINT_FUNCTION(0, 58), + DRV_GRP0, + MTK_FUNCTION(0, "GPIO58"), + MTK_FUNCTION(1, "BPI_BUS11") + ), + MTK_PIN( + 59, "GPIO59", + MTK_EINT_FUNCTION(0, 59), + DRV_GRP0, + MTK_FUNCTION(0, "GPIO59"), + MTK_FUNCTION(1, "BPI_BUS12") + ), + MTK_PIN( + 60, "GPIO60", + MTK_EINT_FUNCTION(0, 60), + DRV_GRP0, + MTK_FUNCTION(0, "GPIO60"), + MTK_FUNCTION(1, "BPI_BUS13") + ), + MTK_PIN( + 61, "GPIO61", + MTK_EINT_FUNCTION(0, 61), + DRV_GRP0, + MTK_FUNCTION(0, "GPIO61"), + MTK_FUNCTION(1, "BPI_BUS14") + ), + MTK_PIN( + 62, "GPIO62", + MTK_EINT_FUNCTION(0, 62), + DRV_GRP0, + MTK_FUNCTION(0, "GPIO62"), + MTK_FUNCTION(1, "RFIC1_BSI_CK") + ), + MTK_PIN( + 63, "GPIO63", + MTK_EINT_FUNCTION(0, 63), + DRV_GRP0, + MTK_FUNCTION(0, "GPIO63"), + MTK_FUNCTION(1, "RFIC1_BSI_D0") + ), + MTK_PIN( + 64, "GPIO64", + MTK_EINT_FUNCTION(0, 64), + DRV_GRP0, + MTK_FUNCTION(0, "GPIO64"), + MTK_FUNCTION(1, "RFIC1_BSI_D1") + ), + MTK_PIN( + 65, "GPIO65", + MTK_EINT_FUNCTION(0, 65), + DRV_GRP0, + MTK_FUNCTION(0, "GPIO65"), + MTK_FUNCTION(1, "RFIC1_BSI_D2") + ), + MTK_PIN( + 66, "GPIO66", + MTK_EINT_FUNCTION(0, 66), + DRV_GRP0, + MTK_FUNCTION(0, "GPIO66"), + MTK_FUNCTION(1, "RFIC1_BSI_CS") + ), + MTK_PIN( + 67, "GPIO67", + MTK_EINT_FUNCTION(0, 67), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO67"), + MTK_FUNCTION(1, "TD_TXBPI") + ), + MTK_PIN( + 68, "GPIO68", + MTK_EINT_FUNCTION(0, 68), + DRV_GRP0, + MTK_FUNCTION(0, "GPIO68"), + MTK_FUNCTION(1, "RFIC0_BSI_CK") + ), + MTK_PIN( + 69, "GPIO69", + MTK_EINT_FUNCTION(0, 69), + DRV_GRP0, + MTK_FUNCTION(0, "GPIO69"), + MTK_FUNCTION(1, "RFIC0_BSI_D0") + ), + MTK_PIN( + 70, "GPIO70", + MTK_EINT_FUNCTION(0, 70), + DRV_GRP0, + MTK_FUNCTION(0, "GPIO70"), + MTK_FUNCTION(1, "RFIC0_BSI_D1") + ), + MTK_PIN( + 71, "GPIO71", + MTK_EINT_FUNCTION(0, 71), + DRV_GRP0, + MTK_FUNCTION(0, "GPIO71"), + MTK_FUNCTION(1, "RFIC0_BSI_D2") + ), + MTK_PIN( + 72, "GPIO72", + MTK_EINT_FUNCTION(0, 72), + DRV_GRP0, + MTK_FUNCTION(0, "GPIO72"), + MTK_FUNCTION(1, "RFIC0_BSI_CS") + ), + MTK_PIN( + 73, "GPIO73", + MTK_EINT_FUNCTION(0, 73), + DRV_GRP0, + MTK_FUNCTION(0, "GPIO73"), + MTK_FUNCTION(1, "MISC_BSI_DO") + ), + MTK_PIN( + 74, "GPIO74", + MTK_EINT_FUNCTION(0, 74), + DRV_GRP0, + MTK_FUNCTION(0, "GPIO74"), + MTK_FUNCTION(1, "MISC_BSI_CK") + ), + MTK_PIN( + 75, "GPIO75", + MTK_EINT_FUNCTION(0, 75), + DRV_GRP0, + MTK_FUNCTION(0, "GPIO75"), + MTK_FUNCTION(1, "MISC_BSI_CS0B"), + MTK_FUNCTION(2, "MIPI1_SCLK") + ), + MTK_PIN( + 76, "GPIO76", + MTK_EINT_FUNCTION(0, 76), + DRV_GRP0, + MTK_FUNCTION(0, "GPIO76"), + MTK_FUNCTION(1, "MISC_BSI_CS1B") + ), + MTK_PIN( + 77, "GPIO77", + MTK_EINT_FUNCTION(0, 77), + DRV_GRP0, + MTK_FUNCTION(0, "GPIO77"), + MTK_FUNCTION(1, "MISC_BSI_DI"), + MTK_FUNCTION(2, "MIPI1_SDATA") + ), + MTK_PIN( + 78, "GPIO78", + MTK_EINT_FUNCTION(0, 78), + DRV_GRP0, + MTK_FUNCTION(0, "GPIO78"), + MTK_FUNCTION(1, "LTE_TXBPI") + ), + MTK_PIN( + 79, "GPIO79", + MTK_EINT_FUNCTION(0, 79), + DRV_GRP0, + MTK_FUNCTION(0, "GPIO79"), + MTK_FUNCTION(1, "BPI_BUS15") + ), + MTK_PIN( + 80, "GPIO80", + MTK_EINT_FUNCTION(0, 80), + DRV_GRP0, + MTK_FUNCTION(0, "GPIO80"), + MTK_FUNCTION(1, "BPI_BUS16") + ), + MTK_PIN( + 81, "GPIO81", + MTK_EINT_FUNCTION(0, 81), + DRV_GRP0, + MTK_FUNCTION(0, "GPIO81"), + MTK_FUNCTION(1, "BPI_BUS17") + ), + MTK_PIN( + 82, "GPIO82", + MTK_EINT_FUNCTION(0, 82), + DRV_GRP0, + MTK_FUNCTION(0, "GPIO82"), + MTK_FUNCTION(1, "BPI_BUS18") + ), + MTK_PIN( + 83, "GPIO83", + MTK_EINT_FUNCTION(0, 83), + DRV_GRP0, + MTK_FUNCTION(0, "GPIO83"), + MTK_FUNCTION(1, "BPI_BUS19") + ), + MTK_PIN( + 84, "GPIO84", + MTK_EINT_FUNCTION(0, 84), + DRV_GRP0, + MTK_FUNCTION(0, "GPIO84"), + MTK_FUNCTION(1, "BPI_BUS20") + ), + MTK_PIN( + 85, "GPIO85", + MTK_EINT_FUNCTION(0, 85), + DRV_GRP0, + MTK_FUNCTION(0, "GPIO85"), + MTK_FUNCTION(1, "BPI_BUS21") + ), + MTK_PIN( + 86, "GPIO86", + MTK_EINT_FUNCTION(0, 86), + DRV_GRP0, + MTK_FUNCTION(0, "GPIO86"), + MTK_FUNCTION(1, "BPI_BUS22") + ), + MTK_PIN( + 87, "GPIO87", + MTK_EINT_FUNCTION(0, 87), + DRV_GRP0, + MTK_FUNCTION(0, "GPIO87"), + MTK_FUNCTION(1, "BPI_BUS23") + ), + MTK_PIN( + 88, "GPIO88", + MTK_EINT_FUNCTION(0, 88), + DRV_GRP0, + MTK_FUNCTION(0, "GPIO88"), + MTK_FUNCTION(1, "BPI_BUS24") + ), + MTK_PIN( + 89, "GPIO89", + MTK_EINT_FUNCTION(0, 89), + DRV_GRP0, + MTK_FUNCTION(0, "GPIO89"), + MTK_FUNCTION(1, "BPI_BUS25") + ), + MTK_PIN( + 90, "GPIO90", + MTK_EINT_FUNCTION(0, 90), + DRV_GRP0, + MTK_FUNCTION(0, "GPIO90"), + MTK_FUNCTION(1, "BPI_BUS26") + ), + MTK_PIN( + 91, "GPIO91", + MTK_EINT_FUNCTION(0, 91), + DRV_GRP0, + MTK_FUNCTION(0, "GPIO91"), + MTK_FUNCTION(1, "BPI_BUS27") + ), + MTK_PIN( + 92, "GPIO92", + MTK_EINT_FUNCTION(0, 92), + DRV_GRP0, + MTK_FUNCTION(0, "GPIO92"), + MTK_FUNCTION(1, "PCM1_CLK"), + MTK_FUNCTION(2, "I2S0_BCK"), + MTK_FUNCTION(3, "NLD6") + ), + MTK_PIN( + 93, "GPIO93", + MTK_EINT_FUNCTION(0, 93), + DRV_GRP0, + MTK_FUNCTION(0, "GPIO93"), + MTK_FUNCTION(1, "PCM1_SYNC"), + MTK_FUNCTION(2, "I2S0_WS"), + MTK_FUNCTION(3, "NLD7") + ), + MTK_PIN( + 94, "GPIO94", + MTK_EINT_FUNCTION(0, 94), + DRV_GRP0, + MTK_FUNCTION(0, "GPIO94"), + MTK_FUNCTION(1, "PCM1_DI"), + MTK_FUNCTION(2, "I2S0_DI"), + MTK_FUNCTION(3, "NREB") + ), + MTK_PIN( + 95, "GPIO95", + MTK_EINT_FUNCTION(0, 95), + DRV_GRP0, + MTK_FUNCTION(0, "GPIO95"), + MTK_FUNCTION(1, "PCM1_DO"), + MTK_FUNCTION(2, "I2S0_DO"), + MTK_FUNCTION(3, "NRNB0") + ), + MTK_PIN( + 96, "GPIO96", + MTK_EINT_FUNCTION(0, 96), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO96"), + MTK_FUNCTION(1, "URXD1"), + MTK_FUNCTION(2, "UTXD1"), + MTK_FUNCTION(3, "NWEB") + ), + MTK_PIN( + 97, "GPIO97", + MTK_EINT_FUNCTION(0, 97), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO97"), + MTK_FUNCTION(1, "UTXD1"), + MTK_FUNCTION(2, "URXD1"), + MTK_FUNCTION(3, "NCEB0") + ), + MTK_PIN( + 98, "GPIO98", + MTK_EINT_FUNCTION(0, 98), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO98"), + MTK_FUNCTION(1, "URTS1"), + MTK_FUNCTION(2, "UCTS1"), + MTK_FUNCTION(3, "NALE") + ), + MTK_PIN( + 99, "GPIO99", + MTK_EINT_FUNCTION(0, 99), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO99"), + MTK_FUNCTION(1, "UCTS1"), + MTK_FUNCTION(2, "URTS1"), + MTK_FUNCTION(3, "NCLE") + ), + MTK_PIN( + 100, "GPIO100", + MTK_EINT_FUNCTION(0, 100), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO100"), + MTK_FUNCTION(1, "MSDC2_DAT0"), + MTK_FUNCTION(2, "URXD1"), + MTK_FUNCTION(3, "USB_DRVVBUS"), + MTK_FUNCTION(4, "SDA4") + ), + MTK_PIN( + 101, "GPIO101", + MTK_EINT_FUNCTION(0, 101), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO101"), + MTK_FUNCTION(1, "MSDC2_DAT1"), + MTK_FUNCTION(2, "UTXD1"), + MTK_FUNCTION(4, "SCL4") + ), + MTK_PIN( + 102, "GPIO102", + MTK_EINT_FUNCTION(0, 102), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO102"), + MTK_FUNCTION(1, "MSDC2_DAT2"), + MTK_FUNCTION(2, "URTS1"), + MTK_FUNCTION(3, "UTXD0"), + MTK_FUNCTION(5, "PWM0"), + MTK_FUNCTION(6, "SPI_CK_1") + ), + MTK_PIN( + 103, "GPIO103", + MTK_EINT_FUNCTION(0, 103), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO103"), + MTK_FUNCTION(1, "MSDC2_DAT3"), + MTK_FUNCTION(2, "UCTS1"), + MTK_FUNCTION(3, "URXD0"), + MTK_FUNCTION(5, "PWM1"), + MTK_FUNCTION(6, "SPI_MI_1") + ), + MTK_PIN( + 104, "GPIO104", + MTK_EINT_FUNCTION(0, 104), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO104"), + MTK_FUNCTION(1, "MSDC2_CLK"), + MTK_FUNCTION(2, "NLD4"), + MTK_FUNCTION(3, "UTXD3"), + MTK_FUNCTION(4, "SDA3"), + MTK_FUNCTION(5, "PWM2"), + MTK_FUNCTION(6, "SPI_MO_1") + ), + MTK_PIN( + 105, "GPIO105", + MTK_EINT_FUNCTION(0, 105), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO105"), + MTK_FUNCTION(1, "MSDC2_CMD"), + MTK_FUNCTION(2, "NLD5"), + MTK_FUNCTION(3, "URXD3"), + MTK_FUNCTION(4, "SCL3"), + MTK_FUNCTION(5, "PWM3"), + MTK_FUNCTION(6, "SPI_CS_1") + ), + MTK_PIN( + 106, "GPIO106", + MTK_EINT_FUNCTION(0, 106), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO106"), + MTK_FUNCTION(1, "LCM_RST") + ), + MTK_PIN( + 107, "GPIO107", + MTK_EINT_FUNCTION(0, 107), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO107"), + MTK_FUNCTION(1, "DSI_TE") + ), + MTK_PIN( + 108, "GPIO108", + MTK_EINT_FUNCTION(0, 108), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO108"), + MTK_FUNCTION(1, "JTMS"), + MTK_FUNCTION(2, "MFG_JTAG_TMS"), + MTK_FUNCTION(3, "TDD_TMS"), + MTK_FUNCTION(4, "LTE_MD32_JTAG_TMS"), + MTK_FUNCTION(5, "AP_MD32_JTAG_TMS"), + MTK_FUNCTION(6, "DFD_TMS") + ), + MTK_PIN( + 109, "GPIO109", + MTK_EINT_FUNCTION(0, 109), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO109"), + MTK_FUNCTION(1, "JTCK"), + MTK_FUNCTION(2, "MFG_JTAG_TCK"), + MTK_FUNCTION(3, "TDD_TCK"), + MTK_FUNCTION(4, "LTE_MD32_JTAG_TCK"), + MTK_FUNCTION(5, "AP_MD32_JTAG_TCK"), + MTK_FUNCTION(6, "DFD_TCK") + ), + MTK_PIN( + 110, "GPIO110", + MTK_EINT_FUNCTION(0, 110), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO110"), + MTK_FUNCTION(1, "JTDI"), + MTK_FUNCTION(2, "MFG_JTAG_TDI"), + MTK_FUNCTION(3, "TDD_TDI"), + MTK_FUNCTION(4, "LTE_MD32_JTAG_TDI"), + MTK_FUNCTION(5, "AP_MD32_JTAG_TDI"), + MTK_FUNCTION(6, "DFD_TDI") + ), + MTK_PIN( + 111, "GPIO111", + MTK_EINT_FUNCTION(0, 111), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO111"), + MTK_FUNCTION(1, "JTDO"), + MTK_FUNCTION(2, "MFG_JTAG_TDO"), + MTK_FUNCTION(3, "TDD_TDO"), + MTK_FUNCTION(4, "LTE_MD32_JTAG_TDO"), + MTK_FUNCTION(5, "AP_MD32_JTAG_TDO"), + MTK_FUNCTION(6, "DFD_TDO") + ), + MTK_PIN( + 112, "GPIO112", + MTK_EINT_FUNCTION(0, 112), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO112"), + MTK_FUNCTION(1, "JTRST_B"), + MTK_FUNCTION(2, "MFG_JTAG_TRSTN"), + MTK_FUNCTION(3, "TDD_TRSTN"), + MTK_FUNCTION(4, "LTE_MD32_JTAG_TRST"), + MTK_FUNCTION(5, "AP_MD32_JTAG_TRST"), + MTK_FUNCTION(6, "DFD_NTRST") + ), + MTK_PIN( + 113, "GPIO113", + MTK_EINT_FUNCTION(0, 113), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO113"), + MTK_FUNCTION(1, "URXD0"), + MTK_FUNCTION(2, "UTXD0"), + MTK_FUNCTION(3, "MD_URXD"), + MTK_FUNCTION(4, "LTE_URXD"), + MTK_FUNCTION(5, "TDD_TXD"), + MTK_FUNCTION(6, "I2S2_WS") + ), + MTK_PIN( + 114, "GPIO114", + MTK_EINT_FUNCTION(0, 114), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO114"), + MTK_FUNCTION(1, "UTXD0"), + MTK_FUNCTION(2, "URXD0"), + MTK_FUNCTION(3, "MD_UTXD"), + MTK_FUNCTION(4, "LTE_UTXD"), + MTK_FUNCTION(5, "TDD_TXD"), + MTK_FUNCTION(6, "I2S2_BCK") + ), + MTK_PIN( + 115, "GPIO115", + MTK_EINT_FUNCTION(0, 115), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO115"), + MTK_FUNCTION(1, "URTS0"), + MTK_FUNCTION(2, "UCTS0"), + MTK_FUNCTION(3, "MD_URXD"), + MTK_FUNCTION(4, "LTE_URXD"), + MTK_FUNCTION(5, "TDD_TXD"), + MTK_FUNCTION(6, "I2S2_MCK") + ), + MTK_PIN( + 116, "GPIO116", + MTK_EINT_FUNCTION(0, 116), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO116"), + MTK_FUNCTION(1, "UCTS0"), + MTK_FUNCTION(2, "URTS0"), + MTK_FUNCTION(3, "MD_UTXD"), + MTK_FUNCTION(4, "LTE_UTXD"), + MTK_FUNCTION(5, "TDD_TXD"), + MTK_FUNCTION(6, "I2S2_DI_1") + ), + MTK_PIN( + 117, "GPIO117", + MTK_EINT_FUNCTION(0, 117), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO117"), + MTK_FUNCTION(1, "URXD3"), + MTK_FUNCTION(2, "UTXD3"), + MTK_FUNCTION(3, "MD_URXD"), + MTK_FUNCTION(4, "LTE_URXD"), + MTK_FUNCTION(5, "TDD_TXD") + ), + MTK_PIN( + 118, "GPIO118", + MTK_EINT_FUNCTION(0, 118), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO118"), + MTK_FUNCTION(1, "UTXD3"), + MTK_FUNCTION(2, "URXD3"), + MTK_FUNCTION(3, "MD_UTXD"), + MTK_FUNCTION(4, "LTE_UTXD"), + MTK_FUNCTION(5, "TDD_TXD") + ), + MTK_PIN( + 119, "GPIO119", + MTK_EINT_FUNCTION(0, 119), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO119"), + MTK_FUNCTION(1, "KROW0") + ), + MTK_PIN( + 120, "GPIO120", + MTK_EINT_FUNCTION(0, 120), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO120"), + MTK_FUNCTION(1, "KROW1"), + MTK_FUNCTION(3, "PWM6") + ), + MTK_PIN( + 121, "GPIO121", + MTK_EINT_FUNCTION(0, 121), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO121"), + MTK_FUNCTION(1, "KROW2"), + MTK_FUNCTION(2, "IRDA_PDN"), + MTK_FUNCTION(3, "I2S1_DO_1"), + MTK_FUNCTION(4, "USB_DRVVBUS"), + MTK_FUNCTION(5, "SPI_CK_2"), + MTK_FUNCTION(6, "PWM4") + ), + MTK_PIN( + 122, "GPIO122", + MTK_EINT_FUNCTION(0, 122), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO122"), + MTK_FUNCTION(1, "KCOL0") + ), + MTK_PIN( + 123, "GPIO123", + MTK_EINT_FUNCTION(0, 123), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO123"), + MTK_FUNCTION(1, "KCOL1"), + MTK_FUNCTION(2, "IRDA_RXD"), + MTK_FUNCTION(3, "I2S2_DI_2"), + MTK_FUNCTION(4, "PWM5") + ), + MTK_PIN( + 124, "GPIO124", + MTK_EINT_FUNCTION(0, 124), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO124"), + MTK_FUNCTION(1, "KCOL2"), + MTK_FUNCTION(2, "IRDA_TXD"), + MTK_FUNCTION(3, "I2S1_DO_2"), + MTK_FUNCTION(4, "USB_DRVVBUS"), + MTK_FUNCTION(5, "SPI_MI_2"), + MTK_FUNCTION(6, "PWM3") + ), + MTK_PIN( + 125, "GPIO125", + MTK_EINT_FUNCTION(0, 125), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO125"), + MTK_FUNCTION(1, "SDA1") + ), + MTK_PIN( + 126, "GPIO126", + MTK_EINT_FUNCTION(0, 126), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO126"), + MTK_FUNCTION(1, "SCL1") + ), + MTK_PIN( + 127, "GPIO127", + MTK_EINT_FUNCTION(1, 127), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO127"), + MTK_FUNCTION(1, "MD_EINT1"), + MTK_FUNCTION(2, "DISP_PWM1"), + MTK_FUNCTION(3, "SPI_MO_2") + ), + MTK_PIN( + 128, "GPIO128", + MTK_EINT_FUNCTION(1, 128), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO128"), + MTK_FUNCTION(1, "MD_EINT2"), + MTK_FUNCTION(2, "DSI1_TE"), + MTK_FUNCTION(3, "SPI_CS_2") + ), + MTK_PIN( + 129, "GPIO129", + MTK_EINT_FUNCTION(0, 129), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO129"), + MTK_FUNCTION(1, "I2S3_WS"), + MTK_FUNCTION(2, "I2S2_WS"), + MTK_FUNCTION(3, "PWM0") + ), + MTK_PIN( + 130, "GPIO130", + MTK_EINT_FUNCTION(0, 130), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO130"), + MTK_FUNCTION(1, "I2S3_BCK"), + MTK_FUNCTION(2, "I2S2_BCK"), + MTK_FUNCTION(3, "PWM1") + ), + MTK_PIN( + 131, "GPIO131", + MTK_EINT_FUNCTION(0, 131), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO131"), + MTK_FUNCTION(1, "I2S3_MCK"), + MTK_FUNCTION(2, "I2S2_MCK"), + MTK_FUNCTION(3, "PWM2") + ), + MTK_PIN( + 132, "GPIO132", + MTK_EINT_FUNCTION(0, 132), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO132"), + MTK_FUNCTION(1, "I2S3_DO_1"), + MTK_FUNCTION(2, "I2S2_DI_1"), + MTK_FUNCTION(3, "PWM3") + ), + MTK_PIN( + 133, "GPIO133", + MTK_EINT_FUNCTION(0, 133), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO133"), + MTK_FUNCTION(1, "I2S3_DO_2"), + MTK_FUNCTION(2, "I2S2_DI_2"), + MTK_FUNCTION(3, "PWM4") + ), + MTK_PIN( + 134, "GPIO134", + MTK_EINT_FUNCTION(0, 134), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO134"), + MTK_FUNCTION(1, "I2S3_DO_3"), + MTK_FUNCTION(2, "DISP_PWM1"), + MTK_FUNCTION(3, "I2S1_DO_1"), + MTK_FUNCTION(4, "PWM5") + ), + MTK_PIN( + 135, "GPIO135", + MTK_EINT_FUNCTION(0, 135), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO135"), + MTK_FUNCTION(1, "I2S3_DO_4"), + MTK_FUNCTION(2, "DSI1_TE"), + MTK_FUNCTION(3, "I2S1_DO_2"), + MTK_FUNCTION(4, "PWM6") + ), + MTK_PIN( + 136, "GPIO136", + MTK_EINT_FUNCTION(0, 136), + DRV_FIXED, + MTK_FUNCTION(0, "GPIO136"), + MTK_FUNCTION(1, "SDA3") + ), + MTK_PIN( + 137, "GPIO137", + MTK_EINT_FUNCTION(0, 137), + DRV_FIXED, + MTK_FUNCTION(0, "GPIO137"), + MTK_FUNCTION(1, "SCL3") + ), + MTK_PIN( + 138, "GPIO138", + MTK_EINT_FUNCTION(0, 138), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO138"), + MTK_FUNCTION(1, "DPI_CK"), + MTK_FUNCTION(2, "NLD6"), + MTK_FUNCTION(3, "UTXD0"), + MTK_FUNCTION(4, "USB_DRVVBUS"), + MTK_FUNCTION(5, "IRDA_PDN") + ), + MTK_PIN( + 139, "GPIO139", + MTK_EINT_FUNCTION(0, 139), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO139"), + MTK_FUNCTION(1, "DPI_DE"), + MTK_FUNCTION(2, "NLD7"), + MTK_FUNCTION(3, "URXD0"), + MTK_FUNCTION(4, "MD_UTXD"), + MTK_FUNCTION(5, "IRDA_RXD") + ), + MTK_PIN( + 140, "GPIO140", + MTK_EINT_FUNCTION(0, 140), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO140"), + MTK_FUNCTION(1, "DPI_D0"), + MTK_FUNCTION(2, "NREB"), + MTK_FUNCTION(3, "UCTS0"), + MTK_FUNCTION(4, "MD_URXD"), + MTK_FUNCTION(5, "IRDA_TXD") + ), + MTK_PIN( + 141, "GPIO141", + MTK_EINT_FUNCTION(0, 141), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO141"), + MTK_FUNCTION(1, "DPI_D1"), + MTK_FUNCTION(2, "NRNB0"), + MTK_FUNCTION(3, "URTS0"), + MTK_FUNCTION(4, "LTE_UTXD"), + MTK_FUNCTION(5, "I2S2_WS") + ), + MTK_PIN( + 142, "GPIO142", + MTK_EINT_FUNCTION(0, 142), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO142"), + MTK_FUNCTION(1, "DPI_D2"), + MTK_FUNCTION(2, "NWEB"), + MTK_FUNCTION(3, "UTXD1"), + MTK_FUNCTION(4, "LTE_URXD"), + MTK_FUNCTION(5, "I2S2_BCK") + ), + MTK_PIN( + 143, "GPIO143", + MTK_EINT_FUNCTION(0, 143), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO143"), + MTK_FUNCTION(1, "DPI_D3"), + MTK_FUNCTION(2, "NCEB0"), + MTK_FUNCTION(3, "URXD1"), + MTK_FUNCTION(4, "TDD_TXD"), + MTK_FUNCTION(5, "I2S2_MCK") + ), + MTK_PIN( + 144, "GPIO144", + MTK_EINT_FUNCTION(0, 144), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO144"), + MTK_FUNCTION(1, "DPI_D4"), + MTK_FUNCTION(2, "NALE"), + MTK_FUNCTION(3, "UCTS1"), + MTK_FUNCTION(4, "TDD_TMS"), + MTK_FUNCTION(5, "I2S2_DI_1") + ), + MTK_PIN( + 145, "GPIO145", + MTK_EINT_FUNCTION(0, 145), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO145"), + MTK_FUNCTION(1, "DPI_D5"), + MTK_FUNCTION(2, "NCLE"), + MTK_FUNCTION(3, "URTS1"), + MTK_FUNCTION(4, "TDD_TCK"), + MTK_FUNCTION(5, "I2S2_DI_2") + ), + MTK_PIN( + 146, "GPIO146", + MTK_EINT_FUNCTION(0, 146), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO146"), + MTK_FUNCTION(1, "DPI_D6"), + MTK_FUNCTION(2, "NLD8"), + MTK_FUNCTION(3, "UTXD2"), + MTK_FUNCTION(4, "TDD_TDI") + ), + MTK_PIN( + 147, "GPIO147", + MTK_EINT_FUNCTION(0, 147), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO147"), + MTK_FUNCTION(1, "DPI_D7"), + MTK_FUNCTION(2, "NLD9"), + MTK_FUNCTION(3, "URXD2"), + MTK_FUNCTION(4, "TDD_TDO"), + MTK_FUNCTION(5, "I2S1_WS") + ), + MTK_PIN( + 148, "GPIO148", + MTK_EINT_FUNCTION(0, 148), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO148"), + MTK_FUNCTION(1, "DPI_D8"), + MTK_FUNCTION(2, "NLD10"), + MTK_FUNCTION(3, "UCTS2"), + MTK_FUNCTION(4, "TDD_TRSTN"), + MTK_FUNCTION(5, "I2S1_BCK") + ), + MTK_PIN( + 149, "GPIO149", + MTK_EINT_FUNCTION(0, 149), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO149"), + MTK_FUNCTION(1, "DPI_D9"), + MTK_FUNCTION(2, "NLD11"), + MTK_FUNCTION(3, "URTS2"), + MTK_FUNCTION(4, "LTE_MD32_JTAG_TMS"), + MTK_FUNCTION(5, "I2S1_MCK") + ), + MTK_PIN( + 150, "GPIO150", + MTK_EINT_FUNCTION(0, 150), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO150"), + MTK_FUNCTION(1, "DPI_D10"), + MTK_FUNCTION(2, "NLD12"), + MTK_FUNCTION(3, "UTXD3"), + MTK_FUNCTION(4, "LTE_MD32_JTAG_TCK"), + MTK_FUNCTION(5, "I2S1_DO_1") + ), + MTK_PIN( + 151, "GPIO151", + MTK_EINT_FUNCTION(0, 151), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO151"), + MTK_FUNCTION(1, "DPI_D11"), + MTK_FUNCTION(2, "NLD13"), + MTK_FUNCTION(3, "URXD3"), + MTK_FUNCTION(4, "LTE_MD32_JTAG_TDI"), + MTK_FUNCTION(5, "I2S1_DO_2") + ), + MTK_PIN( + 152, "GPIO152", + MTK_EINT_FUNCTION(0, 152), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO152"), + MTK_FUNCTION(1, "DPI_HSYNC"), + MTK_FUNCTION(2, "NLD14"), + MTK_FUNCTION(3, "UCTS3"), + MTK_FUNCTION(4, "LTE_MD32_JTAG_TDO"), + MTK_FUNCTION(5, "DSI1_TE") + ), + MTK_PIN( + 153, "GPIO153", + MTK_EINT_FUNCTION(0, 153), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO153"), + MTK_FUNCTION(1, "DPI_VSYNC"), + MTK_FUNCTION(2, "NLD15"), + MTK_FUNCTION(3, "URTS3"), + MTK_FUNCTION(4, "LTE_MD32_JTAG_TRST"), + MTK_FUNCTION(5, "DISP_PWM1") + ), + MTK_PIN( + 154, "GPIO154", + MTK_EINT_FUNCTION(0, 154), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO154"), + MTK_FUNCTION(1, "MSDC0_DAT0"), + MTK_FUNCTION(2, "NLD8") + ), + MTK_PIN( + 155, "GPIO155", + MTK_EINT_FUNCTION(0, 155), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO155"), + MTK_FUNCTION(1, "MSDC0_DAT1"), + MTK_FUNCTION(2, "NLD9") + ), + MTK_PIN( + 156, "GPIO156", + MTK_EINT_FUNCTION(0, 156), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO156"), + MTK_FUNCTION(1, "MSDC0_DAT2"), + MTK_FUNCTION(2, "NLD10") + ), + MTK_PIN( + 157, "GPIO157", + MTK_EINT_FUNCTION(0, 157), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO157"), + MTK_FUNCTION(1, "MSDC0_DAT3"), + MTK_FUNCTION(2, "NLD11") + ), + MTK_PIN( + 158, "GPIO158", + MTK_EINT_FUNCTION(0, 158), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO158"), + MTK_FUNCTION(1, "MSDC0_DAT4"), + MTK_FUNCTION(2, "NLD12") + ), + MTK_PIN( + 159, "GPIO159", + MTK_EINT_FUNCTION(0, 159), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO159"), + MTK_FUNCTION(1, "MSDC0_DAT5"), + MTK_FUNCTION(2, "NLD13") + ), + MTK_PIN( + 160, "GPIO160", + MTK_EINT_FUNCTION(0, 160), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO160"), + MTK_FUNCTION(1, "MSDC0_DAT6"), + MTK_FUNCTION(2, "NLD14") + ), + MTK_PIN( + 161, "GPIO161", + MTK_EINT_FUNCTION(0, 161), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO161"), + MTK_FUNCTION(1, "MSDC0_DAT7"), + MTK_FUNCTION(2, "NLD15") + ), + MTK_PIN( + 162, "GPIO162", + MTK_EINT_FUNCTION(0, 162), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO162"), + MTK_FUNCTION(1, "MSDC0_CMD") + ), + MTK_PIN( + 163, "GPIO163", + MTK_EINT_FUNCTION(0, 163), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO163"), + MTK_FUNCTION(1, "MSDC0_CLK") + ), + MTK_PIN( + 164, "GPIO164", + MTK_EINT_FUNCTION(0, 164), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO164"), + MTK_FUNCTION(1, "MSDC0_DSL") + ), + MTK_PIN( + 165, "GPIO165", + MTK_EINT_FUNCTION(0, 165), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO165"), + MTK_FUNCTION(1, "MSDC0_RSTB") + ), + MTK_PIN( + 166, "GPIO166", + MTK_EINT_FUNCTION(0, 166), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO166"), + MTK_FUNCTION(1, "SPI_CK_0"), + MTK_FUNCTION(3, "PWM0") + ), + MTK_PIN( + 167, "GPIO167", + MTK_EINT_FUNCTION(0, 167), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO167"), + MTK_FUNCTION(1, "SPI_MI_0"), + MTK_FUNCTION(3, "PWM1"), + MTK_FUNCTION(4, "SPI_MO_0") + ), + MTK_PIN( + 168, "GPIO168", + MTK_EINT_FUNCTION(2, 168), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO168"), + MTK_FUNCTION(1, "SPI_MO_0"), + MTK_FUNCTION(2, "MD_EINT3"), + MTK_FUNCTION(3, "PWM2"), + MTK_FUNCTION(4, "SPI_MI_0") + ), + MTK_PIN( + 169, "GPIO169", + MTK_EINT_FUNCTION(2, 169), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO169"), + MTK_FUNCTION(1, "SPI_CS_0"), + MTK_FUNCTION(2, "MD_EINT4"), + MTK_FUNCTION(3, "PWM3") + ), + MTK_PIN( + 170, "GPIO170", + MTK_EINT_FUNCTION(0, 170), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO170"), + MTK_FUNCTION(1, "MSDC1_CMD") + ), + MTK_PIN( + 171, "GPIO171", + MTK_EINT_FUNCTION(0, 171), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO171"), + MTK_FUNCTION(1, "MSDC1_DAT0") + ), + MTK_PIN( + 172, "GPIO172", + MTK_EINT_FUNCTION(0, 172), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO172"), + MTK_FUNCTION(1, "MSDC1_DAT1") + ), + MTK_PIN( + 173, "GPIO173", + MTK_EINT_FUNCTION(0, 173), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO173"), + MTK_FUNCTION(1, "MSDC1_DAT2") + ), + MTK_PIN( + 174, "GPIO174", + MTK_EINT_FUNCTION(0, 174), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO174"), + MTK_FUNCTION(1, "MSDC1_DAT3") + ), + MTK_PIN( + 175, "GPIO175", + MTK_EINT_FUNCTION(0, 175), + DRV_GRP4, + MTK_FUNCTION(0, "GPIO175"), + MTK_FUNCTION(1, "MSDC1_CLK") + ), + MTK_PIN( + 176, "GPIO176", + MTK_EINT_FUNCTION(0, 176), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO176"), + MTK_FUNCTION(1, "PWRAP_SPIMI"), + MTK_FUNCTION(2, "PWRAP_SPIMO") + ), + MTK_PIN( + 177, "GPIO177", + MTK_EINT_FUNCTION(0, 177), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO177"), + MTK_FUNCTION(1, "PWRAP_SPIMO"), + MTK_FUNCTION(2, "PWRAP_SPIMI") + ), + MTK_PIN( + 178, "GPIO178", + MTK_EINT_FUNCTION(0, 178), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO178"), + MTK_FUNCTION(1, "PWRAP_SPICK") + ), + MTK_PIN( + 179, "GPIO179", + MTK_EINT_FUNCTION(0, 179), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO179"), + MTK_FUNCTION(1, "PWRAP_SPICS") + ), + MTK_PIN( + 180, "GPIO180", + MTK_EINT_FUNCTION(0, 180), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO180"), + MTK_FUNCTION(1, "AUD_CLK_MOSI"), + MTK_FUNCTION(2, "I2S1_WS"), + MTK_FUNCTION(3, "I2S2_WS"), + MTK_FUNCTION(4, "I2S0_WS") + ), + MTK_PIN( + 181, "GPIO181", + MTK_EINT_FUNCTION(0, 181), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO181"), + MTK_FUNCTION(1, "AUD_DAT_MISO_1"), + MTK_FUNCTION(2, "I2S1_BCK"), + MTK_FUNCTION(3, "I2S2_BCK"), + MTK_FUNCTION(4, "I2S0_BCK") + ), + MTK_PIN( + 182, "GPIO182", + MTK_EINT_FUNCTION(0, 182), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO182"), + MTK_FUNCTION(1, "AUD_DAT_MOSI_1"), + MTK_FUNCTION(2, "I2S1_MCK"), + MTK_FUNCTION(3, "I2S2_MCK"), + MTK_FUNCTION(4, "I2S0_MCK") + ), + MTK_PIN( + 183, "GPIO183", + MTK_EINT_FUNCTION(0, 183), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO183"), + MTK_FUNCTION(1, "AUD_DAT_MISO_2"), + MTK_FUNCTION(2, "I2S1_DO_1"), + MTK_FUNCTION(3, "I2S2_DI_1"), + MTK_FUNCTION(4, "I2S0_DO") + ), + MTK_PIN( + 184, "GPIO184", + MTK_EINT_FUNCTION(0, 184), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO184"), + MTK_FUNCTION(1, "AUD_DAT_MOSI_2"), + MTK_FUNCTION(2, "I2S1_DO_2"), + MTK_FUNCTION(3, "I2S2_DI_2"), + MTK_FUNCTION(4, "I2S0_DI") + ), + MTK_PIN( + 185, "GPIO185", + MTK_EINT_FUNCTION(0, 185), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO185"), + MTK_FUNCTION(1, "RTC32K_CK") + ), + MTK_PIN( + 186, "GPIO186", + MTK_EINT_FUNCTION(0, 186), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO186"), + MTK_FUNCTION(1, "DISP_PWM0"), + MTK_FUNCTION(2, "DISP_PWM1") + ), + MTK_PIN( + 187, "GPIO187", + MTK_EINT_FUNCTION(0, 187), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO187"), + MTK_FUNCTION(1, "SRCLKENAI") + ), + MTK_PIN( + 188, "GPIO188", + MTK_EINT_FUNCTION(0, 188), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO188"), + MTK_FUNCTION(1, "SRCLKENAI2") + ), + MTK_PIN( + 189, "GPIO189", + MTK_EINT_FUNCTION(0, 189), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO189"), + MTK_FUNCTION(1, "SRCLKENA0") + ), + MTK_PIN( + 190, "GPIO190", + MTK_EINT_FUNCTION(0, 190), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO190"), + MTK_FUNCTION(1, "SRCLKENA1") + ), + MTK_PIN( + 191, "GPIO191", + MTK_EINT_FUNCTION(0, 191), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO191"), + MTK_FUNCTION(1, "WATCHDOG_AO") + ), + MTK_PIN( + 192, "GPIO192", + MTK_EINT_FUNCTION(0, 192), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO192"), + MTK_FUNCTION(1, "I2S0_WS"), + MTK_FUNCTION(2, "I2S1_WS"), + MTK_FUNCTION(3, "I2S2_WS"), + MTK_FUNCTION(4, "NCEB1") + ), + MTK_PIN( + 193, "GPIO193", + MTK_EINT_FUNCTION(0, 193), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO193"), + MTK_FUNCTION(1, "I2S0_BCK"), + MTK_FUNCTION(2, "I2S1_BCK"), + MTK_FUNCTION(3, "I2S2_BCK"), + MTK_FUNCTION(4, "NRNB1") + ), + MTK_PIN( + 194, "GPIO194", + MTK_EINT_FUNCTION(0, 194), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO194"), + MTK_FUNCTION(1, "I2S0_MCK"), + MTK_FUNCTION(2, "I2S1_MCK"), + MTK_FUNCTION(3, "I2S2_MCK") + ), + MTK_PIN( + 195, "GPIO195", + MTK_EINT_FUNCTION(0, 195), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO195"), + MTK_FUNCTION(1, "I2S0_DO"), + MTK_FUNCTION(2, "I2S1_DO_1"), + MTK_FUNCTION(3, "I2S2_DI_1") + ), + MTK_PIN( + 196, "GPIO196", + MTK_EINT_FUNCTION(0, 196), + DRV_GRP2, + MTK_FUNCTION(0, "GPIO196"), + MTK_FUNCTION(1, "I2S0_DI"), + MTK_FUNCTION(2, "I2S1_DO_2"), + MTK_FUNCTION(3, "I2S2_DI_2") + ), +}; + +#endif /* __PINCTRL_MTK_MT6795_H */ diff --git a/drivers/pinctrl/meson/pinctrl-meson-s4.c b/drivers/pinctrl/meson/pinctrl-meson-s4.c index 3c7358f53302a40e9dad47e3f327f3f2c6bc05b2..cea77864b88088b07d8a802e8f153079ff70f282 100644 --- a/drivers/pinctrl/meson/pinctrl-meson-s4.c +++ b/drivers/pinctrl/meson/pinctrl-meson-s4.c @@ -575,6 +575,7 @@ static struct meson_pmx_group meson_s4_periphs_groups[] = { GROUP(tdm_d2_c, 4), GROUP(tdm_d3_c, 4), GROUP(tdm_fs1_c, 4), + GROUP(tdm_sclk1_c, 4), GROUP(mclk_1_c, 4), GROUP(tdm_d4_c, 4), GROUP(tdm_d5_c, 4), @@ -936,7 +937,7 @@ static const char * const iso7816_groups[] = { }; static const char * const tdm_groups[] = { - "tdm_d2_c", "tdm_d3_c", "tdm_fs1_c", "tdm_d4_c", "tdm_d5_c", + "tdm_d2_c", "tdm_d3_c", "tdm_fs1_c", "tdm_d4_c", "tdm_d5_c", "tdm_sclk1_c", "tdm_fs1_d", "tdm_d4_d", "tdm_d3_d", "tdm_d2_d", "tdm_sclk1_d", "tdm_sclk1_h", "tdm_fs1_h", "tdm_d2_h", "tdm_d3_h", "tdm_d4_h", "tdm_d1", "tdm_d0", "tdm_fs0", "tdm_sclk0", "tdm_fs2", "tdm_sclk2", diff --git a/drivers/pinctrl/mvebu/Kconfig b/drivers/pinctrl/mvebu/Kconfig index 0d12894d3ee1ed5df80f87e94ec1d96d1b1d0255..aa5883f09d7b4f548b4f5799e1651d44488bffd2 100644 --- a/drivers/pinctrl/mvebu/Kconfig +++ b/drivers/pinctrl/mvebu/Kconfig @@ -45,6 +45,10 @@ config PINCTRL_ORION bool select PINCTRL_MVEBU +config PINCTRL_AC5 + bool + select PINCTRL_MVEBU + config PINCTRL_ARMADA_37XX bool select GENERIC_PINCONF diff --git a/drivers/pinctrl/mvebu/Makefile b/drivers/pinctrl/mvebu/Makefile index cd082dca44828974ebef40dfadace954b5c11b98..23458ab17c532ddaa73db7a18a34e8ca2f8d8dfe 100644 --- a/drivers/pinctrl/mvebu/Makefile +++ b/drivers/pinctrl/mvebu/Makefile @@ -11,3 +11,4 @@ obj-$(CONFIG_PINCTRL_ARMADA_CP110) += pinctrl-armada-cp110.o obj-$(CONFIG_PINCTRL_ARMADA_XP) += pinctrl-armada-xp.o obj-$(CONFIG_PINCTRL_ARMADA_37XX) += pinctrl-armada-37xx.o obj-$(CONFIG_PINCTRL_ORION) += pinctrl-orion.o +obj-$(CONFIG_PINCTRL_AC5) += pinctrl-ac5.o diff --git a/drivers/pinctrl/mvebu/pinctrl-ac5.c b/drivers/pinctrl/mvebu/pinctrl-ac5.c new file mode 100644 index 0000000000000000000000000000000000000000..292633e61129869a9203dc6967fb8a8f765a2a7d --- /dev/null +++ b/drivers/pinctrl/mvebu/pinctrl-ac5.c @@ -0,0 +1,261 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Marvell ac5 pinctrl driver based on mvebu pinctrl core + * + * Copyright (C) 2021 Marvell + * + * Noam Liron + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "pinctrl-mvebu.h" + +static struct mvebu_mpp_mode ac5_mpp_modes[] = { + MPP_MODE(0, + MPP_FUNCTION(0, "gpio", NULL), + MPP_FUNCTION(1, "sdio", "d0"), + MPP_FUNCTION(2, "nand", "io4")), + MPP_MODE(1, + MPP_FUNCTION(0, "gpio", NULL), + MPP_FUNCTION(1, "sdio", "d1"), + MPP_FUNCTION(2, "nand", "io3")), + MPP_MODE(2, + MPP_FUNCTION(0, "gpio", NULL), + MPP_FUNCTION(1, "sdio", "d2"), + MPP_FUNCTION(2, "nand", "io2")), + MPP_MODE(3, + MPP_FUNCTION(0, "gpio", NULL), + MPP_FUNCTION(1, "sdio", "d3"), + MPP_FUNCTION(2, "nand", "io7")), + MPP_MODE(4, + MPP_FUNCTION(0, "gpio", NULL), + MPP_FUNCTION(1, "sdio", "d4"), + MPP_FUNCTION(2, "nand", "io6"), + MPP_FUNCTION(3, "uart3", "txd"), + MPP_FUNCTION(4, "uart2", "txd")), + MPP_MODE(5, + MPP_FUNCTION(0, "gpio", NULL), + MPP_FUNCTION(1, "sdio", "d5"), + MPP_FUNCTION(2, "nand", "io5"), + MPP_FUNCTION(3, "uart3", "rxd"), + MPP_FUNCTION(4, "uart2", "rxd")), + MPP_MODE(6, + MPP_FUNCTION(0, "gpio", NULL), + MPP_FUNCTION(1, "sdio", "d6"), + MPP_FUNCTION(2, "nand", "io0"), + MPP_FUNCTION(3, "i2c1", "sck")), + MPP_MODE(7, + MPP_FUNCTION(0, "gpio", NULL), + MPP_FUNCTION(1, "sdio", "d7"), + MPP_FUNCTION(2, "nand", "io1"), + MPP_FUNCTION(3, "i2c1", "sda")), + MPP_MODE(8, + MPP_FUNCTION(0, "gpio", NULL), + MPP_FUNCTION(1, "sdio", "clk"), + MPP_FUNCTION(2, "nand", "wen")), + MPP_MODE(9, + MPP_FUNCTION(0, "gpio", NULL), + MPP_FUNCTION(1, "sdio", "cmd"), + MPP_FUNCTION(2, "nand", "ale")), + MPP_MODE(10, + MPP_FUNCTION(0, "gpio", NULL), + MPP_FUNCTION(1, "sdio", "ds"), + MPP_FUNCTION(2, "nand", "cle")), + MPP_MODE(11, + MPP_FUNCTION(0, "gpio", NULL), + MPP_FUNCTION(1, "sdio", "rst"), + MPP_FUNCTION(2, "nand", "cen")), + MPP_MODE(12, + MPP_FUNCTION(0, "gpio", NULL), + MPP_FUNCTION(1, "spi0", "clk")), + MPP_MODE(13, + MPP_FUNCTION(0, "gpio", NULL), + MPP_FUNCTION(1, "spi0", "csn")), + MPP_MODE(14, + MPP_FUNCTION(0, "gpio", NULL), + MPP_FUNCTION(1, "spi0", "mosi")), + MPP_MODE(15, + MPP_FUNCTION(0, "gpio", NULL), + MPP_FUNCTION(1, "spi0", "miso")), + MPP_MODE(16, + MPP_FUNCTION(0, "gpio", NULL), + MPP_FUNCTION(1, "spi0", "wpn"), + MPP_FUNCTION(2, "nand", "ren"), + MPP_FUNCTION(3, "uart1", "txd")), + MPP_MODE(17, + MPP_FUNCTION(0, "gpio", NULL), + MPP_FUNCTION(1, "spi0", "hold"), + MPP_FUNCTION(2, "nand", "rb"), + MPP_FUNCTION(3, "uart1", "rxd")), + MPP_MODE(18, + MPP_FUNCTION(0, "gpio", NULL), + MPP_FUNCTION(1, "tsen_int", NULL), + MPP_FUNCTION(2, "uart2", "rxd"), + MPP_FUNCTION(3, "wd_int", NULL)), + MPP_MODE(19, + MPP_FUNCTION(0, "gpio", NULL), + MPP_FUNCTION(1, "dev_init_done", NULL), + MPP_FUNCTION(2, "uart2", "txd")), + MPP_MODE(20, + MPP_FUNCTION(0, "gpio", NULL), + MPP_FUNCTION(2, "i2c1", "sck"), + MPP_FUNCTION(3, "spi1", "clk"), + MPP_FUNCTION(4, "uart3", "txd")), + MPP_MODE(21, + MPP_FUNCTION(0, "gpio", NULL), + MPP_FUNCTION(2, "i2c1", "sda"), + MPP_FUNCTION(3, "spi1", "csn"), + MPP_FUNCTION(4, "uart3", "rxd")), + MPP_MODE(22, + MPP_FUNCTION(0, "gpio", NULL), + MPP_FUNCTION(3, "spi1", "mosi")), + MPP_MODE(23, + MPP_FUNCTION(0, "gpio", NULL), + MPP_FUNCTION(3, "spi1", "miso")), + MPP_MODE(24, + MPP_FUNCTION(0, "gpio", NULL), + MPP_FUNCTION(1, "wd_int", NULL), + MPP_FUNCTION(2, "uart2", "txd"), + MPP_FUNCTION(3, "uartsd", "txd")), + MPP_MODE(25, + MPP_FUNCTION(0, "gpio", NULL), + MPP_FUNCTION(1, "int_out", NULL), + MPP_FUNCTION(2, "uart2", "rxd"), + MPP_FUNCTION(3, "uartsd", "rxd")), + MPP_MODE(26, + MPP_FUNCTION(0, "gpio", NULL), + MPP_FUNCTION(1, "i2c0", "sck"), + MPP_FUNCTION(2, "ptp", "clk1"), + MPP_FUNCTION(3, "uart3", "txd")), + MPP_MODE(27, + MPP_FUNCTION(0, "gpio", NULL), + MPP_FUNCTION(1, "i2c0", "sda"), + MPP_FUNCTION(2, "ptp", "pulse"), + MPP_FUNCTION(3, "uart3", "rxd")), + MPP_MODE(28, + MPP_FUNCTION(0, "gpio", NULL), + MPP_FUNCTION(1, "xg", "mdio"), + MPP_FUNCTION(2, "ge", "mdio"), + MPP_FUNCTION(3, "uart3", "txd")), + MPP_MODE(29, + MPP_FUNCTION(0, "gpio", NULL), + MPP_FUNCTION(1, "xg", "mdio"), + MPP_FUNCTION(2, "ge", "mdio"), + MPP_FUNCTION(3, "uart3", "rxd")), + MPP_MODE(30, + MPP_FUNCTION(0, "gpio", NULL), + MPP_FUNCTION(1, "xg", "mdio"), + MPP_FUNCTION(2, "ge", "mdio"), + MPP_FUNCTION(3, "ge", "mdio")), + MPP_MODE(31, + MPP_FUNCTION(0, "gpio", NULL), + MPP_FUNCTION(1, "xg", "mdio"), + MPP_FUNCTION(2, "ge", "mdio"), + MPP_FUNCTION(3, "ge", "mdio")), + MPP_MODE(32, + MPP_FUNCTION(0, "gpio", NULL), + MPP_FUNCTION(1, "uart0", "txd")), + MPP_MODE(33, + MPP_FUNCTION(0, "gpio", NULL), + MPP_FUNCTION(1, "uart0", "rxd"), + MPP_FUNCTION(2, "ptp", "clk1"), + MPP_FUNCTION(3, "ptp", "pulse")), + MPP_MODE(34, + MPP_FUNCTION(0, "gpio", NULL), + MPP_FUNCTION(1, "ge", "mdio"), + MPP_FUNCTION(2, "uart3", "rxd")), + MPP_MODE(35, + MPP_FUNCTION(0, "gpio", NULL), + MPP_FUNCTION(1, "ge", "mdio"), + MPP_FUNCTION(2, "uart3", "txd"), + MPP_FUNCTION(3, "pcie", "rstoutn")), + MPP_MODE(36, + MPP_FUNCTION(0, "gpio", NULL), + MPP_FUNCTION(1, "ptp", "clk0_tp"), + MPP_FUNCTION(2, "ptp", "clk1_tp")), + MPP_MODE(37, + MPP_FUNCTION(0, "gpio", NULL), + MPP_FUNCTION(1, "ptp", "pulse_tp"), + MPP_FUNCTION(2, "wd_int", NULL)), + MPP_MODE(38, + MPP_FUNCTION(0, "gpio", NULL), + MPP_FUNCTION(1, "synce", "clk_out0")), + MPP_MODE(39, + MPP_FUNCTION(0, "gpio", NULL), + MPP_FUNCTION(1, "synce", "clk_out1")), + MPP_MODE(40, + MPP_FUNCTION(0, "gpio", NULL), + MPP_FUNCTION(1, "ptp", "pclk_out0"), + MPP_FUNCTION(2, "ptp", "pclk_out1")), + MPP_MODE(41, + MPP_FUNCTION(0, "gpio", NULL), + MPP_FUNCTION(1, "ptp", "ref_clk"), + MPP_FUNCTION(2, "ptp", "clk1"), + MPP_FUNCTION(3, "ptp", "pulse"), + MPP_FUNCTION(4, "uart2", "txd"), + MPP_FUNCTION(5, "i2c1", "sck")), + MPP_MODE(42, + MPP_FUNCTION(0, "gpio", NULL), + MPP_FUNCTION(1, "ptp", "clk0"), + MPP_FUNCTION(2, "ptp", "clk1"), + MPP_FUNCTION(3, "ptp", "pulse"), + MPP_FUNCTION(4, "uart2", "rxd"), + MPP_FUNCTION(5, "i2c1", "sda")), + MPP_MODE(43, + MPP_FUNCTION(0, "gpio", NULL), + MPP_FUNCTION(1, "led", "clk")), + MPP_MODE(44, + MPP_FUNCTION(0, "gpio", NULL), + MPP_FUNCTION(1, "led", "stb")), + MPP_MODE(45, + MPP_FUNCTION(0, "gpio", NULL), + MPP_FUNCTION(1, "led", "data")), +}; + +static struct mvebu_pinctrl_soc_info ac5_pinctrl_info; + +static const struct of_device_id ac5_pinctrl_of_match[] = { + { + .compatible = "marvell,ac5-pinctrl", + }, + { }, +}; + +static const struct mvebu_mpp_ctrl ac5_mpp_controls[] = { + MPP_FUNC_CTRL(0, 45, NULL, mvebu_mmio_mpp_ctrl), }; + +static struct pinctrl_gpio_range ac5_mpp_gpio_ranges[] = { + MPP_GPIO_RANGE(0, 0, 0, 46), }; + +static int ac5_pinctrl_probe(struct platform_device *pdev) +{ + struct mvebu_pinctrl_soc_info *soc = &ac5_pinctrl_info; + + soc->variant = 0; /* no variants for ac5 */ + soc->controls = ac5_mpp_controls; + soc->ncontrols = ARRAY_SIZE(ac5_mpp_controls); + soc->gpioranges = ac5_mpp_gpio_ranges; + soc->ngpioranges = ARRAY_SIZE(ac5_mpp_gpio_ranges); + soc->modes = ac5_mpp_modes; + soc->nmodes = ac5_mpp_controls[0].npins; + + pdev->dev.platform_data = soc; + + return mvebu_pinctrl_simple_mmio_probe(pdev); +} + +static struct platform_driver ac5_pinctrl_driver = { + .driver = { + .name = "ac5-pinctrl", + .of_match_table = of_match_ptr(ac5_pinctrl_of_match), + }, + .probe = ac5_pinctrl_probe, +}; +builtin_platform_driver(ac5_pinctrl_driver); diff --git a/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c b/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c index ef4118e49f16cc1361157b8ffbfe19f982dca416..a140b6bfbfaa675c7eee4ac0b775f2bb862be9f6 100644 --- a/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c +++ b/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c @@ -764,7 +764,7 @@ static int armada_37xx_irqchip_register(struct platform_device *pdev, for (i = 0; i < nr_irq_parent; i++) { int irq = irq_of_parse_and_map(np, i); - if (irq < 0) + if (!irq) continue; girq->parents[i] = irq; } diff --git a/drivers/pinctrl/nomadik/pinctrl-nomadik-db8500.c b/drivers/pinctrl/nomadik/pinctrl-nomadik-db8500.c index 0b9b6cbfd10c31125f2eb86afdce43fe61e55871..ac3d4d91266d7ba7ae1ac6d7b399681db98b7697 100644 --- a/drivers/pinctrl/nomadik/pinctrl-nomadik-db8500.c +++ b/drivers/pinctrl/nomadik/pinctrl-nomadik-db8500.c @@ -440,6 +440,10 @@ static const unsigned mc2_a_1_pins[] = { DB8500_PIN_A5, DB8500_PIN_B4, DB8500_PIN_C8, DB8500_PIN_A12, DB8500_PIN_C10, DB8500_PIN_B10, DB8500_PIN_B9, DB8500_PIN_A9, DB8500_PIN_C7, DB8500_PIN_A7, DB8500_PIN_C5 }; +/* MC2 without the feedback clock */ +static const unsigned mc2_a_2_pins[] = { DB8500_PIN_A5, DB8500_PIN_B4, + DB8500_PIN_A12, DB8500_PIN_C10, DB8500_PIN_B10, DB8500_PIN_B9, + DB8500_PIN_A9, DB8500_PIN_C7, DB8500_PIN_A7, DB8500_PIN_C5 }; static const unsigned ssp1_a_1_pins[] = { DB8500_PIN_C9, DB8500_PIN_B11, DB8500_PIN_C12, DB8500_PIN_C11 }; static const unsigned ssp0_a_1_pins[] = { DB8500_PIN_D12, DB8500_PIN_B13, @@ -699,6 +703,7 @@ static const struct nmk_pingroup nmk_db8500_groups[] = { DB8500_PIN_GROUP(kp_a_1, NMK_GPIO_ALT_A), DB8500_PIN_GROUP(kpskaskb_a_1, NMK_GPIO_ALT_A), DB8500_PIN_GROUP(mc2_a_1, NMK_GPIO_ALT_A), + DB8500_PIN_GROUP(mc2_a_2, NMK_GPIO_ALT_A), DB8500_PIN_GROUP(ssp1_a_1, NMK_GPIO_ALT_A), DB8500_PIN_GROUP(ssp0_a_1, NMK_GPIO_ALT_A), DB8500_PIN_GROUP(i2c0_a_1, NMK_GPIO_ALT_A), @@ -856,7 +861,7 @@ DB8500_FUNC_GROUPS(lcd, "lcdvsi0_a_1", "lcdvsi1_a_1", "lcd_d0_d7_a_1", "lcd_d8_d11_a_1", "lcd_d12_d15_a_1", "lcd_d12_d23_a_1", "lcd_b_1", "lcd_d16_d23_b_1"); DB8500_FUNC_GROUPS(kp, "kp_a_1", "kp_a_2", "kp_b_1", "kp_b_2", "kp_c_1", "kp_oc1_1"); -DB8500_FUNC_GROUPS(mc2, "mc2_a_1", "mc2rstn_c_1"); +DB8500_FUNC_GROUPS(mc2, "mc2_a_1", "mc2_a_2", "mc2rstn_c_1"); DB8500_FUNC_GROUPS(ssp1, "ssp1_a_1"); DB8500_FUNC_GROUPS(ssp0, "ssp0_a_1"); DB8500_FUNC_GROUPS(i2c0, "i2c0_a_1"); diff --git a/drivers/pinctrl/nomadik/pinctrl-nomadik.c b/drivers/pinctrl/nomadik/pinctrl-nomadik.c index 4757bf964d3cd304c3576ce669640a31e661e6da..640e50d94f27ef970837f9e400efd3b928fa3daa 100644 --- a/drivers/pinctrl/nomadik/pinctrl-nomadik.c +++ b/drivers/pinctrl/nomadik/pinctrl-nomadik.c @@ -1113,6 +1113,7 @@ static int nmk_gpio_probe(struct platform_device *dev) spin_lock_init(&nmk_chip->lock); chip = &nmk_chip->chip; + chip->parent = &dev->dev; chip->request = gpiochip_generic_request; chip->free = gpiochip_generic_free; chip->get_direction = nmk_gpio_get_dir; @@ -1154,7 +1155,6 @@ static int nmk_gpio_probe(struct platform_device *dev) clk_enable(nmk_chip->clk); nmk_chip->lowemi = readl_relaxed(nmk_chip->addr + NMK_GPIO_LOWEMI); clk_disable(nmk_chip->clk); - chip->of_node = np; ret = gpiochip_add_data(chip, nmk_chip); if (ret) diff --git a/drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c b/drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c index 4828aa25e5c9b84aa3af3f5f43263b2d625fc42c..64d8a568b3dbd3ec4e056565f0c8b1c3a3829696 100644 --- a/drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c +++ b/drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c @@ -1898,9 +1898,9 @@ static int npcm7xx_gpio_of(struct npcm7xx_pinctrl *pctrl) } ret = irq_of_parse_and_map(np, 0); - if (ret < 0) { + if (!ret) { dev_err(dev, "No IRQ for GPIO bank %u\n", id); - return ret; + return -EINVAL; } pctrl->gpio_bank[id].irq = ret; pctrl->gpio_bank[id].irq_chip = npcmgpio_irqchip; diff --git a/drivers/pinctrl/pinctrl-apple-gpio.c b/drivers/pinctrl/pinctrl-apple-gpio.c index 5e610849dfc3ebf5295adcf0b8d33c29d57dc8ed..2490384ef1b85d3e3f78477c2fd667340582e1bb 100644 --- a/drivers/pinctrl/pinctrl-apple-gpio.c +++ b/drivers/pinctrl/pinctrl-apple-gpio.c @@ -71,6 +71,7 @@ struct regmap_config regmap_config = { .max_register = 512 * sizeof(u32), .num_reg_defaults_raw = 512, .use_relaxed_mmio = true, + .use_raw_spinlock = true, }; /* No locking needed to mask/unmask IRQs as the interrupt mode is per pin-register. */ @@ -509,6 +510,7 @@ static const struct of_device_id apple_gpio_pinctrl_of_match[] = { { .compatible = "apple,pinctrl", }, { } }; +MODULE_DEVICE_TABLE(of, apple_gpio_pinctrl_of_match); static struct platform_driver apple_gpio_pinctrl_driver = { .driver = { diff --git a/drivers/pinctrl/pinctrl-equilibrium.c b/drivers/pinctrl/pinctrl-equilibrium.c index 3f0143087cc779937c4380d0844633f31496037e..99cf24eb67ae661ef17531bbc3dcda0be4c997b7 100644 --- a/drivers/pinctrl/pinctrl-equilibrium.c +++ b/drivers/pinctrl/pinctrl-equilibrium.c @@ -11,6 +11,7 @@ #include #include #include +#include #include "core.h" #include "pinconf.h" @@ -167,11 +168,9 @@ static int gpiochip_setup(struct device *dev, struct eqbr_gpio_ctrl *gctrl) gc = &gctrl->chip; gc->label = gctrl->name; -#if defined(CONFIG_OF_GPIO) - gc->of_node = gctrl->node; -#endif + gc->fwnode = gctrl->fwnode; - if (!of_property_read_bool(gctrl->node, "interrupt-controller")) { + if (!fwnode_property_read_bool(gctrl->fwnode, "interrupt-controller")) { dev_dbg(dev, "gc %s: doesn't act as interrupt controller!\n", gctrl->name); return 0; @@ -209,7 +208,7 @@ static int gpiolib_reg(struct eqbr_pinctrl_drv_data *drvdata) for (i = 0; i < drvdata->nr_gpio_ctrls; i++) { gctrl = drvdata->gpio_ctrls + i; - np = gctrl->node; + np = to_of_node(gctrl->fwnode); gctrl->name = devm_kasprintf(dev, GFP_KERNEL, "gpiochip%d", i); if (!gctrl->name) @@ -895,7 +894,7 @@ static int pinbank_probe(struct eqbr_pinctrl_drv_data *drvdata) pinbank_init(np_gpio, drvdata, banks + i, i); - gctrls[i].node = np_gpio; + gctrls[i].fwnode = of_fwnode_handle(np_gpio); gctrls[i].bank = banks + i; i++; } diff --git a/drivers/pinctrl/pinctrl-equilibrium.h b/drivers/pinctrl/pinctrl-equilibrium.h index 83cb7dafc657f67b4df8fcb30a3b8425b3f17386..0c635a5b79f019fc2cebb1f8cc9f1f64f0b9b236 100644 --- a/drivers/pinctrl/pinctrl-equilibrium.h +++ b/drivers/pinctrl/pinctrl-equilibrium.h @@ -95,22 +95,24 @@ struct eqbr_pin_bank { u32 aval_pinmap; }; +struct fwnode_handle; + /** * struct eqbr_gpio_ctrl: represent a gpio controller. - * @node: device node of gpio controller. + * @chip: gpio chip. + * @fwnode: firmware node of gpio controller. * @bank: pointer to corresponding pin bank. * @membase: base address of the gpio controller. - * @chip: gpio chip. * @ic: irq chip. * @name: gpio chip name. * @virq: irq number of the gpio chip to parent's irq domain. * @lock: spin lock to protect gpio register write. */ struct eqbr_gpio_ctrl { - struct device_node *node; + struct gpio_chip chip; + struct fwnode_handle *fwnode; struct eqbr_pin_bank *bank; void __iomem *membase; - struct gpio_chip chip; struct irq_chip ic; const char *name; unsigned int virq; diff --git a/drivers/pinctrl/pinctrl-ingenic.c b/drivers/pinctrl/pinctrl-ingenic.c index fa6becca17889e84e309b401f1b6c21a9ef780c9..1ca11616db742c55b1302412058ec0d03ec7357e 100644 --- a/drivers/pinctrl/pinctrl-ingenic.c +++ b/drivers/pinctrl/pinctrl-ingenic.c @@ -139,6 +139,30 @@ struct ingenic_gpio_chip { unsigned int irq, reg_base; }; +static const unsigned long enabled_socs = + IS_ENABLED(CONFIG_MACH_JZ4730) << ID_JZ4730 | + IS_ENABLED(CONFIG_MACH_JZ4740) << ID_JZ4740 | + IS_ENABLED(CONFIG_MACH_JZ4725B) << ID_JZ4725B | + IS_ENABLED(CONFIG_MACH_JZ4750) << ID_JZ4750 | + IS_ENABLED(CONFIG_MACH_JZ4755) << ID_JZ4755 | + IS_ENABLED(CONFIG_MACH_JZ4760) << ID_JZ4760 | + IS_ENABLED(CONFIG_MACH_JZ4770) << ID_JZ4770 | + IS_ENABLED(CONFIG_MACH_JZ4775) << ID_JZ4775 | + IS_ENABLED(CONFIG_MACH_JZ4780) << ID_JZ4780 | + IS_ENABLED(CONFIG_MACH_X1000) << ID_X1000 | + IS_ENABLED(CONFIG_MACH_X1500) << ID_X1500 | + IS_ENABLED(CONFIG_MACH_X1830) << ID_X1830 | + IS_ENABLED(CONFIG_MACH_X2000) << ID_X2000 | + IS_ENABLED(CONFIG_MACH_X2100) << ID_X2100; + +static bool +is_soc_or_above(const struct ingenic_pinctrl *jzpc, enum jz_version version) +{ + return (enabled_socs >> version) && + (!(enabled_socs & GENMASK(version - 1, 0)) + || jzpc->info->version >= version); +} + static const u32 jz4730_pull_ups[4] = { 0x3fa3320f, 0xf200ffff, 0xffffffff, 0xffffffff, }; @@ -3242,7 +3266,7 @@ static u32 ingenic_gpio_read_reg(struct ingenic_gpio_chip *jzgc, u8 reg) static void ingenic_gpio_set_bit(struct ingenic_gpio_chip *jzgc, u8 reg, u8 offset, bool set) { - if (jzgc->jzpc->info->version == ID_JZ4730) { + if (!is_soc_or_above(jzgc->jzpc, ID_JZ4740)) { regmap_update_bits(jzgc->jzpc->map, jzgc->reg_base + reg, BIT(offset), set ? BIT(offset) : 0); return; @@ -3300,9 +3324,9 @@ static inline bool ingenic_gpio_get_value(struct ingenic_gpio_chip *jzgc, static void ingenic_gpio_set_value(struct ingenic_gpio_chip *jzgc, u8 offset, int value) { - if (jzgc->jzpc->info->version >= ID_JZ4770) + if (is_soc_or_above(jzgc->jzpc, ID_JZ4770)) ingenic_gpio_set_bit(jzgc, JZ4770_GPIO_PAT0, offset, !!value); - else if (jzgc->jzpc->info->version >= ID_JZ4740) + else if (is_soc_or_above(jzgc->jzpc, ID_JZ4740)) ingenic_gpio_set_bit(jzgc, JZ4740_GPIO_DATA, offset, !!value); else ingenic_gpio_set_bit(jzgc, JZ4730_GPIO_DATA, offset, !!value); @@ -3337,10 +3361,10 @@ static void irq_set_type(struct ingenic_gpio_chip *jzgc, break; } - if (jzgc->jzpc->info->version >= ID_JZ4770) { + if (is_soc_or_above(jzgc->jzpc, ID_JZ4770)) { reg1 = JZ4770_GPIO_PAT1; reg2 = JZ4770_GPIO_PAT0; - } else if (jzgc->jzpc->info->version >= ID_JZ4740) { + } else if (is_soc_or_above(jzgc->jzpc, ID_JZ4740)) { reg1 = JZ4740_GPIO_TRIG; reg2 = JZ4740_GPIO_DIR; } else { @@ -3350,12 +3374,12 @@ static void irq_set_type(struct ingenic_gpio_chip *jzgc, return; } - if (jzgc->jzpc->info->version >= ID_X2000) { + if (is_soc_or_above(jzgc->jzpc, ID_X2000)) { ingenic_gpio_shadow_set_bit(jzgc, reg2, offset, val1); ingenic_gpio_shadow_set_bit(jzgc, reg1, offset, val2); ingenic_gpio_shadow_set_bit_load(jzgc); ingenic_gpio_set_bit(jzgc, X2000_GPIO_EDG, offset, val3); - } else if (jzgc->jzpc->info->version >= ID_X1000) { + } else if (is_soc_or_above(jzgc->jzpc, ID_X1000)) { ingenic_gpio_shadow_set_bit(jzgc, reg2, offset, val1); ingenic_gpio_shadow_set_bit(jzgc, reg1, offset, val2); ingenic_gpio_shadow_set_bit_load(jzgc); @@ -3371,7 +3395,7 @@ static void ingenic_gpio_irq_mask(struct irq_data *irqd) struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc); int irq = irqd->hwirq; - if (jzgc->jzpc->info->version >= ID_JZ4740) + if (is_soc_or_above(jzgc->jzpc, ID_JZ4740)) ingenic_gpio_set_bit(jzgc, GPIO_MSK, irq, true); else ingenic_gpio_set_bit(jzgc, JZ4730_GPIO_GPIMR, irq, true); @@ -3383,7 +3407,7 @@ static void ingenic_gpio_irq_unmask(struct irq_data *irqd) struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc); int irq = irqd->hwirq; - if (jzgc->jzpc->info->version >= ID_JZ4740) + if (is_soc_or_above(jzgc->jzpc, ID_JZ4740)) ingenic_gpio_set_bit(jzgc, GPIO_MSK, irq, false); else ingenic_gpio_set_bit(jzgc, JZ4730_GPIO_GPIMR, irq, false); @@ -3395,9 +3419,9 @@ static void ingenic_gpio_irq_enable(struct irq_data *irqd) struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc); int irq = irqd->hwirq; - if (jzgc->jzpc->info->version >= ID_JZ4770) + if (is_soc_or_above(jzgc->jzpc, ID_JZ4770)) ingenic_gpio_set_bit(jzgc, JZ4770_GPIO_INT, irq, true); - else if (jzgc->jzpc->info->version >= ID_JZ4740) + else if (is_soc_or_above(jzgc->jzpc, ID_JZ4740)) ingenic_gpio_set_bit(jzgc, JZ4740_GPIO_SELECT, irq, true); else ingenic_gpio_set_bit(jzgc, JZ4730_GPIO_GPIER, irq, true); @@ -3413,9 +3437,9 @@ static void ingenic_gpio_irq_disable(struct irq_data *irqd) ingenic_gpio_irq_mask(irqd); - if (jzgc->jzpc->info->version >= ID_JZ4770) + if (is_soc_or_above(jzgc->jzpc, ID_JZ4770)) ingenic_gpio_set_bit(jzgc, JZ4770_GPIO_INT, irq, false); - else if (jzgc->jzpc->info->version >= ID_JZ4740) + else if (is_soc_or_above(jzgc->jzpc, ID_JZ4740)) ingenic_gpio_set_bit(jzgc, JZ4740_GPIO_SELECT, irq, false); else ingenic_gpio_set_bit(jzgc, JZ4730_GPIO_GPIER, irq, false); @@ -3429,7 +3453,7 @@ static void ingenic_gpio_irq_ack(struct irq_data *irqd) bool high; if ((irqd_get_trigger_type(irqd) == IRQ_TYPE_EDGE_BOTH) && - (jzgc->jzpc->info->version < ID_X2000)) { + !is_soc_or_above(jzgc->jzpc, ID_X2000)) { /* * Switch to an interrupt for the opposite edge to the one that * triggered the interrupt being ACKed. @@ -3441,9 +3465,9 @@ static void ingenic_gpio_irq_ack(struct irq_data *irqd) irq_set_type(jzgc, irq, IRQ_TYPE_LEVEL_HIGH); } - if (jzgc->jzpc->info->version >= ID_JZ4770) + if (is_soc_or_above(jzgc->jzpc, ID_JZ4770)) ingenic_gpio_set_bit(jzgc, JZ4770_GPIO_FLAG, irq, false); - else if (jzgc->jzpc->info->version >= ID_JZ4740) + else if (is_soc_or_above(jzgc->jzpc, ID_JZ4740)) ingenic_gpio_set_bit(jzgc, JZ4740_GPIO_DATA, irq, true); else ingenic_gpio_set_bit(jzgc, JZ4730_GPIO_GPFR, irq, false); @@ -3468,7 +3492,7 @@ static int ingenic_gpio_irq_set_type(struct irq_data *irqd, unsigned int type) irq_set_handler_locked(irqd, handle_bad_irq); } - if ((type == IRQ_TYPE_EDGE_BOTH) && (jzgc->jzpc->info->version < ID_X2000)) { + if ((type == IRQ_TYPE_EDGE_BOTH) && !is_soc_or_above(jzgc->jzpc, ID_X2000)) { /* * The hardware does not support interrupts on both edges. The * best we can do is to set up a single-edge interrupt and then @@ -3500,9 +3524,9 @@ static void ingenic_gpio_irq_handler(struct irq_desc *desc) chained_irq_enter(irq_chip, desc); - if (jzgc->jzpc->info->version >= ID_JZ4770) + if (is_soc_or_above(jzgc->jzpc, ID_JZ4770)) flag = ingenic_gpio_read_reg(jzgc, JZ4770_GPIO_FLAG); - else if (jzgc->jzpc->info->version >= ID_JZ4740) + else if (is_soc_or_above(jzgc->jzpc, ID_JZ4740)) flag = ingenic_gpio_read_reg(jzgc, JZ4740_GPIO_FLAG); else flag = ingenic_gpio_read_reg(jzgc, JZ4730_GPIO_GPFR); @@ -3547,14 +3571,14 @@ static inline void ingenic_config_pin(struct ingenic_pinctrl *jzpc, unsigned int offt = pin / PINS_PER_GPIO_CHIP; if (set) { - if (jzpc->info->version >= ID_JZ4740) + if (is_soc_or_above(jzpc, ID_JZ4740)) regmap_write(jzpc->map, offt * jzpc->info->reg_offset + REG_SET(reg), BIT(idx)); else regmap_set_bits(jzpc->map, offt * jzpc->info->reg_offset + reg, BIT(idx)); } else { - if (jzpc->info->version >= ID_JZ4740) + if (is_soc_or_above(jzpc, ID_JZ4740)) regmap_write(jzpc->map, offt * jzpc->info->reg_offset + REG_CLEAR(reg), BIT(idx)); else @@ -3613,12 +3637,12 @@ static int ingenic_gpio_get_direction(struct gpio_chip *gc, unsigned int offset) struct ingenic_pinctrl *jzpc = jzgc->jzpc; unsigned int pin = gc->base + offset; - if (jzpc->info->version >= ID_JZ4770) { + if (is_soc_or_above(jzpc, ID_JZ4770)) { if (ingenic_get_pin_config(jzpc, pin, JZ4770_GPIO_INT) || ingenic_get_pin_config(jzpc, pin, JZ4770_GPIO_PAT1)) return GPIO_LINE_DIRECTION_IN; return GPIO_LINE_DIRECTION_OUT; - } else if (jzpc->info->version == ID_JZ4730) { + } else if (!is_soc_or_above(jzpc, ID_JZ4740)) { if (!ingenic_get_pin_config(jzpc, pin, JZ4730_GPIO_GPDIR)) return GPIO_LINE_DIRECTION_IN; return GPIO_LINE_DIRECTION_OUT; @@ -3669,18 +3693,18 @@ static int ingenic_pinmux_set_pin_fn(struct ingenic_pinctrl *jzpc, dev_dbg(jzpc->dev, "set pin P%c%u to function %u\n", 'A' + offt, idx, func); - if (jzpc->info->version >= ID_X1000) { + if (is_soc_or_above(jzpc, ID_X1000)) { ingenic_shadow_config_pin(jzpc, pin, JZ4770_GPIO_INT, false); ingenic_shadow_config_pin(jzpc, pin, GPIO_MSK, false); ingenic_shadow_config_pin(jzpc, pin, JZ4770_GPIO_PAT1, func & 0x2); ingenic_shadow_config_pin(jzpc, pin, JZ4770_GPIO_PAT0, func & 0x1); ingenic_shadow_config_pin_load(jzpc, pin); - } else if (jzpc->info->version >= ID_JZ4770) { + } else if (is_soc_or_above(jzpc, ID_JZ4770)) { ingenic_config_pin(jzpc, pin, JZ4770_GPIO_INT, false); ingenic_config_pin(jzpc, pin, GPIO_MSK, false); ingenic_config_pin(jzpc, pin, JZ4770_GPIO_PAT1, func & 0x2); ingenic_config_pin(jzpc, pin, JZ4770_GPIO_PAT0, func & 0x1); - } else if (jzpc->info->version >= ID_JZ4740) { + } else if (is_soc_or_above(jzpc, ID_JZ4740)) { ingenic_config_pin(jzpc, pin, JZ4740_GPIO_FUNC, true); ingenic_config_pin(jzpc, pin, JZ4740_GPIO_TRIG, func & 0x2); ingenic_config_pin(jzpc, pin, JZ4740_GPIO_SELECT, func & 0x1); @@ -3738,16 +3762,16 @@ static int ingenic_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev, dev_dbg(pctldev->dev, "set pin P%c%u to %sput\n", 'A' + offt, idx, input ? "in" : "out"); - if (jzpc->info->version >= ID_X1000) { + if (is_soc_or_above(jzpc, ID_X1000)) { ingenic_shadow_config_pin(jzpc, pin, JZ4770_GPIO_INT, false); ingenic_shadow_config_pin(jzpc, pin, GPIO_MSK, true); ingenic_shadow_config_pin(jzpc, pin, JZ4770_GPIO_PAT1, input); ingenic_shadow_config_pin_load(jzpc, pin); - } else if (jzpc->info->version >= ID_JZ4770) { + } else if (is_soc_or_above(jzpc, ID_JZ4770)) { ingenic_config_pin(jzpc, pin, JZ4770_GPIO_INT, false); ingenic_config_pin(jzpc, pin, GPIO_MSK, true); ingenic_config_pin(jzpc, pin, JZ4770_GPIO_PAT1, input); - } else if (jzpc->info->version >= ID_JZ4740) { + } else if (is_soc_or_above(jzpc, ID_JZ4740)) { ingenic_config_pin(jzpc, pin, JZ4740_GPIO_SELECT, false); ingenic_config_pin(jzpc, pin, JZ4740_GPIO_DIR, !input); ingenic_config_pin(jzpc, pin, JZ4740_GPIO_FUNC, false); @@ -3779,7 +3803,7 @@ static int ingenic_pinconf_get(struct pinctrl_dev *pctldev, unsigned int bias, reg; bool pull, pullup, pulldown; - if (jzpc->info->version >= ID_X2000) { + if (is_soc_or_above(jzpc, ID_X2000)) { pullup = ingenic_get_pin_config(jzpc, pin, X2000_GPIO_PEPU) && !ingenic_get_pin_config(jzpc, pin, X2000_GPIO_PEPD) && (jzpc->info->pull_ups[offt] & BIT(idx)); @@ -3787,7 +3811,7 @@ static int ingenic_pinconf_get(struct pinctrl_dev *pctldev, !ingenic_get_pin_config(jzpc, pin, X2000_GPIO_PEPU) && (jzpc->info->pull_downs[offt] & BIT(idx)); - } else if (jzpc->info->version >= ID_X1830) { + } else if (is_soc_or_above(jzpc, ID_X1830)) { unsigned int half = PINS_PER_GPIO_CHIP / 2; unsigned int idxh = (pin % half) * 2; @@ -3804,9 +3828,9 @@ static int ingenic_pinconf_get(struct pinctrl_dev *pctldev, pulldown = (bias == GPIO_PULL_DOWN) && (jzpc->info->pull_downs[offt] & BIT(idx)); } else { - if (jzpc->info->version >= ID_JZ4770) + if (is_soc_or_above(jzpc, ID_JZ4770)) pull = !ingenic_get_pin_config(jzpc, pin, JZ4770_GPIO_PEN); - else if (jzpc->info->version >= ID_JZ4740) + else if (is_soc_or_above(jzpc, ID_JZ4740)) pull = !ingenic_get_pin_config(jzpc, pin, JZ4740_GPIO_PULL_DIS); else pull = ingenic_get_pin_config(jzpc, pin, JZ4730_GPIO_GPPUR); @@ -3835,9 +3859,9 @@ static int ingenic_pinconf_get(struct pinctrl_dev *pctldev, break; case PIN_CONFIG_INPUT_SCHMITT_ENABLE: - if (jzpc->info->version >= ID_X2000) + if (is_soc_or_above(jzpc, ID_X2000)) reg = X2000_GPIO_SMT; - else if (jzpc->info->version >= ID_X1830) + else if (is_soc_or_above(jzpc, ID_X1830)) reg = X1830_GPIO_SMT; else return -EINVAL; @@ -3846,9 +3870,9 @@ static int ingenic_pinconf_get(struct pinctrl_dev *pctldev, break; case PIN_CONFIG_SLEW_RATE: - if (jzpc->info->version >= ID_X2000) + if (is_soc_or_above(jzpc, ID_X2000)) reg = X2000_GPIO_SR; - else if (jzpc->info->version >= ID_X1830) + else if (is_soc_or_above(jzpc, ID_X1830)) reg = X1830_GPIO_SR; else return -EINVAL; @@ -3867,7 +3891,7 @@ static int ingenic_pinconf_get(struct pinctrl_dev *pctldev, static void ingenic_set_bias(struct ingenic_pinctrl *jzpc, unsigned int pin, unsigned int bias) { - if (jzpc->info->version >= ID_X2000) { + if (is_soc_or_above(jzpc, ID_X2000)) { switch (bias) { case GPIO_PULL_UP: ingenic_config_pin(jzpc, pin, X2000_GPIO_PEPD, false); @@ -3885,7 +3909,7 @@ static void ingenic_set_bias(struct ingenic_pinctrl *jzpc, ingenic_config_pin(jzpc, pin, X2000_GPIO_PEPD, false); } - } else if (jzpc->info->version >= ID_X1830) { + } else if (is_soc_or_above(jzpc, ID_X1830)) { unsigned int idx = pin % PINS_PER_GPIO_CHIP; unsigned int half = PINS_PER_GPIO_CHIP / 2; unsigned int idxh = (pin % half) * 2; @@ -3903,9 +3927,9 @@ static void ingenic_set_bias(struct ingenic_pinctrl *jzpc, REG_SET(X1830_GPIO_PEH), bias << idxh); } - } else if (jzpc->info->version >= ID_JZ4770) { + } else if (is_soc_or_above(jzpc, ID_JZ4770)) { ingenic_config_pin(jzpc, pin, JZ4770_GPIO_PEN, !bias); - } else if (jzpc->info->version >= ID_JZ4740) { + } else if (is_soc_or_above(jzpc, ID_JZ4740)) { ingenic_config_pin(jzpc, pin, JZ4740_GPIO_PULL_DIS, !bias); } else { ingenic_config_pin(jzpc, pin, JZ4730_GPIO_GPPUR, bias); @@ -3915,7 +3939,7 @@ static void ingenic_set_bias(struct ingenic_pinctrl *jzpc, static void ingenic_set_schmitt_trigger(struct ingenic_pinctrl *jzpc, unsigned int pin, bool enable) { - if (jzpc->info->version >= ID_X2000) + if (is_soc_or_above(jzpc, ID_X2000)) ingenic_config_pin(jzpc, pin, X2000_GPIO_SMT, enable); else ingenic_config_pin(jzpc, pin, X1830_GPIO_SMT, enable); @@ -3924,9 +3948,9 @@ static void ingenic_set_schmitt_trigger(struct ingenic_pinctrl *jzpc, static void ingenic_set_output_level(struct ingenic_pinctrl *jzpc, unsigned int pin, bool high) { - if (jzpc->info->version >= ID_JZ4770) + if (is_soc_or_above(jzpc, ID_JZ4770)) ingenic_config_pin(jzpc, pin, JZ4770_GPIO_PAT0, high); - else if (jzpc->info->version >= ID_JZ4740) + else if (is_soc_or_above(jzpc, ID_JZ4740)) ingenic_config_pin(jzpc, pin, JZ4740_GPIO_DATA, high); else ingenic_config_pin(jzpc, pin, JZ4730_GPIO_DATA, high); @@ -3935,7 +3959,7 @@ static void ingenic_set_output_level(struct ingenic_pinctrl *jzpc, static void ingenic_set_slew_rate(struct ingenic_pinctrl *jzpc, unsigned int pin, unsigned int slew) { - if (jzpc->info->version >= ID_X2000) + if (is_soc_or_above(jzpc, ID_X2000)) ingenic_config_pin(jzpc, pin, X2000_GPIO_SR, slew); else ingenic_config_pin(jzpc, pin, X1830_GPIO_SR, slew); @@ -3991,7 +4015,7 @@ static int ingenic_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, break; case PIN_CONFIG_INPUT_SCHMITT_ENABLE: - if (jzpc->info->version < ID_X1830) + if (!is_soc_or_above(jzpc, ID_X1830)) return -EINVAL; ingenic_set_schmitt_trigger(jzpc, pin, arg); @@ -4006,7 +4030,7 @@ static int ingenic_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, break; case PIN_CONFIG_SLEW_RATE: - if (jzpc->info->version < ID_X1830) + if (!is_soc_or_above(jzpc, ID_X1830)) return -EINVAL; ingenic_set_slew_rate(jzpc, pin, arg); diff --git a/drivers/pinctrl/pinctrl-max77620.c b/drivers/pinctrl/pinctrl-max77620.c index 1ee94574f0afac6f79b0429442af7df551e260b6..ab723ab4ec1d5d949d0cedb56ccaf35f8972d449 100644 --- a/drivers/pinctrl/pinctrl-max77620.c +++ b/drivers/pinctrl/pinctrl-max77620.c @@ -668,5 +668,4 @@ module_platform_driver(max77620_pinctrl_driver); MODULE_DESCRIPTION("MAX77620/MAX20024 pin control driver"); MODULE_AUTHOR("Chaitanya Bandi"); MODULE_AUTHOR("Laxman Dewangan"); -MODULE_ALIAS("platform:max77620-pinctrl"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/pinctrl/pinctrl-microchip-sgpio.c b/drivers/pinctrl/pinctrl-microchip-sgpio.c index 80a8939ad0c00b978ecc9aac17e0bf3304fd425f..6f55bf7d5e054d73b4cbe19b95868caac57e9808 100644 --- a/drivers/pinctrl/pinctrl-microchip-sgpio.c +++ b/drivers/pinctrl/pinctrl-microchip-sgpio.c @@ -688,11 +688,17 @@ static void microchip_sgpio_irq_setreg(struct irq_data *data, static void microchip_sgpio_irq_mask(struct irq_data *data) { + struct gpio_chip *chip = irq_data_get_irq_chip_data(data); + microchip_sgpio_irq_setreg(data, REG_INT_ENABLE, true); + gpiochip_disable_irq(chip, data->hwirq); } static void microchip_sgpio_irq_unmask(struct irq_data *data) { + struct gpio_chip *chip = irq_data_get_irq_chip_data(data); + + gpiochip_enable_irq(chip, data->hwirq); microchip_sgpio_irq_setreg(data, REG_INT_ENABLE, false); } @@ -746,6 +752,8 @@ static const struct irq_chip microchip_sgpio_irqchip = { .irq_ack = microchip_sgpio_irq_ack, .irq_unmask = microchip_sgpio_irq_unmask, .irq_set_type = microchip_sgpio_irq_set_type, + .flags = IRQCHIP_IMMUTABLE, + GPIOCHIP_IRQ_RESOURCE_HELPERS, }; static void sgpio_irq_handler(struct irq_desc *desc) @@ -840,7 +848,7 @@ static int microchip_sgpio_register_bank(struct device *dev, gc = &bank->gpio; gc->label = pctl_desc->name; gc->parent = dev; - gc->of_node = to_of_node(fwnode); + gc->fwnode = fwnode; gc->owner = THIS_MODULE; gc->get_direction = microchip_sgpio_get_direction; gc->direction_input = microchip_sgpio_direction_input; @@ -861,11 +869,7 @@ static int microchip_sgpio_register_bank(struct device *dev, if (irq) { struct gpio_irq_chip *girq = &gc->irq; - girq->chip = devm_kmemdup(dev, µchip_sgpio_irqchip, - sizeof(microchip_sgpio_irqchip), - GFP_KERNEL); - if (!girq->chip) - return -ENOMEM; + gpio_irq_chip_set_chip(girq, µchip_sgpio_irqchip); girq->parent_handler = sgpio_irq_handler; girq->num_parents = 1; girq->parents = devm_kcalloc(dev, 1, diff --git a/drivers/pinctrl/pinctrl-ocelot.c b/drivers/pinctrl/pinctrl-ocelot.c index 6a956ee94494f50696fca8fb0b3d981b1b1dfb98..5f4a8c5c66508ac6bf96789403e7dd1f061a2cf3 100644 --- a/drivers/pinctrl/pinctrl-ocelot.c +++ b/drivers/pinctrl/pinctrl-ocelot.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include "core.h" @@ -60,6 +61,7 @@ enum { FUNC_CAN0_a, FUNC_CAN0_b, FUNC_CAN1, + FUNC_CLKMON, FUNC_NONE, FUNC_FC0_a, FUNC_FC0_b, @@ -138,6 +140,8 @@ enum { FUNC_PTPSYNC_6, FUNC_PTPSYNC_7, FUNC_PWM, + FUNC_PWM_a, + FUNC_PWM_b, FUNC_QSPI1, FUNC_QSPI2, FUNC_R, @@ -184,6 +188,7 @@ static const char *const ocelot_function_names[] = { [FUNC_CAN0_a] = "can0_a", [FUNC_CAN0_b] = "can0_b", [FUNC_CAN1] = "can1", + [FUNC_CLKMON] = "clkmon", [FUNC_NONE] = "none", [FUNC_FC0_a] = "fc0_a", [FUNC_FC0_b] = "fc0_b", @@ -262,6 +267,8 @@ static const char *const ocelot_function_names[] = { [FUNC_PTPSYNC_6] = "ptpsync_6", [FUNC_PTPSYNC_7] = "ptpsync_7", [FUNC_PWM] = "pwm", + [FUNC_PWM_a] = "pwm_a", + [FUNC_PWM_b] = "pwm_b", [FUNC_QSPI1] = "qspi1", [FUNC_QSPI2] = "qspi2", [FUNC_R] = "reserved", @@ -977,11 +984,11 @@ LAN966X_P(23, GPIO, NONE, NONE, NONE, OB_TRG_a, NONE, NON LAN966X_P(24, GPIO, FC0_b, IB_TRG_a, USB_H_c, OB_TRG_a, IRQ_IN_c, TACHO_a, R); LAN966X_P(25, GPIO, FC0_b, IB_TRG_a, USB_H_c, OB_TRG_a, IRQ_OUT_c, SFP_SD, R); LAN966X_P(26, GPIO, FC0_b, IB_TRG_a, USB_S_c, OB_TRG_a, CAN0_a, SFP_SD, R); -LAN966X_P(27, GPIO, NONE, NONE, NONE, OB_TRG_a, CAN0_a, NONE, R); +LAN966X_P(27, GPIO, NONE, NONE, NONE, OB_TRG_a, CAN0_a, PWM_a, R); LAN966X_P(28, GPIO, MIIM_a, NONE, NONE, OB_TRG_a, IRQ_OUT_c, SFP_SD, R); LAN966X_P(29, GPIO, MIIM_a, NONE, NONE, OB_TRG_a, NONE, NONE, R); -LAN966X_P(30, GPIO, FC3_c, CAN1, NONE, OB_TRG, RECO_b, NONE, R); -LAN966X_P(31, GPIO, FC3_c, CAN1, NONE, OB_TRG, RECO_b, NONE, R); +LAN966X_P(30, GPIO, FC3_c, CAN1, CLKMON, OB_TRG, RECO_b, NONE, R); +LAN966X_P(31, GPIO, FC3_c, CAN1, CLKMON, OB_TRG, RECO_b, NONE, R); LAN966X_P(32, GPIO, FC3_c, NONE, SGPIO_a, NONE, MIIM_Sa, NONE, R); LAN966X_P(33, GPIO, FC1_b, NONE, SGPIO_a, NONE, MIIM_Sa, MIIM_b, R); LAN966X_P(34, GPIO, FC1_b, NONE, SGPIO_a, NONE, MIIM_Sa, MIIM_b, R); @@ -1001,7 +1008,7 @@ LAN966X_P(47, GPIO, FC1_c, OB_TRG_b, IB_TRG_b, IRQ_OUT_a, FC_SHRD5, IRQ_IN LAN966X_P(48, GPIO, FC1_c, OB_TRG_b, IB_TRG_b, IRQ_OUT_a, FC_SHRD6, IRQ_IN_a, R); LAN966X_P(49, GPIO, FC_SHRD7, OB_TRG_b, IB_TRG_b, IRQ_OUT_a, TWI_SLC_GATE, IRQ_IN_a, R); LAN966X_P(50, GPIO, FC_SHRD16, OB_TRG_b, IB_TRG_b, IRQ_OUT_a, TWI_SLC_GATE, NONE, R); -LAN966X_P(51, GPIO, FC3_b, OB_TRG_b, IB_TRG_c, IRQ_OUT_b, NONE, IRQ_IN_b, R); +LAN966X_P(51, GPIO, FC3_b, OB_TRG_b, IB_TRG_c, IRQ_OUT_b, PWM_b, IRQ_IN_b, R); LAN966X_P(52, GPIO, FC3_b, OB_TRG_b, IB_TRG_c, IRQ_OUT_b, TACHO_b, IRQ_IN_b, R); LAN966X_P(53, GPIO, FC3_b, OB_TRG_b, IB_TRG_c, IRQ_OUT_b, NONE, IRQ_IN_b, R); LAN966X_P(54, GPIO, FC_SHRD8, OB_TRG_b, IB_TRG_c, IRQ_OUT_b, TWI_SLC_GATE, IRQ_IN_b, R); @@ -1908,6 +1915,7 @@ static int ocelot_pinctrl_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct ocelot_pinctrl *info; + struct reset_control *reset; struct regmap *pincfg; void __iomem *base; int ret; @@ -1923,6 +1931,12 @@ static int ocelot_pinctrl_probe(struct platform_device *pdev) info->desc = (struct pinctrl_desc *)device_get_match_data(dev); + reset = devm_reset_control_get_optional_shared(dev, "switch"); + if (IS_ERR(reset)) + return dev_err_probe(dev, PTR_ERR(reset), + "Failed to get reset\n"); + reset_control_reset(reset); + base = devm_ioremap_resource(dev, platform_get_resource(pdev, IORESOURCE_MEM, 0)); if (IS_ERR(base)) diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c index 2cb79e649fcf31e96be5d6d99fd20ec43e7fc512..32e41395fc76875dd551acaef2442385c9297a08 100644 --- a/drivers/pinctrl/pinctrl-rockchip.c +++ b/drivers/pinctrl/pinctrl-rockchip.c @@ -103,6 +103,25 @@ }, \ } +#define PIN_BANK_IOMUX_FLAGS_PULL_FLAGS(id, pins, label, iom0, iom1, \ + iom2, iom3, pull0, pull1, \ + pull2, pull3) \ + { \ + .bank_num = id, \ + .nr_pins = pins, \ + .name = label, \ + .iomux = { \ + { .type = iom0, .offset = -1 }, \ + { .type = iom1, .offset = -1 }, \ + { .type = iom2, .offset = -1 }, \ + { .type = iom3, .offset = -1 }, \ + }, \ + .pull_type[0] = pull0, \ + .pull_type[1] = pull1, \ + .pull_type[2] = pull2, \ + .pull_type[3] = pull3, \ + } + #define PIN_BANK_DRV_FLAGS_PULL_FLAGS(id, pins, label, drv0, drv1, \ drv2, drv3, pull0, pull1, \ pull2, pull3) \ @@ -197,6 +216,9 @@ #define RK_MUXROUTE_PMU(ID, PIN, FUNC, REG, VAL) \ PIN_BANK_MUX_ROUTE_FLAGS(ID, PIN, FUNC, REG, VAL, ROCKCHIP_ROUTE_PMU) +#define RK3588_PIN_BANK_FLAGS(ID, PIN, LABEL, M, P) \ + PIN_BANK_IOMUX_FLAGS_PULL_FLAGS(ID, PIN, LABEL, M, M, M, M, P, P, P, P) + static struct regmap_config rockchip_regmap_config = { .reg_bits = 32, .val_bits = 32, @@ -837,6 +859,7 @@ static bool rockchip_get_mux_route(struct rockchip_pin_bank *bank, int pin, static int rockchip_get_mux(struct rockchip_pin_bank *bank, int pin) { struct rockchip_pinctrl *info = bank->drvdata; + struct rockchip_pin_ctrl *ctrl = info->ctrl; int iomux_num = (pin / 8); struct regmap *regmap; unsigned int val; @@ -878,6 +901,27 @@ static int rockchip_get_mux(struct rockchip_pin_bank *bank, int pin) if (bank->recalced_mask & BIT(pin)) rockchip_get_recalced_mux(bank, pin, ®, &bit, &mask); + if (ctrl->type == RK3588) { + if (bank->bank_num == 0) { + if ((pin >= RK_PB4) && (pin <= RK_PD7)) { + u32 reg0 = 0; + + reg0 = reg + 0x4000 - 0xC; /* PMU2_IOC_BASE */ + ret = regmap_read(regmap, reg0, &val); + if (ret) + return ret; + + if (!(val & BIT(8))) + return ((val >> bit) & mask); + + reg = reg + 0x8000; /* BUS_IOC_BASE */ + regmap = info->regmap_base; + } + } else if (bank->bank_num > 0) { + reg += 0x8000; /* BUS_IOC_BASE */ + } + } + ret = regmap_read(regmap, reg, &val); if (ret) return ret; @@ -926,6 +970,7 @@ static int rockchip_verify_mux(struct rockchip_pin_bank *bank, static int rockchip_set_mux(struct rockchip_pin_bank *bank, int pin, int mux) { struct rockchip_pinctrl *info = bank->drvdata; + struct rockchip_pin_ctrl *ctrl = info->ctrl; struct device *dev = info->dev; int iomux_num = (pin / 8); struct regmap *regmap; @@ -966,6 +1011,46 @@ static int rockchip_set_mux(struct rockchip_pin_bank *bank, int pin, int mux) if (bank->recalced_mask & BIT(pin)) rockchip_get_recalced_mux(bank, pin, ®, &bit, &mask); + if (ctrl->type == RK3588) { + if (bank->bank_num == 0) { + if ((pin >= RK_PB4) && (pin <= RK_PD7)) { + if (mux < 8) { + reg += 0x4000 - 0xC; /* PMU2_IOC_BASE */ + data = (mask << (bit + 16)); + rmask = data | (data >> 16); + data |= (mux & mask) << bit; + ret = regmap_update_bits(regmap, reg, rmask, data); + } else { + u32 reg0 = 0; + + reg0 = reg + 0x4000 - 0xC; /* PMU2_IOC_BASE */ + data = (mask << (bit + 16)); + rmask = data | (data >> 16); + data |= 8 << bit; + ret = regmap_update_bits(regmap, reg0, rmask, data); + + reg0 = reg + 0x8000; /* BUS_IOC_BASE */ + data = (mask << (bit + 16)); + rmask = data | (data >> 16); + data |= mux << bit; + regmap = info->regmap_base; + ret |= regmap_update_bits(regmap, reg0, rmask, data); + } + } else { + data = (mask << (bit + 16)); + rmask = data | (data >> 16); + data |= (mux & mask) << bit; + ret = regmap_update_bits(regmap, reg, rmask, data); + } + return ret; + } else if (bank->bank_num > 0) { + reg += 0x8000; /* BUS_IOC_BASE */ + } + } + + if (mux > mask) + return -EINVAL; + if (bank->route_mask & BIT(pin)) { if (rockchip_get_mux_route(bank, pin, mux, &route_location, &route_reg, &route_val)) { @@ -1001,9 +1086,9 @@ static int rockchip_set_mux(struct rockchip_pin_bank *bank, int pin, int mux) #define PX30_PULL_PINS_PER_REG 8 #define PX30_PULL_BANK_STRIDE 16 -static void px30_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, - int pin_num, struct regmap **regmap, - int *reg, u8 *bit) +static int px30_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, + int pin_num, struct regmap **regmap, + int *reg, u8 *bit) { struct rockchip_pinctrl *info = bank->drvdata; @@ -1023,6 +1108,8 @@ static void px30_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, *reg += ((pin_num / PX30_PULL_PINS_PER_REG) * 4); *bit = (pin_num % PX30_PULL_PINS_PER_REG); *bit *= PX30_PULL_BITS_PER_PIN; + + return 0; } #define PX30_DRV_PMU_OFFSET 0x20 @@ -1031,9 +1118,9 @@ static void px30_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, #define PX30_DRV_PINS_PER_REG 8 #define PX30_DRV_BANK_STRIDE 16 -static void px30_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, - int pin_num, struct regmap **regmap, - int *reg, u8 *bit) +static int px30_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, + int pin_num, struct regmap **regmap, + int *reg, u8 *bit) { struct rockchip_pinctrl *info = bank->drvdata; @@ -1053,6 +1140,8 @@ static void px30_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, *reg += ((pin_num / PX30_DRV_PINS_PER_REG) * 4); *bit = (pin_num % PX30_DRV_PINS_PER_REG); *bit *= PX30_DRV_BITS_PER_PIN; + + return 0; } #define PX30_SCHMITT_PMU_OFFSET 0x38 @@ -1092,9 +1181,9 @@ static int px30_calc_schmitt_reg_and_bit(struct rockchip_pin_bank *bank, #define RV1108_PULL_BITS_PER_PIN 2 #define RV1108_PULL_BANK_STRIDE 16 -static void rv1108_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, - int pin_num, struct regmap **regmap, - int *reg, u8 *bit) +static int rv1108_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, + int pin_num, struct regmap **regmap, + int *reg, u8 *bit) { struct rockchip_pinctrl *info = bank->drvdata; @@ -1113,6 +1202,8 @@ static void rv1108_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, *reg += ((pin_num / RV1108_PULL_PINS_PER_REG) * 4); *bit = (pin_num % RV1108_PULL_PINS_PER_REG); *bit *= RV1108_PULL_BITS_PER_PIN; + + return 0; } #define RV1108_DRV_PMU_OFFSET 0x20 @@ -1121,9 +1212,9 @@ static void rv1108_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, #define RV1108_DRV_PINS_PER_REG 8 #define RV1108_DRV_BANK_STRIDE 16 -static void rv1108_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, - int pin_num, struct regmap **regmap, - int *reg, u8 *bit) +static int rv1108_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, + int pin_num, struct regmap **regmap, + int *reg, u8 *bit) { struct rockchip_pinctrl *info = bank->drvdata; @@ -1143,6 +1234,8 @@ static void rv1108_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, *reg += ((pin_num / RV1108_DRV_PINS_PER_REG) * 4); *bit = pin_num % RV1108_DRV_PINS_PER_REG; *bit *= RV1108_DRV_BITS_PER_PIN; + + return 0; } #define RV1108_SCHMITT_PMU_OFFSET 0x30 @@ -1199,9 +1292,9 @@ static int rk3308_calc_schmitt_reg_and_bit(struct rockchip_pin_bank *bank, #define RK2928_PULL_PINS_PER_REG 16 #define RK2928_PULL_BANK_STRIDE 8 -static void rk2928_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, - int pin_num, struct regmap **regmap, - int *reg, u8 *bit) +static int rk2928_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, + int pin_num, struct regmap **regmap, + int *reg, u8 *bit) { struct rockchip_pinctrl *info = bank->drvdata; @@ -1211,13 +1304,15 @@ static void rk2928_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, *reg += (pin_num / RK2928_PULL_PINS_PER_REG) * 4; *bit = pin_num % RK2928_PULL_PINS_PER_REG; + + return 0; }; #define RK3128_PULL_OFFSET 0x118 -static void rk3128_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, - int pin_num, struct regmap **regmap, - int *reg, u8 *bit) +static int rk3128_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, + int pin_num, struct regmap **regmap, + int *reg, u8 *bit) { struct rockchip_pinctrl *info = bank->drvdata; @@ -1227,6 +1322,8 @@ static void rk3128_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, *reg += ((pin_num / RK2928_PULL_PINS_PER_REG) * 4); *bit = pin_num % RK2928_PULL_PINS_PER_REG; + + return 0; } #define RK3188_PULL_OFFSET 0x164 @@ -1235,9 +1332,9 @@ static void rk3128_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, #define RK3188_PULL_BANK_STRIDE 16 #define RK3188_PULL_PMU_OFFSET 0x64 -static void rk3188_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, - int pin_num, struct regmap **regmap, - int *reg, u8 *bit) +static int rk3188_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, + int pin_num, struct regmap **regmap, + int *reg, u8 *bit) { struct rockchip_pinctrl *info = bank->drvdata; @@ -1267,12 +1364,14 @@ static void rk3188_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, *bit = 7 - (pin_num % RK3188_PULL_PINS_PER_REG); *bit *= RK3188_PULL_BITS_PER_PIN; } + + return 0; } #define RK3288_PULL_OFFSET 0x140 -static void rk3288_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, - int pin_num, struct regmap **regmap, - int *reg, u8 *bit) +static int rk3288_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, + int pin_num, struct regmap **regmap, + int *reg, u8 *bit) { struct rockchip_pinctrl *info = bank->drvdata; @@ -1296,6 +1395,8 @@ static void rk3288_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, *bit = (pin_num % RK3188_PULL_PINS_PER_REG); *bit *= RK3188_PULL_BITS_PER_PIN; } + + return 0; } #define RK3288_DRV_PMU_OFFSET 0x70 @@ -1304,9 +1405,9 @@ static void rk3288_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, #define RK3288_DRV_PINS_PER_REG 8 #define RK3288_DRV_BANK_STRIDE 16 -static void rk3288_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, - int pin_num, struct regmap **regmap, - int *reg, u8 *bit) +static int rk3288_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, + int pin_num, struct regmap **regmap, + int *reg, u8 *bit) { struct rockchip_pinctrl *info = bank->drvdata; @@ -1330,13 +1431,15 @@ static void rk3288_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, *bit = (pin_num % RK3288_DRV_PINS_PER_REG); *bit *= RK3288_DRV_BITS_PER_PIN; } + + return 0; } #define RK3228_PULL_OFFSET 0x100 -static void rk3228_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, - int pin_num, struct regmap **regmap, - int *reg, u8 *bit) +static int rk3228_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, + int pin_num, struct regmap **regmap, + int *reg, u8 *bit) { struct rockchip_pinctrl *info = bank->drvdata; @@ -1347,13 +1450,15 @@ static void rk3228_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, *bit = (pin_num % RK3188_PULL_PINS_PER_REG); *bit *= RK3188_PULL_BITS_PER_PIN; + + return 0; } #define RK3228_DRV_GRF_OFFSET 0x200 -static void rk3228_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, - int pin_num, struct regmap **regmap, - int *reg, u8 *bit) +static int rk3228_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, + int pin_num, struct regmap **regmap, + int *reg, u8 *bit) { struct rockchip_pinctrl *info = bank->drvdata; @@ -1364,13 +1469,15 @@ static void rk3228_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, *bit = (pin_num % RK3288_DRV_PINS_PER_REG); *bit *= RK3288_DRV_BITS_PER_PIN; + + return 0; } #define RK3308_PULL_OFFSET 0xa0 -static void rk3308_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, - int pin_num, struct regmap **regmap, - int *reg, u8 *bit) +static int rk3308_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, + int pin_num, struct regmap **regmap, + int *reg, u8 *bit) { struct rockchip_pinctrl *info = bank->drvdata; @@ -1381,13 +1488,15 @@ static void rk3308_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, *bit = (pin_num % RK3188_PULL_PINS_PER_REG); *bit *= RK3188_PULL_BITS_PER_PIN; + + return 0; } #define RK3308_DRV_GRF_OFFSET 0x100 -static void rk3308_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, - int pin_num, struct regmap **regmap, - int *reg, u8 *bit) +static int rk3308_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, + int pin_num, struct regmap **regmap, + int *reg, u8 *bit) { struct rockchip_pinctrl *info = bank->drvdata; @@ -1398,14 +1507,16 @@ static void rk3308_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, *bit = (pin_num % RK3288_DRV_PINS_PER_REG); *bit *= RK3288_DRV_BITS_PER_PIN; + + return 0; } #define RK3368_PULL_GRF_OFFSET 0x100 #define RK3368_PULL_PMU_OFFSET 0x10 -static void rk3368_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, - int pin_num, struct regmap **regmap, - int *reg, u8 *bit) +static int rk3368_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, + int pin_num, struct regmap **regmap, + int *reg, u8 *bit) { struct rockchip_pinctrl *info = bank->drvdata; @@ -1429,14 +1540,16 @@ static void rk3368_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, *bit = (pin_num % RK3188_PULL_PINS_PER_REG); *bit *= RK3188_PULL_BITS_PER_PIN; } + + return 0; } #define RK3368_DRV_PMU_OFFSET 0x20 #define RK3368_DRV_GRF_OFFSET 0x200 -static void rk3368_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, - int pin_num, struct regmap **regmap, - int *reg, u8 *bit) +static int rk3368_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, + int pin_num, struct regmap **regmap, + int *reg, u8 *bit) { struct rockchip_pinctrl *info = bank->drvdata; @@ -1460,15 +1573,17 @@ static void rk3368_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, *bit = (pin_num % RK3288_DRV_PINS_PER_REG); *bit *= RK3288_DRV_BITS_PER_PIN; } + + return 0; } #define RK3399_PULL_GRF_OFFSET 0xe040 #define RK3399_PULL_PMU_OFFSET 0x40 #define RK3399_DRV_3BITS_PER_PIN 3 -static void rk3399_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, - int pin_num, struct regmap **regmap, - int *reg, u8 *bit) +static int rk3399_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, + int pin_num, struct regmap **regmap, + int *reg, u8 *bit) { struct rockchip_pinctrl *info = bank->drvdata; @@ -1494,11 +1609,13 @@ static void rk3399_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, *bit = (pin_num % RK3188_PULL_PINS_PER_REG); *bit *= RK3188_PULL_BITS_PER_PIN; } + + return 0; } -static void rk3399_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, - int pin_num, struct regmap **regmap, - int *reg, u8 *bit) +static int rk3399_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, + int pin_num, struct regmap **regmap, + int *reg, u8 *bit) { struct rockchip_pinctrl *info = bank->drvdata; int drv_num = (pin_num / 8); @@ -1515,6 +1632,8 @@ static void rk3399_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, *bit = (pin_num % 8) * 3; else *bit = (pin_num % 8) * 2; + + return 0; } #define RK3568_PULL_PMU_OFFSET 0x20 @@ -1523,9 +1642,9 @@ static void rk3399_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, #define RK3568_PULL_PINS_PER_REG 8 #define RK3568_PULL_BANK_STRIDE 0x10 -static void rk3568_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, - int pin_num, struct regmap **regmap, - int *reg, u8 *bit) +static int rk3568_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, + int pin_num, struct regmap **regmap, + int *reg, u8 *bit) { struct rockchip_pinctrl *info = bank->drvdata; @@ -1546,6 +1665,8 @@ static void rk3568_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, *bit = (pin_num % RK3568_PULL_PINS_PER_REG); *bit *= RK3568_PULL_BITS_PER_PIN; } + + return 0; } #define RK3568_DRV_PMU_OFFSET 0x70 @@ -1554,9 +1675,9 @@ static void rk3568_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, #define RK3568_DRV_PINS_PER_REG 2 #define RK3568_DRV_BANK_STRIDE 0x40 -static void rk3568_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, - int pin_num, struct regmap **regmap, - int *reg, u8 *bit) +static int rk3568_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, + int pin_num, struct regmap **regmap, + int *reg, u8 *bit) { struct rockchip_pinctrl *info = bank->drvdata; @@ -1577,6 +1698,189 @@ static void rk3568_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, *bit = (pin_num % RK3568_DRV_PINS_PER_REG); *bit *= RK3568_DRV_BITS_PER_PIN; } + + return 0; +} + +#define RK3588_PMU1_IOC_REG (0x0000) +#define RK3588_PMU2_IOC_REG (0x4000) +#define RK3588_BUS_IOC_REG (0x8000) +#define RK3588_VCCIO1_4_IOC_REG (0x9000) +#define RK3588_VCCIO3_5_IOC_REG (0xA000) +#define RK3588_VCCIO2_IOC_REG (0xB000) +#define RK3588_VCCIO6_IOC_REG (0xC000) +#define RK3588_EMMC_IOC_REG (0xD000) + +static const u32 rk3588_ds_regs[][2] = { + {RK_GPIO0_A0, RK3588_PMU1_IOC_REG + 0x0010}, + {RK_GPIO0_A4, RK3588_PMU1_IOC_REG + 0x0014}, + {RK_GPIO0_B0, RK3588_PMU1_IOC_REG + 0x0018}, + {RK_GPIO0_B4, RK3588_PMU2_IOC_REG + 0x0014}, + {RK_GPIO0_C0, RK3588_PMU2_IOC_REG + 0x0018}, + {RK_GPIO0_C4, RK3588_PMU2_IOC_REG + 0x001C}, + {RK_GPIO0_D0, RK3588_PMU2_IOC_REG + 0x0020}, + {RK_GPIO0_D4, RK3588_PMU2_IOC_REG + 0x0024}, + {RK_GPIO1_A0, RK3588_VCCIO1_4_IOC_REG + 0x0020}, + {RK_GPIO1_A4, RK3588_VCCIO1_4_IOC_REG + 0x0024}, + {RK_GPIO1_B0, RK3588_VCCIO1_4_IOC_REG + 0x0028}, + {RK_GPIO1_B4, RK3588_VCCIO1_4_IOC_REG + 0x002C}, + {RK_GPIO1_C0, RK3588_VCCIO1_4_IOC_REG + 0x0030}, + {RK_GPIO1_C4, RK3588_VCCIO1_4_IOC_REG + 0x0034}, + {RK_GPIO1_D0, RK3588_VCCIO1_4_IOC_REG + 0x0038}, + {RK_GPIO1_D4, RK3588_VCCIO1_4_IOC_REG + 0x003C}, + {RK_GPIO2_A0, RK3588_EMMC_IOC_REG + 0x0040}, + {RK_GPIO2_A4, RK3588_VCCIO3_5_IOC_REG + 0x0044}, + {RK_GPIO2_B0, RK3588_VCCIO3_5_IOC_REG + 0x0048}, + {RK_GPIO2_B4, RK3588_VCCIO3_5_IOC_REG + 0x004C}, + {RK_GPIO2_C0, RK3588_VCCIO3_5_IOC_REG + 0x0050}, + {RK_GPIO2_C4, RK3588_VCCIO3_5_IOC_REG + 0x0054}, + {RK_GPIO2_D0, RK3588_EMMC_IOC_REG + 0x0058}, + {RK_GPIO2_D4, RK3588_EMMC_IOC_REG + 0x005C}, + {RK_GPIO3_A0, RK3588_VCCIO3_5_IOC_REG + 0x0060}, + {RK_GPIO3_A4, RK3588_VCCIO3_5_IOC_REG + 0x0064}, + {RK_GPIO3_B0, RK3588_VCCIO3_5_IOC_REG + 0x0068}, + {RK_GPIO3_B4, RK3588_VCCIO3_5_IOC_REG + 0x006C}, + {RK_GPIO3_C0, RK3588_VCCIO3_5_IOC_REG + 0x0070}, + {RK_GPIO3_C4, RK3588_VCCIO3_5_IOC_REG + 0x0074}, + {RK_GPIO3_D0, RK3588_VCCIO3_5_IOC_REG + 0x0078}, + {RK_GPIO3_D4, RK3588_VCCIO3_5_IOC_REG + 0x007C}, + {RK_GPIO4_A0, RK3588_VCCIO6_IOC_REG + 0x0080}, + {RK_GPIO4_A4, RK3588_VCCIO6_IOC_REG + 0x0084}, + {RK_GPIO4_B0, RK3588_VCCIO6_IOC_REG + 0x0088}, + {RK_GPIO4_B4, RK3588_VCCIO6_IOC_REG + 0x008C}, + {RK_GPIO4_C0, RK3588_VCCIO6_IOC_REG + 0x0090}, + {RK_GPIO4_C2, RK3588_VCCIO3_5_IOC_REG + 0x0090}, + {RK_GPIO4_C4, RK3588_VCCIO3_5_IOC_REG + 0x0094}, + {RK_GPIO4_D0, RK3588_VCCIO2_IOC_REG + 0x0098}, + {RK_GPIO4_D4, RK3588_VCCIO2_IOC_REG + 0x009C}, +}; + +static const u32 rk3588_p_regs[][2] = { + {RK_GPIO0_A0, RK3588_PMU1_IOC_REG + 0x0020}, + {RK_GPIO0_B0, RK3588_PMU1_IOC_REG + 0x0024}, + {RK_GPIO0_B5, RK3588_PMU2_IOC_REG + 0x0028}, + {RK_GPIO0_C0, RK3588_PMU2_IOC_REG + 0x002C}, + {RK_GPIO0_D0, RK3588_PMU2_IOC_REG + 0x0030}, + {RK_GPIO1_A0, RK3588_VCCIO1_4_IOC_REG + 0x0110}, + {RK_GPIO1_B0, RK3588_VCCIO1_4_IOC_REG + 0x0114}, + {RK_GPIO1_C0, RK3588_VCCIO1_4_IOC_REG + 0x0118}, + {RK_GPIO1_D0, RK3588_VCCIO1_4_IOC_REG + 0x011C}, + {RK_GPIO2_A0, RK3588_EMMC_IOC_REG + 0x0120}, + {RK_GPIO2_A6, RK3588_VCCIO3_5_IOC_REG + 0x0120}, + {RK_GPIO2_B0, RK3588_VCCIO3_5_IOC_REG + 0x0124}, + {RK_GPIO2_C0, RK3588_VCCIO3_5_IOC_REG + 0x0128}, + {RK_GPIO2_D0, RK3588_EMMC_IOC_REG + 0x012C}, + {RK_GPIO3_A0, RK3588_VCCIO3_5_IOC_REG + 0x0130}, + {RK_GPIO3_B0, RK3588_VCCIO3_5_IOC_REG + 0x0134}, + {RK_GPIO3_C0, RK3588_VCCIO3_5_IOC_REG + 0x0138}, + {RK_GPIO3_D0, RK3588_VCCIO3_5_IOC_REG + 0x013C}, + {RK_GPIO4_A0, RK3588_VCCIO6_IOC_REG + 0x0140}, + {RK_GPIO4_B0, RK3588_VCCIO6_IOC_REG + 0x0144}, + {RK_GPIO4_C0, RK3588_VCCIO6_IOC_REG + 0x0148}, + {RK_GPIO4_C2, RK3588_VCCIO3_5_IOC_REG + 0x0148}, + {RK_GPIO4_D0, RK3588_VCCIO2_IOC_REG + 0x014C}, +}; + +static const u32 rk3588_smt_regs[][2] = { + {RK_GPIO0_A0, RK3588_PMU1_IOC_REG + 0x0030}, + {RK_GPIO0_B0, RK3588_PMU1_IOC_REG + 0x0034}, + {RK_GPIO0_B5, RK3588_PMU2_IOC_REG + 0x0040}, + {RK_GPIO0_C0, RK3588_PMU2_IOC_REG + 0x0044}, + {RK_GPIO0_D0, RK3588_PMU2_IOC_REG + 0x0048}, + {RK_GPIO1_A0, RK3588_VCCIO1_4_IOC_REG + 0x0210}, + {RK_GPIO1_B0, RK3588_VCCIO1_4_IOC_REG + 0x0214}, + {RK_GPIO1_C0, RK3588_VCCIO1_4_IOC_REG + 0x0218}, + {RK_GPIO1_D0, RK3588_VCCIO1_4_IOC_REG + 0x021C}, + {RK_GPIO2_A0, RK3588_EMMC_IOC_REG + 0x0220}, + {RK_GPIO2_A6, RK3588_VCCIO3_5_IOC_REG + 0x0220}, + {RK_GPIO2_B0, RK3588_VCCIO3_5_IOC_REG + 0x0224}, + {RK_GPIO2_C0, RK3588_VCCIO3_5_IOC_REG + 0x0228}, + {RK_GPIO2_D0, RK3588_EMMC_IOC_REG + 0x022C}, + {RK_GPIO3_A0, RK3588_VCCIO3_5_IOC_REG + 0x0230}, + {RK_GPIO3_B0, RK3588_VCCIO3_5_IOC_REG + 0x0234}, + {RK_GPIO3_C0, RK3588_VCCIO3_5_IOC_REG + 0x0238}, + {RK_GPIO3_D0, RK3588_VCCIO3_5_IOC_REG + 0x023C}, + {RK_GPIO4_A0, RK3588_VCCIO6_IOC_REG + 0x0240}, + {RK_GPIO4_B0, RK3588_VCCIO6_IOC_REG + 0x0244}, + {RK_GPIO4_C0, RK3588_VCCIO6_IOC_REG + 0x0248}, + {RK_GPIO4_C2, RK3588_VCCIO3_5_IOC_REG + 0x0248}, + {RK_GPIO4_D0, RK3588_VCCIO2_IOC_REG + 0x024C}, +}; + +#define RK3588_PULL_BITS_PER_PIN 2 +#define RK3588_PULL_PINS_PER_REG 8 + +static int rk3588_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, + int pin_num, struct regmap **regmap, + int *reg, u8 *bit) +{ + struct rockchip_pinctrl *info = bank->drvdata; + u8 bank_num = bank->bank_num; + u32 pin = bank_num * 32 + pin_num; + int i; + + for (i = ARRAY_SIZE(rk3588_p_regs) - 1; i >= 0; i--) { + if (pin >= rk3588_p_regs[i][0]) { + *reg = rk3588_p_regs[i][1]; + *regmap = info->regmap_base; + *bit = pin_num % RK3588_PULL_PINS_PER_REG; + *bit *= RK3588_PULL_BITS_PER_PIN; + return 0; + } + } + + return -EINVAL; +} + +#define RK3588_DRV_BITS_PER_PIN 4 +#define RK3588_DRV_PINS_PER_REG 4 + +static int rk3588_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, + int pin_num, struct regmap **regmap, + int *reg, u8 *bit) +{ + struct rockchip_pinctrl *info = bank->drvdata; + u8 bank_num = bank->bank_num; + u32 pin = bank_num * 32 + pin_num; + int i; + + for (i = ARRAY_SIZE(rk3588_ds_regs) - 1; i >= 0; i--) { + if (pin >= rk3588_ds_regs[i][0]) { + *reg = rk3588_ds_regs[i][1]; + *regmap = info->regmap_base; + *bit = pin_num % RK3588_DRV_PINS_PER_REG; + *bit *= RK3588_DRV_BITS_PER_PIN; + return 0; + } + } + + return -EINVAL; +} + +#define RK3588_SMT_BITS_PER_PIN 1 +#define RK3588_SMT_PINS_PER_REG 8 + +static int rk3588_calc_schmitt_reg_and_bit(struct rockchip_pin_bank *bank, + int pin_num, + struct regmap **regmap, + int *reg, u8 *bit) +{ + struct rockchip_pinctrl *info = bank->drvdata; + u8 bank_num = bank->bank_num; + u32 pin = bank_num * 32 + pin_num; + int i; + + for (i = ARRAY_SIZE(rk3588_smt_regs) - 1; i >= 0; i--) { + if (pin >= rk3588_smt_regs[i][0]) { + *reg = rk3588_smt_regs[i][1]; + *regmap = info->regmap_base; + *bit = pin_num % RK3588_SMT_PINS_PER_REG; + *bit *= RK3588_SMT_BITS_PER_PIN; + return 0; + } + } + + return -EINVAL; } static int rockchip_perpin_drv_list[DRV_TYPE_MAX][8] = { @@ -1599,7 +1903,9 @@ static int rockchip_get_drive_perpin(struct rockchip_pin_bank *bank, u8 bit; int drv_type = bank->drv[pin_num / 8].drv_type; - ctrl->drv_calc_reg(bank, pin_num, ®map, ®, &bit); + ret = ctrl->drv_calc_reg(bank, pin_num, ®map, ®, &bit); + if (ret) + return ret; switch (drv_type) { case DRV_TYPE_IO_1V8_3V0_AUTO: @@ -1679,8 +1985,14 @@ static int rockchip_set_drive_perpin(struct rockchip_pin_bank *bank, dev_dbg(dev, "setting drive of GPIO%d-%d to %d\n", bank->bank_num, pin_num, strength); - ctrl->drv_calc_reg(bank, pin_num, ®map, ®, &bit); - if (ctrl->type == RK3568) { + ret = ctrl->drv_calc_reg(bank, pin_num, ®map, ®, &bit); + if (ret) + return ret; + if (ctrl->type == RK3588) { + rmask_bits = RK3588_DRV_BITS_PER_PIN; + ret = strength; + goto config; + } else if (ctrl->type == RK3568) { rmask_bits = RK3568_DRV_BITS_PER_PIN; ret = (1 << (strength + 1)) - 1; goto config; @@ -1792,7 +2104,9 @@ static int rockchip_get_pull(struct rockchip_pin_bank *bank, int pin_num) if (ctrl->type == RK3066B) return PIN_CONFIG_BIAS_DISABLE; - ctrl->pull_calc_reg(bank, pin_num, ®map, ®, &bit); + ret = ctrl->pull_calc_reg(bank, pin_num, ®map, ®, &bit); + if (ret) + return ret; ret = regmap_read(regmap, reg, &data); if (ret) @@ -1811,6 +2125,7 @@ static int rockchip_get_pull(struct rockchip_pin_bank *bank, int pin_num) case RK3308: case RK3368: case RK3399: + case RK3588: pull_type = bank->pull_type[pin_num / 8]; data >>= bit; data &= (1 << RK3188_PULL_BITS_PER_PIN) - 1; @@ -1839,7 +2154,9 @@ static int rockchip_set_pull(struct rockchip_pin_bank *bank, if (ctrl->type == RK3066B) return pull ? -EINVAL : 0; - ctrl->pull_calc_reg(bank, pin_num, ®map, ®, &bit); + ret = ctrl->pull_calc_reg(bank, pin_num, ®map, ®, &bit); + if (ret) + return ret; switch (ctrl->type) { case RK2928: @@ -1857,6 +2174,7 @@ static int rockchip_set_pull(struct rockchip_pin_bank *bank, case RK3368: case RK3399: case RK3568: + case RK3588: pull_type = bank->pull_type[pin_num / 8]; ret = -EINVAL; for (i = 0; i < ARRAY_SIZE(rockchip_pull_list[pull_type]); @@ -2104,25 +2422,27 @@ static bool rockchip_pinconf_pull_valid(struct rockchip_pin_ctrl *ctrl, case RK3368: case RK3399: case RK3568: + case RK3588: return (pull != PIN_CONFIG_BIAS_PULL_PIN_DEFAULT); } return false; } -static int rockchip_pinconf_defer_output(struct rockchip_pin_bank *bank, - unsigned int pin, u32 arg) +static int rockchip_pinconf_defer_pin(struct rockchip_pin_bank *bank, + unsigned int pin, u32 param, u32 arg) { - struct rockchip_pin_output_deferred *cfg; + struct rockchip_pin_deferred *cfg; cfg = kzalloc(sizeof(*cfg), GFP_KERNEL); if (!cfg) return -ENOMEM; cfg->pin = pin; + cfg->param = param; cfg->arg = arg; - list_add_tail(&cfg->head, &bank->deferred_output); + list_add_tail(&cfg->head, &bank->deferred_pins); return 0; } @@ -2143,6 +2463,25 @@ static int rockchip_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, param = pinconf_to_config_param(configs[i]); arg = pinconf_to_config_argument(configs[i]); + if (param == PIN_CONFIG_OUTPUT || param == PIN_CONFIG_INPUT_ENABLE) { + /* + * Check for gpio driver not being probed yet. + * The lock makes sure that either gpio-probe has completed + * or the gpio driver hasn't probed yet. + */ + mutex_lock(&bank->deferred_lock); + if (!gpio || !gpio->direction_output) { + rc = rockchip_pinconf_defer_pin(bank, pin - bank->pin_base, param, + arg); + mutex_unlock(&bank->deferred_lock); + if (rc) + return rc; + + break; + } + mutex_unlock(&bank->deferred_lock); + } + switch (param) { case PIN_CONFIG_BIAS_DISABLE: rc = rockchip_set_pull(bank, pin - bank->pin_base, @@ -2171,27 +2510,21 @@ static int rockchip_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, if (rc != RK_FUNC_GPIO) return -EINVAL; - /* - * Check for gpio driver not being probed yet. - * The lock makes sure that either gpio-probe has completed - * or the gpio driver hasn't probed yet. - */ - mutex_lock(&bank->deferred_lock); - if (!gpio || !gpio->direction_output) { - rc = rockchip_pinconf_defer_output(bank, pin - bank->pin_base, arg); - mutex_unlock(&bank->deferred_lock); - if (rc) - return rc; - - break; - } - mutex_unlock(&bank->deferred_lock); - rc = gpio->direction_output(gpio, pin - bank->pin_base, arg); if (rc) return rc; break; + case PIN_CONFIG_INPUT_ENABLE: + rc = rockchip_set_mux(bank, pin - bank->pin_base, + RK_FUNC_GPIO); + if (rc != RK_FUNC_GPIO) + return -EINVAL; + + rc = gpio->direction_input(gpio, pin - bank->pin_base); + if (rc) + return rc; + break; case PIN_CONFIG_DRIVE_STRENGTH: /* rk3288 is the first with per-pin drive-strength */ if (!info->ctrl->drv_calc_reg) @@ -2500,7 +2833,7 @@ static int rockchip_pinctrl_register(struct platform_device *pdev, pdesc++; } - INIT_LIST_HEAD(&pin_bank->deferred_output); + INIT_LIST_HEAD(&pin_bank->deferred_pins); mutex_init(&pin_bank->deferred_lock); } @@ -2763,7 +3096,7 @@ static int rockchip_pinctrl_remove(struct platform_device *pdev) { struct rockchip_pinctrl *info = platform_get_drvdata(pdev); struct rockchip_pin_bank *bank; - struct rockchip_pin_output_deferred *cfg; + struct rockchip_pin_deferred *cfg; int i; of_platform_depopulate(&pdev->dev); @@ -2772,9 +3105,9 @@ static int rockchip_pinctrl_remove(struct platform_device *pdev) bank = &info->ctrl->pin_banks[i]; mutex_lock(&bank->deferred_lock); - while (!list_empty(&bank->deferred_output)) { - cfg = list_first_entry(&bank->deferred_output, - struct rockchip_pin_output_deferred, head); + while (!list_empty(&bank->deferred_pins)) { + cfg = list_first_entry(&bank->deferred_pins, + struct rockchip_pin_deferred, head); list_del(&cfg->head); kfree(cfg); } @@ -3207,6 +3540,29 @@ static struct rockchip_pin_ctrl rk3568_pin_ctrl = { .schmitt_calc_reg = rk3568_calc_schmitt_reg_and_bit, }; +static struct rockchip_pin_bank rk3588_pin_banks[] = { + RK3588_PIN_BANK_FLAGS(0, 32, "gpio0", + IOMUX_WIDTH_4BIT, PULL_TYPE_IO_1V8_ONLY), + RK3588_PIN_BANK_FLAGS(1, 32, "gpio1", + IOMUX_WIDTH_4BIT, PULL_TYPE_IO_1V8_ONLY), + RK3588_PIN_BANK_FLAGS(2, 32, "gpio2", + IOMUX_WIDTH_4BIT, PULL_TYPE_IO_1V8_ONLY), + RK3588_PIN_BANK_FLAGS(3, 32, "gpio3", + IOMUX_WIDTH_4BIT, PULL_TYPE_IO_1V8_ONLY), + RK3588_PIN_BANK_FLAGS(4, 32, "gpio4", + IOMUX_WIDTH_4BIT, PULL_TYPE_IO_1V8_ONLY), +}; + +static struct rockchip_pin_ctrl rk3588_pin_ctrl = { + .pin_banks = rk3588_pin_banks, + .nr_banks = ARRAY_SIZE(rk3588_pin_banks), + .label = "RK3588-GPIO", + .type = RK3588, + .pull_calc_reg = rk3588_calc_pull_reg_and_bit, + .drv_calc_reg = rk3588_calc_drv_reg_and_bit, + .schmitt_calc_reg = rk3588_calc_schmitt_reg_and_bit, +}; + static const struct of_device_id rockchip_pinctrl_dt_match[] = { { .compatible = "rockchip,px30-pinctrl", .data = &px30_pin_ctrl }, @@ -3238,6 +3594,8 @@ static const struct of_device_id rockchip_pinctrl_dt_match[] = { .data = &rk3399_pin_ctrl }, { .compatible = "rockchip,rk3568-pinctrl", .data = &rk3568_pin_ctrl }, + { .compatible = "rockchip,rk3588-pinctrl", + .data = &rk3588_pin_ctrl }, {}, }; diff --git a/drivers/pinctrl/pinctrl-rockchip.h b/drivers/pinctrl/pinctrl-rockchip.h index 91f10279d08442d1a4c441131649bea211771f74..ec46f8815ac9002820e7300404467b8cdd1fe824 100644 --- a/drivers/pinctrl/pinctrl-rockchip.h +++ b/drivers/pinctrl/pinctrl-rockchip.h @@ -18,6 +18,171 @@ #ifndef _PINCTRL_ROCKCHIP_H #define _PINCTRL_ROCKCHIP_H +#define RK_GPIO0_A0 0 +#define RK_GPIO0_A1 1 +#define RK_GPIO0_A2 2 +#define RK_GPIO0_A3 3 +#define RK_GPIO0_A4 4 +#define RK_GPIO0_A5 5 +#define RK_GPIO0_A6 6 +#define RK_GPIO0_A7 7 +#define RK_GPIO0_B0 8 +#define RK_GPIO0_B1 9 +#define RK_GPIO0_B2 10 +#define RK_GPIO0_B3 11 +#define RK_GPIO0_B4 12 +#define RK_GPIO0_B5 13 +#define RK_GPIO0_B6 14 +#define RK_GPIO0_B7 15 +#define RK_GPIO0_C0 16 +#define RK_GPIO0_C1 17 +#define RK_GPIO0_C2 18 +#define RK_GPIO0_C3 19 +#define RK_GPIO0_C4 20 +#define RK_GPIO0_C5 21 +#define RK_GPIO0_C6 22 +#define RK_GPIO0_C7 23 +#define RK_GPIO0_D0 24 +#define RK_GPIO0_D1 25 +#define RK_GPIO0_D2 26 +#define RK_GPIO0_D3 27 +#define RK_GPIO0_D4 28 +#define RK_GPIO0_D5 29 +#define RK_GPIO0_D6 30 +#define RK_GPIO0_D7 31 + +#define RK_GPIO1_A0 32 +#define RK_GPIO1_A1 33 +#define RK_GPIO1_A2 34 +#define RK_GPIO1_A3 35 +#define RK_GPIO1_A4 36 +#define RK_GPIO1_A5 37 +#define RK_GPIO1_A6 38 +#define RK_GPIO1_A7 39 +#define RK_GPIO1_B0 40 +#define RK_GPIO1_B1 41 +#define RK_GPIO1_B2 42 +#define RK_GPIO1_B3 43 +#define RK_GPIO1_B4 44 +#define RK_GPIO1_B5 45 +#define RK_GPIO1_B6 46 +#define RK_GPIO1_B7 47 +#define RK_GPIO1_C0 48 +#define RK_GPIO1_C1 49 +#define RK_GPIO1_C2 50 +#define RK_GPIO1_C3 51 +#define RK_GPIO1_C4 52 +#define RK_GPIO1_C5 53 +#define RK_GPIO1_C6 54 +#define RK_GPIO1_C7 55 +#define RK_GPIO1_D0 56 +#define RK_GPIO1_D1 57 +#define RK_GPIO1_D2 58 +#define RK_GPIO1_D3 59 +#define RK_GPIO1_D4 60 +#define RK_GPIO1_D5 61 +#define RK_GPIO1_D6 62 +#define RK_GPIO1_D7 63 + +#define RK_GPIO2_A0 64 +#define RK_GPIO2_A1 65 +#define RK_GPIO2_A2 66 +#define RK_GPIO2_A3 67 +#define RK_GPIO2_A4 68 +#define RK_GPIO2_A5 69 +#define RK_GPIO2_A6 70 +#define RK_GPIO2_A7 71 +#define RK_GPIO2_B0 72 +#define RK_GPIO2_B1 73 +#define RK_GPIO2_B2 74 +#define RK_GPIO2_B3 75 +#define RK_GPIO2_B4 76 +#define RK_GPIO2_B5 77 +#define RK_GPIO2_B6 78 +#define RK_GPIO2_B7 79 +#define RK_GPIO2_C0 80 +#define RK_GPIO2_C1 81 +#define RK_GPIO2_C2 82 +#define RK_GPIO2_C3 83 +#define RK_GPIO2_C4 84 +#define RK_GPIO2_C5 85 +#define RK_GPIO2_C6 86 +#define RK_GPIO2_C7 87 +#define RK_GPIO2_D0 88 +#define RK_GPIO2_D1 89 +#define RK_GPIO2_D2 90 +#define RK_GPIO2_D3 91 +#define RK_GPIO2_D4 92 +#define RK_GPIO2_D5 93 +#define RK_GPIO2_D6 94 +#define RK_GPIO2_D7 95 + +#define RK_GPIO3_A0 96 +#define RK_GPIO3_A1 97 +#define RK_GPIO3_A2 98 +#define RK_GPIO3_A3 99 +#define RK_GPIO3_A4 100 +#define RK_GPIO3_A5 101 +#define RK_GPIO3_A6 102 +#define RK_GPIO3_A7 103 +#define RK_GPIO3_B0 104 +#define RK_GPIO3_B1 105 +#define RK_GPIO3_B2 106 +#define RK_GPIO3_B3 107 +#define RK_GPIO3_B4 108 +#define RK_GPIO3_B5 109 +#define RK_GPIO3_B6 110 +#define RK_GPIO3_B7 111 +#define RK_GPIO3_C0 112 +#define RK_GPIO3_C1 113 +#define RK_GPIO3_C2 114 +#define RK_GPIO3_C3 115 +#define RK_GPIO3_C4 116 +#define RK_GPIO3_C5 117 +#define RK_GPIO3_C6 118 +#define RK_GPIO3_C7 119 +#define RK_GPIO3_D0 120 +#define RK_GPIO3_D1 121 +#define RK_GPIO3_D2 122 +#define RK_GPIO3_D3 123 +#define RK_GPIO3_D4 124 +#define RK_GPIO3_D5 125 +#define RK_GPIO3_D6 126 +#define RK_GPIO3_D7 127 + +#define RK_GPIO4_A0 128 +#define RK_GPIO4_A1 129 +#define RK_GPIO4_A2 130 +#define RK_GPIO4_A3 131 +#define RK_GPIO4_A4 132 +#define RK_GPIO4_A5 133 +#define RK_GPIO4_A6 134 +#define RK_GPIO4_A7 135 +#define RK_GPIO4_B0 136 +#define RK_GPIO4_B1 137 +#define RK_GPIO4_B2 138 +#define RK_GPIO4_B3 139 +#define RK_GPIO4_B4 140 +#define RK_GPIO4_B5 141 +#define RK_GPIO4_B6 142 +#define RK_GPIO4_B7 143 +#define RK_GPIO4_C0 144 +#define RK_GPIO4_C1 145 +#define RK_GPIO4_C2 146 +#define RK_GPIO4_C3 147 +#define RK_GPIO4_C4 148 +#define RK_GPIO4_C5 149 +#define RK_GPIO4_C6 150 +#define RK_GPIO4_C7 151 +#define RK_GPIO4_D0 152 +#define RK_GPIO4_D1 153 +#define RK_GPIO4_D2 154 +#define RK_GPIO4_D3 155 +#define RK_GPIO4_D4 156 +#define RK_GPIO4_D5 157 +#define RK_GPIO4_D6 158 +#define RK_GPIO4_D7 159 + enum rockchip_pinctrl_type { PX30, RV1108, @@ -30,6 +195,7 @@ enum rockchip_pinctrl_type { RK3368, RK3399, RK3568, + RK3588, }; /** @@ -171,7 +337,7 @@ struct rockchip_pin_bank { u32 toggle_edge_mode; u32 recalced_mask; u32 route_mask; - struct list_head deferred_output; + struct list_head deferred_pins; struct mutex deferred_lock; }; @@ -230,10 +396,10 @@ struct rockchip_pin_ctrl { struct rockchip_mux_route_data *iomux_routes; u32 niomux_routes; - void (*pull_calc_reg)(struct rockchip_pin_bank *bank, + int (*pull_calc_reg)(struct rockchip_pin_bank *bank, int pin_num, struct regmap **regmap, int *reg, u8 *bit); - void (*drv_calc_reg)(struct rockchip_pin_bank *bank, + int (*drv_calc_reg)(struct rockchip_pin_bank *bank, int pin_num, struct regmap **regmap, int *reg, u8 *bit); int (*schmitt_calc_reg)(struct rockchip_pin_bank *bank, @@ -247,9 +413,12 @@ struct rockchip_pin_config { unsigned int nconfigs; }; -struct rockchip_pin_output_deferred { +enum pin_config_param; + +struct rockchip_pin_deferred { struct list_head head; unsigned int pin; + enum pin_config_param param; u32 arg; }; diff --git a/drivers/pinctrl/pinctrl-starfive.c b/drivers/pinctrl/pinctrl-starfive.c index c586cfd09fa874b1d0bfa4809c48bf228088c603..2a86c1035cc88cf415a406e0d85893855705ac9c 100644 --- a/drivers/pinctrl/pinctrl-starfive.c +++ b/drivers/pinctrl/pinctrl-starfive.c @@ -1074,6 +1074,8 @@ static void starfive_irq_mask(struct irq_data *d) value = readl_relaxed(ie) & ~mask; writel_relaxed(value, ie); raw_spin_unlock_irqrestore(&sfp->lock, flags); + + gpiochip_disable_irq(&sfp->gc, d->hwirq); } static void starfive_irq_mask_ack(struct irq_data *d) @@ -1102,6 +1104,8 @@ static void starfive_irq_unmask(struct irq_data *d) unsigned long flags; u32 value; + gpiochip_enable_irq(&sfp->gc, d->hwirq); + raw_spin_lock_irqsave(&sfp->lock, flags); value = readl_relaxed(ie) | mask; writel_relaxed(value, ie); @@ -1163,14 +1167,15 @@ static int starfive_irq_set_type(struct irq_data *d, unsigned int trigger) return 0; } -static struct irq_chip starfive_irq_chip = { +static const struct irq_chip starfive_irq_chip = { .name = "StarFive GPIO", .irq_ack = starfive_irq_ack, .irq_mask = starfive_irq_mask, .irq_mask_ack = starfive_irq_mask_ack, .irq_unmask = starfive_irq_unmask, .irq_set_type = starfive_irq_set_type, - .flags = IRQCHIP_SET_TYPE_MASKED, + .flags = IRQCHIP_IMMUTABLE | IRQCHIP_SET_TYPE_MASKED, + GPIOCHIP_IRQ_RESOURCE_HELPERS, }; static void starfive_gpio_irq_handler(struct irq_desc *desc) @@ -1308,7 +1313,7 @@ static int starfive_probe(struct platform_device *pdev) sfp->gc.base = -1; sfp->gc.ngpio = NR_GPIOS; - sfp->gc.irq.chip = &starfive_irq_chip; + gpio_irq_chip_set_chip(&sfp->gc.irq, &starfive_irq_chip); sfp->gc.irq.parent_handler = starfive_gpio_irq_handler; sfp->gc.irq.num_parents = 1; sfp->gc.irq.parents = devm_kcalloc(dev, sfp->gc.irq.num_parents, diff --git a/drivers/pinctrl/pinctrl-thunderbay.c b/drivers/pinctrl/pinctrl-thunderbay.c index 79d44bca039e1c65ecd667908463f37d12cf2a16..9328b17485cf02971cec79a9010f1001c075f34e 100644 --- a/drivers/pinctrl/pinctrl-thunderbay.c +++ b/drivers/pinctrl/pinctrl-thunderbay.c @@ -1229,7 +1229,6 @@ static int thunderbay_pinctrl_probe(struct platform_device *pdev) const struct of_device_id *of_id; struct device *dev = &pdev->dev; struct thunderbay_pinctrl *tpc; - struct resource *iomem; int ret; of_id = of_match_node(thunderbay_pinctrl_match, pdev->dev.of_node); @@ -1243,11 +1242,7 @@ static int thunderbay_pinctrl_probe(struct platform_device *pdev) tpc->dev = dev; tpc->soc = of_id->data; - iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!iomem) - return -ENXIO; - - tpc->base0 = devm_ioremap_resource(dev, iomem); + tpc->base0 = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(tpc->base0)) return PTR_ERR(tpc->base0); diff --git a/drivers/pinctrl/qcom/Kconfig b/drivers/pinctrl/qcom/Kconfig index c51ef54a9f61061e9fb3e75f62ec472e7a84675b..3daeb97723918f0a3dea6d98d9c46fbdc214bfe0 100644 --- a/drivers/pinctrl/qcom/Kconfig +++ b/drivers/pinctrl/qcom/Kconfig @@ -239,6 +239,15 @@ config PINCTRL_SC7280 Qualcomm Technologies Inc TLMM block found on the Qualcomm Technologies Inc SC7280 platform. +config PINCTRL_SC7280_LPASS_LPI + tristate "Qualcomm Technologies Inc SC7280 LPASS LPI pin controller driver" + depends on GPIOLIB + depends on PINCTRL_LPASS_LPI + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm Technologies Inc LPASS (Low Power Audio SubSystem) LPI + (Low Power Island) found on the Qualcomm Technologies Inc SC7280 platform. + config PINCTRL_SC8180X tristate "Qualcomm Technologies Inc SC8180x pin controller driver" depends on (OF || ACPI) @@ -338,6 +347,15 @@ config PINCTRL_SM8250 Qualcomm Technologies Inc TLMM block found on the Qualcomm Technologies Inc SM8250 platform. +config PINCTRL_SM8250_LPASS_LPI + tristate "Qualcomm Technologies Inc SM8250 LPASS LPI pin controller driver" + depends on GPIOLIB + depends on PINCTRL_LPASS_LPI + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm Technologies Inc LPASS (Low Power Audio SubSystem) LPI + (Low Power Island) found on the Qualcomm Technologies Inc SM8250 platform. + config PINCTRL_SM8350 tristate "Qualcomm Technologies Inc SM8350 pin controller driver" depends on PINCTRL_MSM @@ -360,6 +378,7 @@ config PINCTRL_LPASS_LPI select PINMUX select PINCONF select GENERIC_PINCONF + select GENERIC_PINCTRL_GROUPS depends on GPIOLIB help This is the pinctrl, pinmux, pinconf and gpiolib driver for the diff --git a/drivers/pinctrl/qcom/Makefile b/drivers/pinctrl/qcom/Makefile index 5efbfd9f62483a5f5cccfc199289315e4d2923a5..4f0ee7597f81c1fe9b5a7da7680de6460f5b4787 100644 --- a/drivers/pinctrl/qcom/Makefile +++ b/drivers/pinctrl/qcom/Makefile @@ -28,6 +28,7 @@ obj-$(CONFIG_PINCTRL_QCOM_SSBI_PMIC) += pinctrl-ssbi-gpio.o obj-$(CONFIG_PINCTRL_QCOM_SSBI_PMIC) += pinctrl-ssbi-mpp.o obj-$(CONFIG_PINCTRL_SC7180) += pinctrl-sc7180.o obj-$(CONFIG_PINCTRL_SC7280) += pinctrl-sc7280.o +obj-$(CONFIG_PINCTRL_SC7280_LPASS_LPI) += pinctrl-sc7280-lpass-lpi.o obj-$(CONFIG_PINCTRL_SC8180X) += pinctrl-sc8180x.o obj-$(CONFIG_PINCTRL_SC8280XP) += pinctrl-sc8280xp.o obj-$(CONFIG_PINCTRL_SDM660) += pinctrl-sdm660.o @@ -39,6 +40,7 @@ obj-$(CONFIG_PINCTRL_SM6350) += pinctrl-sm6350.o obj-$(CONFIG_PINCTRL_SDX65) += pinctrl-sdx65.o obj-$(CONFIG_PINCTRL_SM8150) += pinctrl-sm8150.o obj-$(CONFIG_PINCTRL_SM8250) += pinctrl-sm8250.o +obj-$(CONFIG_PINCTRL_SM8250_LPASS_LPI) += pinctrl-sm8250-lpass-lpi.o obj-$(CONFIG_PINCTRL_SM8350) += pinctrl-sm8350.o obj-$(CONFIG_PINCTRL_SM8450) += pinctrl-sm8450.o obj-$(CONFIG_PINCTRL_LPASS_LPI) += pinctrl-lpass-lpi.o diff --git a/drivers/pinctrl/qcom/pinctrl-lpass-lpi.c b/drivers/pinctrl/qcom/pinctrl-lpass-lpi.c index 2f19ab4db720834cdc29f15f4421ec776c9a6159..74810ec4df4478eb9a80dba79da34ecaad06c5c8 100644 --- a/drivers/pinctrl/qcom/pinctrl-lpass-lpi.c +++ b/drivers/pinctrl/qcom/pinctrl-lpass-lpi.c @@ -4,93 +4,15 @@ * Copyright (c) 2020 Linaro Ltd. */ -#include -#include #include #include -#include #include #include -#include #include #include #include -#include -#include -#include -#include "../core.h" #include "../pinctrl-utils.h" - -#define LPI_SLEW_RATE_CTL_REG 0xa000 -#define LPI_TLMM_REG_OFFSET 0x1000 -#define LPI_SLEW_RATE_MAX 0x03 -#define LPI_SLEW_BITS_SIZE 0x02 -#define LPI_SLEW_RATE_MASK GENMASK(1, 0) -#define LPI_GPIO_CFG_REG 0x00 -#define LPI_GPIO_PULL_MASK GENMASK(1, 0) -#define LPI_GPIO_FUNCTION_MASK GENMASK(5, 2) -#define LPI_GPIO_OUT_STRENGTH_MASK GENMASK(8, 6) -#define LPI_GPIO_OE_MASK BIT(9) -#define LPI_GPIO_VALUE_REG 0x04 -#define LPI_GPIO_VALUE_IN_MASK BIT(0) -#define LPI_GPIO_VALUE_OUT_MASK BIT(1) - -#define LPI_GPIO_BIAS_DISABLE 0x0 -#define LPI_GPIO_PULL_DOWN 0x1 -#define LPI_GPIO_KEEPER 0x2 -#define LPI_GPIO_PULL_UP 0x3 -#define LPI_GPIO_DS_TO_VAL(v) (v / 2 - 1) -#define NO_SLEW -1 - -#define LPI_FUNCTION(fname) \ - [LPI_MUX_##fname] = { \ - .name = #fname, \ - .groups = fname##_groups, \ - .ngroups = ARRAY_SIZE(fname##_groups), \ - } - -#define LPI_PINGROUP(id, soff, f1, f2, f3, f4) \ - { \ - .name = "gpio" #id, \ - .pins = gpio##id##_pins, \ - .pin = id, \ - .slew_offset = soff, \ - .npins = ARRAY_SIZE(gpio##id##_pins), \ - .funcs = (int[]){ \ - LPI_MUX_gpio, \ - LPI_MUX_##f1, \ - LPI_MUX_##f2, \ - LPI_MUX_##f3, \ - LPI_MUX_##f4, \ - }, \ - .nfuncs = 5, \ - } - -struct lpi_pingroup { - const char *name; - const unsigned int *pins; - unsigned int npins; - unsigned int pin; - /* Bit offset in slew register for SoundWire pins only */ - int slew_offset; - unsigned int *funcs; - unsigned int nfuncs; -}; - -struct lpi_function { - const char *name; - const char * const *groups; - unsigned int ngroups; -}; - -struct lpi_pinctrl_variant_data { - const struct pinctrl_pin_desc *pins; - int npins; - const struct lpi_pingroup *groups; - int ngroups; - const struct lpi_function *functions; - int nfunctions; -}; +#include "pinctrl-lpass-lpi.h" #define MAX_LPI_NUM_CLKS 2 @@ -106,136 +28,6 @@ struct lpi_pinctrl { const struct lpi_pinctrl_variant_data *data; }; -/* sm8250 variant specific data */ -static const struct pinctrl_pin_desc sm8250_lpi_pins[] = { - PINCTRL_PIN(0, "gpio0"), - PINCTRL_PIN(1, "gpio1"), - PINCTRL_PIN(2, "gpio2"), - PINCTRL_PIN(3, "gpio3"), - PINCTRL_PIN(4, "gpio4"), - PINCTRL_PIN(5, "gpio5"), - PINCTRL_PIN(6, "gpio6"), - PINCTRL_PIN(7, "gpio7"), - PINCTRL_PIN(8, "gpio8"), - PINCTRL_PIN(9, "gpio9"), - PINCTRL_PIN(10, "gpio10"), - PINCTRL_PIN(11, "gpio11"), - PINCTRL_PIN(12, "gpio12"), - PINCTRL_PIN(13, "gpio13"), -}; - -enum sm8250_lpi_functions { - LPI_MUX_dmic1_clk, - LPI_MUX_dmic1_data, - LPI_MUX_dmic2_clk, - LPI_MUX_dmic2_data, - LPI_MUX_dmic3_clk, - LPI_MUX_dmic3_data, - LPI_MUX_i2s1_clk, - LPI_MUX_i2s1_data, - LPI_MUX_i2s1_ws, - LPI_MUX_i2s2_clk, - LPI_MUX_i2s2_data, - LPI_MUX_i2s2_ws, - LPI_MUX_qua_mi2s_data, - LPI_MUX_qua_mi2s_sclk, - LPI_MUX_qua_mi2s_ws, - LPI_MUX_swr_rx_clk, - LPI_MUX_swr_rx_data, - LPI_MUX_swr_tx_clk, - LPI_MUX_swr_tx_data, - LPI_MUX_wsa_swr_clk, - LPI_MUX_wsa_swr_data, - LPI_MUX_gpio, - LPI_MUX__, -}; - -static const unsigned int gpio0_pins[] = { 0 }; -static const unsigned int gpio1_pins[] = { 1 }; -static const unsigned int gpio2_pins[] = { 2 }; -static const unsigned int gpio3_pins[] = { 3 }; -static const unsigned int gpio4_pins[] = { 4 }; -static const unsigned int gpio5_pins[] = { 5 }; -static const unsigned int gpio6_pins[] = { 6 }; -static const unsigned int gpio7_pins[] = { 7 }; -static const unsigned int gpio8_pins[] = { 8 }; -static const unsigned int gpio9_pins[] = { 9 }; -static const unsigned int gpio10_pins[] = { 10 }; -static const unsigned int gpio11_pins[] = { 11 }; -static const unsigned int gpio12_pins[] = { 12 }; -static const unsigned int gpio13_pins[] = { 13 }; -static const char * const swr_tx_clk_groups[] = { "gpio0" }; -static const char * const swr_tx_data_groups[] = { "gpio1", "gpio2", "gpio5" }; -static const char * const swr_rx_clk_groups[] = { "gpio3" }; -static const char * const swr_rx_data_groups[] = { "gpio4", "gpio5" }; -static const char * const dmic1_clk_groups[] = { "gpio6" }; -static const char * const dmic1_data_groups[] = { "gpio7" }; -static const char * const dmic2_clk_groups[] = { "gpio8" }; -static const char * const dmic2_data_groups[] = { "gpio9" }; -static const char * const i2s2_clk_groups[] = { "gpio10" }; -static const char * const i2s2_ws_groups[] = { "gpio11" }; -static const char * const dmic3_clk_groups[] = { "gpio12" }; -static const char * const dmic3_data_groups[] = { "gpio13" }; -static const char * const qua_mi2s_sclk_groups[] = { "gpio0" }; -static const char * const qua_mi2s_ws_groups[] = { "gpio1" }; -static const char * const qua_mi2s_data_groups[] = { "gpio2", "gpio3", "gpio4" }; -static const char * const i2s1_clk_groups[] = { "gpio6" }; -static const char * const i2s1_ws_groups[] = { "gpio7" }; -static const char * const i2s1_data_groups[] = { "gpio8", "gpio9" }; -static const char * const wsa_swr_clk_groups[] = { "gpio10" }; -static const char * const wsa_swr_data_groups[] = { "gpio11" }; -static const char * const i2s2_data_groups[] = { "gpio12", "gpio12" }; - -static const struct lpi_pingroup sm8250_groups[] = { - LPI_PINGROUP(0, 0, swr_tx_clk, qua_mi2s_sclk, _, _), - LPI_PINGROUP(1, 2, swr_tx_data, qua_mi2s_ws, _, _), - LPI_PINGROUP(2, 4, swr_tx_data, qua_mi2s_data, _, _), - LPI_PINGROUP(3, 8, swr_rx_clk, qua_mi2s_data, _, _), - LPI_PINGROUP(4, 10, swr_rx_data, qua_mi2s_data, _, _), - LPI_PINGROUP(5, 12, swr_tx_data, swr_rx_data, _, _), - LPI_PINGROUP(6, NO_SLEW, dmic1_clk, i2s1_clk, _, _), - LPI_PINGROUP(7, NO_SLEW, dmic1_data, i2s1_ws, _, _), - LPI_PINGROUP(8, NO_SLEW, dmic2_clk, i2s1_data, _, _), - LPI_PINGROUP(9, NO_SLEW, dmic2_data, i2s1_data, _, _), - LPI_PINGROUP(10, 16, i2s2_clk, wsa_swr_clk, _, _), - LPI_PINGROUP(11, 18, i2s2_ws, wsa_swr_data, _, _), - LPI_PINGROUP(12, NO_SLEW, dmic3_clk, i2s2_data, _, _), - LPI_PINGROUP(13, NO_SLEW, dmic3_data, i2s2_data, _, _), -}; - -static const struct lpi_function sm8250_functions[] = { - LPI_FUNCTION(dmic1_clk), - LPI_FUNCTION(dmic1_data), - LPI_FUNCTION(dmic2_clk), - LPI_FUNCTION(dmic2_data), - LPI_FUNCTION(dmic3_clk), - LPI_FUNCTION(dmic3_data), - LPI_FUNCTION(i2s1_clk), - LPI_FUNCTION(i2s1_data), - LPI_FUNCTION(i2s1_ws), - LPI_FUNCTION(i2s2_clk), - LPI_FUNCTION(i2s2_data), - LPI_FUNCTION(i2s2_ws), - LPI_FUNCTION(qua_mi2s_data), - LPI_FUNCTION(qua_mi2s_sclk), - LPI_FUNCTION(qua_mi2s_ws), - LPI_FUNCTION(swr_rx_clk), - LPI_FUNCTION(swr_rx_data), - LPI_FUNCTION(swr_tx_clk), - LPI_FUNCTION(swr_tx_data), - LPI_FUNCTION(wsa_swr_clk), - LPI_FUNCTION(wsa_swr_data), -}; - -static struct lpi_pinctrl_variant_data sm8250_lpi_data = { - .pins = sm8250_lpi_pins, - .npins = ARRAY_SIZE(sm8250_lpi_pins), - .groups = sm8250_groups, - .ngroups = ARRAY_SIZE(sm8250_groups), - .functions = sm8250_functions, - .nfunctions = ARRAY_SIZE(sm8250_functions), -}; - static int lpi_gpio_read(struct lpi_pinctrl *state, unsigned int pin, unsigned int addr) { @@ -250,38 +42,10 @@ static int lpi_gpio_write(struct lpi_pinctrl *state, unsigned int pin, return 0; } -static int lpi_gpio_get_groups_count(struct pinctrl_dev *pctldev) -{ - struct lpi_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); - - return pctrl->data->ngroups; -} - -static const char *lpi_gpio_get_group_name(struct pinctrl_dev *pctldev, - unsigned int group) -{ - struct lpi_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); - - return pctrl->data->groups[group].name; -} - -static int lpi_gpio_get_group_pins(struct pinctrl_dev *pctldev, - unsigned int group, - const unsigned int **pins, - unsigned int *num_pins) -{ - struct lpi_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); - - *pins = pctrl->data->groups[group].pins; - *num_pins = pctrl->data->groups[group].npins; - - return 0; -} - static const struct pinctrl_ops lpi_gpio_pinctrl_ops = { - .get_groups_count = lpi_gpio_get_groups_count, - .get_group_name = lpi_gpio_get_group_name, - .get_group_pins = lpi_gpio_get_group_pins, + .get_groups_count = pinctrl_generic_get_group_count, + .get_group_name = pinctrl_generic_get_group_name, + .get_group_pins = pinctrl_generic_get_group_pins, .dt_node_to_map = pinconf_generic_dt_node_to_map_group, .dt_free_map = pinctrl_utils_free_map, }; @@ -435,7 +199,7 @@ static int lpi_config_set(struct pinctrl_dev *pctldev, unsigned int group, } slew_offset = g->slew_offset; - if (slew_offset == NO_SLEW) + if (slew_offset == LPI_NO_SLEW) break; mutex_lock(&pctrl->slew_access_lock); @@ -582,7 +346,29 @@ static const struct gpio_chip lpi_gpio_template = { .dbg_show = lpi_gpio_dbg_show, }; -static int lpi_pinctrl_probe(struct platform_device *pdev) +static int lpi_build_pin_desc_groups(struct lpi_pinctrl *pctrl) +{ + int i, ret; + + for (i = 0; i < pctrl->data->npins; i++) { + const struct pinctrl_pin_desc *pin_info = pctrl->desc.pins + i; + + ret = pinctrl_generic_add_group(pctrl->ctrl, pin_info->name, + (int *)&pin_info->number, 1, NULL); + if (ret < 0) + goto err_pinctrl; + } + + return 0; + +err_pinctrl: + for (; i > 0; i--) + pinctrl_generic_remove_group(pctrl->ctrl, i - 1); + + return ret; +} + +int lpi_pinctrl_probe(struct platform_device *pdev) { const struct lpi_pinctrl_variant_data *data; struct device *dev = &pdev->dev; @@ -615,9 +401,13 @@ static int lpi_pinctrl_probe(struct platform_device *pdev) return dev_err_probe(dev, PTR_ERR(pctrl->slew_base), "Slew resource not provided\n"); - ret = devm_clk_bulk_get(dev, MAX_LPI_NUM_CLKS, pctrl->clks); + if (data->is_clk_optional) + ret = devm_clk_bulk_get_optional(dev, MAX_LPI_NUM_CLKS, pctrl->clks); + else + ret = devm_clk_bulk_get(dev, MAX_LPI_NUM_CLKS, pctrl->clks); + if (ret) - return dev_err_probe(dev, ret, "Can't get clocks\n"); + return ret; ret = clk_bulk_prepare_enable(MAX_LPI_NUM_CLKS, pctrl->clks); if (ret) @@ -647,6 +437,10 @@ static int lpi_pinctrl_probe(struct platform_device *pdev) goto err_pinctrl; } + ret = lpi_build_pin_desc_groups(pctrl); + if (ret) + goto err_pinctrl; + ret = devm_gpiochip_add_data(dev, &pctrl->chip, pctrl); if (ret) { dev_err(pctrl->dev, "can't add gpio chip\n"); @@ -661,35 +455,22 @@ err_pinctrl: return ret; } +EXPORT_SYMBOL_GPL(lpi_pinctrl_probe); -static int lpi_pinctrl_remove(struct platform_device *pdev) +int lpi_pinctrl_remove(struct platform_device *pdev) { struct lpi_pinctrl *pctrl = platform_get_drvdata(pdev); + int i; mutex_destroy(&pctrl->slew_access_lock); clk_bulk_disable_unprepare(MAX_LPI_NUM_CLKS, pctrl->clks); + for (i = 0; i < pctrl->data->npins; i++) + pinctrl_generic_remove_group(pctrl->ctrl, i); + return 0; } +EXPORT_SYMBOL_GPL(lpi_pinctrl_remove); -static const struct of_device_id lpi_pinctrl_of_match[] = { - { - .compatible = "qcom,sm8250-lpass-lpi-pinctrl", - .data = &sm8250_lpi_data, - }, - { } -}; -MODULE_DEVICE_TABLE(of, lpi_pinctrl_of_match); - -static struct platform_driver lpi_pinctrl_driver = { - .driver = { - .name = "qcom-lpass-lpi-pinctrl", - .of_match_table = lpi_pinctrl_of_match, - }, - .probe = lpi_pinctrl_probe, - .remove = lpi_pinctrl_remove, -}; - -module_platform_driver(lpi_pinctrl_driver); MODULE_DESCRIPTION("QTI LPI GPIO pin control driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/pinctrl/qcom/pinctrl-lpass-lpi.h b/drivers/pinctrl/qcom/pinctrl-lpass-lpi.h new file mode 100644 index 0000000000000000000000000000000000000000..759d5d8da562ae197ec0599b3ed50352e4e9fc4c --- /dev/null +++ b/drivers/pinctrl/qcom/pinctrl-lpass-lpi.h @@ -0,0 +1,86 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2020 Linaro Ltd. + */ +#ifndef __PINCTRL_LPASS_LPI_H__ +#define __PINCTRL_LPASS_LPI_H__ + +#include +#include +#include "../core.h" + +#define LPI_SLEW_RATE_CTL_REG 0xa000 +#define LPI_TLMM_REG_OFFSET 0x1000 +#define LPI_SLEW_RATE_MAX 0x03 +#define LPI_SLEW_BITS_SIZE 0x02 +#define LPI_SLEW_RATE_MASK GENMASK(1, 0) +#define LPI_GPIO_CFG_REG 0x00 +#define LPI_GPIO_PULL_MASK GENMASK(1, 0) +#define LPI_GPIO_FUNCTION_MASK GENMASK(5, 2) +#define LPI_GPIO_OUT_STRENGTH_MASK GENMASK(8, 6) +#define LPI_GPIO_OE_MASK BIT(9) +#define LPI_GPIO_VALUE_REG 0x04 +#define LPI_GPIO_VALUE_IN_MASK BIT(0) +#define LPI_GPIO_VALUE_OUT_MASK BIT(1) + +#define LPI_GPIO_BIAS_DISABLE 0x0 +#define LPI_GPIO_PULL_DOWN 0x1 +#define LPI_GPIO_KEEPER 0x2 +#define LPI_GPIO_PULL_UP 0x3 +#define LPI_GPIO_DS_TO_VAL(v) (v / 2 - 1) +#define LPI_NO_SLEW -1 + +#define LPI_FUNCTION(fname) \ + [LPI_MUX_##fname] = { \ + .name = #fname, \ + .groups = fname##_groups, \ + .ngroups = ARRAY_SIZE(fname##_groups), \ + } + +#define LPI_PINGROUP(id, soff, f1, f2, f3, f4) \ + { \ + .group.name = "gpio" #id, \ + .group.pins = gpio##id##_pins, \ + .pin = id, \ + .slew_offset = soff, \ + .group.num_pins = ARRAY_SIZE(gpio##id##_pins), \ + .funcs = (int[]){ \ + LPI_MUX_gpio, \ + LPI_MUX_##f1, \ + LPI_MUX_##f2, \ + LPI_MUX_##f3, \ + LPI_MUX_##f4, \ + }, \ + .nfuncs = 5, \ + } + +struct lpi_pingroup { + struct group_desc group; + unsigned int pin; + /* Bit offset in slew register for SoundWire pins only */ + int slew_offset; + unsigned int *funcs; + unsigned int nfuncs; +}; + +struct lpi_function { + const char *name; + const char * const *groups; + unsigned int ngroups; +}; + +struct lpi_pinctrl_variant_data { + const struct pinctrl_pin_desc *pins; + int npins; + const struct lpi_pingroup *groups; + int ngroups; + const struct lpi_function *functions; + int nfunctions; + bool is_clk_optional; +}; + +int lpi_pinctrl_probe(struct platform_device *pdev); +int lpi_pinctrl_remove(struct platform_device *pdev); + +#endif /*__PINCTRL_LPASS_LPI_H__*/ diff --git a/drivers/pinctrl/qcom/pinctrl-sc7280-lpass-lpi.c b/drivers/pinctrl/qcom/pinctrl-sc7280-lpass-lpi.c new file mode 100644 index 0000000000000000000000000000000000000000..2add9a4520c254153e7ef27544db0c63715dd767 --- /dev/null +++ b/drivers/pinctrl/qcom/pinctrl-sc7280-lpass-lpi.c @@ -0,0 +1,167 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. + * ALSA SoC platform-machine driver for QTi LPASS + */ + +#include +#include +#include + +#include "pinctrl-lpass-lpi.h" + +enum lpass_lpi_functions { + LPI_MUX_dmic1_clk, + LPI_MUX_dmic1_data, + LPI_MUX_dmic2_clk, + LPI_MUX_dmic2_data, + LPI_MUX_dmic3_clk, + LPI_MUX_dmic3_data, + LPI_MUX_i2s1_clk, + LPI_MUX_i2s1_data, + LPI_MUX_i2s1_ws, + LPI_MUX_i2s2_clk, + LPI_MUX_i2s2_data, + LPI_MUX_i2s2_ws, + LPI_MUX_qua_mi2s_data, + LPI_MUX_qua_mi2s_sclk, + LPI_MUX_qua_mi2s_ws, + LPI_MUX_swr_rx_clk, + LPI_MUX_swr_rx_data, + LPI_MUX_swr_tx_clk, + LPI_MUX_swr_tx_data, + LPI_MUX_wsa_swr_clk, + LPI_MUX_wsa_swr_data, + LPI_MUX_gpio, + LPI_MUX__, +}; + +static int gpio0_pins[] = { 0 }; +static int gpio1_pins[] = { 1 }; +static int gpio2_pins[] = { 2 }; +static int gpio3_pins[] = { 3 }; +static int gpio4_pins[] = { 4 }; +static int gpio5_pins[] = { 5 }; +static int gpio6_pins[] = { 6 }; +static int gpio7_pins[] = { 7 }; +static int gpio8_pins[] = { 8 }; +static int gpio9_pins[] = { 9 }; +static int gpio10_pins[] = { 10 }; +static int gpio11_pins[] = { 11 }; +static int gpio12_pins[] = { 12 }; +static int gpio13_pins[] = { 13 }; +static int gpio14_pins[] = { 14 }; + +static const struct pinctrl_pin_desc sc7280_lpi_pins[] = { + PINCTRL_PIN(0, "gpio0"), + PINCTRL_PIN(1, "gpio1"), + PINCTRL_PIN(2, "gpio2"), + PINCTRL_PIN(3, "gpio3"), + PINCTRL_PIN(4, "gpio4"), + PINCTRL_PIN(5, "gpio5"), + PINCTRL_PIN(6, "gpio6"), + PINCTRL_PIN(7, "gpio7"), + PINCTRL_PIN(8, "gpio8"), + PINCTRL_PIN(9, "gpio9"), + PINCTRL_PIN(10, "gpio10"), + PINCTRL_PIN(11, "gpio11"), + PINCTRL_PIN(12, "gpio12"), + PINCTRL_PIN(13, "gpio13"), + PINCTRL_PIN(14, "gpio14"), +}; + +static const char * const swr_tx_clk_groups[] = { "gpio0" }; +static const char * const swr_tx_data_groups[] = { "gpio1", "gpio2", "gpio14" }; +static const char * const swr_rx_clk_groups[] = { "gpio3" }; +static const char * const swr_rx_data_groups[] = { "gpio4", "gpio5" }; +static const char * const dmic1_clk_groups[] = { "gpio6" }; +static const char * const dmic1_data_groups[] = { "gpio7" }; +static const char * const dmic2_clk_groups[] = { "gpio8" }; +static const char * const dmic2_data_groups[] = { "gpio9" }; +static const char * const i2s2_clk_groups[] = { "gpio10" }; +static const char * const i2s2_ws_groups[] = { "gpio11" }; +static const char * const dmic3_clk_groups[] = { "gpio12" }; +static const char * const dmic3_data_groups[] = { "gpio13" }; +static const char * const qua_mi2s_sclk_groups[] = { "gpio0" }; +static const char * const qua_mi2s_ws_groups[] = { "gpio1" }; +static const char * const qua_mi2s_data_groups[] = { "gpio2", "gpio3", "gpio4" }; +static const char * const i2s1_clk_groups[] = { "gpio6" }; +static const char * const i2s1_ws_groups[] = { "gpio7" }; +static const char * const i2s1_data_groups[] = { "gpio8", "gpio9" }; +static const char * const wsa_swr_clk_groups[] = { "gpio10" }; +static const char * const wsa_swr_data_groups[] = { "gpio11" }; +static const char * const i2s2_data_groups[] = { "gpio12", "gpio13" }; + +static const struct lpi_pingroup sc7280_groups[] = { + LPI_PINGROUP(0, 0, swr_tx_clk, qua_mi2s_sclk, _, _), + LPI_PINGROUP(1, 2, swr_tx_data, qua_mi2s_ws, _, _), + LPI_PINGROUP(2, 4, swr_tx_data, qua_mi2s_data, _, _), + LPI_PINGROUP(3, 8, swr_rx_clk, qua_mi2s_data, _, _), + LPI_PINGROUP(4, 10, swr_rx_data, qua_mi2s_data, _, _), + LPI_PINGROUP(5, 12, swr_rx_data, _, _, _), + LPI_PINGROUP(6, LPI_NO_SLEW, dmic1_clk, i2s1_clk, _, _), + LPI_PINGROUP(7, LPI_NO_SLEW, dmic1_data, i2s1_ws, _, _), + LPI_PINGROUP(8, LPI_NO_SLEW, dmic2_clk, i2s1_data, _, _), + LPI_PINGROUP(9, LPI_NO_SLEW, dmic2_data, i2s1_data, _, _), + LPI_PINGROUP(10, 16, i2s2_clk, wsa_swr_clk, _, _), + LPI_PINGROUP(11, 18, i2s2_ws, wsa_swr_data, _, _), + LPI_PINGROUP(12, LPI_NO_SLEW, dmic3_clk, i2s2_data, _, _), + LPI_PINGROUP(13, LPI_NO_SLEW, dmic3_data, i2s2_data, _, _), + LPI_PINGROUP(14, 6, swr_tx_data, _, _, _), +}; + +static const struct lpi_function sc7280_functions[] = { + LPI_FUNCTION(dmic1_clk), + LPI_FUNCTION(dmic1_data), + LPI_FUNCTION(dmic2_clk), + LPI_FUNCTION(dmic2_data), + LPI_FUNCTION(dmic3_clk), + LPI_FUNCTION(dmic3_data), + LPI_FUNCTION(i2s1_clk), + LPI_FUNCTION(i2s1_data), + LPI_FUNCTION(i2s1_ws), + LPI_FUNCTION(i2s2_clk), + LPI_FUNCTION(i2s2_data), + LPI_FUNCTION(i2s2_ws), + LPI_FUNCTION(qua_mi2s_data), + LPI_FUNCTION(qua_mi2s_sclk), + LPI_FUNCTION(qua_mi2s_ws), + LPI_FUNCTION(swr_rx_clk), + LPI_FUNCTION(swr_rx_data), + LPI_FUNCTION(swr_tx_clk), + LPI_FUNCTION(swr_tx_data), + LPI_FUNCTION(wsa_swr_clk), + LPI_FUNCTION(wsa_swr_data), +}; + +static const struct lpi_pinctrl_variant_data sc7280_lpi_data = { + .pins = sc7280_lpi_pins, + .npins = ARRAY_SIZE(sc7280_lpi_pins), + .groups = sc7280_groups, + .ngroups = ARRAY_SIZE(sc7280_groups), + .functions = sc7280_functions, + .nfunctions = ARRAY_SIZE(sc7280_functions), + .is_clk_optional = true, +}; + +static const struct of_device_id lpi_pinctrl_of_match[] = { + { + .compatible = "qcom,sc7280-lpass-lpi-pinctrl", + .data = &sc7280_lpi_data, + }, + { } +}; +MODULE_DEVICE_TABLE(of, lpi_pinctrl_of_match); + +static struct platform_driver lpi_pinctrl_driver = { + .driver = { + .name = "qcom-sc7280-lpass-lpi-pinctrl", + .of_match_table = lpi_pinctrl_of_match, + }, + .probe = lpi_pinctrl_probe, + .remove = lpi_pinctrl_remove, +}; + +module_platform_driver(lpi_pinctrl_driver); +MODULE_DESCRIPTION("QTI SC7280 LPI GPIO pin control driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/pinctrl/qcom/pinctrl-sm8150.c b/drivers/pinctrl/qcom/pinctrl-sm8150.c index 7359bae68c698dddbc615fb04bcbb63a02a05eb8..1cc622694553d6d3506e085732cd605405c7907a 100644 --- a/drivers/pinctrl/qcom/pinctrl-sm8150.c +++ b/drivers/pinctrl/qcom/pinctrl-sm8150.c @@ -1500,6 +1500,25 @@ static const struct msm_pingroup sm8150_groups[] = { [178] = SDC_QDSD_PINGROUP(sdc2_data, 0xB2000, 9, 0), }; +static const struct msm_gpio_wakeirq_map sm8150_pdc_map[] = { + { 3, 31 }, { 5, 32 }, { 8, 33 }, { 9, 34 }, { 10, 100 }, + { 12, 104 }, { 24, 37 }, { 26, 38 }, { 27, 41 }, { 28, 42 }, + { 30, 39 }, { 36, 43 }, { 37, 44 }, { 38, 30 }, { 39, 118 }, + { 39, 125 }, { 41, 47 }, { 42, 48 }, { 46, 50 }, { 47, 49 }, + { 48, 51 }, { 49, 53 }, { 50, 52 }, { 51, 116 }, { 51, 123 }, + { 53, 54 }, { 54, 55 }, { 55, 56 }, { 56, 57 }, { 58, 58 }, + { 60, 60 }, { 61, 61 }, { 68, 62 }, { 70, 63 }, { 76, 71 }, + { 77, 66 }, { 81, 64 }, { 83, 65 }, { 86, 67 }, { 87, 84 }, + { 88, 117 }, { 88, 124 }, { 90, 69 }, { 91, 70 }, { 93, 75 }, + { 95, 72 }, { 96, 73 }, { 97, 74 }, { 101, 40 }, { 103, 77 }, + { 104, 78 }, { 108, 79 }, { 112, 80 }, { 113, 81 }, { 114, 82 }, + { 117, 85 }, { 118, 101 }, { 119, 87 }, { 120, 88 }, { 121, 89 }, + { 122, 90 }, { 123, 91 }, { 124, 92 }, { 125, 93 }, { 129, 94 }, + { 132, 105 }, { 133, 83 }, { 134, 36 }, { 136, 97 }, { 142, 103 }, + { 144, 115 }, { 144, 122 }, { 147, 102 }, { 150, 107 }, + { 152, 108 }, { 153, 109 } +}; + static const struct msm_pinctrl_soc_data sm8150_pinctrl = { .pins = sm8150_pins, .npins = ARRAY_SIZE(sm8150_pins), @@ -1510,6 +1529,9 @@ static const struct msm_pinctrl_soc_data sm8150_pinctrl = { .ngpios = 176, .tiles = sm8150_tiles, .ntiles = ARRAY_SIZE(sm8150_tiles), + .wakeirq_map = sm8150_pdc_map, + .nwakeirq_map = ARRAY_SIZE(sm8150_pdc_map), + .wakeirq_dual_edge_errata = true, }; static int sm8150_pinctrl_probe(struct platform_device *pdev) diff --git a/drivers/pinctrl/qcom/pinctrl-sm8250-lpass-lpi.c b/drivers/pinctrl/qcom/pinctrl-sm8250-lpass-lpi.c new file mode 100644 index 0000000000000000000000000000000000000000..ddbc6317f2a745d6e926369c08600305a092ccc1 --- /dev/null +++ b/drivers/pinctrl/qcom/pinctrl-sm8250-lpass-lpi.c @@ -0,0 +1,163 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2020 Linaro Ltd. + */ + +#include +#include +#include + +#include "pinctrl-lpass-lpi.h" + +enum lpass_lpi_functions { + LPI_MUX_dmic1_clk, + LPI_MUX_dmic1_data, + LPI_MUX_dmic2_clk, + LPI_MUX_dmic2_data, + LPI_MUX_dmic3_clk, + LPI_MUX_dmic3_data, + LPI_MUX_i2s1_clk, + LPI_MUX_i2s1_data, + LPI_MUX_i2s1_ws, + LPI_MUX_i2s2_clk, + LPI_MUX_i2s2_data, + LPI_MUX_i2s2_ws, + LPI_MUX_qua_mi2s_data, + LPI_MUX_qua_mi2s_sclk, + LPI_MUX_qua_mi2s_ws, + LPI_MUX_swr_rx_clk, + LPI_MUX_swr_rx_data, + LPI_MUX_swr_tx_clk, + LPI_MUX_swr_tx_data, + LPI_MUX_wsa_swr_clk, + LPI_MUX_wsa_swr_data, + LPI_MUX_gpio, + LPI_MUX__, +}; + +static int gpio0_pins[] = { 0 }; +static int gpio1_pins[] = { 1 }; +static int gpio2_pins[] = { 2 }; +static int gpio3_pins[] = { 3 }; +static int gpio4_pins[] = { 4 }; +static int gpio5_pins[] = { 5 }; +static int gpio6_pins[] = { 6 }; +static int gpio7_pins[] = { 7 }; +static int gpio8_pins[] = { 8 }; +static int gpio9_pins[] = { 9 }; +static int gpio10_pins[] = { 10 }; +static int gpio11_pins[] = { 11 }; +static int gpio12_pins[] = { 12 }; +static int gpio13_pins[] = { 13 }; + +static const struct pinctrl_pin_desc sm8250_lpi_pins[] = { + PINCTRL_PIN(0, "gpio0"), + PINCTRL_PIN(1, "gpio1"), + PINCTRL_PIN(2, "gpio2"), + PINCTRL_PIN(3, "gpio3"), + PINCTRL_PIN(4, "gpio4"), + PINCTRL_PIN(5, "gpio5"), + PINCTRL_PIN(6, "gpio6"), + PINCTRL_PIN(7, "gpio7"), + PINCTRL_PIN(8, "gpio8"), + PINCTRL_PIN(9, "gpio9"), + PINCTRL_PIN(10, "gpio10"), + PINCTRL_PIN(11, "gpio11"), + PINCTRL_PIN(12, "gpio12"), + PINCTRL_PIN(13, "gpio13"), +}; + +static const char * const swr_tx_clk_groups[] = { "gpio0" }; +static const char * const swr_tx_data_groups[] = { "gpio1", "gpio2", "gpio5" }; +static const char * const swr_rx_clk_groups[] = { "gpio3" }; +static const char * const swr_rx_data_groups[] = { "gpio4", "gpio5" }; +static const char * const dmic1_clk_groups[] = { "gpio6" }; +static const char * const dmic1_data_groups[] = { "gpio7" }; +static const char * const dmic2_clk_groups[] = { "gpio8" }; +static const char * const dmic2_data_groups[] = { "gpio9" }; +static const char * const i2s2_clk_groups[] = { "gpio10" }; +static const char * const i2s2_ws_groups[] = { "gpio11" }; +static const char * const dmic3_clk_groups[] = { "gpio12" }; +static const char * const dmic3_data_groups[] = { "gpio13" }; +static const char * const qua_mi2s_sclk_groups[] = { "gpio0" }; +static const char * const qua_mi2s_ws_groups[] = { "gpio1" }; +static const char * const qua_mi2s_data_groups[] = { "gpio2", "gpio3", "gpio4" }; +static const char * const i2s1_clk_groups[] = { "gpio6" }; +static const char * const i2s1_ws_groups[] = { "gpio7" }; +static const char * const i2s1_data_groups[] = { "gpio8", "gpio9" }; +static const char * const wsa_swr_clk_groups[] = { "gpio10" }; +static const char * const wsa_swr_data_groups[] = { "gpio11" }; +static const char * const i2s2_data_groups[] = { "gpio12", "gpio12" }; + +static const struct lpi_pingroup sm8250_groups[] = { + LPI_PINGROUP(0, 0, swr_tx_clk, qua_mi2s_sclk, _, _), + LPI_PINGROUP(1, 2, swr_tx_data, qua_mi2s_ws, _, _), + LPI_PINGROUP(2, 4, swr_tx_data, qua_mi2s_data, _, _), + LPI_PINGROUP(3, 8, swr_rx_clk, qua_mi2s_data, _, _), + LPI_PINGROUP(4, 10, swr_rx_data, qua_mi2s_data, _, _), + LPI_PINGROUP(5, 12, swr_tx_data, swr_rx_data, _, _), + LPI_PINGROUP(6, LPI_NO_SLEW, dmic1_clk, i2s1_clk, _, _), + LPI_PINGROUP(7, LPI_NO_SLEW, dmic1_data, i2s1_ws, _, _), + LPI_PINGROUP(8, LPI_NO_SLEW, dmic2_clk, i2s1_data, _, _), + LPI_PINGROUP(9, LPI_NO_SLEW, dmic2_data, i2s1_data, _, _), + LPI_PINGROUP(10, 16, i2s2_clk, wsa_swr_clk, _, _), + LPI_PINGROUP(11, 18, i2s2_ws, wsa_swr_data, _, _), + LPI_PINGROUP(12, LPI_NO_SLEW, dmic3_clk, i2s2_data, _, _), + LPI_PINGROUP(13, LPI_NO_SLEW, dmic3_data, i2s2_data, _, _), +}; + +static const struct lpi_function sm8250_functions[] = { + LPI_FUNCTION(dmic1_clk), + LPI_FUNCTION(dmic1_data), + LPI_FUNCTION(dmic2_clk), + LPI_FUNCTION(dmic2_data), + LPI_FUNCTION(dmic3_clk), + LPI_FUNCTION(dmic3_data), + LPI_FUNCTION(i2s1_clk), + LPI_FUNCTION(i2s1_data), + LPI_FUNCTION(i2s1_ws), + LPI_FUNCTION(i2s2_clk), + LPI_FUNCTION(i2s2_data), + LPI_FUNCTION(i2s2_ws), + LPI_FUNCTION(qua_mi2s_data), + LPI_FUNCTION(qua_mi2s_sclk), + LPI_FUNCTION(qua_mi2s_ws), + LPI_FUNCTION(swr_rx_clk), + LPI_FUNCTION(swr_rx_data), + LPI_FUNCTION(swr_tx_clk), + LPI_FUNCTION(swr_tx_data), + LPI_FUNCTION(wsa_swr_clk), + LPI_FUNCTION(wsa_swr_data), +}; + +static const struct lpi_pinctrl_variant_data sm8250_lpi_data = { + .pins = sm8250_lpi_pins, + .npins = ARRAY_SIZE(sm8250_lpi_pins), + .groups = sm8250_groups, + .ngroups = ARRAY_SIZE(sm8250_groups), + .functions = sm8250_functions, + .nfunctions = ARRAY_SIZE(sm8250_functions), +}; + +static const struct of_device_id lpi_pinctrl_of_match[] = { + { + .compatible = "qcom,sm8250-lpass-lpi-pinctrl", + .data = &sm8250_lpi_data, + }, + { } +}; +MODULE_DEVICE_TABLE(of, lpi_pinctrl_of_match); + +static struct platform_driver lpi_pinctrl_driver = { + .driver = { + .name = "qcom-sm8250-lpass-lpi-pinctrl", + .of_match_table = lpi_pinctrl_of_match, + }, + .probe = lpi_pinctrl_probe, + .remove = lpi_pinctrl_remove, +}; + +module_platform_driver(lpi_pinctrl_driver); +MODULE_DESCRIPTION("QTI SM8250 LPI GPIO pin control driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c b/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c index 4fbf8d3938ef9ff7a4757fb6a236a3f2b0dbd5fb..fd5fff9adff083e64b734253f4c65b3902035266 100644 --- a/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c +++ b/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c @@ -1146,6 +1146,7 @@ static const struct of_device_id pmic_gpio_of_match[] = { { .compatible = "qcom,pm660-gpio", .data = (void *) 13 }, /* pm660l has 12 GPIOs with holes on 1, 2, 10, 11 and 12 */ { .compatible = "qcom,pm660l-gpio", .data = (void *) 12 }, + { .compatible = "qcom,pm6125-gpio", .data = (void *) 9 }, { .compatible = "qcom,pm6150-gpio", .data = (void *) 10 }, { .compatible = "qcom,pm6150l-gpio", .data = (void *) 12 }, { .compatible = "qcom,pm6350-gpio", .data = (void *) 9 }, @@ -1183,6 +1184,7 @@ static const struct of_device_id pmic_gpio_of_match[] = { { .compatible = "qcom,pms405-gpio", .data = (void *) 12 }, /* pmx55 has 11 GPIOs with holes on 3, 7, 10, 11 */ { .compatible = "qcom,pmx55-gpio", .data = (void *) 11 }, + { .compatible = "qcom,pmx65-gpio", .data = (void *) 16 }, { }, }; diff --git a/drivers/pinctrl/ralink/Kconfig b/drivers/pinctrl/ralink/Kconfig index a76ee3deb8c31d55e7f9dfb3ff9f3ec4eeecb3ed..1e4c5e43d69b45c4e0f8dfdac91b0a9fc94bbaf7 100644 --- a/drivers/pinctrl/ralink/Kconfig +++ b/drivers/pinctrl/ralink/Kconfig @@ -3,37 +3,33 @@ menu "Ralink pinctrl drivers" depends on RALINK config PINCTRL_RALINK - bool "Ralink pin control support" - default y if RALINK - -config PINCTRL_RT2880 - bool "RT2880 pinctrl driver for RALINK/Mediatek SOCs" + bool "Ralink pinctrl driver" select PINMUX select GENERIC_PINCONF config PINCTRL_MT7620 - bool "mt7620 pinctrl driver for RALINK/Mediatek SOCs" + bool "MT7620 pinctrl subdriver" depends on RALINK && SOC_MT7620 - select PINCTRL_RT2880 + select PINCTRL_RALINK config PINCTRL_MT7621 - bool "mt7621 pinctrl driver for RALINK/Mediatek SOCs" + bool "MT7621 pinctrl subdriver" depends on RALINK && SOC_MT7621 - select PINCTRL_RT2880 + select PINCTRL_RALINK -config PINCTRL_RT288X - bool "RT288X pinctrl driver for RALINK/Mediatek SOCs" +config PINCTRL_RT2880 + bool "RT2880 pinctrl subdriver" depends on RALINK && SOC_RT288X - select PINCTRL_RT2880 + select PINCTRL_RALINK config PINCTRL_RT305X - bool "RT305X pinctrl driver for RALINK/Mediatek SOCs" + bool "RT305X pinctrl subdriver" depends on RALINK && SOC_RT305X - select PINCTRL_RT2880 + select PINCTRL_RALINK config PINCTRL_RT3883 - bool "RT3883 pinctrl driver for RALINK/Mediatek SOCs" + bool "RT3883 pinctrl subdriver" depends on RALINK && SOC_RT3883 - select PINCTRL_RT2880 + select PINCTRL_RALINK endmenu diff --git a/drivers/pinctrl/ralink/Makefile b/drivers/pinctrl/ralink/Makefile index a15610206ced45395a018c3985c5c980d202fdc0..0ebbe552526d7bfdddb648fcd23ce1f668308c0a 100644 --- a/drivers/pinctrl/ralink/Makefile +++ b/drivers/pinctrl/ralink/Makefile @@ -1,8 +1,8 @@ # SPDX-License-Identifier: GPL-2.0 -obj-$(CONFIG_PINCTRL_RT2880) += pinctrl-rt2880.o +obj-$(CONFIG_PINCTRL_RALINK) += pinctrl-ralink.o obj-$(CONFIG_PINCTRL_MT7620) += pinctrl-mt7620.o obj-$(CONFIG_PINCTRL_MT7621) += pinctrl-mt7621.o -obj-$(CONFIG_PINCTRL_RT288X) += pinctrl-rt288x.o +obj-$(CONFIG_PINCTRL_RT2880) += pinctrl-rt2880.o obj-$(CONFIG_PINCTRL_RT305X) += pinctrl-rt305x.o obj-$(CONFIG_PINCTRL_RT3883) += pinctrl-rt3883.o diff --git a/drivers/pinctrl/ralink/pinctrl-mt7620.c b/drivers/pinctrl/ralink/pinctrl-mt7620.c index 6853b5b8b0fe7fbe08eb04fa6dae601567252dff..22ff16eff02ff92ab58f6dffed134e68f646f55a 100644 --- a/drivers/pinctrl/ralink/pinctrl-mt7620.c +++ b/drivers/pinctrl/ralink/pinctrl-mt7620.c @@ -5,7 +5,7 @@ #include #include #include -#include "pinmux.h" +#include "pinctrl-ralink.h" #define MT7620_GPIO_MODE_UART0_SHIFT 2 #define MT7620_GPIO_MODE_UART0_MASK 0x7 @@ -54,20 +54,20 @@ #define MT7620_GPIO_MODE_EPHY 15 #define MT7620_GPIO_MODE_PA 20 -static struct rt2880_pmx_func i2c_grp[] = { FUNC("i2c", 0, 1, 2) }; -static struct rt2880_pmx_func spi_grp[] = { FUNC("spi", 0, 3, 4) }; -static struct rt2880_pmx_func uartlite_grp[] = { FUNC("uartlite", 0, 15, 2) }; -static struct rt2880_pmx_func mdio_grp[] = { +static struct ralink_pmx_func i2c_func[] = { FUNC("i2c", 0, 1, 2) }; +static struct ralink_pmx_func spi_func[] = { FUNC("spi", 0, 3, 4) }; +static struct ralink_pmx_func uartlite_func[] = { FUNC("uartlite", 0, 15, 2) }; +static struct ralink_pmx_func mdio_func[] = { FUNC("mdio", MT7620_GPIO_MODE_MDIO, 22, 2), FUNC("refclk", MT7620_GPIO_MODE_MDIO_REFCLK, 22, 2), }; -static struct rt2880_pmx_func rgmii1_grp[] = { FUNC("rgmii1", 0, 24, 12) }; -static struct rt2880_pmx_func refclk_grp[] = { FUNC("spi refclk", 0, 37, 3) }; -static struct rt2880_pmx_func ephy_grp[] = { FUNC("ephy", 0, 40, 5) }; -static struct rt2880_pmx_func rgmii2_grp[] = { FUNC("rgmii2", 0, 60, 12) }; -static struct rt2880_pmx_func wled_grp[] = { FUNC("wled", 0, 72, 1) }; -static struct rt2880_pmx_func pa_grp[] = { FUNC("pa", 0, 18, 4) }; -static struct rt2880_pmx_func uartf_grp[] = { +static struct ralink_pmx_func rgmii1_func[] = { FUNC("rgmii1", 0, 24, 12) }; +static struct ralink_pmx_func refclk_func[] = { FUNC("spi refclk", 0, 37, 3) }; +static struct ralink_pmx_func ephy_func[] = { FUNC("ephy", 0, 40, 5) }; +static struct ralink_pmx_func rgmii2_func[] = { FUNC("rgmii2", 0, 60, 12) }; +static struct ralink_pmx_func wled_func[] = { FUNC("wled", 0, 72, 1) }; +static struct ralink_pmx_func pa_func[] = { FUNC("pa", 0, 18, 4) }; +static struct ralink_pmx_func uartf_func[] = { FUNC("uartf", MT7620_GPIO_MODE_UARTF, 7, 8), FUNC("pcm uartf", MT7620_GPIO_MODE_PCM_UARTF, 7, 8), FUNC("pcm i2s", MT7620_GPIO_MODE_PCM_I2S, 7, 8), @@ -76,316 +76,316 @@ static struct rt2880_pmx_func uartf_grp[] = { FUNC("gpio uartf", MT7620_GPIO_MODE_GPIO_UARTF, 7, 4), FUNC("gpio i2s", MT7620_GPIO_MODE_GPIO_I2S, 7, 4), }; -static struct rt2880_pmx_func wdt_grp[] = { +static struct ralink_pmx_func wdt_func[] = { FUNC("wdt rst", 0, 17, 1), FUNC("wdt refclk", 0, 17, 1), }; -static struct rt2880_pmx_func pcie_rst_grp[] = { +static struct ralink_pmx_func pcie_rst_func[] = { FUNC("pcie rst", MT7620_GPIO_MODE_PCIE_RST, 36, 1), FUNC("pcie refclk", MT7620_GPIO_MODE_PCIE_REF, 36, 1) }; -static struct rt2880_pmx_func nd_sd_grp[] = { +static struct ralink_pmx_func nd_sd_func[] = { FUNC("nand", MT7620_GPIO_MODE_NAND, 45, 15), FUNC("sd", MT7620_GPIO_MODE_SD, 47, 13) }; -static struct rt2880_pmx_group mt7620a_pinmux_data[] = { - GRP("i2c", i2c_grp, 1, MT7620_GPIO_MODE_I2C), - GRP("uartf", uartf_grp, MT7620_GPIO_MODE_UART0_MASK, +static struct ralink_pmx_group mt7620a_pinmux_data[] = { + GRP("i2c", i2c_func, 1, MT7620_GPIO_MODE_I2C), + GRP("uartf", uartf_func, MT7620_GPIO_MODE_UART0_MASK, MT7620_GPIO_MODE_UART0_SHIFT), - GRP("spi", spi_grp, 1, MT7620_GPIO_MODE_SPI), - GRP("uartlite", uartlite_grp, 1, MT7620_GPIO_MODE_UART1), - GRP_G("wdt", wdt_grp, MT7620_GPIO_MODE_WDT_MASK, + GRP("spi", spi_func, 1, MT7620_GPIO_MODE_SPI), + GRP("uartlite", uartlite_func, 1, MT7620_GPIO_MODE_UART1), + GRP_G("wdt", wdt_func, MT7620_GPIO_MODE_WDT_MASK, MT7620_GPIO_MODE_WDT_GPIO, MT7620_GPIO_MODE_WDT_SHIFT), - GRP_G("mdio", mdio_grp, MT7620_GPIO_MODE_MDIO_MASK, + GRP_G("mdio", mdio_func, MT7620_GPIO_MODE_MDIO_MASK, MT7620_GPIO_MODE_MDIO_GPIO, MT7620_GPIO_MODE_MDIO_SHIFT), - GRP("rgmii1", rgmii1_grp, 1, MT7620_GPIO_MODE_RGMII1), - GRP("spi refclk", refclk_grp, 1, MT7620_GPIO_MODE_SPI_REF_CLK), - GRP_G("pcie", pcie_rst_grp, MT7620_GPIO_MODE_PCIE_MASK, + GRP("rgmii1", rgmii1_func, 1, MT7620_GPIO_MODE_RGMII1), + GRP("spi refclk", refclk_func, 1, MT7620_GPIO_MODE_SPI_REF_CLK), + GRP_G("pcie", pcie_rst_func, MT7620_GPIO_MODE_PCIE_MASK, MT7620_GPIO_MODE_PCIE_GPIO, MT7620_GPIO_MODE_PCIE_SHIFT), - GRP_G("nd_sd", nd_sd_grp, MT7620_GPIO_MODE_ND_SD_MASK, + GRP_G("nd_sd", nd_sd_func, MT7620_GPIO_MODE_ND_SD_MASK, MT7620_GPIO_MODE_ND_SD_GPIO, MT7620_GPIO_MODE_ND_SD_SHIFT), - GRP("rgmii2", rgmii2_grp, 1, MT7620_GPIO_MODE_RGMII2), - GRP("wled", wled_grp, 1, MT7620_GPIO_MODE_WLED), - GRP("ephy", ephy_grp, 1, MT7620_GPIO_MODE_EPHY), - GRP("pa", pa_grp, 1, MT7620_GPIO_MODE_PA), + GRP("rgmii2", rgmii2_func, 1, MT7620_GPIO_MODE_RGMII2), + GRP("wled", wled_func, 1, MT7620_GPIO_MODE_WLED), + GRP("ephy", ephy_func, 1, MT7620_GPIO_MODE_EPHY), + GRP("pa", pa_func, 1, MT7620_GPIO_MODE_PA), { 0 } }; -static struct rt2880_pmx_func pwm1_grp_mt7628[] = { +static struct ralink_pmx_func pwm1_func_mt76x8[] = { FUNC("sdxc d6", 3, 19, 1), FUNC("utif", 2, 19, 1), FUNC("gpio", 1, 19, 1), FUNC("pwm1", 0, 19, 1), }; -static struct rt2880_pmx_func pwm0_grp_mt7628[] = { +static struct ralink_pmx_func pwm0_func_mt76x8[] = { FUNC("sdxc d7", 3, 18, 1), FUNC("utif", 2, 18, 1), FUNC("gpio", 1, 18, 1), FUNC("pwm0", 0, 18, 1), }; -static struct rt2880_pmx_func uart2_grp_mt7628[] = { +static struct ralink_pmx_func uart2_func_mt76x8[] = { FUNC("sdxc d5 d4", 3, 20, 2), FUNC("pwm", 2, 20, 2), FUNC("gpio", 1, 20, 2), FUNC("uart2", 0, 20, 2), }; -static struct rt2880_pmx_func uart1_grp_mt7628[] = { +static struct ralink_pmx_func uart1_func_mt76x8[] = { FUNC("sw_r", 3, 45, 2), FUNC("pwm", 2, 45, 2), FUNC("gpio", 1, 45, 2), FUNC("uart1", 0, 45, 2), }; -static struct rt2880_pmx_func i2c_grp_mt7628[] = { +static struct ralink_pmx_func i2c_func_mt76x8[] = { FUNC("-", 3, 4, 2), FUNC("debug", 2, 4, 2), FUNC("gpio", 1, 4, 2), FUNC("i2c", 0, 4, 2), }; -static struct rt2880_pmx_func refclk_grp_mt7628[] = { FUNC("refclk", 0, 37, 1) }; -static struct rt2880_pmx_func perst_grp_mt7628[] = { FUNC("perst", 0, 36, 1) }; -static struct rt2880_pmx_func wdt_grp_mt7628[] = { FUNC("wdt", 0, 38, 1) }; -static struct rt2880_pmx_func spi_grp_mt7628[] = { FUNC("spi", 0, 7, 4) }; +static struct ralink_pmx_func refclk_func_mt76x8[] = { FUNC("refclk", 0, 37, 1) }; +static struct ralink_pmx_func perst_func_mt76x8[] = { FUNC("perst", 0, 36, 1) }; +static struct ralink_pmx_func wdt_func_mt76x8[] = { FUNC("wdt", 0, 38, 1) }; +static struct ralink_pmx_func spi_func_mt76x8[] = { FUNC("spi", 0, 7, 4) }; -static struct rt2880_pmx_func sd_mode_grp_mt7628[] = { +static struct ralink_pmx_func sd_mode_func_mt76x8[] = { FUNC("jtag", 3, 22, 8), FUNC("utif", 2, 22, 8), FUNC("gpio", 1, 22, 8), FUNC("sdxc", 0, 22, 8), }; -static struct rt2880_pmx_func uart0_grp_mt7628[] = { +static struct ralink_pmx_func uart0_func_mt76x8[] = { FUNC("-", 3, 12, 2), FUNC("-", 2, 12, 2), FUNC("gpio", 1, 12, 2), FUNC("uart0", 0, 12, 2), }; -static struct rt2880_pmx_func i2s_grp_mt7628[] = { +static struct ralink_pmx_func i2s_func_mt76x8[] = { FUNC("antenna", 3, 0, 4), FUNC("pcm", 2, 0, 4), FUNC("gpio", 1, 0, 4), FUNC("i2s", 0, 0, 4), }; -static struct rt2880_pmx_func spi_cs1_grp_mt7628[] = { +static struct ralink_pmx_func spi_cs1_func_mt76x8[] = { FUNC("-", 3, 6, 1), FUNC("refclk", 2, 6, 1), FUNC("gpio", 1, 6, 1), FUNC("spi cs1", 0, 6, 1), }; -static struct rt2880_pmx_func spis_grp_mt7628[] = { +static struct ralink_pmx_func spis_func_mt76x8[] = { FUNC("pwm_uart2", 3, 14, 4), FUNC("utif", 2, 14, 4), FUNC("gpio", 1, 14, 4), FUNC("spis", 0, 14, 4), }; -static struct rt2880_pmx_func gpio_grp_mt7628[] = { +static struct ralink_pmx_func gpio_func_mt76x8[] = { FUNC("pcie", 3, 11, 1), FUNC("refclk", 2, 11, 1), FUNC("gpio", 1, 11, 1), FUNC("gpio", 0, 11, 1), }; -static struct rt2880_pmx_func p4led_kn_grp_mt7628[] = { +static struct ralink_pmx_func p4led_kn_func_mt76x8[] = { FUNC("jtag", 3, 30, 1), FUNC("utif", 2, 30, 1), FUNC("gpio", 1, 30, 1), FUNC("p4led_kn", 0, 30, 1), }; -static struct rt2880_pmx_func p3led_kn_grp_mt7628[] = { +static struct ralink_pmx_func p3led_kn_func_mt76x8[] = { FUNC("jtag", 3, 31, 1), FUNC("utif", 2, 31, 1), FUNC("gpio", 1, 31, 1), FUNC("p3led_kn", 0, 31, 1), }; -static struct rt2880_pmx_func p2led_kn_grp_mt7628[] = { +static struct ralink_pmx_func p2led_kn_func_mt76x8[] = { FUNC("jtag", 3, 32, 1), FUNC("utif", 2, 32, 1), FUNC("gpio", 1, 32, 1), FUNC("p2led_kn", 0, 32, 1), }; -static struct rt2880_pmx_func p1led_kn_grp_mt7628[] = { +static struct ralink_pmx_func p1led_kn_func_mt76x8[] = { FUNC("jtag", 3, 33, 1), FUNC("utif", 2, 33, 1), FUNC("gpio", 1, 33, 1), FUNC("p1led_kn", 0, 33, 1), }; -static struct rt2880_pmx_func p0led_kn_grp_mt7628[] = { +static struct ralink_pmx_func p0led_kn_func_mt76x8[] = { FUNC("jtag", 3, 34, 1), FUNC("rsvd", 2, 34, 1), FUNC("gpio", 1, 34, 1), FUNC("p0led_kn", 0, 34, 1), }; -static struct rt2880_pmx_func wled_kn_grp_mt7628[] = { +static struct ralink_pmx_func wled_kn_func_mt76x8[] = { FUNC("rsvd", 3, 35, 1), FUNC("rsvd", 2, 35, 1), FUNC("gpio", 1, 35, 1), FUNC("wled_kn", 0, 35, 1), }; -static struct rt2880_pmx_func p4led_an_grp_mt7628[] = { +static struct ralink_pmx_func p4led_an_func_mt76x8[] = { FUNC("jtag", 3, 39, 1), FUNC("utif", 2, 39, 1), FUNC("gpio", 1, 39, 1), FUNC("p4led_an", 0, 39, 1), }; -static struct rt2880_pmx_func p3led_an_grp_mt7628[] = { +static struct ralink_pmx_func p3led_an_func_mt76x8[] = { FUNC("jtag", 3, 40, 1), FUNC("utif", 2, 40, 1), FUNC("gpio", 1, 40, 1), FUNC("p3led_an", 0, 40, 1), }; -static struct rt2880_pmx_func p2led_an_grp_mt7628[] = { +static struct ralink_pmx_func p2led_an_func_mt76x8[] = { FUNC("jtag", 3, 41, 1), FUNC("utif", 2, 41, 1), FUNC("gpio", 1, 41, 1), FUNC("p2led_an", 0, 41, 1), }; -static struct rt2880_pmx_func p1led_an_grp_mt7628[] = { +static struct ralink_pmx_func p1led_an_func_mt76x8[] = { FUNC("jtag", 3, 42, 1), FUNC("utif", 2, 42, 1), FUNC("gpio", 1, 42, 1), FUNC("p1led_an", 0, 42, 1), }; -static struct rt2880_pmx_func p0led_an_grp_mt7628[] = { +static struct ralink_pmx_func p0led_an_func_mt76x8[] = { FUNC("jtag", 3, 43, 1), FUNC("rsvd", 2, 43, 1), FUNC("gpio", 1, 43, 1), FUNC("p0led_an", 0, 43, 1), }; -static struct rt2880_pmx_func wled_an_grp_mt7628[] = { +static struct ralink_pmx_func wled_an_func_mt76x8[] = { FUNC("rsvd", 3, 44, 1), FUNC("rsvd", 2, 44, 1), FUNC("gpio", 1, 44, 1), FUNC("wled_an", 0, 44, 1), }; -#define MT7628_GPIO_MODE_MASK 0x3 - -#define MT7628_GPIO_MODE_P4LED_KN 58 -#define MT7628_GPIO_MODE_P3LED_KN 56 -#define MT7628_GPIO_MODE_P2LED_KN 54 -#define MT7628_GPIO_MODE_P1LED_KN 52 -#define MT7628_GPIO_MODE_P0LED_KN 50 -#define MT7628_GPIO_MODE_WLED_KN 48 -#define MT7628_GPIO_MODE_P4LED_AN 42 -#define MT7628_GPIO_MODE_P3LED_AN 40 -#define MT7628_GPIO_MODE_P2LED_AN 38 -#define MT7628_GPIO_MODE_P1LED_AN 36 -#define MT7628_GPIO_MODE_P0LED_AN 34 -#define MT7628_GPIO_MODE_WLED_AN 32 -#define MT7628_GPIO_MODE_PWM1 30 -#define MT7628_GPIO_MODE_PWM0 28 -#define MT7628_GPIO_MODE_UART2 26 -#define MT7628_GPIO_MODE_UART1 24 -#define MT7628_GPIO_MODE_I2C 20 -#define MT7628_GPIO_MODE_REFCLK 18 -#define MT7628_GPIO_MODE_PERST 16 -#define MT7628_GPIO_MODE_WDT 14 -#define MT7628_GPIO_MODE_SPI 12 -#define MT7628_GPIO_MODE_SDMODE 10 -#define MT7628_GPIO_MODE_UART0 8 -#define MT7628_GPIO_MODE_I2S 6 -#define MT7628_GPIO_MODE_CS1 4 -#define MT7628_GPIO_MODE_SPIS 2 -#define MT7628_GPIO_MODE_GPIO 0 - -static struct rt2880_pmx_group mt7628an_pinmux_data[] = { - GRP_G("pwm1", pwm1_grp_mt7628, MT7628_GPIO_MODE_MASK, - 1, MT7628_GPIO_MODE_PWM1), - GRP_G("pwm0", pwm0_grp_mt7628, MT7628_GPIO_MODE_MASK, - 1, MT7628_GPIO_MODE_PWM0), - GRP_G("uart2", uart2_grp_mt7628, MT7628_GPIO_MODE_MASK, - 1, MT7628_GPIO_MODE_UART2), - GRP_G("uart1", uart1_grp_mt7628, MT7628_GPIO_MODE_MASK, - 1, MT7628_GPIO_MODE_UART1), - GRP_G("i2c", i2c_grp_mt7628, MT7628_GPIO_MODE_MASK, - 1, MT7628_GPIO_MODE_I2C), - GRP("refclk", refclk_grp_mt7628, 1, MT7628_GPIO_MODE_REFCLK), - GRP("perst", perst_grp_mt7628, 1, MT7628_GPIO_MODE_PERST), - GRP("wdt", wdt_grp_mt7628, 1, MT7628_GPIO_MODE_WDT), - GRP("spi", spi_grp_mt7628, 1, MT7628_GPIO_MODE_SPI), - GRP_G("sdmode", sd_mode_grp_mt7628, MT7628_GPIO_MODE_MASK, - 1, MT7628_GPIO_MODE_SDMODE), - GRP_G("uart0", uart0_grp_mt7628, MT7628_GPIO_MODE_MASK, - 1, MT7628_GPIO_MODE_UART0), - GRP_G("i2s", i2s_grp_mt7628, MT7628_GPIO_MODE_MASK, - 1, MT7628_GPIO_MODE_I2S), - GRP_G("spi cs1", spi_cs1_grp_mt7628, MT7628_GPIO_MODE_MASK, - 1, MT7628_GPIO_MODE_CS1), - GRP_G("spis", spis_grp_mt7628, MT7628_GPIO_MODE_MASK, - 1, MT7628_GPIO_MODE_SPIS), - GRP_G("gpio", gpio_grp_mt7628, MT7628_GPIO_MODE_MASK, - 1, MT7628_GPIO_MODE_GPIO), - GRP_G("wled_an", wled_an_grp_mt7628, MT7628_GPIO_MODE_MASK, - 1, MT7628_GPIO_MODE_WLED_AN), - GRP_G("p0led_an", p0led_an_grp_mt7628, MT7628_GPIO_MODE_MASK, - 1, MT7628_GPIO_MODE_P0LED_AN), - GRP_G("p1led_an", p1led_an_grp_mt7628, MT7628_GPIO_MODE_MASK, - 1, MT7628_GPIO_MODE_P1LED_AN), - GRP_G("p2led_an", p2led_an_grp_mt7628, MT7628_GPIO_MODE_MASK, - 1, MT7628_GPIO_MODE_P2LED_AN), - GRP_G("p3led_an", p3led_an_grp_mt7628, MT7628_GPIO_MODE_MASK, - 1, MT7628_GPIO_MODE_P3LED_AN), - GRP_G("p4led_an", p4led_an_grp_mt7628, MT7628_GPIO_MODE_MASK, - 1, MT7628_GPIO_MODE_P4LED_AN), - GRP_G("wled_kn", wled_kn_grp_mt7628, MT7628_GPIO_MODE_MASK, - 1, MT7628_GPIO_MODE_WLED_KN), - GRP_G("p0led_kn", p0led_kn_grp_mt7628, MT7628_GPIO_MODE_MASK, - 1, MT7628_GPIO_MODE_P0LED_KN), - GRP_G("p1led_kn", p1led_kn_grp_mt7628, MT7628_GPIO_MODE_MASK, - 1, MT7628_GPIO_MODE_P1LED_KN), - GRP_G("p2led_kn", p2led_kn_grp_mt7628, MT7628_GPIO_MODE_MASK, - 1, MT7628_GPIO_MODE_P2LED_KN), - GRP_G("p3led_kn", p3led_kn_grp_mt7628, MT7628_GPIO_MODE_MASK, - 1, MT7628_GPIO_MODE_P3LED_KN), - GRP_G("p4led_kn", p4led_kn_grp_mt7628, MT7628_GPIO_MODE_MASK, - 1, MT7628_GPIO_MODE_P4LED_KN), +#define MT76X8_GPIO_MODE_MASK 0x3 + +#define MT76X8_GPIO_MODE_P4LED_KN 58 +#define MT76X8_GPIO_MODE_P3LED_KN 56 +#define MT76X8_GPIO_MODE_P2LED_KN 54 +#define MT76X8_GPIO_MODE_P1LED_KN 52 +#define MT76X8_GPIO_MODE_P0LED_KN 50 +#define MT76X8_GPIO_MODE_WLED_KN 48 +#define MT76X8_GPIO_MODE_P4LED_AN 42 +#define MT76X8_GPIO_MODE_P3LED_AN 40 +#define MT76X8_GPIO_MODE_P2LED_AN 38 +#define MT76X8_GPIO_MODE_P1LED_AN 36 +#define MT76X8_GPIO_MODE_P0LED_AN 34 +#define MT76X8_GPIO_MODE_WLED_AN 32 +#define MT76X8_GPIO_MODE_PWM1 30 +#define MT76X8_GPIO_MODE_PWM0 28 +#define MT76X8_GPIO_MODE_UART2 26 +#define MT76X8_GPIO_MODE_UART1 24 +#define MT76X8_GPIO_MODE_I2C 20 +#define MT76X8_GPIO_MODE_REFCLK 18 +#define MT76X8_GPIO_MODE_PERST 16 +#define MT76X8_GPIO_MODE_WDT 14 +#define MT76X8_GPIO_MODE_SPI 12 +#define MT76X8_GPIO_MODE_SDMODE 10 +#define MT76X8_GPIO_MODE_UART0 8 +#define MT76X8_GPIO_MODE_I2S 6 +#define MT76X8_GPIO_MODE_CS1 4 +#define MT76X8_GPIO_MODE_SPIS 2 +#define MT76X8_GPIO_MODE_GPIO 0 + +static struct ralink_pmx_group mt76x8_pinmux_data[] = { + GRP_G("pwm1", pwm1_func_mt76x8, MT76X8_GPIO_MODE_MASK, + 1, MT76X8_GPIO_MODE_PWM1), + GRP_G("pwm0", pwm0_func_mt76x8, MT76X8_GPIO_MODE_MASK, + 1, MT76X8_GPIO_MODE_PWM0), + GRP_G("uart2", uart2_func_mt76x8, MT76X8_GPIO_MODE_MASK, + 1, MT76X8_GPIO_MODE_UART2), + GRP_G("uart1", uart1_func_mt76x8, MT76X8_GPIO_MODE_MASK, + 1, MT76X8_GPIO_MODE_UART1), + GRP_G("i2c", i2c_func_mt76x8, MT76X8_GPIO_MODE_MASK, + 1, MT76X8_GPIO_MODE_I2C), + GRP("refclk", refclk_func_mt76x8, 1, MT76X8_GPIO_MODE_REFCLK), + GRP("perst", perst_func_mt76x8, 1, MT76X8_GPIO_MODE_PERST), + GRP("wdt", wdt_func_mt76x8, 1, MT76X8_GPIO_MODE_WDT), + GRP("spi", spi_func_mt76x8, 1, MT76X8_GPIO_MODE_SPI), + GRP_G("sdmode", sd_mode_func_mt76x8, MT76X8_GPIO_MODE_MASK, + 1, MT76X8_GPIO_MODE_SDMODE), + GRP_G("uart0", uart0_func_mt76x8, MT76X8_GPIO_MODE_MASK, + 1, MT76X8_GPIO_MODE_UART0), + GRP_G("i2s", i2s_func_mt76x8, MT76X8_GPIO_MODE_MASK, + 1, MT76X8_GPIO_MODE_I2S), + GRP_G("spi cs1", spi_cs1_func_mt76x8, MT76X8_GPIO_MODE_MASK, + 1, MT76X8_GPIO_MODE_CS1), + GRP_G("spis", spis_func_mt76x8, MT76X8_GPIO_MODE_MASK, + 1, MT76X8_GPIO_MODE_SPIS), + GRP_G("gpio", gpio_func_mt76x8, MT76X8_GPIO_MODE_MASK, + 1, MT76X8_GPIO_MODE_GPIO), + GRP_G("wled_an", wled_an_func_mt76x8, MT76X8_GPIO_MODE_MASK, + 1, MT76X8_GPIO_MODE_WLED_AN), + GRP_G("p0led_an", p0led_an_func_mt76x8, MT76X8_GPIO_MODE_MASK, + 1, MT76X8_GPIO_MODE_P0LED_AN), + GRP_G("p1led_an", p1led_an_func_mt76x8, MT76X8_GPIO_MODE_MASK, + 1, MT76X8_GPIO_MODE_P1LED_AN), + GRP_G("p2led_an", p2led_an_func_mt76x8, MT76X8_GPIO_MODE_MASK, + 1, MT76X8_GPIO_MODE_P2LED_AN), + GRP_G("p3led_an", p3led_an_func_mt76x8, MT76X8_GPIO_MODE_MASK, + 1, MT76X8_GPIO_MODE_P3LED_AN), + GRP_G("p4led_an", p4led_an_func_mt76x8, MT76X8_GPIO_MODE_MASK, + 1, MT76X8_GPIO_MODE_P4LED_AN), + GRP_G("wled_kn", wled_kn_func_mt76x8, MT76X8_GPIO_MODE_MASK, + 1, MT76X8_GPIO_MODE_WLED_KN), + GRP_G("p0led_kn", p0led_kn_func_mt76x8, MT76X8_GPIO_MODE_MASK, + 1, MT76X8_GPIO_MODE_P0LED_KN), + GRP_G("p1led_kn", p1led_kn_func_mt76x8, MT76X8_GPIO_MODE_MASK, + 1, MT76X8_GPIO_MODE_P1LED_KN), + GRP_G("p2led_kn", p2led_kn_func_mt76x8, MT76X8_GPIO_MODE_MASK, + 1, MT76X8_GPIO_MODE_P2LED_KN), + GRP_G("p3led_kn", p3led_kn_func_mt76x8, MT76X8_GPIO_MODE_MASK, + 1, MT76X8_GPIO_MODE_P3LED_KN), + GRP_G("p4led_kn", p4led_kn_func_mt76x8, MT76X8_GPIO_MODE_MASK, + 1, MT76X8_GPIO_MODE_P4LED_KN), { 0 } }; -static int mt7620_pinmux_probe(struct platform_device *pdev) +static int mt7620_pinctrl_probe(struct platform_device *pdev) { if (is_mt76x8()) - return rt2880_pinmux_init(pdev, mt7628an_pinmux_data); + return ralink_pinctrl_init(pdev, mt76x8_pinmux_data); else - return rt2880_pinmux_init(pdev, mt7620a_pinmux_data); + return ralink_pinctrl_init(pdev, mt7620a_pinmux_data); } -static const struct of_device_id mt7620_pinmux_match[] = { - { .compatible = "ralink,rt2880-pinmux" }, +static const struct of_device_id mt7620_pinctrl_match[] = { + { .compatible = "ralink,mt7620-pinctrl" }, {} }; -MODULE_DEVICE_TABLE(of, mt7620_pinmux_match); +MODULE_DEVICE_TABLE(of, mt7620_pinctrl_match); -static struct platform_driver mt7620_pinmux_driver = { - .probe = mt7620_pinmux_probe, +static struct platform_driver mt7620_pinctrl_driver = { + .probe = mt7620_pinctrl_probe, .driver = { - .name = "rt2880-pinmux", - .of_match_table = mt7620_pinmux_match, + .name = "mt7620-pinctrl", + .of_match_table = mt7620_pinctrl_match, }, }; -static int __init mt7620_pinmux_init(void) +static int __init mt7620_pinctrl_init(void) { - return platform_driver_register(&mt7620_pinmux_driver); + return platform_driver_register(&mt7620_pinctrl_driver); } -core_initcall_sync(mt7620_pinmux_init); +core_initcall_sync(mt7620_pinctrl_init); diff --git a/drivers/pinctrl/ralink/pinctrl-mt7621.c b/drivers/pinctrl/ralink/pinctrl-mt7621.c index 7d96144c474e7c98b0c7b0c1812c868f6276a14c..b47968f40e0c2a6dd15cf0214eba63867e1fa062 100644 --- a/drivers/pinctrl/ralink/pinctrl-mt7621.c +++ b/drivers/pinctrl/ralink/pinctrl-mt7621.c @@ -3,7 +3,7 @@ #include #include #include -#include "pinmux.h" +#include "pinctrl-ralink.h" #define MT7621_GPIO_MODE_UART1 1 #define MT7621_GPIO_MODE_I2C 2 @@ -34,83 +34,83 @@ #define MT7621_GPIO_MODE_SDHCI_SHIFT 18 #define MT7621_GPIO_MODE_SDHCI_GPIO 1 -static struct rt2880_pmx_func uart1_grp[] = { FUNC("uart1", 0, 1, 2) }; -static struct rt2880_pmx_func i2c_grp[] = { FUNC("i2c", 0, 3, 2) }; -static struct rt2880_pmx_func uart3_grp[] = { +static struct ralink_pmx_func uart1_func[] = { FUNC("uart1", 0, 1, 2) }; +static struct ralink_pmx_func i2c_func[] = { FUNC("i2c", 0, 3, 2) }; +static struct ralink_pmx_func uart3_func[] = { FUNC("uart3", 0, 5, 4), FUNC("i2s", 2, 5, 4), FUNC("spdif3", 3, 5, 4), }; -static struct rt2880_pmx_func uart2_grp[] = { +static struct ralink_pmx_func uart2_func[] = { FUNC("uart2", 0, 9, 4), FUNC("pcm", 2, 9, 4), FUNC("spdif2", 3, 9, 4), }; -static struct rt2880_pmx_func jtag_grp[] = { FUNC("jtag", 0, 13, 5) }; -static struct rt2880_pmx_func wdt_grp[] = { +static struct ralink_pmx_func jtag_func[] = { FUNC("jtag", 0, 13, 5) }; +static struct ralink_pmx_func wdt_func[] = { FUNC("wdt rst", 0, 18, 1), FUNC("wdt refclk", 2, 18, 1), }; -static struct rt2880_pmx_func pcie_rst_grp[] = { +static struct ralink_pmx_func pcie_rst_func[] = { FUNC("pcie rst", MT7621_GPIO_MODE_PCIE_RST, 19, 1), FUNC("pcie refclk", MT7621_GPIO_MODE_PCIE_REF, 19, 1) }; -static struct rt2880_pmx_func mdio_grp[] = { FUNC("mdio", 0, 20, 2) }; -static struct rt2880_pmx_func rgmii2_grp[] = { FUNC("rgmii2", 0, 22, 12) }; -static struct rt2880_pmx_func spi_grp[] = { +static struct ralink_pmx_func mdio_func[] = { FUNC("mdio", 0, 20, 2) }; +static struct ralink_pmx_func rgmii2_func[] = { FUNC("rgmii2", 0, 22, 12) }; +static struct ralink_pmx_func spi_func[] = { FUNC("spi", 0, 34, 7), FUNC("nand1", 2, 34, 7), }; -static struct rt2880_pmx_func sdhci_grp[] = { +static struct ralink_pmx_func sdhci_func[] = { FUNC("sdhci", 0, 41, 8), FUNC("nand2", 2, 41, 8), }; -static struct rt2880_pmx_func rgmii1_grp[] = { FUNC("rgmii1", 0, 49, 12) }; +static struct ralink_pmx_func rgmii1_func[] = { FUNC("rgmii1", 0, 49, 12) }; -static struct rt2880_pmx_group mt7621_pinmux_data[] = { - GRP("uart1", uart1_grp, 1, MT7621_GPIO_MODE_UART1), - GRP("i2c", i2c_grp, 1, MT7621_GPIO_MODE_I2C), - GRP_G("uart3", uart3_grp, MT7621_GPIO_MODE_UART3_MASK, +static struct ralink_pmx_group mt7621_pinmux_data[] = { + GRP("uart1", uart1_func, 1, MT7621_GPIO_MODE_UART1), + GRP("i2c", i2c_func, 1, MT7621_GPIO_MODE_I2C), + GRP_G("uart3", uart3_func, MT7621_GPIO_MODE_UART3_MASK, MT7621_GPIO_MODE_UART3_GPIO, MT7621_GPIO_MODE_UART3_SHIFT), - GRP_G("uart2", uart2_grp, MT7621_GPIO_MODE_UART2_MASK, + GRP_G("uart2", uart2_func, MT7621_GPIO_MODE_UART2_MASK, MT7621_GPIO_MODE_UART2_GPIO, MT7621_GPIO_MODE_UART2_SHIFT), - GRP("jtag", jtag_grp, 1, MT7621_GPIO_MODE_JTAG), - GRP_G("wdt", wdt_grp, MT7621_GPIO_MODE_WDT_MASK, + GRP("jtag", jtag_func, 1, MT7621_GPIO_MODE_JTAG), + GRP_G("wdt", wdt_func, MT7621_GPIO_MODE_WDT_MASK, MT7621_GPIO_MODE_WDT_GPIO, MT7621_GPIO_MODE_WDT_SHIFT), - GRP_G("pcie", pcie_rst_grp, MT7621_GPIO_MODE_PCIE_MASK, + GRP_G("pcie", pcie_rst_func, MT7621_GPIO_MODE_PCIE_MASK, MT7621_GPIO_MODE_PCIE_GPIO, MT7621_GPIO_MODE_PCIE_SHIFT), - GRP_G("mdio", mdio_grp, MT7621_GPIO_MODE_MDIO_MASK, + GRP_G("mdio", mdio_func, MT7621_GPIO_MODE_MDIO_MASK, MT7621_GPIO_MODE_MDIO_GPIO, MT7621_GPIO_MODE_MDIO_SHIFT), - GRP("rgmii2", rgmii2_grp, 1, MT7621_GPIO_MODE_RGMII2), - GRP_G("spi", spi_grp, MT7621_GPIO_MODE_SPI_MASK, + GRP("rgmii2", rgmii2_func, 1, MT7621_GPIO_MODE_RGMII2), + GRP_G("spi", spi_func, MT7621_GPIO_MODE_SPI_MASK, MT7621_GPIO_MODE_SPI_GPIO, MT7621_GPIO_MODE_SPI_SHIFT), - GRP_G("sdhci", sdhci_grp, MT7621_GPIO_MODE_SDHCI_MASK, + GRP_G("sdhci", sdhci_func, MT7621_GPIO_MODE_SDHCI_MASK, MT7621_GPIO_MODE_SDHCI_GPIO, MT7621_GPIO_MODE_SDHCI_SHIFT), - GRP("rgmii1", rgmii1_grp, 1, MT7621_GPIO_MODE_RGMII1), + GRP("rgmii1", rgmii1_func, 1, MT7621_GPIO_MODE_RGMII1), { 0 } }; -static int mt7621_pinmux_probe(struct platform_device *pdev) +static int mt7621_pinctrl_probe(struct platform_device *pdev) { - return rt2880_pinmux_init(pdev, mt7621_pinmux_data); + return ralink_pinctrl_init(pdev, mt7621_pinmux_data); } -static const struct of_device_id mt7621_pinmux_match[] = { - { .compatible = "ralink,rt2880-pinmux" }, +static const struct of_device_id mt7621_pinctrl_match[] = { + { .compatible = "ralink,mt7621-pinctrl" }, {} }; -MODULE_DEVICE_TABLE(of, mt7621_pinmux_match); +MODULE_DEVICE_TABLE(of, mt7621_pinctrl_match); -static struct platform_driver mt7621_pinmux_driver = { - .probe = mt7621_pinmux_probe, +static struct platform_driver mt7621_pinctrl_driver = { + .probe = mt7621_pinctrl_probe, .driver = { - .name = "rt2880-pinmux", - .of_match_table = mt7621_pinmux_match, + .name = "mt7621-pinctrl", + .of_match_table = mt7621_pinctrl_match, }, }; -static int __init mt7621_pinmux_init(void) +static int __init mt7621_pinctrl_init(void) { - return platform_driver_register(&mt7621_pinmux_driver); + return platform_driver_register(&mt7621_pinctrl_driver); } -core_initcall_sync(mt7621_pinmux_init); +core_initcall_sync(mt7621_pinctrl_init); diff --git a/drivers/pinctrl/ralink/pinctrl-ralink.c b/drivers/pinctrl/ralink/pinctrl-ralink.c new file mode 100644 index 0000000000000000000000000000000000000000..63429a2874343a984966925261a4608f00a9f6d0 --- /dev/null +++ b/drivers/pinctrl/ralink/pinctrl-ralink.c @@ -0,0 +1,349 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2013 John Crispin + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "pinctrl-ralink.h" +#include "../core.h" +#include "../pinctrl-utils.h" + +#define SYSC_REG_GPIO_MODE 0x60 +#define SYSC_REG_GPIO_MODE2 0x64 + +struct ralink_priv { + struct device *dev; + + struct pinctrl_pin_desc *pads; + struct pinctrl_desc *desc; + + struct ralink_pmx_func **func; + int func_count; + + struct ralink_pmx_group *groups; + const char **group_names; + int group_count; + + u8 *gpio; + int max_pins; +}; + +static int ralink_get_group_count(struct pinctrl_dev *pctrldev) +{ + struct ralink_priv *p = pinctrl_dev_get_drvdata(pctrldev); + + return p->group_count; +} + +static const char *ralink_get_group_name(struct pinctrl_dev *pctrldev, + unsigned int group) +{ + struct ralink_priv *p = pinctrl_dev_get_drvdata(pctrldev); + + return (group >= p->group_count) ? NULL : p->group_names[group]; +} + +static int ralink_get_group_pins(struct pinctrl_dev *pctrldev, + unsigned int group, + const unsigned int **pins, + unsigned int *num_pins) +{ + struct ralink_priv *p = pinctrl_dev_get_drvdata(pctrldev); + + if (group >= p->group_count) + return -EINVAL; + + *pins = p->groups[group].func[0].pins; + *num_pins = p->groups[group].func[0].pin_count; + + return 0; +} + +static const struct pinctrl_ops ralink_pctrl_ops = { + .get_groups_count = ralink_get_group_count, + .get_group_name = ralink_get_group_name, + .get_group_pins = ralink_get_group_pins, + .dt_node_to_map = pinconf_generic_dt_node_to_map_all, + .dt_free_map = pinconf_generic_dt_free_map, +}; + +static int ralink_pmx_func_count(struct pinctrl_dev *pctrldev) +{ + struct ralink_priv *p = pinctrl_dev_get_drvdata(pctrldev); + + return p->func_count; +} + +static const char *ralink_pmx_func_name(struct pinctrl_dev *pctrldev, + unsigned int func) +{ + struct ralink_priv *p = pinctrl_dev_get_drvdata(pctrldev); + + return p->func[func]->name; +} + +static int ralink_pmx_group_get_groups(struct pinctrl_dev *pctrldev, + unsigned int func, + const char * const **groups, + unsigned int * const num_groups) +{ + struct ralink_priv *p = pinctrl_dev_get_drvdata(pctrldev); + + if (p->func[func]->group_count == 1) + *groups = &p->group_names[p->func[func]->groups[0]]; + else + *groups = p->group_names; + + *num_groups = p->func[func]->group_count; + + return 0; +} + +static int ralink_pmx_group_enable(struct pinctrl_dev *pctrldev, + unsigned int func, unsigned int group) +{ + struct ralink_priv *p = pinctrl_dev_get_drvdata(pctrldev); + u32 mode = 0; + u32 reg = SYSC_REG_GPIO_MODE; + int i; + int shift; + + /* dont allow double use */ + if (p->groups[group].enabled) { + dev_err(p->dev, "%s is already enabled\n", + p->groups[group].name); + return 0; + } + + p->groups[group].enabled = 1; + p->func[func]->enabled = 1; + + shift = p->groups[group].shift; + if (shift >= 32) { + shift -= 32; + reg = SYSC_REG_GPIO_MODE2; + } + mode = rt_sysc_r32(reg); + mode &= ~(p->groups[group].mask << shift); + + /* mark the pins as gpio */ + for (i = 0; i < p->groups[group].func[0].pin_count; i++) + p->gpio[p->groups[group].func[0].pins[i]] = 1; + + /* function 0 is gpio and needs special handling */ + if (func == 0) { + mode |= p->groups[group].gpio << shift; + } else { + for (i = 0; i < p->func[func]->pin_count; i++) + p->gpio[p->func[func]->pins[i]] = 0; + mode |= p->func[func]->value << shift; + } + rt_sysc_w32(mode, reg); + + return 0; +} + +static int ralink_pmx_group_gpio_request_enable(struct pinctrl_dev *pctrldev, + struct pinctrl_gpio_range *range, + unsigned int pin) +{ + struct ralink_priv *p = pinctrl_dev_get_drvdata(pctrldev); + + if (!p->gpio[pin]) { + dev_err(p->dev, "pin %d is not set to gpio mux\n", pin); + return -EINVAL; + } + + return 0; +} + +static const struct pinmux_ops ralink_pmx_group_ops = { + .get_functions_count = ralink_pmx_func_count, + .get_function_name = ralink_pmx_func_name, + .get_function_groups = ralink_pmx_group_get_groups, + .set_mux = ralink_pmx_group_enable, + .gpio_request_enable = ralink_pmx_group_gpio_request_enable, +}; + +static struct pinctrl_desc ralink_pctrl_desc = { + .owner = THIS_MODULE, + .name = "ralink-pinctrl", + .pctlops = &ralink_pctrl_ops, + .pmxops = &ralink_pmx_group_ops, +}; + +static struct ralink_pmx_func gpio_func = { + .name = "gpio", +}; + +static int ralink_pinctrl_index(struct ralink_priv *p) +{ + struct ralink_pmx_group *mux = p->groups; + int i, j, c = 0; + + /* count the mux functions */ + while (mux->name) { + p->group_count++; + mux++; + } + + /* allocate the group names array needed by the gpio function */ + p->group_names = devm_kcalloc(p->dev, p->group_count, + sizeof(char *), GFP_KERNEL); + if (!p->group_names) + return -ENOMEM; + + for (i = 0; i < p->group_count; i++) { + p->group_names[i] = p->groups[i].name; + p->func_count += p->groups[i].func_count; + } + + /* we have a dummy function[0] for gpio */ + p->func_count++; + + /* allocate our function and group mapping index buffers */ + p->func = devm_kcalloc(p->dev, p->func_count, + sizeof(*p->func), GFP_KERNEL); + gpio_func.groups = devm_kcalloc(p->dev, p->group_count, sizeof(int), + GFP_KERNEL); + if (!p->func || !gpio_func.groups) + return -ENOMEM; + + /* add a backpointer to the function so it knows its group */ + gpio_func.group_count = p->group_count; + for (i = 0; i < gpio_func.group_count; i++) + gpio_func.groups[i] = i; + + p->func[c] = &gpio_func; + c++; + + /* add remaining functions */ + for (i = 0; i < p->group_count; i++) { + for (j = 0; j < p->groups[i].func_count; j++) { + p->func[c] = &p->groups[i].func[j]; + p->func[c]->groups = devm_kzalloc(p->dev, sizeof(int), + GFP_KERNEL); + if (!p->func[c]->groups) + return -ENOMEM; + p->func[c]->groups[0] = i; + p->func[c]->group_count = 1; + c++; + } + } + return 0; +} + +static int ralink_pinctrl_pins(struct ralink_priv *p) +{ + int i, j; + + /* + * loop over the functions and initialize the pins array. + * also work out the highest pin used. + */ + for (i = 0; i < p->func_count; i++) { + int pin; + + if (!p->func[i]->pin_count) + continue; + + p->func[i]->pins = devm_kcalloc(p->dev, + p->func[i]->pin_count, + sizeof(int), + GFP_KERNEL); + for (j = 0; j < p->func[i]->pin_count; j++) + p->func[i]->pins[j] = p->func[i]->pin_first + j; + + pin = p->func[i]->pin_first + p->func[i]->pin_count; + if (pin > p->max_pins) + p->max_pins = pin; + } + + /* the buffer that tells us which pins are gpio */ + p->gpio = devm_kcalloc(p->dev, p->max_pins, sizeof(u8), GFP_KERNEL); + /* the pads needed to tell pinctrl about our pins */ + p->pads = devm_kcalloc(p->dev, p->max_pins, + sizeof(struct pinctrl_pin_desc), GFP_KERNEL); + if (!p->pads || !p->gpio) + return -ENOMEM; + + memset(p->gpio, 1, sizeof(u8) * p->max_pins); + for (i = 0; i < p->func_count; i++) { + if (!p->func[i]->pin_count) + continue; + + for (j = 0; j < p->func[i]->pin_count; j++) + p->gpio[p->func[i]->pins[j]] = 0; + } + + /* pin 0 is always a gpio */ + p->gpio[0] = 1; + + /* set the pads */ + for (i = 0; i < p->max_pins; i++) { + /* strlen("ioXY") + 1 = 5 */ + char *name = devm_kzalloc(p->dev, 5, GFP_KERNEL); + + if (!name) + return -ENOMEM; + snprintf(name, 5, "io%d", i); + p->pads[i].number = i; + p->pads[i].name = name; + } + p->desc->pins = p->pads; + p->desc->npins = p->max_pins; + + return 0; +} + +int ralink_pinctrl_init(struct platform_device *pdev, + struct ralink_pmx_group *data) +{ + struct ralink_priv *p; + struct pinctrl_dev *dev; + int err; + + if (!data) + return -ENOTSUPP; + + /* setup the private data */ + p = devm_kzalloc(&pdev->dev, sizeof(struct ralink_priv), GFP_KERNEL); + if (!p) + return -ENOMEM; + + p->dev = &pdev->dev; + p->desc = &ralink_pctrl_desc; + p->groups = data; + platform_set_drvdata(pdev, p); + + /* init the device */ + err = ralink_pinctrl_index(p); + if (err) { + dev_err(&pdev->dev, "failed to load index\n"); + return err; + } + + err = ralink_pinctrl_pins(p); + if (err) { + dev_err(&pdev->dev, "failed to load pins\n"); + return err; + } + dev = pinctrl_register(p->desc, &pdev->dev, p); + + return PTR_ERR_OR_ZERO(dev); +} diff --git a/drivers/pinctrl/ralink/pinmux.h b/drivers/pinctrl/ralink/pinctrl-ralink.h similarity index 75% rename from drivers/pinctrl/ralink/pinmux.h rename to drivers/pinctrl/ralink/pinctrl-ralink.h index 0046abe3bcc798df3f6cb0f51c70dc6a713a475e..e6037be1e153b68b58553a79064f005fc01bf948 100644 --- a/drivers/pinctrl/ralink/pinmux.h +++ b/drivers/pinctrl/ralink/pinctrl-ralink.h @@ -3,8 +3,8 @@ * Copyright (C) 2012 John Crispin */ -#ifndef _RT288X_PINMUX_H__ -#define _RT288X_PINMUX_H__ +#ifndef _PINCTRL_RALINK_H__ +#define _PINCTRL_RALINK_H__ #define FUNC(name, value, pin_first, pin_count) \ { name, value, pin_first, pin_count } @@ -19,9 +19,9 @@ .func = _func, .gpio = _gpio, \ .func_count = ARRAY_SIZE(_func) } -struct rt2880_pmx_group; +struct ralink_pmx_group; -struct rt2880_pmx_func { +struct ralink_pmx_func { const char *name; const char value; @@ -35,7 +35,7 @@ struct rt2880_pmx_func { int enabled; }; -struct rt2880_pmx_group { +struct ralink_pmx_group { const char *name; int enabled; @@ -43,11 +43,11 @@ struct rt2880_pmx_group { const char mask; const char gpio; - struct rt2880_pmx_func *func; + struct ralink_pmx_func *func; int func_count; }; -int rt2880_pinmux_init(struct platform_device *pdev, - struct rt2880_pmx_group *data); +int ralink_pinctrl_init(struct platform_device *pdev, + struct ralink_pmx_group *data); #endif diff --git a/drivers/pinctrl/ralink/pinctrl-rt2880.c b/drivers/pinctrl/ralink/pinctrl-rt2880.c index 96fc06d1b8b92d98199b1aa3cac2e0c5dc0050c5..811e12df113317751d40a9d7c9226d8ccdc5a986 100644 --- a/drivers/pinctrl/ralink/pinctrl-rt2880.c +++ b/drivers/pinctrl/ralink/pinctrl-rt2880.c @@ -1,349 +1,60 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (C) 2013 John Crispin - */ +// SPDX-License-Identifier: GPL-2.0-only +#include #include -#include -#include #include -#include #include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "pinmux.h" -#include "../core.h" -#include "../pinctrl-utils.h" - -#define SYSC_REG_GPIO_MODE 0x60 -#define SYSC_REG_GPIO_MODE2 0x64 - -struct rt2880_priv { - struct device *dev; - - struct pinctrl_pin_desc *pads; - struct pinctrl_desc *desc; - - struct rt2880_pmx_func **func; - int func_count; - - struct rt2880_pmx_group *groups; - const char **group_names; - int group_count; - - u8 *gpio; - int max_pins; +#include "pinctrl-ralink.h" + +#define RT2880_GPIO_MODE_I2C BIT(0) +#define RT2880_GPIO_MODE_UART0 BIT(1) +#define RT2880_GPIO_MODE_SPI BIT(2) +#define RT2880_GPIO_MODE_UART1 BIT(3) +#define RT2880_GPIO_MODE_JTAG BIT(4) +#define RT2880_GPIO_MODE_MDIO BIT(5) +#define RT2880_GPIO_MODE_SDRAM BIT(6) +#define RT2880_GPIO_MODE_PCI BIT(7) + +static struct ralink_pmx_func i2c_func[] = { FUNC("i2c", 0, 1, 2) }; +static struct ralink_pmx_func spi_func[] = { FUNC("spi", 0, 3, 4) }; +static struct ralink_pmx_func uartlite_func[] = { FUNC("uartlite", 0, 7, 8) }; +static struct ralink_pmx_func jtag_func[] = { FUNC("jtag", 0, 17, 5) }; +static struct ralink_pmx_func mdio_func[] = { FUNC("mdio", 0, 22, 2) }; +static struct ralink_pmx_func sdram_func[] = { FUNC("sdram", 0, 24, 16) }; +static struct ralink_pmx_func pci_func[] = { FUNC("pci", 0, 40, 32) }; + +static struct ralink_pmx_group rt2880_pinmux_data_act[] = { + GRP("i2c", i2c_func, 1, RT2880_GPIO_MODE_I2C), + GRP("spi", spi_func, 1, RT2880_GPIO_MODE_SPI), + GRP("uartlite", uartlite_func, 1, RT2880_GPIO_MODE_UART0), + GRP("jtag", jtag_func, 1, RT2880_GPIO_MODE_JTAG), + GRP("mdio", mdio_func, 1, RT2880_GPIO_MODE_MDIO), + GRP("sdram", sdram_func, 1, RT2880_GPIO_MODE_SDRAM), + GRP("pci", pci_func, 1, RT2880_GPIO_MODE_PCI), + { 0 } }; -static int rt2880_get_group_count(struct pinctrl_dev *pctrldev) +static int rt2880_pinctrl_probe(struct platform_device *pdev) { - struct rt2880_priv *p = pinctrl_dev_get_drvdata(pctrldev); - - return p->group_count; + return ralink_pinctrl_init(pdev, rt2880_pinmux_data_act); } -static const char *rt2880_get_group_name(struct pinctrl_dev *pctrldev, - unsigned int group) -{ - struct rt2880_priv *p = pinctrl_dev_get_drvdata(pctrldev); - - return (group >= p->group_count) ? NULL : p->group_names[group]; -} - -static int rt2880_get_group_pins(struct pinctrl_dev *pctrldev, - unsigned int group, - const unsigned int **pins, - unsigned int *num_pins) -{ - struct rt2880_priv *p = pinctrl_dev_get_drvdata(pctrldev); - - if (group >= p->group_count) - return -EINVAL; - - *pins = p->groups[group].func[0].pins; - *num_pins = p->groups[group].func[0].pin_count; - - return 0; -} - -static const struct pinctrl_ops rt2880_pctrl_ops = { - .get_groups_count = rt2880_get_group_count, - .get_group_name = rt2880_get_group_name, - .get_group_pins = rt2880_get_group_pins, - .dt_node_to_map = pinconf_generic_dt_node_to_map_all, - .dt_free_map = pinconf_generic_dt_free_map, +static const struct of_device_id rt2880_pinctrl_match[] = { + { .compatible = "ralink,rt2880-pinctrl" }, + {} }; - -static int rt2880_pmx_func_count(struct pinctrl_dev *pctrldev) -{ - struct rt2880_priv *p = pinctrl_dev_get_drvdata(pctrldev); - - return p->func_count; -} - -static const char *rt2880_pmx_func_name(struct pinctrl_dev *pctrldev, - unsigned int func) -{ - struct rt2880_priv *p = pinctrl_dev_get_drvdata(pctrldev); - - return p->func[func]->name; -} - -static int rt2880_pmx_group_get_groups(struct pinctrl_dev *pctrldev, - unsigned int func, - const char * const **groups, - unsigned int * const num_groups) -{ - struct rt2880_priv *p = pinctrl_dev_get_drvdata(pctrldev); - - if (p->func[func]->group_count == 1) - *groups = &p->group_names[p->func[func]->groups[0]]; - else - *groups = p->group_names; - - *num_groups = p->func[func]->group_count; - - return 0; -} - -static int rt2880_pmx_group_enable(struct pinctrl_dev *pctrldev, - unsigned int func, unsigned int group) -{ - struct rt2880_priv *p = pinctrl_dev_get_drvdata(pctrldev); - u32 mode = 0; - u32 reg = SYSC_REG_GPIO_MODE; - int i; - int shift; - - /* dont allow double use */ - if (p->groups[group].enabled) { - dev_err(p->dev, "%s is already enabled\n", - p->groups[group].name); - return 0; - } - - p->groups[group].enabled = 1; - p->func[func]->enabled = 1; - - shift = p->groups[group].shift; - if (shift >= 32) { - shift -= 32; - reg = SYSC_REG_GPIO_MODE2; - } - mode = rt_sysc_r32(reg); - mode &= ~(p->groups[group].mask << shift); - - /* mark the pins as gpio */ - for (i = 0; i < p->groups[group].func[0].pin_count; i++) - p->gpio[p->groups[group].func[0].pins[i]] = 1; - - /* function 0 is gpio and needs special handling */ - if (func == 0) { - mode |= p->groups[group].gpio << shift; - } else { - for (i = 0; i < p->func[func]->pin_count; i++) - p->gpio[p->func[func]->pins[i]] = 0; - mode |= p->func[func]->value << shift; - } - rt_sysc_w32(mode, reg); - - return 0; -} - -static int rt2880_pmx_group_gpio_request_enable(struct pinctrl_dev *pctrldev, - struct pinctrl_gpio_range *range, - unsigned int pin) -{ - struct rt2880_priv *p = pinctrl_dev_get_drvdata(pctrldev); - - if (!p->gpio[pin]) { - dev_err(p->dev, "pin %d is not set to gpio mux\n", pin); - return -EINVAL; - } - - return 0; -} - -static const struct pinmux_ops rt2880_pmx_group_ops = { - .get_functions_count = rt2880_pmx_func_count, - .get_function_name = rt2880_pmx_func_name, - .get_function_groups = rt2880_pmx_group_get_groups, - .set_mux = rt2880_pmx_group_enable, - .gpio_request_enable = rt2880_pmx_group_gpio_request_enable, +MODULE_DEVICE_TABLE(of, rt2880_pinctrl_match); + +static struct platform_driver rt2880_pinctrl_driver = { + .probe = rt2880_pinctrl_probe, + .driver = { + .name = "rt2880-pinctrl", + .of_match_table = rt2880_pinctrl_match, + }, }; -static struct pinctrl_desc rt2880_pctrl_desc = { - .owner = THIS_MODULE, - .name = "rt2880-pinmux", - .pctlops = &rt2880_pctrl_ops, - .pmxops = &rt2880_pmx_group_ops, -}; - -static struct rt2880_pmx_func gpio_func = { - .name = "gpio", -}; - -static int rt2880_pinmux_index(struct rt2880_priv *p) -{ - struct rt2880_pmx_group *mux = p->groups; - int i, j, c = 0; - - /* count the mux functions */ - while (mux->name) { - p->group_count++; - mux++; - } - - /* allocate the group names array needed by the gpio function */ - p->group_names = devm_kcalloc(p->dev, p->group_count, - sizeof(char *), GFP_KERNEL); - if (!p->group_names) - return -ENOMEM; - - for (i = 0; i < p->group_count; i++) { - p->group_names[i] = p->groups[i].name; - p->func_count += p->groups[i].func_count; - } - - /* we have a dummy function[0] for gpio */ - p->func_count++; - - /* allocate our function and group mapping index buffers */ - p->func = devm_kcalloc(p->dev, p->func_count, - sizeof(*p->func), GFP_KERNEL); - gpio_func.groups = devm_kcalloc(p->dev, p->group_count, sizeof(int), - GFP_KERNEL); - if (!p->func || !gpio_func.groups) - return -ENOMEM; - - /* add a backpointer to the function so it knows its group */ - gpio_func.group_count = p->group_count; - for (i = 0; i < gpio_func.group_count; i++) - gpio_func.groups[i] = i; - - p->func[c] = &gpio_func; - c++; - - /* add remaining functions */ - for (i = 0; i < p->group_count; i++) { - for (j = 0; j < p->groups[i].func_count; j++) { - p->func[c] = &p->groups[i].func[j]; - p->func[c]->groups = devm_kzalloc(p->dev, sizeof(int), - GFP_KERNEL); - if (!p->func[c]->groups) - return -ENOMEM; - p->func[c]->groups[0] = i; - p->func[c]->group_count = 1; - c++; - } - } - return 0; -} - -static int rt2880_pinmux_pins(struct rt2880_priv *p) +static int __init rt2880_pinctrl_init(void) { - int i, j; - - /* - * loop over the functions and initialize the pins array. - * also work out the highest pin used. - */ - for (i = 0; i < p->func_count; i++) { - int pin; - - if (!p->func[i]->pin_count) - continue; - - p->func[i]->pins = devm_kcalloc(p->dev, - p->func[i]->pin_count, - sizeof(int), - GFP_KERNEL); - for (j = 0; j < p->func[i]->pin_count; j++) - p->func[i]->pins[j] = p->func[i]->pin_first + j; - - pin = p->func[i]->pin_first + p->func[i]->pin_count; - if (pin > p->max_pins) - p->max_pins = pin; - } - - /* the buffer that tells us which pins are gpio */ - p->gpio = devm_kcalloc(p->dev, p->max_pins, sizeof(u8), GFP_KERNEL); - /* the pads needed to tell pinctrl about our pins */ - p->pads = devm_kcalloc(p->dev, p->max_pins, - sizeof(struct pinctrl_pin_desc), GFP_KERNEL); - if (!p->pads || !p->gpio) - return -ENOMEM; - - memset(p->gpio, 1, sizeof(u8) * p->max_pins); - for (i = 0; i < p->func_count; i++) { - if (!p->func[i]->pin_count) - continue; - - for (j = 0; j < p->func[i]->pin_count; j++) - p->gpio[p->func[i]->pins[j]] = 0; - } - - /* pin 0 is always a gpio */ - p->gpio[0] = 1; - - /* set the pads */ - for (i = 0; i < p->max_pins; i++) { - /* strlen("ioXY") + 1 = 5 */ - char *name = devm_kzalloc(p->dev, 5, GFP_KERNEL); - - if (!name) - return -ENOMEM; - snprintf(name, 5, "io%d", i); - p->pads[i].number = i; - p->pads[i].name = name; - } - p->desc->pins = p->pads; - p->desc->npins = p->max_pins; - - return 0; -} - -int rt2880_pinmux_init(struct platform_device *pdev, - struct rt2880_pmx_group *data) -{ - struct rt2880_priv *p; - struct pinctrl_dev *dev; - int err; - - if (!data) - return -ENOTSUPP; - - /* setup the private data */ - p = devm_kzalloc(&pdev->dev, sizeof(struct rt2880_priv), GFP_KERNEL); - if (!p) - return -ENOMEM; - - p->dev = &pdev->dev; - p->desc = &rt2880_pctrl_desc; - p->groups = data; - platform_set_drvdata(pdev, p); - - /* init the device */ - err = rt2880_pinmux_index(p); - if (err) { - dev_err(&pdev->dev, "failed to load index\n"); - return err; - } - - err = rt2880_pinmux_pins(p); - if (err) { - dev_err(&pdev->dev, "failed to load pins\n"); - return err; - } - dev = pinctrl_register(p->desc, &pdev->dev, p); - - return PTR_ERR_OR_ZERO(dev); + return platform_driver_register(&rt2880_pinctrl_driver); } +core_initcall_sync(rt2880_pinctrl_init); diff --git a/drivers/pinctrl/ralink/pinctrl-rt288x.c b/drivers/pinctrl/ralink/pinctrl-rt288x.c deleted file mode 100644 index 0744aebbace529101a4c14206dd7f0e81df9042c..0000000000000000000000000000000000000000 --- a/drivers/pinctrl/ralink/pinctrl-rt288x.c +++ /dev/null @@ -1,60 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only - -#include -#include -#include -#include -#include "pinmux.h" - -#define RT2880_GPIO_MODE_I2C BIT(0) -#define RT2880_GPIO_MODE_UART0 BIT(1) -#define RT2880_GPIO_MODE_SPI BIT(2) -#define RT2880_GPIO_MODE_UART1 BIT(3) -#define RT2880_GPIO_MODE_JTAG BIT(4) -#define RT2880_GPIO_MODE_MDIO BIT(5) -#define RT2880_GPIO_MODE_SDRAM BIT(6) -#define RT2880_GPIO_MODE_PCI BIT(7) - -static struct rt2880_pmx_func i2c_func[] = { FUNC("i2c", 0, 1, 2) }; -static struct rt2880_pmx_func spi_func[] = { FUNC("spi", 0, 3, 4) }; -static struct rt2880_pmx_func uartlite_func[] = { FUNC("uartlite", 0, 7, 8) }; -static struct rt2880_pmx_func jtag_func[] = { FUNC("jtag", 0, 17, 5) }; -static struct rt2880_pmx_func mdio_func[] = { FUNC("mdio", 0, 22, 2) }; -static struct rt2880_pmx_func sdram_func[] = { FUNC("sdram", 0, 24, 16) }; -static struct rt2880_pmx_func pci_func[] = { FUNC("pci", 0, 40, 32) }; - -static struct rt2880_pmx_group rt2880_pinmux_data_act[] = { - GRP("i2c", i2c_func, 1, RT2880_GPIO_MODE_I2C), - GRP("spi", spi_func, 1, RT2880_GPIO_MODE_SPI), - GRP("uartlite", uartlite_func, 1, RT2880_GPIO_MODE_UART0), - GRP("jtag", jtag_func, 1, RT2880_GPIO_MODE_JTAG), - GRP("mdio", mdio_func, 1, RT2880_GPIO_MODE_MDIO), - GRP("sdram", sdram_func, 1, RT2880_GPIO_MODE_SDRAM), - GRP("pci", pci_func, 1, RT2880_GPIO_MODE_PCI), - { 0 } -}; - -static int rt288x_pinmux_probe(struct platform_device *pdev) -{ - return rt2880_pinmux_init(pdev, rt2880_pinmux_data_act); -} - -static const struct of_device_id rt288x_pinmux_match[] = { - { .compatible = "ralink,rt2880-pinmux" }, - {} -}; -MODULE_DEVICE_TABLE(of, rt288x_pinmux_match); - -static struct platform_driver rt288x_pinmux_driver = { - .probe = rt288x_pinmux_probe, - .driver = { - .name = "rt2880-pinmux", - .of_match_table = rt288x_pinmux_match, - }, -}; - -static int __init rt288x_pinmux_init(void) -{ - return platform_driver_register(&rt288x_pinmux_driver); -} -core_initcall_sync(rt288x_pinmux_init); diff --git a/drivers/pinctrl/ralink/pinctrl-rt305x.c b/drivers/pinctrl/ralink/pinctrl-rt305x.c index 5d8fa156c0037be21c6b8c8ccf21a2492d61ae8a..5b204b7ca1f3c6e119125f978e15363afd4df3a5 100644 --- a/drivers/pinctrl/ralink/pinctrl-rt305x.c +++ b/drivers/pinctrl/ralink/pinctrl-rt305x.c @@ -5,7 +5,7 @@ #include #include #include -#include "pinmux.h" +#include "pinctrl-ralink.h" #define RT305X_GPIO_MODE_UART0_SHIFT 2 #define RT305X_GPIO_MODE_UART0_MASK 0x7 @@ -31,9 +31,9 @@ #define RT3352_GPIO_MODE_LNA 18 #define RT3352_GPIO_MODE_PA 20 -static struct rt2880_pmx_func i2c_func[] = { FUNC("i2c", 0, 1, 2) }; -static struct rt2880_pmx_func spi_func[] = { FUNC("spi", 0, 3, 4) }; -static struct rt2880_pmx_func uartf_func[] = { +static struct ralink_pmx_func i2c_func[] = { FUNC("i2c", 0, 1, 2) }; +static struct ralink_pmx_func spi_func[] = { FUNC("spi", 0, 3, 4) }; +static struct ralink_pmx_func uartf_func[] = { FUNC("uartf", RT305X_GPIO_MODE_UARTF, 7, 8), FUNC("pcm uartf", RT305X_GPIO_MODE_PCM_UARTF, 7, 8), FUNC("pcm i2s", RT305X_GPIO_MODE_PCM_I2S, 7, 8), @@ -42,28 +42,28 @@ static struct rt2880_pmx_func uartf_func[] = { FUNC("gpio uartf", RT305X_GPIO_MODE_GPIO_UARTF, 7, 4), FUNC("gpio i2s", RT305X_GPIO_MODE_GPIO_I2S, 7, 4), }; -static struct rt2880_pmx_func uartlite_func[] = { FUNC("uartlite", 0, 15, 2) }; -static struct rt2880_pmx_func jtag_func[] = { FUNC("jtag", 0, 17, 5) }; -static struct rt2880_pmx_func mdio_func[] = { FUNC("mdio", 0, 22, 2) }; -static struct rt2880_pmx_func rt5350_led_func[] = { FUNC("led", 0, 22, 5) }; -static struct rt2880_pmx_func rt5350_cs1_func[] = { +static struct ralink_pmx_func uartlite_func[] = { FUNC("uartlite", 0, 15, 2) }; +static struct ralink_pmx_func jtag_func[] = { FUNC("jtag", 0, 17, 5) }; +static struct ralink_pmx_func mdio_func[] = { FUNC("mdio", 0, 22, 2) }; +static struct ralink_pmx_func rt5350_led_func[] = { FUNC("led", 0, 22, 5) }; +static struct ralink_pmx_func rt5350_cs1_func[] = { FUNC("spi_cs1", 0, 27, 1), FUNC("wdg_cs1", 1, 27, 1), }; -static struct rt2880_pmx_func sdram_func[] = { FUNC("sdram", 0, 24, 16) }; -static struct rt2880_pmx_func rt3352_rgmii_func[] = { +static struct ralink_pmx_func sdram_func[] = { FUNC("sdram", 0, 24, 16) }; +static struct ralink_pmx_func rt3352_rgmii_func[] = { FUNC("rgmii", 0, 24, 12) }; -static struct rt2880_pmx_func rgmii_func[] = { FUNC("rgmii", 0, 40, 12) }; -static struct rt2880_pmx_func rt3352_lna_func[] = { FUNC("lna", 0, 36, 2) }; -static struct rt2880_pmx_func rt3352_pa_func[] = { FUNC("pa", 0, 38, 2) }; -static struct rt2880_pmx_func rt3352_led_func[] = { FUNC("led", 0, 40, 5) }; -static struct rt2880_pmx_func rt3352_cs1_func[] = { +static struct ralink_pmx_func rgmii_func[] = { FUNC("rgmii", 0, 40, 12) }; +static struct ralink_pmx_func rt3352_lna_func[] = { FUNC("lna", 0, 36, 2) }; +static struct ralink_pmx_func rt3352_pa_func[] = { FUNC("pa", 0, 38, 2) }; +static struct ralink_pmx_func rt3352_led_func[] = { FUNC("led", 0, 40, 5) }; +static struct ralink_pmx_func rt3352_cs1_func[] = { FUNC("spi_cs1", 0, 45, 1), FUNC("wdg_cs1", 1, 45, 1), }; -static struct rt2880_pmx_group rt3050_pinmux_data[] = { +static struct ralink_pmx_group rt3050_pinmux_data[] = { GRP("i2c", i2c_func, 1, RT305X_GPIO_MODE_I2C), GRP("spi", spi_func, 1, RT305X_GPIO_MODE_SPI), GRP("uartf", uartf_func, RT305X_GPIO_MODE_UART0_MASK, @@ -76,7 +76,7 @@ static struct rt2880_pmx_group rt3050_pinmux_data[] = { { 0 } }; -static struct rt2880_pmx_group rt3352_pinmux_data[] = { +static struct ralink_pmx_group rt3352_pinmux_data[] = { GRP("i2c", i2c_func, 1, RT305X_GPIO_MODE_I2C), GRP("spi", spi_func, 1, RT305X_GPIO_MODE_SPI), GRP("uartf", uartf_func, RT305X_GPIO_MODE_UART0_MASK, @@ -92,7 +92,7 @@ static struct rt2880_pmx_group rt3352_pinmux_data[] = { { 0 } }; -static struct rt2880_pmx_group rt5350_pinmux_data[] = { +static struct ralink_pmx_group rt5350_pinmux_data[] = { GRP("i2c", i2c_func, 1, RT305X_GPIO_MODE_I2C), GRP("spi", spi_func, 1, RT305X_GPIO_MODE_SPI), GRP("uartf", uartf_func, RT305X_GPIO_MODE_UART0_MASK, @@ -104,34 +104,34 @@ static struct rt2880_pmx_group rt5350_pinmux_data[] = { { 0 } }; -static int rt305x_pinmux_probe(struct platform_device *pdev) +static int rt305x_pinctrl_probe(struct platform_device *pdev) { if (soc_is_rt5350()) - return rt2880_pinmux_init(pdev, rt5350_pinmux_data); + return ralink_pinctrl_init(pdev, rt5350_pinmux_data); else if (soc_is_rt305x() || soc_is_rt3350()) - return rt2880_pinmux_init(pdev, rt3050_pinmux_data); + return ralink_pinctrl_init(pdev, rt3050_pinmux_data); else if (soc_is_rt3352()) - return rt2880_pinmux_init(pdev, rt3352_pinmux_data); + return ralink_pinctrl_init(pdev, rt3352_pinmux_data); else return -EINVAL; } -static const struct of_device_id rt305x_pinmux_match[] = { - { .compatible = "ralink,rt2880-pinmux" }, +static const struct of_device_id rt305x_pinctrl_match[] = { + { .compatible = "ralink,rt305x-pinctrl" }, {} }; -MODULE_DEVICE_TABLE(of, rt305x_pinmux_match); +MODULE_DEVICE_TABLE(of, rt305x_pinctrl_match); -static struct platform_driver rt305x_pinmux_driver = { - .probe = rt305x_pinmux_probe, +static struct platform_driver rt305x_pinctrl_driver = { + .probe = rt305x_pinctrl_probe, .driver = { - .name = "rt2880-pinmux", - .of_match_table = rt305x_pinmux_match, + .name = "rt305x-pinctrl", + .of_match_table = rt305x_pinctrl_match, }, }; -static int __init rt305x_pinmux_init(void) +static int __init rt305x_pinctrl_init(void) { - return platform_driver_register(&rt305x_pinmux_driver); + return platform_driver_register(&rt305x_pinctrl_driver); } -core_initcall_sync(rt305x_pinmux_init); +core_initcall_sync(rt305x_pinctrl_init); diff --git a/drivers/pinctrl/ralink/pinctrl-rt3883.c b/drivers/pinctrl/ralink/pinctrl-rt3883.c index 3e0e1b4caa647ecaf4fd36489ecca5e6667090b1..44a66c3d2d2a1138a8e3b53bc76a6cd0c30c7882 100644 --- a/drivers/pinctrl/ralink/pinctrl-rt3883.c +++ b/drivers/pinctrl/ralink/pinctrl-rt3883.c @@ -3,7 +3,7 @@ #include #include #include -#include "pinmux.h" +#include "pinctrl-ralink.h" #define RT3883_GPIO_MODE_UART0_SHIFT 2 #define RT3883_GPIO_MODE_UART0_MASK 0x7 @@ -39,9 +39,9 @@ #define RT3883_GPIO_MODE_LNA_G_GPIO 0x3 #define RT3883_GPIO_MODE_LNA_G _RT3883_GPIO_MODE_LNA_G(RT3883_GPIO_MODE_LNA_G_MASK) -static struct rt2880_pmx_func i2c_func[] = { FUNC("i2c", 0, 1, 2) }; -static struct rt2880_pmx_func spi_func[] = { FUNC("spi", 0, 3, 4) }; -static struct rt2880_pmx_func uartf_func[] = { +static struct ralink_pmx_func i2c_func[] = { FUNC("i2c", 0, 1, 2) }; +static struct ralink_pmx_func spi_func[] = { FUNC("spi", 0, 3, 4) }; +static struct ralink_pmx_func uartf_func[] = { FUNC("uartf", RT3883_GPIO_MODE_UARTF, 7, 8), FUNC("pcm uartf", RT3883_GPIO_MODE_PCM_UARTF, 7, 8), FUNC("pcm i2s", RT3883_GPIO_MODE_PCM_I2S, 7, 8), @@ -50,21 +50,21 @@ static struct rt2880_pmx_func uartf_func[] = { FUNC("gpio uartf", RT3883_GPIO_MODE_GPIO_UARTF, 7, 4), FUNC("gpio i2s", RT3883_GPIO_MODE_GPIO_I2S, 7, 4), }; -static struct rt2880_pmx_func uartlite_func[] = { FUNC("uartlite", 0, 15, 2) }; -static struct rt2880_pmx_func jtag_func[] = { FUNC("jtag", 0, 17, 5) }; -static struct rt2880_pmx_func mdio_func[] = { FUNC("mdio", 0, 22, 2) }; -static struct rt2880_pmx_func lna_a_func[] = { FUNC("lna a", 0, 32, 3) }; -static struct rt2880_pmx_func lna_g_func[] = { FUNC("lna g", 0, 35, 3) }; -static struct rt2880_pmx_func pci_func[] = { +static struct ralink_pmx_func uartlite_func[] = { FUNC("uartlite", 0, 15, 2) }; +static struct ralink_pmx_func jtag_func[] = { FUNC("jtag", 0, 17, 5) }; +static struct ralink_pmx_func mdio_func[] = { FUNC("mdio", 0, 22, 2) }; +static struct ralink_pmx_func lna_a_func[] = { FUNC("lna a", 0, 32, 3) }; +static struct ralink_pmx_func lna_g_func[] = { FUNC("lna g", 0, 35, 3) }; +static struct ralink_pmx_func pci_func[] = { FUNC("pci-dev", 0, 40, 32), FUNC("pci-host2", 1, 40, 32), FUNC("pci-host1", 2, 40, 32), FUNC("pci-fnc", 3, 40, 32) }; -static struct rt2880_pmx_func ge1_func[] = { FUNC("ge1", 0, 72, 12) }; -static struct rt2880_pmx_func ge2_func[] = { FUNC("ge2", 0, 84, 12) }; +static struct ralink_pmx_func ge1_func[] = { FUNC("ge1", 0, 72, 12) }; +static struct ralink_pmx_func ge2_func[] = { FUNC("ge2", 0, 84, 12) }; -static struct rt2880_pmx_group rt3883_pinmux_data[] = { +static struct ralink_pmx_group rt3883_pinmux_data[] = { GRP("i2c", i2c_func, 1, RT3883_GPIO_MODE_I2C), GRP("spi", spi_func, 1, RT3883_GPIO_MODE_SPI), GRP("uartf", uartf_func, RT3883_GPIO_MODE_UART0_MASK, @@ -81,27 +81,27 @@ static struct rt2880_pmx_group rt3883_pinmux_data[] = { { 0 } }; -static int rt3883_pinmux_probe(struct platform_device *pdev) +static int rt3883_pinctrl_probe(struct platform_device *pdev) { - return rt2880_pinmux_init(pdev, rt3883_pinmux_data); + return ralink_pinctrl_init(pdev, rt3883_pinmux_data); } -static const struct of_device_id rt3883_pinmux_match[] = { - { .compatible = "ralink,rt2880-pinmux" }, +static const struct of_device_id rt3883_pinctrl_match[] = { + { .compatible = "ralink,rt3883-pinctrl" }, {} }; -MODULE_DEVICE_TABLE(of, rt3883_pinmux_match); +MODULE_DEVICE_TABLE(of, rt3883_pinctrl_match); -static struct platform_driver rt3883_pinmux_driver = { - .probe = rt3883_pinmux_probe, +static struct platform_driver rt3883_pinctrl_driver = { + .probe = rt3883_pinctrl_probe, .driver = { - .name = "rt2880-pinmux", - .of_match_table = rt3883_pinmux_match, + .name = "rt3883-pinctrl", + .of_match_table = rt3883_pinctrl_match, }, }; -static int __init rt3883_pinmux_init(void) +static int __init rt3883_pinctrl_init(void) { - return platform_driver_register(&rt3883_pinmux_driver); + return platform_driver_register(&rt3883_pinctrl_driver); } -core_initcall_sync(rt3883_pinmux_init); +core_initcall_sync(rt3883_pinctrl_init); diff --git a/drivers/pinctrl/renesas/Kconfig b/drivers/pinctrl/renesas/Kconfig index 6b38720c56e34c21658c7a5145c237e0706e3399..961007ce7b3aa2af1812f2074cad2d52ac0126bd 100644 --- a/drivers/pinctrl/renesas/Kconfig +++ b/drivers/pinctrl/renesas/Kconfig @@ -38,8 +38,7 @@ config PINCTRL_RENESAS select PINCTRL_PFC_R8A77995 if ARCH_R8A77995 select PINCTRL_PFC_R8A779A0 if ARCH_R8A779A0 select PINCTRL_PFC_R8A779F0 if ARCH_R8A779F0 - select PINCTRL_RZG2L if ARCH_R9A07G044 - select PINCTRL_RZG2L if ARCH_R9A07G054 + select PINCTRL_RZG2L if ARCH_RZG2L select PINCTRL_PFC_SH7203 if CPU_SUBTYPE_SH7203 select PINCTRL_PFC_SH7264 if CPU_SUBTYPE_SH7264 select PINCTRL_PFC_SH7269 if CPU_SUBTYPE_SH7269 @@ -184,14 +183,14 @@ config PINCTRL_RZA2 This selects GPIO and pinctrl driver for Renesas RZ/A2 platforms. config PINCTRL_RZG2L - bool "pin control support for RZ/{G2L,V2L}" if COMPILE_TEST + bool "pin control support for RZ/{G2L,G2UL,V2L}" if COMPILE_TEST depends on OF select GPIOLIB select GENERIC_PINCTRL_GROUPS select GENERIC_PINMUX_FUNCTIONS select GENERIC_PINCONF help - This selects GPIO and pinctrl driver for Renesas RZ/{G2L,V2L} + This selects GPIO and pinctrl driver for Renesas RZ/{G2L,G2UL,V2L} platforms. config PINCTRL_PFC_R8A77470 diff --git a/drivers/pinctrl/renesas/core.c b/drivers/pinctrl/renesas/core.c index d0d4714731c14cf54b8f600c9371fd304d5c3827..8c14b2021bf0cd2dbdb6dead137d369a13deb330 100644 --- a/drivers/pinctrl/renesas/core.c +++ b/drivers/pinctrl/renesas/core.c @@ -13,10 +13,11 @@ #include #include #include +#include #include #include #include -#include +#include #include #include #include @@ -71,12 +72,11 @@ static int sh_pfc_map_resources(struct sh_pfc *pfc, /* Fill them. */ for (i = 0; i < num_windows; i++) { - res = platform_get_resource(pdev, IORESOURCE_MEM, i); - windows->phys = res->start; - windows->size = resource_size(res); - windows->virt = devm_ioremap_resource(pfc->dev, res); + windows->virt = devm_platform_get_and_ioremap_resource(pdev, i, &res); if (IS_ERR(windows->virt)) return -ENOMEM; + windows->phys = res->start; + windows->size = resource_size(res); windows++; } for (i = 0; i < num_irqs; i++) @@ -214,7 +214,7 @@ static void sh_pfc_config_reg_helper(struct sh_pfc *pfc, *maskp = (1 << crp->var_field_width[in_pos]) - 1; *posp = crp->reg_width; for (k = 0; k <= in_pos; k++) - *posp -= crp->var_field_width[k]; + *posp -= abs(crp->var_field_width[k]); } } @@ -262,14 +262,17 @@ static int sh_pfc_get_config_reg(struct sh_pfc *pfc, u16 enum_id, if (!r_width) break; - for (bit_pos = 0; bit_pos < r_width; bit_pos += curr_width) { + for (bit_pos = 0; bit_pos < r_width; bit_pos += curr_width, m++) { u32 ncomb; u32 n; - if (f_width) + if (f_width) { curr_width = f_width; - else - curr_width = config_reg->var_field_width[m]; + } else { + curr_width = abs(config_reg->var_field_width[m]); + if (config_reg->var_field_width[m] < 0) + continue; + } ncomb = 1 << curr_width; for (n = 0; n < ncomb; n++) { @@ -281,7 +284,6 @@ static int sh_pfc_get_config_reg(struct sh_pfc *pfc, u16 enum_id, } } pos += ncomb; - m++; } k++; } @@ -875,7 +877,8 @@ static const struct sh_pfc_pin __init *sh_pfc_find_pin( static void __init sh_pfc_check_cfg_reg(const char *drvname, const struct pinmux_cfg_reg *cfg_reg) { - unsigned int i, n, rw, fw; + unsigned int i, n, rw, r; + int fw; sh_pfc_check_reg(drvname, cfg_reg->reg, GENMASK(cfg_reg->reg_width - 1, 0)); @@ -883,16 +886,29 @@ static void __init sh_pfc_check_cfg_reg(const char *drvname, if (cfg_reg->field_width) { fw = cfg_reg->field_width; n = (cfg_reg->reg_width / fw) << fw; + for (i = 0, r = 0; i < n; i += 1 << fw) { + if (is0s(&cfg_reg->enum_ids[i], 1 << fw)) + r++; + } + + if ((r << fw) * sizeof(u16) > cfg_reg->reg_width / fw) + sh_pfc_warn("reg 0x%x can be described with variable-width reserved fields\n", + cfg_reg->reg); + /* Skip field checks (done at build time) */ goto check_enum_ids; } for (i = 0, n = 0, rw = 0; (fw = cfg_reg->var_field_width[i]); i++) { - if (fw > 3 && is0s(&cfg_reg->enum_ids[n], 1 << fw)) - sh_pfc_warn("reg 0x%x: reserved field [%u:%u] can be split to reduce table size\n", - cfg_reg->reg, rw, rw + fw - 1); - n += 1 << fw; - rw += fw; + if (fw < 0) { + rw += -fw; + } else { + if (is0s(&cfg_reg->enum_ids[n], 1 << fw)) + sh_pfc_warn("reg 0x%x: field [%u:%u] can be described as reserved\n", + cfg_reg->reg, rw, rw + fw - 1); + n += 1 << fw; + rw += fw; + } } if (rw != cfg_reg->reg_width) @@ -1007,7 +1023,18 @@ static void __init sh_pfc_compare_groups(const char *drvname, static void __init sh_pfc_check_info(const struct sh_pfc_soc_info *info) { const struct pinmux_drive_reg *drive_regs = info->drive_regs; +#define drive_nfields ARRAY_SIZE(drive_regs->fields) +#define drive_ofs(i) drive_regs[(i) / drive_nfields] +#define drive_reg(i) drive_ofs(i).reg +#define drive_bit(i) ((i) % drive_nfields) +#define drive_field(i) drive_ofs(i).fields[drive_bit(i)] const struct pinmux_bias_reg *bias_regs = info->bias_regs; +#define bias_npins ARRAY_SIZE(bias_regs->pins) +#define bias_ofs(i) bias_regs[(i) / bias_npins] +#define bias_puen(i) bias_ofs(i).puen +#define bias_pud(i) bias_ofs(i).pud +#define bias_bit(i) ((i) % bias_npins) +#define bias_pin(i) bias_ofs(i).pins[bias_bit(i)] const char *drvname = info->name; unsigned int *refcnts; unsigned int i, j, k; @@ -1076,17 +1103,17 @@ static void __init sh_pfc_check_info(const struct sh_pfc_soc_info *info) if (!drive_regs) { sh_pfc_err_once(drive, "SH_PFC_PIN_CFG_DRIVE_STRENGTH flag set but drive_regs missing\n"); } else { - for (j = 0; drive_regs[j / 8].reg; j++) { - if (!drive_regs[j / 8].fields[j % 8].pin && - !drive_regs[j / 8].fields[j % 8].offset && - !drive_regs[j / 8].fields[j % 8].size) + for (j = 0; drive_reg(j); j++) { + if (!drive_field(j).pin && + !drive_field(j).offset && + !drive_field(j).size) continue; - if (drive_regs[j / 8].fields[j % 8].pin == pin->pin) + if (drive_field(j).pin == pin->pin) break; } - if (!drive_regs[j / 8].reg) + if (!drive_reg(j)) sh_pfc_err("pin %s: SH_PFC_PIN_CFG_DRIVE_STRENGTH flag set but not in drive_regs\n", pin->name); } @@ -1164,20 +1191,17 @@ static void __init sh_pfc_check_info(const struct sh_pfc_soc_info *info) for (i = 0; drive_regs && drive_regs[i].reg; i++) sh_pfc_check_drive_reg(info, &drive_regs[i]); - for (i = 0; drive_regs && drive_regs[i / 8].reg; i++) { - if (!drive_regs[i / 8].fields[i % 8].pin && - !drive_regs[i / 8].fields[i % 8].offset && - !drive_regs[i / 8].fields[i % 8].size) + for (i = 0; drive_regs && drive_reg(i); i++) { + if (!drive_field(i).pin && !drive_field(i).offset && + !drive_field(i).size) continue; for (j = 0; j < i; j++) { - if (drive_regs[i / 8].fields[i % 8].pin == - drive_regs[j / 8].fields[j % 8].pin && - drive_regs[j / 8].fields[j % 8].offset && - drive_regs[j / 8].fields[j % 8].size) { - sh_pfc_err("drive_reg 0x%x:%u/0x%x:%u: pin conflict\n", - drive_regs[i / 8].reg, i % 8, - drive_regs[j / 8].reg, j % 8); + if (drive_field(i).pin == drive_field(j).pin && + drive_field(j).offset && drive_field(j).size) { + sh_pfc_err("drive_reg 0x%x:%zu/0x%x:%zu: pin conflict\n", + drive_reg(i), drive_bit(i), + drive_reg(j), drive_bit(j)); } } } @@ -1186,26 +1210,23 @@ static void __init sh_pfc_check_info(const struct sh_pfc_soc_info *info) for (i = 0; bias_regs && (bias_regs[i].puen || bias_regs[i].pud); i++) sh_pfc_check_bias_reg(info, &bias_regs[i]); - for (i = 0; bias_regs && - (bias_regs[i / 32].puen || bias_regs[i / 32].pud); i++) { - if (bias_regs[i / 32].pins[i % 32] == SH_PFC_PIN_NONE) + for (i = 0; bias_regs && (bias_puen(i) || bias_pud(i)); i++) { + if (bias_pin(i) == SH_PFC_PIN_NONE) continue; for (j = 0; j < i; j++) { - if (bias_regs[i / 32].pins[i % 32] != - bias_regs[j / 32].pins[j % 32]) + if (bias_pin(i) != bias_pin(j)) continue; - if (bias_regs[i / 32].puen && bias_regs[j / 32].puen) - sh_pfc_err("bias_reg 0x%x:%u/0x%x:%u: pin conflict\n", - bias_regs[i / 32].puen, i % 32, - bias_regs[j / 32].puen, j % 32); - if (bias_regs[i / 32].pud && bias_regs[j / 32].pud) - sh_pfc_err("bias_reg 0x%x:%u/0x%x:%u: pin conflict\n", - bias_regs[i / 32].pud, i % 32, - bias_regs[j / 32].pud, j % 32); + if (bias_puen(i) && bias_puen(j)) + sh_pfc_err("bias_reg 0x%x:%zu/0x%x:%zu: pin conflict\n", + bias_puen(i), bias_bit(i), + bias_puen(j), bias_bit(j)); + if (bias_pud(i) && bias_pud(j)) + sh_pfc_err("bias_reg 0x%x:%zu/0x%x:%zu: pin conflict\n", + bias_pud(i), bias_bit(i), + bias_pud(j), bias_bit(j)); } - } /* Check ioctrl registers */ diff --git a/drivers/pinctrl/renesas/gpio.c b/drivers/pinctrl/renesas/gpio.c index ad06f5355d1ed1c59d99a6826ad5b6a796cfed2c..ea3d38b4af8da4e1a56ab5dfb086bf8152a2ff41 100644 --- a/drivers/pinctrl/renesas/gpio.c +++ b/drivers/pinctrl/renesas/gpio.c @@ -8,7 +8,6 @@ #include #include -#include #include #include #include diff --git a/drivers/pinctrl/renesas/pfc-emev2.c b/drivers/pinctrl/renesas/pfc-emev2.c index 2326d348447d41231ddca2d3ebee72fdf4f0ee4a..1d8b540110f23e4c3c1160e9779054d8593384a5 100644 --- a/drivers/pinctrl/renesas/pfc-emev2.c +++ b/drivers/pinctrl/renesas/pfc-emev2.c @@ -4,7 +4,6 @@ * * Copyright (C) 2015 Niklas Söderlund */ -#include #include #include "sh_pfc.h" @@ -1570,61 +1569,39 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { )) }, { PINMUX_CFG_REG_VAR("CHG_PINSEL_LCD3", 0xe0140284, 32, - GROUP(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, - 2, 2), + GROUP(-20, 2, 2, -6, 2), GROUP( - /* 31 - 12 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, + /* 31 - 12 RESERVED */ /* 11 - 10 */ FN_SEL_LCD3_11_10_00, FN_SEL_LCD3_11_10_01, FN_SEL_LCD3_11_10_10, 0, /* 9 - 8 */ FN_SEL_LCD3_9_8_00, 0, FN_SEL_LCD3_9_8_10, 0, - /* 7 - 2 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 7 - 2 RESERVED */ /* 1 - 0 */ FN_SEL_LCD3_1_0_00, FN_SEL_LCD3_1_0_01, 0, 0, )) }, { PINMUX_CFG_REG_VAR("CHG_PINSEL_UART", 0xe0140288, 32, - GROUP(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 2), + GROUP(-30, 2), GROUP( - /* 31 - 2 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 31 - 2 RESERVED */ /* 1 - 0 */ FN_SEL_UART_1_0_00, FN_SEL_UART_1_0_01, 0, 0, )) }, { PINMUX_CFG_REG_VAR("CHG_PINSEL_IIC", 0xe014028c, 32, - GROUP(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 2), + GROUP(-30, 2), GROUP( - /* 31 - 2 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 31 - 2 RESERVED */ /* 1 - 0 */ FN_SEL_IIC_1_0_00, FN_SEL_IIC_1_0_01, 0, 0, )) }, { PINMUX_CFG_REG_VAR("CHG_PINSEL_AB", 0xe0140294, 32, - GROUP(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2), + GROUP(-18, 2, 2, 2, 2, 2, 2, 2), GROUP( - /* 31 - 14 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, + /* 31 - 14 RESERVED */ /* 13 - 12 */ FN_SEL_AB_13_12_00, 0, FN_SEL_AB_13_12_10, 0, /* 11 - 10 */ @@ -1644,14 +1621,9 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { )) }, { PINMUX_CFG_REG_VAR("CHG_PINSEL_USI", 0xe0140298, 32, - GROUP(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, - 2, 2, 2), + GROUP(-22, 2, 2, 2, 2, 2), GROUP( - /* 31 - 10 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 31 - 10 RESERVED */ /* 9 - 8 */ FN_SEL_USI_9_8_00, FN_SEL_USI_9_8_01, 0, 0, /* 7 - 6 */ @@ -1665,15 +1637,9 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { )) }, { PINMUX_CFG_REG_VAR("CHG_PINSEL_HSI", 0xe01402a8, 32, - GROUP(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 2), + GROUP(-30, 2), GROUP( - /* 31 - 2 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 31 - 2 RESERVED */ /* 1 - 0 */ FN_SEL_HSI_1_0_00, FN_SEL_HSI_1_0_01, 0, 0, )) diff --git a/drivers/pinctrl/renesas/pfc-r8a73a4.c b/drivers/pinctrl/renesas/pfc-r8a73a4.c index ba3a1857f80a08c4a36b540264d3c81adf765c11..dbfc46fe2f2770924f047bbbf48d1283ecb67205 100644 --- a/drivers/pinctrl/renesas/pfc-r8a73a4.c +++ b/drivers/pinctrl/renesas/pfc-r8a73a4.c @@ -2270,15 +2270,17 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { MSEL1CR_00_0, MSEL1CR_00_1, )) }, - { PINMUX_CFG_REG("MSEL3CR", 0xe6058020, 32, 1, GROUP( + { PINMUX_CFG_REG_VAR("MSEL3CR", 0xe6058020, 32, + GROUP(1, -2, 1, 1, 1, -2, 1, 1, 1, 1, 1, 1, + 1, 1, 1, -2, 1, 1, 1, 1, -2, 1, -2, 1, + -1, 1, 1), + GROUP( MSEL3CR_31_0, MSEL3CR_31_1, - 0, 0, - 0, 0, + /* RESERVED [2] */ MSEL3CR_28_0, MSEL3CR_28_1, MSEL3CR_27_0, MSEL3CR_27_1, MSEL3CR_26_0, MSEL3CR_26_1, - 0, 0, - 0, 0, + /* RESERVED [2] */ MSEL3CR_23_0, MSEL3CR_23_1, MSEL3CR_22_0, MSEL3CR_22_1, MSEL3CR_21_0, MSEL3CR_21_1, @@ -2288,19 +2290,16 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { MSEL3CR_17_0, MSEL3CR_17_1, MSEL3CR_16_0, MSEL3CR_16_1, MSEL3CR_15_0, MSEL3CR_15_1, - 0, 0, - 0, 0, + /* RESERVED [2] */ MSEL3CR_12_0, MSEL3CR_12_1, MSEL3CR_11_0, MSEL3CR_11_1, MSEL3CR_10_0, MSEL3CR_10_1, MSEL3CR_09_0, MSEL3CR_09_1, - 0, 0, - 0, 0, + /* RESERVED [2] */ MSEL3CR_06_0, MSEL3CR_06_1, - 0, 0, - 0, 0, + /* RESERVED [2] */ MSEL3CR_03_0, MSEL3CR_03_1, - 0, 0, + /* RESERVED [1] */ MSEL3CR_01_0, MSEL3CR_01_1, MSEL3CR_00_0, MSEL3CR_00_1, )) @@ -2375,37 +2374,12 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { 0, 0, )) }, - { PINMUX_CFG_REG("MSEL8CR", 0xe6058034, 32, 1, GROUP( - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("MSEL8CR", 0xe6058034, 32, + GROUP(-15, 1, -14, 1, 1), + GROUP( + /* RESERVED [15] */ MSEL8CR_16_0, MSEL8CR_16_1, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + /* RESERVED [14] */ MSEL8CR_01_0, MSEL8CR_01_1, MSEL8CR_00_0, MSEL8CR_00_1, )) diff --git a/drivers/pinctrl/renesas/pfc-r8a7740.c b/drivers/pinctrl/renesas/pfc-r8a7740.c index e8b9fb74a802ac035bc26151b408ba632292ac10..6dcd39918daf96bca1d255c9d6e46917a3bfd9bb 100644 --- a/drivers/pinctrl/renesas/pfc-r8a7740.c +++ b/drivers/pinctrl/renesas/pfc-r8a7740.c @@ -3250,89 +3250,93 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { PORTCR(210, 0xe60530d2), /* PORT210CR */ PORTCR(211, 0xe60530d3), /* PORT211CR */ - { PINMUX_CFG_REG("MSEL1CR", 0xe605800c, 32, 1, GROUP( + { PINMUX_CFG_REG_VAR("MSEL1CR", 0xe605800c, 32, + GROUP(1, 1, 1, 1, 1, 1, -9, 1, 1, 1, 1, 1, + -2, 1, -1, 1, 1, 1, 1, 1, 1, -1, 1), + GROUP( MSEL1CR_31_0, MSEL1CR_31_1, MSEL1CR_30_0, MSEL1CR_30_1, MSEL1CR_29_0, MSEL1CR_29_1, MSEL1CR_28_0, MSEL1CR_28_1, MSEL1CR_27_0, MSEL1CR_27_1, MSEL1CR_26_0, MSEL1CR_26_1, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, + /* RESERVED [9] */ MSEL1CR_16_0, MSEL1CR_16_1, MSEL1CR_15_0, MSEL1CR_15_1, MSEL1CR_14_0, MSEL1CR_14_1, MSEL1CR_13_0, MSEL1CR_13_1, MSEL1CR_12_0, MSEL1CR_12_1, - 0, 0, 0, 0, + /* RESERVED [2] */ MSEL1CR_9_0, MSEL1CR_9_1, - 0, 0, + /* RESERVED [1] */ MSEL1CR_7_0, MSEL1CR_7_1, MSEL1CR_6_0, MSEL1CR_6_1, MSEL1CR_5_0, MSEL1CR_5_1, MSEL1CR_4_0, MSEL1CR_4_1, MSEL1CR_3_0, MSEL1CR_3_1, MSEL1CR_2_0, MSEL1CR_2_1, - 0, 0, + /* RESERVED [1] */ MSEL1CR_0_0, MSEL1CR_0_1, )) }, - { PINMUX_CFG_REG("MSEL3CR", 0xE6058020, 32, 1, GROUP( - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, + { PINMUX_CFG_REG_VAR("MSEL3CR", 0xE6058020, 32, + GROUP(-16, 1, -8, 1, -6), + GROUP( + /* RESERVED [16] */ MSEL3CR_15_0, MSEL3CR_15_1, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, + /* RESERVED [8] */ MSEL3CR_6_0, MSEL3CR_6_1, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, + /* RESERVED [6] */ )) }, - { PINMUX_CFG_REG("MSEL4CR", 0xE6058024, 32, 1, GROUP( - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, + { PINMUX_CFG_REG_VAR("MSEL4CR", 0xE6058024, 32, + GROUP(-12, 1, 1, -2, 1, -4, 1, -3, 1, -1, 1, -2, + 1, -1), + GROUP( + /* RESERVED [12] */ MSEL4CR_19_0, MSEL4CR_19_1, MSEL4CR_18_0, MSEL4CR_18_1, - 0, 0, 0, 0, + /* RESERVED [2] */ MSEL4CR_15_0, MSEL4CR_15_1, - 0, 0, 0, 0, 0, 0, 0, 0, + /* RESERVED [4] */ MSEL4CR_10_0, MSEL4CR_10_1, - 0, 0, 0, 0, 0, 0, + /* RESERVED [3] */ MSEL4CR_6_0, MSEL4CR_6_1, - 0, 0, + /* RESERVED [1] */ MSEL4CR_4_0, MSEL4CR_4_1, - 0, 0, 0, 0, + /* RESERVED [2] */ MSEL4CR_1_0, MSEL4CR_1_1, - 0, 0, + /* RESERVED [1] */ )) }, - { PINMUX_CFG_REG("MSEL5CR", 0xE6058028, 32, 1, GROUP( + { PINMUX_CFG_REG_VAR("MSEL5CR", 0xE6058028, 32, + GROUP(1, 1, 1, -1, 1, -1, 1, -1, 1, -1, 1, + -1, 1, -1, 1, -1, 1, 1, 1, 1, 1, 1, + -1, 1, 1, 1, 1, 1, 1, 1, -1, 1), + GROUP( MSEL5CR_31_0, MSEL5CR_31_1, MSEL5CR_30_0, MSEL5CR_30_1, MSEL5CR_29_0, MSEL5CR_29_1, - 0, 0, + /* RESERVED [1] */ MSEL5CR_27_0, MSEL5CR_27_1, - 0, 0, + /* RESERVED [1] */ MSEL5CR_25_0, MSEL5CR_25_1, - 0, 0, + /* RESERVED [1] */ MSEL5CR_23_0, MSEL5CR_23_1, - 0, 0, + /* RESERVED [1] */ MSEL5CR_21_0, MSEL5CR_21_1, - 0, 0, + /* RESERVED [1] */ MSEL5CR_19_0, MSEL5CR_19_1, - 0, 0, + /* RESERVED [1] */ MSEL5CR_17_0, MSEL5CR_17_1, - 0, 0, + /* RESERVED [1] */ MSEL5CR_15_0, MSEL5CR_15_1, MSEL5CR_14_0, MSEL5CR_14_1, MSEL5CR_13_0, MSEL5CR_13_1, MSEL5CR_12_0, MSEL5CR_12_1, MSEL5CR_11_0, MSEL5CR_11_1, MSEL5CR_10_0, MSEL5CR_10_1, - 0, 0, + /* RESERVED [1] */ MSEL5CR_8_0, MSEL5CR_8_1, MSEL5CR_7_0, MSEL5CR_7_1, MSEL5CR_6_0, MSEL5CR_6_1, @@ -3340,7 +3344,7 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { MSEL5CR_4_0, MSEL5CR_4_1, MSEL5CR_3_0, MSEL5CR_3_1, MSEL5CR_2_0, MSEL5CR_2_1, - 0, 0, + /* RESERVED [1] */ MSEL5CR_0_0, MSEL5CR_0_1, )) }, diff --git a/drivers/pinctrl/renesas/pfc-r8a77470.c b/drivers/pinctrl/renesas/pfc-r8a77470.c index ee6e8fabab246c2b4deb134964ed8aacd9a316fa..b5725c3ed2b60e8828bfbd28796ef61e1ebbf656 100644 --- a/drivers/pinctrl/renesas/pfc-r8a77470.c +++ b/drivers/pinctrl/renesas/pfc-r8a77470.c @@ -2485,16 +2485,11 @@ static const struct sh_pfc_function pinmux_functions[] = { }; static const struct pinmux_cfg_reg pinmux_config_regs[] = { - { PINMUX_CFG_REG("GPSR0", 0xE6060004, 32, 1, GROUP( - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("GPSR0", 0xE6060004, 32, + GROUP(-9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), + GROUP( + /* GP0_31_23 RESERVED */ GP_0_22_FN, FN_MMC0_D7, GP_0_21_FN, FN_MMC0_D6, GP_0_20_FN, FN_IP1_7_4, @@ -2519,16 +2514,11 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { GP_0_1_FN, FN_USB0_OVC, GP_0_0_FN, FN_USB0_PWEN, )) }, - { PINMUX_CFG_REG("GPSR1", 0xE6060008, 32, 1, GROUP( - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("GPSR1", 0xE6060008, 32, + GROUP(-9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), + GROUP( + /* GP1_31_23 RESERVED */ GP_1_22_FN, FN_IP4_3_0, GP_1_21_FN, FN_IP3_31_28, GP_1_20_FN, FN_IP3_27_24, @@ -2587,22 +2577,15 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { GP_2_1_FN, FN_IP4_11_8, GP_2_0_FN, FN_IP4_7_4, )) }, - { PINMUX_CFG_REG("GPSR3", 0xE6060010, 32, 1, GROUP( - 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("GPSR3", 0xE6060010, 32, + GROUP(-2, 1, 1, -10, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), + GROUP( + /* GP3_31_30 RESERVED */ GP_3_29_FN, FN_IP10_19_16, GP_3_28_FN, FN_IP10_15_12, GP_3_27_FN, FN_IP10_11_8, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + /* GP3_26_17 RESERVED */ GP_3_16_FN, FN_IP10_7_4, GP_3_15_FN, FN_IP10_3_0, GP_3_14_FN, FN_IP9_31_28, @@ -2689,9 +2672,7 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { GP_5_1_FN, FN_IP14_3_0, GP_5_0_FN, FN_IP13_31_28, )) }, - { PINMUX_CFG_REG_VAR("IPSR0", 0xE6060040, 32, - GROUP(4, 4, 4, 4, 4, 4, 4, 4), - GROUP( + { PINMUX_CFG_REG("IPSR0", 0xE6060040, 32, 4, GROUP( /* IP0_31_28 [4] */ FN_SD0_WP, FN_IRQ7, FN_CAN0_TX_A, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -2717,9 +2698,7 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_SD0_CLK, 0, 0, FN_SSI_SCK1_C, FN_RX3_C, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, )) }, - { PINMUX_CFG_REG_VAR("IPSR1", 0xE6060044, 32, - GROUP(4, 4, 4, 4, 4, 4, 4, 4), - GROUP( + { PINMUX_CFG_REG("IPSR1", 0xE6060044, 32, 4, GROUP( /* IP1_31_28 [4] */ FN_D5, FN_HRX2, FN_SCL1_B, FN_PWM2_C, FN_TCLK2_B, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -2745,9 +2724,7 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_MMC0_D4, FN_SD1_CD, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, )) }, - { PINMUX_CFG_REG_VAR("IPSR2", 0xE6060048, 32, - GROUP(4, 4, 4, 4, 4, 4, 4, 4), - GROUP( + { PINMUX_CFG_REG("IPSR2", 0xE6060048, 32, 4, GROUP( /* IP2_31_28 [4] */ FN_D13, FN_MSIOF2_SYNC_A, 0, FN_RX4_C, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -2773,9 +2750,7 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_D6, FN_HTX2, FN_SDA1_B, FN_PWM4_C, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, )) }, - { PINMUX_CFG_REG_VAR("IPSR3", 0xE606004C, 32, - GROUP(4, 4, 4, 4, 4, 4, 4, 4), - GROUP( + { PINMUX_CFG_REG("IPSR3", 0xE606004C, 32, 4, GROUP( /* IP3_31_28 [4] */ FN_QSPI0_SSL, FN_WE1_N, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -2802,9 +2777,7 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { 0, FN_AVB_AVTP_CAPTURE_A, 0, 0, 0, 0, 0, 0, 0, 0, 0, )) }, - { PINMUX_CFG_REG_VAR("IPSR4", 0xE6060050, 32, - GROUP(4, 4, 4, 4, 4, 4, 4, 4), - GROUP( + { PINMUX_CFG_REG("IPSR4", 0xE6060050, 32, 4, GROUP( /* IP4_31_28 [4] */ FN_DU0_DR6, 0, FN_RX2_C, 0, 0, 0, FN_A6, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -2830,9 +2803,7 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_EX_WAIT0, FN_CAN_CLK_B, FN_SCIF_CLK_A, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, )) }, - { PINMUX_CFG_REG_VAR("IPSR5", 0xE6060054, 32, - GROUP(4, 4, 4, 4, 4, 4, 4, 4), - GROUP( + { PINMUX_CFG_REG("IPSR5", 0xE6060054, 32, 4, GROUP( /* IP5_31_28 [4] */ FN_DU0_DG6, 0, FN_HRX1_C, 0, 0, 0, FN_A14, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -2858,9 +2829,7 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_DU0_DR7, 0, FN_TX2_C, 0, FN_PWM2_B, 0, FN_A7, 0, 0, 0, 0, 0, 0, 0, 0, 0, )) }, - { PINMUX_CFG_REG_VAR("IPSR6", 0xE6060058, 32, - GROUP(4, 4, 4, 4, 4, 4, 4, 4), - GROUP( + { PINMUX_CFG_REG("IPSR6", 0xE6060058, 32, 4, GROUP( /* IP6_31_28 [4] */ FN_DU0_DB6, 0, 0, 0, 0, 0, FN_A22, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -2886,9 +2855,7 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_DU0_DG7, 0, FN_HTX1_C, 0, FN_PWM6_B, 0, FN_A15, 0, 0, 0, 0, 0, 0, 0, 0, 0, )) }, - { PINMUX_CFG_REG_VAR("IPSR7", 0xE606005C, 32, - GROUP(4, 4, 4, 4, 4, 4, 4, 4), - GROUP( + { PINMUX_CFG_REG("IPSR7", 0xE606005C, 32, 4, GROUP( /* IP7_31_28 [4] */ FN_DU0_DISP, 0, 0, 0, FN_CAN1_RX_C, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -2914,9 +2881,7 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_DU0_DB7, 0, 0, 0, 0, 0, FN_A23, 0, 0, 0, 0, 0, 0, 0, 0, 0, )) }, - { PINMUX_CFG_REG_VAR("IPSR8", 0xE6060060, 32, - GROUP(4, 4, 4, 4, 4, 4, 4, 4), - GROUP( + { PINMUX_CFG_REG("IPSR8", 0xE6060060, 32, 4, GROUP( /* IP8_31_28 [4] */ FN_VI1_DATA5, 0, 0, 0, FN_AVB_RXD4, FN_ETH_LINK, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -2942,9 +2907,7 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_DU0_CDE, 0, 0, 0, FN_CAN1_TX_C, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, )) }, - { PINMUX_CFG_REG_VAR("IPSR9", 0xE6060064, 32, - GROUP(4, 4, 4, 4, 4, 4, 4, 4), - GROUP( + { PINMUX_CFG_REG("IPSR9", 0xE6060064, 32, 4, GROUP( /* IP9_31_28 [4] */ FN_VI1_DATA9, 0, 0, FN_SDA2_B, FN_AVB_TXD0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -2970,9 +2933,7 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_VI1_DATA6, 0, 0, 0, FN_AVB_RXD5, FN_ETH_TXD1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, )) }, - { PINMUX_CFG_REG_VAR("IPSR10", 0xE6060068, 32, - GROUP(4, 4, 4, 4, 4, 4, 4, 4), - GROUP( + { PINMUX_CFG_REG("IPSR10", 0xE6060068, 32, 4, GROUP( /* IP10_31_28 [4] */ FN_SCL1_A, FN_RX4_A, FN_PWM5_D, FN_DU1_DR0, 0, 0, FN_SSI_SCK6_B, FN_VI0_G0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -2999,9 +2960,7 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_VI1_DATA10, 0, 0, FN_CAN0_RX_B, FN_AVB_TXD1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, )) }, - { PINMUX_CFG_REG_VAR("IPSR11", 0xE606006C, 32, - GROUP(4, 4, 4, 4, 4, 4, 4, 4), - GROUP( + { PINMUX_CFG_REG("IPSR11", 0xE606006C, 32, 4, GROUP( /* IP11_31_28 [4] */ FN_HRX1_A, FN_SCL4_A, FN_PWM6_A, FN_DU1_DG0, FN_RX0_A, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -3031,9 +2990,7 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_SDA1_A, FN_TX4_A, 0, FN_DU1_DR1, 0, 0, FN_SSI_WS6_B, FN_VI0_G1, 0, 0, 0, 0, 0, 0, 0, 0, )) }, - { PINMUX_CFG_REG_VAR("IPSR12", 0xE6060070, 32, - GROUP(4, 4, 4, 4, 4, 4, 4, 4), - GROUP( + { PINMUX_CFG_REG("IPSR12", 0xE6060070, 32, 4, GROUP( /* IP12_31_28 [4] */ FN_SD2_DAT2, FN_RX2_A, 0, FN_DU1_DB0, FN_SSI_SDATA2_B, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -3059,9 +3016,7 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_HTX1_A, FN_SDA4_A, 0, FN_DU1_DG1, FN_TX0_A, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, )) }, - { PINMUX_CFG_REG_VAR("IPSR13", 0xE6060074, 32, - GROUP(4, 4, 4, 4, 4, 4, 4, 4), - GROUP( + { PINMUX_CFG_REG("IPSR13", 0xE6060074, 32, 4, GROUP( /* IP13_31_28 [4] */ FN_SSI_SCK5_A, 0, 0, FN_DU1_DOTCLKOUT1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -3088,9 +3043,7 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_SD2_DAT3, FN_TX2_A, 0, FN_DU1_DB1, FN_SSI_WS9_B, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, )) }, - { PINMUX_CFG_REG_VAR("IPSR14", 0xE6060078, 32, - GROUP(4, 4, 4, 4, 4, 4, 4, 4), - GROUP( + { PINMUX_CFG_REG("IPSR14", 0xE6060078, 32, 4, GROUP( /* IP14_31_28 [4] */ FN_SSI_SDATA7_A, 0, 0, FN_IRQ8, FN_AUDIO_CLKA_D, FN_CAN_CLK_D, FN_VI0_G5, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -3116,9 +3069,7 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_SSI_WS5_A, 0, FN_SCL3_C, FN_DU1_DOTCLKIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, )) }, - { PINMUX_CFG_REG_VAR("IPSR15", 0xE606007C, 32, - GROUP(4, 4, 4, 4, 4, 4, 4, 4), - GROUP( + { PINMUX_CFG_REG("IPSR15", 0xE606007C, 32, 4, GROUP( /* IP15_31_28 [4] */ FN_SSI_WS4_A, 0, FN_AVB_PHY_INT, 0, 0, 0, FN_VI0_R5, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -3144,9 +3095,7 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_SSI_SCK0129_A, FN_MSIOF1_RXD_A, FN_RX5_D, 0, 0, 0, FN_VI0_G6, 0, 0, 0, 0, 0, 0, 0, 0, 0, )) }, - { PINMUX_CFG_REG_VAR("IPSR16", 0xE6060080, 32, - GROUP(4, 4, 4, 4, 4, 4, 4, 4), - GROUP( + { PINMUX_CFG_REG("IPSR16", 0xE6060080, 32, 4, GROUP( /* IP16_31_28 [4] */ FN_SSI_SDATA2_A, FN_HRTS1_N_B, 0, 0, 0, 0, FN_VI0_DATA4_VI0_B4, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -3174,10 +3123,9 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { 0, 0, 0, 0, 0, 0, )) }, { PINMUX_CFG_REG_VAR("IPSR17", 0xE6060084, 32, - GROUP(4, 4, 4, 4, 4, 4, 4, 4), + GROUP(-4, 4, 4, 4, 4, 4, 4, 4), GROUP( - /* IP17_31_28 [4] */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* IP17_31_28 [4] RESERVED */ /* IP17_27_24 [4] */ FN_AUDIO_CLKOUT_A, FN_SDA4_B, 0, 0, 0, 0, FN_VI0_VSYNC_N, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -3201,25 +3149,13 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_VI0_DATA5_VI0_B5, 0, 0, 0, 0, 0, 0, 0, 0, 0, )) }, { PINMUX_CFG_REG_VAR("MOD_SEL0", 0xE60600C0, 32, - GROUP(1, 1, 1, 1, 1, 2, 1, 1, 2, 2, 2, 1, - 3, 3, 1, 2, 3, 3, 1), + GROUP(-5, 2, -2, 2, 2, 2, -1, + 3, 3, -1, 2, 3, 3, 1), GROUP( - /* RESERVED [1] */ - 0, 0, - /* RESERVED [1] */ - 0, 0, - /* RESERVED [1] */ - 0, 0, - /* RESERVED [1] */ - 0, 0, - /* RESERVED [1] */ - 0, 0, + /* RESERVED [5] */ /* SEL_ADGA [2] */ FN_SEL_ADGA_0, FN_SEL_ADGA_1, FN_SEL_ADGA_2, FN_SEL_ADGA_3, - /* RESERVED [1] */ - 0, 0, - /* RESERVED [1] */ - 0, 0, + /* RESERVED [2] */ /* SEL_CANCLK [2] */ FN_SEL_CANCLK_0, FN_SEL_CANCLK_1, FN_SEL_CANCLK_2, FN_SEL_CANCLK_3, @@ -3228,7 +3164,6 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { /* SEL_CAN0 [2] */ FN_SEL_CAN0_0, FN_SEL_CAN0_1, FN_SEL_CAN0_2, FN_SEL_CAN0_3, /* RESERVED [1] */ - 0, 0, /* SEL_I2C04 [3] */ FN_SEL_I2C04_0, FN_SEL_I2C04_1, FN_SEL_I2C04_2, FN_SEL_I2C04_3, FN_SEL_I2C04_4, 0, 0, 0, @@ -3236,7 +3171,6 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_SEL_I2C03_0, FN_SEL_I2C03_1, FN_SEL_I2C03_2, FN_SEL_I2C03_3, FN_SEL_I2C03_4, 0, 0, 0, /* RESERVED [1] */ - 0, 0, /* SEL_I2C02 [2] */ FN_SEL_I2C02_0, FN_SEL_I2C02_1, FN_SEL_I2C02_2, FN_SEL_I2C02_3, /* SEL_I2C01 [3] */ @@ -3249,8 +3183,8 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_SEL_AVB_0, FN_SEL_AVB_1, )) }, { PINMUX_CFG_REG_VAR("MOD_SEL1", 0xE60600C4, 32, - GROUP(1, 3, 3, 2, 2, 1, 2, 2, 2, 1, 1, 1, - 1, 1, 2, 1, 1, 2, 2, 1), + GROUP(1, 3, 3, 2, 2, 1, 2, 2, 2, -1, 1, -1, + 1, 1, -2, 1, 1, -2, 2, 1), GROUP( /* SEL_SCIFCLK [1] */ FN_SEL_SCIFCLK_0, FN_SEL_SCIFCLK_1, @@ -3273,52 +3207,28 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { /* SEL_MSIOF2 [2] */ FN_SEL_MSIOF2_0, FN_SEL_MSIOF2_1, FN_SEL_MSIOF2_2, 0, /* RESERVED [1] */ - 0, 0, /* SEL_MSIOF1 [1] */ FN_SEL_MSIOF1_0, FN_SEL_MSIOF1_1, /* RESERVED [1] */ - 0, 0, /* SEL_MSIOF0 [1] */ FN_SEL_MSIOF0_0, FN_SEL_MSIOF0_1, /* SEL_RCN [1] */ FN_SEL_RCN_0, FN_SEL_RCN_1, /* RESERVED [2] */ - 0, 0, 0, 0, /* SEL_TMU2 [1] */ FN_SEL_TMU2_0, FN_SEL_TMU2_1, /* SEL_TMU1 [1] */ FN_SEL_TMU1_0, FN_SEL_TMU1_1, /* RESERVED [2] */ - 0, 0, 0, 0, /* SEL_HSCIF1 [2] */ FN_SEL_HSCIF1_0, FN_SEL_HSCIF1_1, FN_SEL_HSCIF1_2, 0, /* SEL_HSCIF0 [1] */ FN_SEL_HSCIF0_0, FN_SEL_HSCIF0_1, )) }, { PINMUX_CFG_REG_VAR("MOD_SEL2", 0xE60600C8, 32, - GROUP(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2), + GROUP(-10, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2), GROUP( - /* RESERVED [1] */ - 0, 0, - /* RESERVED [1] */ - 0, 0, - /* RESERVED [1] */ - 0, 0, - /* RESERVED [1] */ - 0, 0, - /* RESERVED [1] */ - 0, 0, - /* RESERVED [1] */ - 0, 0, - /* RESERVED [1] */ - 0, 0, - /* RESERVED [1] */ - 0, 0, - /* RESERVED [1] */ - 0, 0, - /* RESERVED [1] */ - 0, 0, + /* RESERVED [10] */ /* SEL_ADGB [2] */ FN_SEL_ADGB_0, FN_SEL_ADGB_1, FN_SEL_ADGB_2, 0, /* SEL_ADGC [2] */ diff --git a/drivers/pinctrl/renesas/pfc-r8a7778.c b/drivers/pinctrl/renesas/pfc-r8a7778.c index a24672ca3c01babe0fcd0d4fd413a3fcc39e4cb2..35bdb9af8160756680a2a0b1844c6319845bc198 100644 --- a/drivers/pinctrl/renesas/pfc-r8a7778.c +++ b/drivers/pinctrl/renesas/pfc-r8a7778.c @@ -2240,11 +2240,10 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { }, { PINMUX_CFG_REG_VAR("IPSR0", 0xfffc0020, 32, - GROUP(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + GROUP(-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 4, 3, 3, 2), GROUP( - /* IP0_31 [1] */ - 0, 0, + /* IP0_31 [1] RESERVED */ /* IP0_30 [1] */ FN_A19, 0, /* IP0_29 [1] */ @@ -2296,13 +2295,10 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { )) }, { PINMUX_CFG_REG_VAR("IPSR1", 0xfffc0024, 32, - GROUP(1, 1, 2, 3, 1, 3, 3, 1, 2, 4, 3, 3, + GROUP(-2, 2, 3, 1, 3, 3, 1, 2, 4, 3, 3, 3, 1, 1), GROUP( - /* IP1_31 [1] */ - 0, 0, - /* IP1_30 [1] */ - 0, 0, + /* IP1_31_30 [2] RESERVED */ /* IP1_29_28 [2] */ FN_EX_CS1, FN_MMC_D4, 0, 0, /* IP1_27_25 [3] */ @@ -2437,11 +2433,10 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { )) }, { PINMUX_CFG_REG_VAR("IPSR4", 0xfffc0030, 32, - GROUP(1, 2, 2, 2, 4, 4, 2, 2, 2, 2, 1, 1, + GROUP(-1, 2, 2, 2, 4, 4, 2, 2, 2, 2, 1, 1, 3, 3, 1), GROUP( - /* IP4_31 [1] */ - 0, 0, + /* IP4_31 [1] RESERVED */ /* IP4_30_29 [2] */ FN_VI0_R4_B, FN_DU0_DB4, FN_LCDOUT20, 0, /* IP4_28_27 [2] */ @@ -2481,12 +2476,11 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { )) }, { PINMUX_CFG_REG_VAR("IPSR5", 0xfffc0034, 32, - GROUP(1, 2, 3, 3, 2, 3, 3, 2, 1, 2, 2, 1, + GROUP(-1, 2, 3, 3, 2, 3, 3, 2, 1, 2, 2, 1, 1, 2, 2, 2), GROUP( - /* IP5_31 [1] */ - 0, 0, + /* IP5_31 [1] RESERVED */ /* IP5_30_29 [2] */ FN_SSI_SDATA7, FN_HSPI_TX0_B, FN_RX2_A, FN_CAN0_RX_B, /* IP5_28_26 [3] */ @@ -2619,12 +2613,9 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { )) }, { PINMUX_CFG_REG_VAR("IPSR8", 0xfffc0040, 32, - GROUP(1, 1, 3, 3, 2, 3, 3, 2, 3, 2, 3, 3, 3), + GROUP(-2, 3, 3, 2, 3, 3, 2, 3, 2, 3, 3, 3), GROUP( - /* IP8_31 [1] */ - 0, 0, - /* IP8_30 [1] */ - 0, 0, + /* IP8_31_30 [2] RESERVED */ /* IP8_29_27 [3] */ FN_VI0_G3, FN_SD2_CMD_B, FN_VI1_DATA5, FN_DU1_DR5, 0, FN_HRX1_B, 0, 0, @@ -2660,12 +2651,9 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { )) }, { PINMUX_CFG_REG_VAR("IPSR9", 0xfffc0044, 32, - GROUP(1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3), + GROUP(-2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3), GROUP( - /* IP9_31 [1] */ - 0, 0, - /* IP9_30 [1] */ - 0, 0, + /* IP9_31_30 [2] RESERVED */ /* IP9_29_27 [3] */ FN_VI1_DATA11_A, FN_DU1_EXHSYNC_DU1_HSYNC, FN_ETH_RXD1, FN_FMIN_C, @@ -2703,24 +2691,10 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { )) }, { PINMUX_CFG_REG_VAR("IPSR10", 0xfffc0048, 32, - GROUP(1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 4, - 3, 3, 3), + GROUP(-7, 3, 3, 3, 3, 4, 3, 3, 3), GROUP( - /* IP10_31 [1] */ - 0, 0, - /* IP10_30 [1] */ - 0, 0, - /* IP10_29 [1] */ - 0, 0, - /* IP10_28 [1] */ - 0, 0, - /* IP10_27 [1] */ - 0, 0, - /* IP10_26 [1] */ - 0, 0, - /* IP10_25 [1] */ - 0, 0, + /* IP10_31_25 [7] RESERVED */ /* IP10_24_22 [3] */ FN_SD2_WP_A, FN_VI1_DATA15, FN_EX_WAIT2_B, FN_DACK0_B, FN_HSPI_TX2_B, FN_CAN_CLK_C, 0, 0, @@ -2754,12 +2728,11 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { )) }, { PINMUX_CFG_REG_VAR("MOD_SEL0", 0xfffc0050, 32, - GROUP(1, 1, 2, 2, 3, 2, 2, 1, 1, 1, 1, 2, - 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1), + GROUP(-1, 1, 2, 2, 3, 2, 2, -1, 1, 1, 1, 2, + -1, 1, 1, 1, 2, 1, -1, 1, 1, 1, 1, 1), GROUP( - /* SEL 31 [1] */ - 0, 0, + /* SEL 31 [1] RESERVED */ /* SEL_30 (SCIF5) [1] */ FN_SEL_SCIF5_A, FN_SEL_SCIF5_B, /* SEL_29_28 (SCIF4) [2] */ @@ -2779,8 +2752,7 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { /* SEL_20_19 (SCIF0) [2] */ FN_SEL_SCIF0_A, FN_SEL_SCIF0_B, FN_SEL_SCIF0_C, FN_SEL_SCIF0_D, - /* SEL_18 [1] */ - 0, 0, + /* SEL_18 [1] RESERVED */ /* SEL_17 (SSI2) [1] */ FN_SEL_SSI2_A, FN_SEL_SSI2_B, /* SEL_16 (SSI1) [1] */ @@ -2790,8 +2762,7 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { /* SEL_14_13 (VI0) [2] */ FN_SEL_VI0_A, FN_SEL_VI0_B, FN_SEL_VI0_C, FN_SEL_VI0_D, - /* SEL_12 [1] */ - 0, 0, + /* SEL_12 [1] RESERVED */ /* SEL_11 (SD2) [1] */ FN_SEL_SD2_A, FN_SEL_SD2_B, /* SEL_10 (SD1) [1] */ @@ -2803,8 +2774,7 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_SEL_IRQ2_C, 0, /* SEL_6 (IRQ1) [1] */ FN_SEL_IRQ1_A, FN_SEL_IRQ1_B, - /* SEL_5 [1] */ - 0, 0, + /* SEL_5 [1] RESERVED */ /* SEL_4 (DREQ2) [1] */ FN_SEL_DREQ2_A, FN_SEL_DREQ2_B, /* SEL_3 (DREQ1) [1] */ @@ -2818,18 +2788,11 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { )) }, { PINMUX_CFG_REG_VAR("MOD_SEL1", 0xfffc0054, 32, - GROUP(1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 2, 2, 1), + GROUP(-4, 1, 1, 2, 1, 1, -7, + 2, 2, 2, 1, 1, 1, 1, 2, 2, 1), GROUP( - /* SEL_31 [1] */ - 0, 0, - /* SEL_30 [1] */ - 0, 0, - /* SEL_29 [1] */ - 0, 0, - /* SEL_28 [1] */ - 0, 0, + /* SEL_31_28 [4] RESERVED */ /* SEL_27 (CAN1) [1] */ FN_SEL_CAN1_A, FN_SEL_CAN1_B, /* SEL_26 (CAN0) [1] */ @@ -2841,20 +2804,7 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_SEL_HSCIF1_A, FN_SEL_HSCIF1_B, /* SEL_22 (HSCIF0) [1] */ FN_SEL_HSCIF0_A, FN_SEL_HSCIF0_B, - /* SEL_21 [1] */ - 0, 0, - /* SEL_20 [1] */ - 0, 0, - /* SEL_19 [1] */ - 0, 0, - /* SEL_18 [1] */ - 0, 0, - /* SEL_17 [1] */ - 0, 0, - /* SEL_16 [1] */ - 0, 0, - /* SEL_15 [1] */ - 0, 0, + /* SEL_21_15 [7] RESERVED */ /* SEL_14_13 (REMOCON) [2] */ FN_SEL_REMOCON_A, FN_SEL_REMOCON_B, FN_SEL_REMOCON_C, 0, diff --git a/drivers/pinctrl/renesas/pfc-r8a7779.c b/drivers/pinctrl/renesas/pfc-r8a7779.c index 296b5fb0f349025552abc2710e39a52c5d4bab20..fcc8ea48881fb961cdf9480f0486745fce350dfe 100644 --- a/drivers/pinctrl/renesas/pfc-r8a7779.c +++ b/drivers/pinctrl/renesas/pfc-r8a7779.c @@ -3300,13 +3300,10 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { GP_5_1_FN, FN_A2, GP_5_0_FN, FN_A1 )) }, - { PINMUX_CFG_REG("GPSR6", 0xfffc001c, 32, 1, GROUP( - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, - 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("GPSR6", 0xfffc001c, 32, + GROUP(-23, 1, 1, 1, 1, 1, 1, 1, 1, 1), + GROUP( + /* GP6_31_9 RESERVED */ GP_6_8_FN, FN_IP3_20, GP_6_7_FN, FN_IP3_19, GP_6_6_FN, FN_IP3_18, @@ -3319,10 +3316,9 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { }, { PINMUX_CFG_REG_VAR("IPSR0", 0xfffc0020, 32, - GROUP(1, 3, 2, 1, 2, 4, 3, 2, 2, 2, 2, 2, 3, 3), + GROUP(-1, 3, 2, 1, 2, 4, 3, 2, 2, 2, 2, 2, 3, 3), GROUP( - /* IP0_31 [1] */ - 0, 0, + /* IP0_31 [1] RESERVED */ /* IP0_30_28 [3] */ FN_RD_WR, FN_FWE, FN_ATAG0, FN_VI1_R7, FN_HRTS1, FN_RX4_C, 0, 0, @@ -3358,10 +3354,9 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_SCIF_CLK, FN_TCLK0_C, 0, 0 )) }, { PINMUX_CFG_REG_VAR("IPSR1", 0xfffc0024, 32, - GROUP(3, 4, 2, 2, 2, 4, 4, 4, 3, 2, 2), + GROUP(-3, 4, 2, 2, 2, 4, 4, 4, 3, 2, 2), GROUP( - /* IP1_31_29 [3] */ - 0, 0, 0, 0, 0, 0, 0, 0, + /* IP1_31_29 [3] RESERVED */ /* IP1_28_25 [4] */ FN_HTX0, FN_TX1, FN_SDATA, FN_CTS0_C, FN_SUB_TCK, FN_CC5_STATE2, FN_CC5_STATE10, FN_CC5_STATE18, @@ -3397,10 +3392,9 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_EX_CS0, FN_RX3_C_IRDA_RX_C, FN_MMC0_D6, FN_FD6 )) }, { PINMUX_CFG_REG_VAR("IPSR2", 0xfffc0028, 32, - GROUP(1, 3, 1, 1, 1, 1, 1, 1, 3, 3, 4, 4, 4, 4), + GROUP(-1, 3, 1, 1, 1, 1, 1, 1, 3, 3, 4, 4, 4, 4), GROUP( - /* IP2_31 [1] */ - 0, 0, + /* IP2_31 [1] RESERVED */ /* IP2_30_28 [3] */ FN_DU0_DG0, FN_LCDOUT8, FN_DREQ1, FN_SCL2, FN_AUDATA2, 0, 0, 0, @@ -3545,11 +3539,10 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_DU0_DISP, FN_QPOLA, FN_CAN_CLK_C, FN_SCK2_C )) }, { PINMUX_CFG_REG_VAR("IPSR5", 0xfffc0034, 32, - GROUP(1, 2, 1, 4, 3, 4, 2, 2, 2, 2, 1, 1, + GROUP(-1, 2, 1, 4, 3, 4, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 3), GROUP( - /* IP5_31 [1] */ - 0, 0, + /* IP5_31 [1] RESERVED */ /* IP5_30_29 [2] */ FN_AUDIO_CLKB, FN_USB_OVC2, FN_CAN_DEBUGOUT0, FN_MOUT0, /* IP5_28 [1] */ @@ -3592,15 +3585,13 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_RX5, FN_RTS0_D_TANS_D, 0, 0 )) }, { PINMUX_CFG_REG_VAR("IPSR6", 0xfffc0038, 32, - GROUP(1, 2, 2, 2, 2, 3, 2, 3, 3, 3, 1, 2, + GROUP(-1, 2, -2, 2, 2, 3, 2, 3, 3, 3, 1, 2, 2, 2, 2), GROUP( - /* IP6_31 [1] */ - 0, 0, + /* IP6_31 [1] RESERVED */ /* IP6_30_29 [2] */ FN_SSI_SCK6, FN_ADICHS0, FN_CAN0_TX, FN_IERX_B, - /* IP_28_27 [2] */ - 0, 0, 0, 0, + /* IP_28_27 [2] RESERVED */ /* IP6_26_25 [2] */ FN_SSI_SDATA5, FN_ADIDATA, FN_CAN_DEBUGOUT12, FN_RX3_IRDA_RX, /* IP6_24_23 [2] */ @@ -3631,11 +3622,10 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_SSI_SCK0129, FN_CAN_DEBUGOUT1, FN_MOUT1, 0 )) }, { PINMUX_CFG_REG_VAR("IPSR7", 0xfffc003c, 32, - GROUP(1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, + GROUP(-1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 2, 2), GROUP( - /* IP7_31 [1] */ - 0, 0, + /* IP7_31 [1] RESERVED */ /* IP7_30_29 [2] */ FN_SD0_WP, FN_DACK2, FN_CTS1_B, 0, /* IP7_28_27 [2] */ @@ -3669,10 +3659,9 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_SSI_WS6, FN_ADICHS1, FN_CAN0_RX, FN_IETX_B )) }, { PINMUX_CFG_REG_VAR("IPSR8", 0xfffc0040, 32, - GROUP(1, 3, 3, 2, 2, 1, 1, 1, 2, 4, 4, 4, 4), + GROUP(-1, 3, 3, 2, 2, 1, 1, 1, 2, 4, 4, 4, 4), GROUP( - /* IP8_31 [1] */ - 0, 0, + /* IP8_31 [1] RESERVED */ /* IP8_30_28 [3] */ FN_VI0_VSYNC, FN_VI0_DATA1_B_VI0_B1_B, FN_RTS1_C_TANS_C, FN_RX4_D, FN_PWMFSW0_C, 0, 0, 0, @@ -3713,11 +3702,10 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { 0, 0, 0, 0 )) }, { PINMUX_CFG_REG_VAR("IPSR9", 0xfffc0044, 32, - GROUP(2, 2, 2, 2, 2, 3, 3, 2, 2, 2, 2, 1, + GROUP(-2, 2, 2, 2, 2, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 2, 2), GROUP( - /* IP9_31_30 [2] */ - 0, 0, 0, 0, + /* IP9_31_30 [2] RESERVED */ /* IP9_29_28 [2] */ FN_VI0_G7, FN_ETH_RXD1, FN_SD2_DAT3_B, FN_ARM_TRACEDATA_9, /* IP9_27_26 [2] */ @@ -3790,10 +3778,9 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_ARM_TRACEDATA_10, FN_DREQ0_C, 0, 0 )) }, { PINMUX_CFG_REG_VAR("IPSR11", 0xfffc004c, 32, - GROUP(2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3), + GROUP(-2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3), GROUP( - /* IP11_31_30 [2] */ - 0, 0, 0, 0, + /* IP11_31_30 [2] RESERVED */ /* IP11_29_27 [3] */ FN_VI1_G1, FN_VI3_DATA1, FN_SSI_SCK1, FN_TS_SDEN1, FN_DACK2_B, FN_RX2, FN_HRTS0_B, 0, @@ -3826,19 +3813,9 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_ADICLK_B, 0, 0, 0 )) }, { PINMUX_CFG_REG_VAR("IPSR12", 0xfffc0050, 32, - GROUP(4, 4, 4, 2, 3, 3, 3, 3, 3, 3), + GROUP(-14, 3, 3, 3, 3, 3, 3), GROUP( - /* IP12_31_28 [4] */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - /* IP12_27_24 [4] */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - /* IP12_23_20 [4] */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - /* IP12_19_18 [2] */ - 0, 0, 0, 0, + /* IP12_31_18 [14] RESERVED */ /* IP12_17_15 [3] */ FN_VI1_G7, FN_VI3_DATA7, FN_GPS_MAG, FN_FCE, FN_SCK4_B, 0, 0, 0, @@ -3904,7 +3881,7 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_SEL_EXBUS0_0, FN_SEL_EXBUS0_1, FN_SEL_EXBUS0_2, 0 )) }, { PINMUX_CFG_REG_VAR("MOD_SEL2", 0xfffc0094, 32, - GROUP(2, 2, 2, 2, 1, 1, 1, 3, 1, 2, 2, 2, + GROUP(2, 2, 2, 2, 1, 1, 1, 3, 1, -6, 2, 1, 1, 2, 1, 2, 2), GROUP( /* SEL_TMU1 [2] */ @@ -3926,12 +3903,7 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_SEL_PWMFSW_3, FN_SEL_PWMFSW_4, 0, 0, 0, /* SEL_ADI [1] */ FN_SEL_ADI_0, FN_SEL_ADI_1, - /* [2] */ - 0, 0, 0, 0, - /* [2] */ - 0, 0, 0, 0, - /* [2] */ - 0, 0, 0, 0, + /* [6] RESERVED */ /* SEL_GPS [2] */ FN_SEL_GPS_0, FN_SEL_GPS_1, FN_SEL_GPS_2, FN_SEL_GPS_3, /* SEL_SIM [1] */ diff --git a/drivers/pinctrl/renesas/pfc-r8a7790.c b/drivers/pinctrl/renesas/pfc-r8a7790.c index 9db9e61d96bcca5abdc314d79bda42fa821a5878..ee21d650991bcec39bb1adc39bace5b0f7fcd6a5 100644 --- a/drivers/pinctrl/renesas/pfc-r8a7790.c +++ b/drivers/pinctrl/renesas/pfc-r8a7790.c @@ -5122,10 +5122,9 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { GP_5_0_FN, FN_IP14_21_19 )) }, { PINMUX_CFG_REG_VAR("IPSR0", 0xE6060020, 32, - GROUP(1, 4, 4, 3, 4, 4, 3, 3, 3, 3), + GROUP(-1, 4, 4, 3, 4, 4, 3, 3, 3, 3), GROUP( - /* IP0_31 [1] */ - 0, 0, + /* IP0_31 [1] RESERVED */ /* IP0_30_27 [4] */ FN_D8, FN_SCIFA1_SCK_C, FN_AVB_TXD0, 0, FN_VI0_G0, FN_VI0_G0_B, FN_VI2_DATA0_VI2_B0, @@ -5159,10 +5158,9 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { 0, 0, 0, )) }, { PINMUX_CFG_REG_VAR("IPSR1", 0xE6060024, 32, - GROUP(2, 2, 2, 4, 4, 3, 3, 4, 4, 4), + GROUP(-2, 2, 2, 4, 4, 3, 3, 4, 4, 4), GROUP( - /* IP1_31_30 [2] */ - 0, 0, 0, 0, + /* IP1_31_30 [2] RESERVED */ /* IP1_29_28 [2] */ FN_A1, FN_PWM4, 0, 0, /* IP1_27_26 [2] */ @@ -5197,10 +5195,9 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, )) }, { PINMUX_CFG_REG_VAR("IPSR2", 0xE6060028, 32, - GROUP(3, 3, 4, 4, 3, 3, 3, 3, 3, 3), + GROUP(-3, 3, 4, 4, 3, 3, 3, 3, 3, 3), GROUP( - /* IP2_31_29 [3] */ - 0, 0, 0, 0, 0, 0, 0, 0, + /* IP2_31_29 [3] RESERVED */ /* IP2_28_26 [3] */ FN_A10, FN_SSI_SDATA5_B, FN_MSIOF2_SYNC, FN_VI0_R6, FN_VI0_R6_B, FN_VI2_DATA2_VI2_B2_B, 0, 0, @@ -5261,10 +5258,9 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { 0, 0, 0, 0, 0, 0, 0, 0, )) }, { PINMUX_CFG_REG_VAR("IPSR4", 0xE6060030, 32, - GROUP(2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3), + GROUP(-2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3), GROUP( - /* IP4_31_30 [2] */ - 0, 0, 0, 0, + /* IP4_31_30 [2] RESERVED */ /* IP4_29_27 [3] */ FN_EX_CS2_N, FN_GPS_SIGN, FN_HRTS1_N_B, FN_VI3_CLKENB, FN_VI1_G0, FN_VI1_G0_B, FN_VI2_R2, 0, @@ -5295,10 +5291,9 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { )) }, { PINMUX_CFG_REG_VAR("IPSR5", 0xE6060034, 32, - GROUP(2, 3, 3, 3, 3, 3, 2, 3, 4, 3, 3), + GROUP(-2, 3, 3, 3, 3, 3, 2, 3, 4, 3, 3), GROUP( - /* IP5_31_30 [2] */ - 0, 0, 0, 0, + /* IP5_31_30 [2] RESERVED */ /* IP5_29_27 [3] */ FN_DREQ0_N, FN_VI1_HSYNC_N, FN_VI1_HSYNC_N_B, FN_VI2_R7, FN_SSI_SCK78_C, FN_SSI_WS78_B, 0, 0, @@ -5368,10 +5363,9 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_VI1_VSYNC_N_B, FN_SSI_WS78_C, 0, )) }, { PINMUX_CFG_REG_VAR("IPSR7", 0xE606003C, 32, - GROUP(1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 3, 3), + GROUP(-1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 3, 3), GROUP( - /* IP7_31 [1] */ - 0, 0, + /* IP7_31 [1] RESERVED */ /* IP7_30_29 [2] */ FN_VI0_DATA0_VI0_B0, FN_ATACS10_N, FN_AVB_RXD2, 0, /* IP7_28_27 [2] */ @@ -5404,11 +5398,10 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_SIM0_D_C, FN_HCTS0_N_F, 0, 0, 0, )) }, { PINMUX_CFG_REG_VAR("IPSR8", 0xE6060040, 32, - GROUP(1, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, + GROUP(-1, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2), GROUP( - /* IP8_31 [1] */ - 0, 0, + /* IP8_31 [1] RESERVED */ /* IP8_30_29 [2] */ FN_SD0_CMD, FN_SCIFB1_SCK_B, FN_VI1_DATA1_VI1_B1_B, 0, /* IP8_28 [1] */ @@ -5482,10 +5475,9 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_SD0_DAT0, FN_SCIFB1_RXD_B, FN_VI1_DATA2_VI1_B2_B, 0, )) }, { PINMUX_CFG_REG_VAR("IPSR10", 0xE6060048, 32, - GROUP(2, 4, 3, 4, 4, 4, 4, 3, 4), + GROUP(-2, 4, 3, 4, 4, 4, 4, 3, 4), GROUP( - /* IP10_31_30 [2] */ - 0, 0, 0, 0, + /* IP10_31_30 [2] RESERVED */ /* IP10_29_26 [4] */ FN_SD2_CD, FN_MMC0_D4, FN_TS_SDAT0_B, FN_USB2_EXTP, FN_GLO_I0, FN_VI0_DATA6_VI0_B6_B, FN_HCTS0_N_D, FN_TS_SDAT1_B, @@ -5558,10 +5550,9 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_TS_SCK1_B, FN_GLO_I1_B, FN_VI3_DATA7_B, 0, 0, 0, 0, 0, 0, )) }, { PINMUX_CFG_REG_VAR("IPSR12", 0xE6060050, 32, - GROUP(1, 3, 3, 2, 3, 3, 3, 3, 3, 2, 2, 2, 2), + GROUP(-1, 3, 3, 2, 3, 3, 3, 3, 3, 2, 2, 2, 2), GROUP( - /* IP12_31 [1] */ - 0, 0, + /* IP12_31 [1] RESERVED */ /* IP12_30_28 [3] */ FN_SSI_WS5, FN_SCIFB1_RXD, FN_IECLK_B, FN_DU2_EXVSYNC_DU2_VSYNC, FN_QSTB_QHE, @@ -5598,10 +5589,9 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_SSI_WS0129, FN_CAN0_TX_B, FN_MOUT1, 0, )) }, { PINMUX_CFG_REG_VAR("IPSR13", 0xE6060054, 32, - GROUP(1, 2, 3, 3, 4, 3, 3, 3, 3, 4, 3), + GROUP(-1, 2, 3, 3, 4, 3, 3, 3, 3, 4, 3), GROUP( - /* IP13_31 [1] */ - 0, 0, + /* IP13_31 [1] RESERVED */ /* IP13_30_29 [2] */ FN_AUDIO_CLKA, FN_SCIFB2_RTS_N, FN_CAN_DEBUGOUT14, 0, /* IP13_28_26 [3] */ @@ -5635,10 +5625,9 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_LCDOUT2, FN_CAN_DEBUGOUT5, 0, 0, )) }, { PINMUX_CFG_REG_VAR("IPSR14", 0xE6060058, 32, - GROUP(1, 3, 3, 3, 3, 3, 4, 3, 3, 3, 3), + GROUP(-1, 3, 3, 3, 3, 3, 4, 3, 3, 3, 3), GROUP( - /* IP14_30 [1] */ - 0, 0, + /* IP14_30 [1] RESERVED */ /* IP14_30_28 [3] */ FN_SCIFA1_RTS_N, FN_AD_NCS_N, FN_RTS1_N, FN_MSIOF3_TXD, FN_DU1_DOTCLKOUT, FN_QSTVB_QVE, @@ -5674,10 +5663,9 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_REMOCON, 0, )) }, { PINMUX_CFG_REG_VAR("IPSR15", 0xE606005C, 32, - GROUP(2, 2, 2, 3, 3, 2, 2, 2, 2, 3, 3, 3, 3), + GROUP(-2, 2, 2, 3, 3, 2, 2, 2, 2, 3, 3, 3, 3), GROUP( - /* IP15_31_30 [2] */ - 0, 0, 0, 0, + /* IP15_31_30 [2] RESERVED */ /* IP15_29_28 [2] */ FN_MSIOF0_TXD, FN_ADICHS1, FN_DU2_DG6, FN_LCDOUT14, /* IP15_27_26 [2] */ @@ -5710,26 +5698,9 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_LCDOUT15, FN_SCIF_CLK_B, 0, )) }, { PINMUX_CFG_REG_VAR("IPSR16", 0xE6060160, 32, - GROUP(4, 4, 4, 4, 4, 4, 1, 1, 3, 3), + GROUP(-24, 1, 1, 3, 3), GROUP( - /* IP16_31_28 [4] */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - /* IP16_27_24 [4] */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - /* IP16_23_20 [4] */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - /* IP16_19_16 [4] */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - /* IP16_15_12 [4] */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - /* IP16_11_8 [4] */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, + /* IP16_31_8 [24] RESERVED */ /* IP16_7 [1] */ FN_USB1_OVC, FN_TCLK1_B, /* IP16_6 [1] */ @@ -5743,7 +5714,7 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { }, { PINMUX_CFG_REG_VAR("MOD_SEL", 0xE6060090, 32, GROUP(3, 2, 2, 3, 2, 1, 1, 1, 2, 1, 2, 1, - 1, 1, 1, 2, 1, 1, 2, 1, 1), + 1, 1, 1, 2, -1, 1, 2, 1, 1), GROUP( /* SEL_SCIF1 [3] */ FN_SEL_SCIF1_0, FN_SEL_SCIF1_1, FN_SEL_SCIF1_2, FN_SEL_SCIF1_3, @@ -5782,7 +5753,6 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { /* SEL_TSIF1 [2] */ FN_SEL_TSIF1_0, FN_SEL_TSIF1_1, FN_SEL_TSIF1_2, 0, /* RESERVED [1] */ - 0, 0, /* SEL_LBS [1] */ FN_SEL_LBS_0, FN_SEL_LBS_1, /* SEL_TSIF0 [2] */ @@ -5793,11 +5763,10 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_SEL_SOF0_0, FN_SEL_SOF0_1, )) }, { PINMUX_CFG_REG_VAR("MOD_SEL2", 0xE6060094, 32, - GROUP(3, 1, 1, 1, 2, 1, 2, 1, 2, 1, 1, 1, - 3, 3, 2, 3, 2, 2), + GROUP(-3, 1, 1, 1, 2, 1, 2, 1, -2, 1, 1, 1, + 3, 3, 2, -3, 2, 2), GROUP( /* RESERVED [3] */ - 0, 0, 0, 0, 0, 0, 0, 0, /* SEL_TMU1 [1] */ FN_SEL_TMU1_0, FN_SEL_TMU1_1, /* SEL_HSCIF1 [1] */ @@ -5813,7 +5782,6 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { /* SEL_CAN1 [1] */ FN_SEL_CAN1_0, FN_SEL_CAN1_1, /* RESERVED [2] */ - 0, 0, 0, 0, /* SEL_SCIF2 [1] */ FN_SEL_SCIF2_0, FN_SEL_SCIF2_1, /* SEL_ADI [1] */ @@ -5829,36 +5797,22 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { /* SEL_GPS [2] */ FN_SEL_GPS_0, FN_SEL_GPS_1, FN_SEL_GPS_2, 0, /* RESERVED [3] */ - 0, 0, 0, 0, 0, 0, 0, 0, /* SEL_SIM [2] */ FN_SEL_SIM_0, FN_SEL_SIM_1, FN_SEL_SIM_2, 0, /* SEL_SSI8 [2] */ FN_SEL_SSI8_0, FN_SEL_SSI8_1, FN_SEL_SSI8_2, 0, )) }, { PINMUX_CFG_REG_VAR("MOD_SEL3", 0xE6060098, 32, - GROUP(1, 1, 2, 4, 4, 2, 2, 4, 2, 3, 2, 3, 2), + GROUP(1, 1, -12, 2, -6, 3, 2, 3, 2), GROUP( /* SEL_IICDVFS [1] */ FN_SEL_IICDVFS_0, FN_SEL_IICDVFS_1, /* SEL_IIC0 [1] */ FN_SEL_IIC0_0, FN_SEL_IIC0_1, - /* RESERVED [2] */ - 0, 0, 0, 0, - /* RESERVED [4] */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - /* RESERVED [4] */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - /* RESERVED [2] */ - 0, 0, 0, 0, + /* RESERVED [12] */ /* SEL_IEB [2] */ FN_SEL_IEB_0, FN_SEL_IEB_1, FN_SEL_IEB_2, 0, - /* RESERVED [4] */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - /* RESERVED [2] */ - 0, 0, 0, 0, + /* RESERVED [6] */ /* SEL_IIC2 [3] */ FN_SEL_IIC2_0, FN_SEL_IIC2_1, FN_SEL_IIC2_2, FN_SEL_IIC2_3, FN_SEL_IIC2_4, 0, 0, 0, diff --git a/drivers/pinctrl/renesas/pfc-r8a7791.c b/drivers/pinctrl/renesas/pfc-r8a7791.c index 076a8b7d71de04d22d9a6c27768347f10d45883c..d57458504117daa3cd6ba2ffc1583a7b559c47b9 100644 --- a/drivers/pinctrl/renesas/pfc-r8a7791.c +++ b/drivers/pinctrl/renesas/pfc-r8a7791.c @@ -5686,11 +5686,10 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { GP_7_0_FN, FN_IP15_17_15 )) }, { PINMUX_CFG_REG_VAR("IPSR0", 0xE6060020, 32, - GROUP(1, 2, 2, 2, 2, 2, 2, 3, 1, 1, 1, 1, + GROUP(-1, 2, 2, 2, 2, 2, 2, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), GROUP( - /* IP0_31 [1] */ - 0, 0, + /* IP0_31 [1] RESERVED */ /* IP0_30_29 [2] */ FN_A6, FN_MSIOF1_SCK, 0, 0, @@ -5783,10 +5782,9 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { 0, 0, )) }, { PINMUX_CFG_REG_VAR("IPSR2", 0xE6060028, 32, - GROUP(2, 3, 2, 2, 2, 2, 3, 3, 3, 3, 2, 2, 3), + GROUP(-2, 3, 2, 2, 2, 2, 3, 3, 3, 3, 2, 2, 3), GROUP( - /* IP2_31_30 [2] */ - 0, 0, 0, 0, + /* IP2_31_30 [2] RESERVED */ /* IP2_29_27 [3] */ FN_EX_CS3_N, FN_ATADIR0_N, FN_MSIOF2_TXD, FN_ATAG0_N, 0, FN_EX_WAIT1, @@ -5820,10 +5818,9 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_SCIFB1_TXD_C, 0, FN_SCIFB1_SCK_B, 0, )) }, { PINMUX_CFG_REG_VAR("IPSR3", 0xE606002C, 32, - GROUP(1, 3, 3, 3, 2, 2, 2, 2, 2, 3, 3, 3, 3), + GROUP(-1, 3, 3, 3, 2, 2, 2, 2, 2, 3, 3, 3, 3), GROUP( - /* IP3_31 [1] */ - 0, 0, + /* IP3_31 [1] RESERVED */ /* IP3_30_28 [3] */ FN_SSI_WS0129, FN_HTX0_C, FN_HTX2_C, FN_SCIFB0_TXD_C, FN_SCIFB2_TXD_C, @@ -5859,11 +5856,10 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { 0, 0, 0, )) }, { PINMUX_CFG_REG_VAR("IPSR4", 0xE6060030, 32, - GROUP(1, 3, 2, 2, 2, 1, 1, 1, 3, 3, 3, 2, + GROUP(-1, 3, 2, 2, 2, 1, 1, 1, 3, 3, 3, 2, 3, 3, 2), GROUP( - /* IP4_31 [1] */ - 0, 0, + /* IP4_31 [1] RESERVED */ /* IP4_30_28 [3] */ FN_SSI_SCK5, FN_MSIOF1_SCK_C, FN_TS_SDATA0, FN_GLO_I0, FN_MSIOF2_SYNC_D, FN_VI1_R2_B, @@ -5943,10 +5939,9 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { 0, 0, )) }, { PINMUX_CFG_REG_VAR("IPSR6", 0xE6060038, 32, - GROUP(2, 3, 3, 3, 2, 3, 2, 2, 2, 2, 2, 3, 3), + GROUP(-2, 3, 3, 3, 2, 3, 2, 2, 2, 2, 2, 3, 3), GROUP( - /* IP6_31_30 [2] */ - 0, 0, 0, 0, + /* IP6_31_30 [2] RESERVED */ /* IP6_29_27 [3] */ FN_IRQ8, FN_HRTS1_N_C, FN_MSIOF1_RXD_B, FN_GPS_SIGN_C, FN_GPS_SIGN_D, @@ -5984,10 +5979,9 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { 0, 0, )) }, { PINMUX_CFG_REG_VAR("IPSR7", 0xE606003C, 32, - GROUP(2, 3, 3, 3, 2, 2, 2, 2, 2, 2, 3, 3, 3), + GROUP(-2, 3, 3, 3, 2, 2, 2, 2, 2, 2, 3, 3, 3), GROUP( - /* IP7_31_30 [2] */ - 0, 0, 0, 0, + /* IP7_31_30 [2] RESERVED */ /* IP7_29_27 [3] */ FN_DU1_DG2, FN_LCDOUT10, FN_VI1_DATA4_B, FN_SCIF1_SCK_B, FN_SCIFA1_SCK, FN_SSI_SCK78_B, @@ -6026,10 +6020,9 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { 0, 0, )) }, { PINMUX_CFG_REG_VAR("IPSR8", 0xE6060040, 32, - GROUP(1, 3, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3), + GROUP(-1, 3, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3), GROUP( - /* IP8_31 [1] */ - 0, 0, + /* IP8_31 [1] RESERVED */ /* IP8_30_28 [3] */ FN_DU1_DB5, FN_LCDOUT21, FN_TX3, FN_SCIFA3_TXD, FN_CAN1_TX, 0, 0, 0, @@ -6201,10 +6194,9 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_I2C1_SDA_D, 0, 0, 0, )) }, { PINMUX_CFG_REG_VAR("IPSR12", 0xE6060050, 32, - GROUP(2, 3, 3, 2, 2, 2, 2, 3, 3, 3, 3, 2, 2), + GROUP(-2, 3, 3, 2, 2, 2, 2, 3, 3, 3, 3, 2, 2), GROUP( - /* IP12_31_30 [2] */ - 0, 0, 0, 0, + /* IP12_31_30 [2] RESERVED */ /* IP12_29_27 [3] */ FN_STP_ISCLK_0, FN_AVB_TX_EN, FN_SCIFB2_RXD_D, FN_ADICS_SAMP_B, FN_MSIOF0_SCK_C, @@ -6243,11 +6235,10 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_ETH_RX_ER, FN_AVB_CRS, FN_I2C3_SCL, FN_IIC0_SCL, )) }, { PINMUX_CFG_REG_VAR("IPSR13", 0xE6060054, 32, - GROUP(1, 3, 1, 1, 1, 2, 1, 3, 3, 1, 1, 1, + GROUP(-1, 3, 1, 1, 1, 2, 1, 3, 3, 1, 1, 1, 1, 1, 1, 3, 2, 2, 3), GROUP( - /* IP13_31 [1] */ - 0, 0, + /* IP13_31 [1] RESERVED */ /* IP13_30_28 [3] */ FN_SD1_CD, FN_PWM0, FN_TPU_TO0, FN_I2C1_SCL_C, 0, 0, 0, 0, @@ -6340,10 +6331,9 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_SD1_WP, FN_PWM1_B, FN_I2C1_SDA_C, 0, )) }, { PINMUX_CFG_REG_VAR("IPSR15", 0xE606005C, 32, - GROUP(2, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2), + GROUP(-2, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2), GROUP( - /* IP15_31_30 [2] */ - 0, 0, 0, 0, + /* IP15_31_30 [2] RESERVED */ /* IP15_29_27 [3] */ FN_HTX0, FN_SCIFB0_TXD, 0, FN_GLO_SCLK_C, FN_CAN0_TX_B, FN_VI1_DATA5_C, @@ -6382,23 +6372,9 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_SIM0_RST, FN_IETX, FN_CAN1_TX_D, 0, )) }, { PINMUX_CFG_REG_VAR("IPSR16", 0xE6060160, 32, - GROUP(4, 4, 4, 4, 4, 2, 2, 2, 3, 3), + GROUP(-20, 2, 2, 2, 3, 3), GROUP( - /* IP16_31_28 [4] */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - /* IP16_27_24 [4] */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - /* IP16_23_20 [4] */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - /* IP16_19_16 [4] */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - /* IP16_15_12 [4] */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, + /* RESERVED [20] */ /* IP16_11_10 [2] */ FN_HRTS1_N, FN_SCIFB1_RTS_N, FN_MLB_DAT, FN_CAN1_RX_B, /* IP16_9_8 [2] */ @@ -6415,11 +6391,10 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { 0, 0, 0, )) }, { PINMUX_CFG_REG_VAR("MOD_SEL", 0xE6060090, 32, - GROUP(1, 2, 2, 2, 3, 2, 1, 1, 1, 1, 3, 2, - 2, 2, 1, 2, 2, 2), + GROUP(-1, 2, 2, 2, 3, 2, 1, 1, 1, 1, 3, -2, + 2, -2, 1, 2, 2, 2), GROUP( /* RESERVED [1] */ - 0, 0, /* SEL_SCIF1 [2] */ FN_SEL_SCIF1_0, FN_SEL_SCIF1_1, FN_SEL_SCIF1_2, FN_SEL_SCIF1_3, /* SEL_SCIFB [2] */ @@ -6446,11 +6421,9 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_SEL_HSCIF1_3, FN_SEL_HSCIF1_4, 0, 0, 0, /* RESERVED [2] */ - 0, 0, 0, 0, /* SEL_VI1 [2] */ FN_SEL_VI1_0, FN_SEL_VI1_1, FN_SEL_VI1_2, 0, /* RESERVED [2] */ - 0, 0, 0, 0, /* SEL_TMU [1] */ FN_SEL_TMU1_0, FN_SEL_TMU1_1, /* SEL_LBS [2] */ @@ -6461,15 +6434,14 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_SEL_SOF0_0, FN_SEL_SOF0_1, FN_SEL_SOF0_2, 0, )) }, { PINMUX_CFG_REG_VAR("MOD_SEL2", 0xE6060094, 32, - GROUP(3, 1, 1, 3, 2, 1, 1, 2, 2, 1, 3, 2, - 1, 2, 2, 2, 1, 1, 1), + GROUP(3, -1, 1, 3, 2, -1, 1, 2, -2, 1, 3, 2, + -1, 2, 2, 2, 1, -1, 1), GROUP( /* SEL_SCIF0 [3] */ FN_SEL_SCIF0_0, FN_SEL_SCIF0_1, FN_SEL_SCIF0_2, FN_SEL_SCIF0_3, FN_SEL_SCIF0_4, 0, 0, 0, /* RESERVED [1] */ - 0, 0, /* SEL_SCIF [1] */ FN_SEL_SCIF_0, FN_SEL_SCIF_1, /* SEL_CAN0 [3] */ @@ -6479,13 +6451,11 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { /* SEL_CAN1 [2] */ FN_SEL_CAN1_0, FN_SEL_CAN1_1, FN_SEL_CAN1_2, FN_SEL_CAN1_3, /* RESERVED [1] */ - 0, 0, /* SEL_SCIFA2 [1] */ FN_SEL_SCIFA2_0, FN_SEL_SCIFA2_1, /* SEL_SCIF4 [2] */ FN_SEL_SCIF4_0, FN_SEL_SCIF4_1, FN_SEL_SCIF4_2, 0, /* RESERVED [2] */ - 0, 0, 0, 0, /* SEL_ADG [1] */ FN_SEL_ADG_0, FN_SEL_ADG_1, /* SEL_FM [3] */ @@ -6495,7 +6465,6 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { /* SEL_SCIFA5 [2] */ FN_SEL_SCIFA5_0, FN_SEL_SCIFA5_1, FN_SEL_SCIFA5_2, 0, /* RESERVED [1] */ - 0, 0, /* SEL_GPS [2] */ FN_SEL_GPS_0, FN_SEL_GPS_1, FN_SEL_GPS_2, FN_SEL_GPS_3, /* SEL_SCIFA4 [2] */ @@ -6505,13 +6474,12 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { /* SEL_SIM [1] */ FN_SEL_SIM_0, FN_SEL_SIM_1, /* RESERVED [1] */ - 0, 0, /* SEL_SSI8 [1] */ FN_SEL_SSI8_0, FN_SEL_SSI8_1, )) }, { PINMUX_CFG_REG_VAR("MOD_SEL3", 0xE6060098, 32, - GROUP(2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 2, 2, - 3, 2, 2, 2, 1), + GROUP(2, 2, 2, 2, 2, 2, 2, 2, 1, 1, -2, 2, + 3, 2, -5), GROUP( /* SEL_HSCIF2 [2] */ FN_SEL_HSCIF2_0, FN_SEL_HSCIF2_1, @@ -6536,7 +6504,6 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { /* SEL_SCIF5 [1] */ FN_SEL_SCIF5_0, FN_SEL_SCIF5_1, /* RESERVED [2] */ - 0, 0, 0, 0, /* SEL_I2C2 [2] */ FN_SEL_I2C2_0, FN_SEL_I2C2_1, FN_SEL_I2C2_2, FN_SEL_I2C2_3, /* SEL_I2C1 [3] */ @@ -6545,16 +6512,11 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { 0, 0, 0, /* SEL_I2C0 [2] */ FN_SEL_I2C0_0, FN_SEL_I2C0_1, FN_SEL_I2C0_2, 0, - /* RESERVED [2] */ - 0, 0, 0, 0, - /* RESERVED [2] */ - 0, 0, 0, 0, - /* RESERVED [1] */ - 0, 0, )) + /* RESERVED [5] */ )) }, { PINMUX_CFG_REG_VAR("MOD_SEL4", 0xE606009C, 32, - GROUP(3, 2, 2, 1, 1, 1, 1, 3, 2, 2, 3, 1, - 1, 1, 2, 2, 2, 2), + GROUP(3, 2, 2, -1, 1, 1, 1, 3, -4, 3, -1, + 1, 1, 2, -6), GROUP( /* SEL_SOF1 [3] */ FN_SEL_SOF1_0, FN_SEL_SOF1_1, FN_SEL_SOF1_2, FN_SEL_SOF1_3, @@ -6565,7 +6527,6 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { /* SEL_DIS [2] */ FN_SEL_DIS_0, FN_SEL_DIS_1, FN_SEL_DIS_2, 0, /* RESERVED [1] */ - 0, 0, /* SEL_RAD [1] */ FN_SEL_RAD_0, FN_SEL_RAD_1, /* SEL_RCN [1] */ @@ -6577,27 +6538,19 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_SEL_SCIF2_3, FN_SEL_SCIF2_4, 0, 0, 0, /* RESERVED [2] */ - 0, 0, 0, 0, /* RESERVED [2] */ - 0, 0, 0, 0, /* SEL_SOF2 [3] */ FN_SEL_SOF2_0, FN_SEL_SOF2_1, FN_SEL_SOF2_2, FN_SEL_SOF2_3, FN_SEL_SOF2_4, 0, 0, 0, /* RESERVED [1] */ - 0, 0, /* SEL_SSI1 [1] */ FN_SEL_SSI1_0, FN_SEL_SSI1_1, /* SEL_SSI0 [1] */ FN_SEL_SSI0_0, FN_SEL_SSI0_1, /* SEL_SSP [2] */ FN_SEL_SSP_0, FN_SEL_SSP_1, FN_SEL_SSP_2, 0, - /* RESERVED [2] */ - 0, 0, 0, 0, - /* RESERVED [2] */ - 0, 0, 0, 0, - /* RESERVED [2] */ - 0, 0, 0, 0, )) + /* RESERVED [6] */ )) }, { }, }; diff --git a/drivers/pinctrl/renesas/pfc-r8a7792.c b/drivers/pinctrl/renesas/pfc-r8a7792.c index 3e101f63014825febc1aa4e688e077308608f192..808a85d62415399fe0eadf37e77f83c6ec07ba72 100644 --- a/drivers/pinctrl/renesas/pfc-r8a7792.c +++ b/drivers/pinctrl/renesas/pfc-r8a7792.c @@ -1999,16 +1999,11 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { GP_0_1_FN, FN_IP0_1, GP_0_0_FN, FN_IP0_0 )) }, - { PINMUX_CFG_REG("GPSR1", 0xE6060008, 32, 1, GROUP( - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("GPSR1", 0xE6060008, 32, + GROUP(-9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), + GROUP( + /* GP1_31_23 RESERVED */ GP_1_22_FN, FN_DU1_CDE, GP_1_21_FN, FN_DU1_DISP, GP_1_20_FN, FN_DU1_EXODDF_DU1_ODDF_DISP_CDE, @@ -2101,22 +2096,11 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { GP_3_1_FN, FN_A17, GP_3_0_FN, FN_A16 )) }, - { PINMUX_CFG_REG("GPSR4", 0xE6060014, 32, 1, GROUP( - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("GPSR4", 0xE6060014, 32, + GROUP(-15, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1), + GROUP( + /* GP4_31_17 RESERVED */ GP_4_16_FN, FN_VI0_FIELD, GP_4_15_FN, FN_VI0_D11_G3_Y3, GP_4_14_FN, FN_VI0_D10_G2_Y2, @@ -2135,22 +2119,11 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { GP_4_1_FN, FN_VI0_CLKENB, GP_4_0_FN, FN_VI0_CLK )) }, - { PINMUX_CFG_REG("GPSR5", 0xE6060018, 32, 1, GROUP( - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("GPSR5", 0xE6060018, 32, + GROUP(-15, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1), + GROUP( + /* GP5_31_17 RESERVED */ GP_5_16_FN, FN_VI1_FIELD, GP_5_15_FN, FN_VI1_D11_G3_Y3, GP_5_14_FN, FN_VI1_D10_G2_Y2, @@ -2169,22 +2142,11 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { GP_5_1_FN, FN_VI1_CLKENB, GP_5_0_FN, FN_VI1_CLK )) }, - { PINMUX_CFG_REG("GPSR6", 0xE606001C, 32, 1, GROUP( - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("GPSR6", 0xE606001C, 32, + GROUP(-15, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1), + GROUP( + /* GP6_31_17 RESERVED */ GP_6_16_FN, FN_IP2_16, GP_6_15_FN, FN_IP2_15, GP_6_14_FN, FN_IP2_14, @@ -2203,22 +2165,11 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { GP_6_1_FN, FN_IP2_1, GP_6_0_FN, FN_IP2_0 )) }, - { PINMUX_CFG_REG("GPSR7", 0xE6060020, 32, 1, GROUP( - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("GPSR7", 0xE6060020, 32, + GROUP(-15, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1), + GROUP( + /* GP7_31_17 RESERVED */ GP_7_16_FN, FN_VI3_FIELD, GP_7_15_FN, FN_IP3_14, GP_7_14_FN, FN_VI3_D10_Y2, @@ -2237,22 +2188,11 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { GP_7_1_FN, FN_IP3_1, GP_7_0_FN, FN_IP3_0 )) }, - { PINMUX_CFG_REG("GPSR8", 0xE6060024, 32, 1, GROUP( - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("GPSR8", 0xE6060024, 32, + GROUP(-15, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1), + GROUP( + /* GP8_31_17 RESERVED */ GP_8_16_FN, FN_IP4_24, GP_8_15_FN, FN_IP4_23, GP_8_14_FN, FN_IP4_22, @@ -2271,22 +2211,11 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { GP_8_1_FN, FN_IP4_0, GP_8_0_FN, FN_VI4_CLK )) }, - { PINMUX_CFG_REG("GPSR9", 0xE6060028, 32, 1, GROUP( - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("GPSR9", 0xE6060028, 32, + GROUP(-15, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1), + GROUP( + /* GP9_31_17 RESERVED */ GP_9_16_FN, FN_VI5_FIELD, GP_9_15_FN, FN_VI5_D11_Y3, GP_9_14_FN, FN_VI5_D10_Y2, @@ -2374,15 +2303,12 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { GP_11_0_FN, FN_IP7_1_0 )) }, { PINMUX_CFG_REG_VAR("IPSR0", 0xE6060040, 32, - GROUP(4, 4, + GROUP(-8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), GROUP( - /* IP0_31_28 [4] */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* IP0_27_24 [4] */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* IP0_31_24 [8] RESERVED */ /* IP0_23 [1] */ FN_DU0_DB7_C5, 0, /* IP0_22 [1] */ @@ -2433,17 +2359,11 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_DU0_DR0_DATA0, 0 )) }, { PINMUX_CFG_REG_VAR("IPSR1", 0xE6060044, 32, - GROUP(4, 4, - 1, 1, 1, 1, 1, 1, 1, 1, + GROUP(-9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), GROUP( - /* IP1_31_28 [4] */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* IP1_27_24 [4] */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* IP1_23 [1] */ - 0, 0, + /* IP1_31_23 [9] RESERVED */ /* IP1_22 [1] */ FN_A25, FN_SSL, /* IP1_21 [1] */ @@ -2492,19 +2412,11 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_DU0_EXHSYNC_DU0_HSYNC, 0 )) }, { PINMUX_CFG_REG_VAR("IPSR2", 0xE6060048, 32, - GROUP(4, 4, - 4, 3, 1, + GROUP(-15, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), GROUP( - /* IP2_31_28 [4] */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* IP2_27_24 [4] */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* IP2_23_20 [4] */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* IP2_19_17 [3] */ - 0, 0, 0, 0, 0, 0, 0, 0, + /* IP2_31_17 [15] RESERVED */ /* IP2_16 [1] */ FN_VI2_FIELD, FN_AVB_TXD2, /* IP2_15 [1] */ @@ -2541,21 +2453,10 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_VI2_CLK, FN_AVB_RX_CLK )) }, { PINMUX_CFG_REG_VAR("IPSR3", 0xE606004C, 32, - GROUP(4, 4, - 4, 4, - 1, 1, 1, 1, 1, 1, 1, 1, + GROUP(-17, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), GROUP( - /* IP3_31_28 [4] */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* IP3_27_24 [4] */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* IP3_23_20 [4] */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* IP3_19_16 [4] */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* IP3_15 [1] */ - 0, 0, + /* IP3_31_15 [17] RESERVED */ /* IP3_14 [1] */ FN_VI3_D11_Y3, FN_AVB_AVTP_MATCH, /* IP3_13 [1] */ @@ -2588,14 +2489,10 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_VI3_CLK, FN_AVB_TX_CLK )) }, { PINMUX_CFG_REG_VAR("IPSR4", 0xE6060050, 32, - GROUP(4, 3, 1, - 1, 1, 1, 2, 2, 2, + GROUP(-7, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 1, 1), GROUP( - /* IP4_31_28 [4] */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* IP4_27_25 [3] */ - 0, 0, 0, 0, 0, 0, 0, 0, + /* IP4_31_25 [7] RESERVED */ /* IP4_24 [1] */ FN_VI4_FIELD, FN_VI3_D15_Y7, /* IP4_23 [1] */ @@ -2630,21 +2527,10 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_VI4_CLKENB, FN_VI0_D12_G4_Y4 )) }, { PINMUX_CFG_REG_VAR("IPSR5", 0xE6060054, 32, - GROUP(4, 4, - 4, 4, - 4, 1, 1, 1, 1, + GROUP(-20, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), GROUP( - /* IP5_31_28 [4] */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* IP5_27_24 [4] */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* IP5_23_20 [4] */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* IP5_19_16 [4] */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* IP5_15_12 [4] */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* IP5_31_12 [20] RESERVED */ /* IP5_11 [1] */ FN_VI5_D8_Y0, FN_VI1_D23_R7, /* IP5_10 [1] */ @@ -2671,19 +2557,10 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_VI5_CLKENB, FN_VI1_D12_G4_Y4_B )) }, { PINMUX_CFG_REG_VAR("IPSR6", 0xE6060058, 32, - GROUP(4, 4, - 4, 1, 2, 1, - 2, 2, 2, 2, + GROUP(-13, 2, 1, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1), GROUP( - /* IP6_31_28 [4] */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* IP6_27_24 [4] */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* IP6_23_20 [4] */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* IP6_19 [1] */ - 0, 0, + /* IP6_31_19 [13] RESERVED */ /* IP6_18_17 [2] */ FN_DREQ1_N, FN_RX3, 0, 0, /* IP6_16 [1] */ @@ -2714,17 +2591,11 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_MSIOF0_SCK, FN_HSCK0 )) }, { PINMUX_CFG_REG_VAR("IPSR7", 0xE606005C, 32, - GROUP(4, 4, - 3, 1, 1, 1, 1, 1, + GROUP(-11, 1, 1, 1, 1, 1, 2, 2, 2, 2, 1, 1, 2, 2, 2), GROUP( - /* IP7_31_28 [4] */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* IP7_27_24 [4] */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* IP7_23_21 [3] */ - 0, 0, 0, 0, 0, 0, 0, 0, + /* IP7_31_21 [11] RESERVED */ /* IP7_20 [1] */ FN_AUDIO_CLKB, 0, /* IP7_19 [1] */ diff --git a/drivers/pinctrl/renesas/pfc-r8a7794.c b/drivers/pinctrl/renesas/pfc-r8a7794.c index d1b0e651738249ca589f1bf1a8e4196a1a026621..668643553a70a71aa6cde9bf40b5c6af7dff779d 100644 --- a/drivers/pinctrl/renesas/pfc-r8a7794.c +++ b/drivers/pinctrl/renesas/pfc-r8a7794.c @@ -4867,7 +4867,7 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { }, { PINMUX_CFG_REG_VAR("IPSR0", 0xE6060020, 32, GROUP(2, 2, 2, 1, 1, 2, 2, 2, 1, 1, 1, 1, - 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1), + 1, 1, 1, 1, 2, -7, 1), GROUP( /* IP0_31_30 [2] */ FN_D5, FN_SCIF4_RXD_B, FN_I2C0_SCL_D, 0, @@ -4903,25 +4903,12 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_MMC_CLK, FN_SD2_CLK, /* IP0_9_8 [2] */ FN_SD1_WP, FN_IRQ7, FN_CAN0_TX, 0, - /* IP0_7 [1] */ - 0, 0, - /* IP0_6 [1] */ - 0, 0, - /* IP0_5 [1] */ - 0, 0, - /* IP0_4 [1] */ - 0, 0, - /* IP0_3 [1] */ - 0, 0, - /* IP0_2 [1] */ - 0, 0, - /* IP0_1 [1] */ - 0, 0, + /* IP0_7_1 [7] RESERVED */ /* IP0_0 [1] */ FN_SD1_CD, FN_CAN0_RX, )) }, { PINMUX_CFG_REG_VAR("IPSR1", 0xE6060024, 32, - GROUP(2, 2, 1, 1, 1, 1, 2, 2, 2, 3, 2, 2, + GROUP(2, 2, 1, 1, -1, 1, 2, 2, 2, 3, 2, 2, 3, 2, 2, 2, 2), GROUP( /* IP1_31_30 [2] */ @@ -4932,8 +4919,7 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_A4, FN_SCIFB0_TXD, /* IP1_26 [1] */ FN_A3, FN_SCIFB0_SCK, - /* IP1_25 [1] */ - 0, 0, + /* IP1_25 [1] RESERVED */ /* IP1_24 [1] */ FN_A1, FN_SCIFB1_TXD, /* IP1_23_22 [2] */ @@ -5160,12 +5146,11 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_DU0_EXVSYNC_DU0_VSYNC, FN_QSTB_QHE, 0, 0, )) }, { PINMUX_CFG_REG_VAR("IPSR7", 0xE606003C, 32, - GROUP(1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3), + GROUP(1, -1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3), GROUP( /* IP7_31 [1] */ FN_DREQ0_N, FN_SCIFB1_RXD, - /* IP7_30 [1] */ - 0, 0, + /* IP7_30 [1] RESERVED */ /* IP7_29_27 [3] */ FN_ETH_TXD0, FN_VI0_R2, FN_SCIF3_RXD_B, FN_I2C4_SCL_E, FN_AVB_GTX_CLK, FN_SSI_WS6_B, 0, 0, @@ -5234,10 +5219,9 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_AVB_MDC, FN_SSI_SDATA6_B, 0, 0, )) }, { PINMUX_CFG_REG_VAR("IPSR9", 0xE6060044, 32, - GROUP(1, 3, 3, 3, 3, 2, 2, 3, 3, 3, 3, 3), + GROUP(-1, 3, 3, 3, 3, 2, 2, 3, 3, 3, 3, 3), GROUP( - /* IP9_31 [1] */ - 0, 0, + /* IP9_31 [1] RESERVED */ /* IP9_30_28 [3] */ FN_SCIF1_SCK, FN_PWM3, FN_TCLK2, FN_DU1_DG5, FN_SSI_SDATA1_B, 0, 0, 0, @@ -5307,10 +5291,9 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { 0, 0, 0, 0, )) }, { PINMUX_CFG_REG_VAR("IPSR11", 0xE606004C, 32, - GROUP(2, 3, 3, 3, 3, 2, 2, 3, 3, 2, 3, 3), + GROUP(-2, 3, 3, 3, 3, 2, 2, 3, 3, 2, 3, 3), GROUP( - /* IP11_31_30 [2] */ - 0, 0, 0, 0, + /* IP11_31_30 [2] RESERVED */ /* IP11_29_27 [3] */ FN_SSI_SDATA0, FN_MSIOF1_SCK_B, FN_PWM0_B, FN_ADICLK_B, 0, 0, 0, 0, @@ -5343,10 +5326,9 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { 0, 0, 0, 0, )) }, { PINMUX_CFG_REG_VAR("IPSR12", 0xE6060050, 32, - GROUP(2, 3, 3, 3, 3, 3, 2, 2, 2, 3, 3, 3), + GROUP(-2, 3, 3, 3, 3, 3, 2, 2, 2, 3, 3, 3), GROUP( - /* IP12_31_30 [2] */ - 0, 0, 0, 0, + /* IP12_31_30 [2] RESERVED */ /* IP12_29_27 [3] */ FN_SSI_SCK2, FN_HSCIF1_HTX_B, FN_VI1_DATA2, 0, FN_ATAG0_N, FN_ETH_RXD1_B, 0, 0, @@ -5379,18 +5361,9 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { 0, FN_DREQ1_N_B, 0, 0, )) }, { PINMUX_CFG_REG_VAR("IPSR13", 0xE6060054, 32, - GROUP(1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3), + GROUP(-5, 3, 3, 3, 3, 3, 3, 3, 3, 3), GROUP( - /* IP13_31 [1] */ - 0, 0, - /* IP13_30 [1] */ - 0, 0, - /* IP13_29 [1] */ - 0, 0, - /* IP13_28 [1] */ - 0, 0, - /* IP13_27 [1] */ - 0, 0, + /* IP13_31_27 [5] RESERVED */ /* IP13_26_24 [3] */ FN_AUDIO_CLKOUT, FN_I2C4_SDA_B, FN_SCIFA5_TXD_D, FN_VI1_VSYNC_N, FN_TS_SPSYNC_C, 0, FN_FMIN_E, 0, @@ -5420,23 +5393,21 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { 0, FN_ATACS00_N, FN_ETH_LINK_B, 0, )) }, { PINMUX_CFG_REG_VAR("MOD_SEL", 0xE6060090, 32, - GROUP(2, 1, 2, 3, 4, 1, 1, 3, 3, 3, 3, 3, 2, 1), + GROUP(2, -1, 2, 3, -4, 1, -1, + 3, 3, 3, 3, 3, 2, -1), GROUP( /* SEL_ADG [2] */ FN_SEL_ADG_0, FN_SEL_ADG_1, FN_SEL_ADG_2, FN_SEL_ADG_3, /* RESERVED [1] */ - 0, 0, /* SEL_CAN [2] */ FN_SEL_CAN_0, FN_SEL_CAN_1, FN_SEL_CAN_2, FN_SEL_CAN_3, /* SEL_DARC [3] */ FN_SEL_DARC_0, FN_SEL_DARC_1, FN_SEL_DARC_2, FN_SEL_DARC_3, FN_SEL_DARC_4, 0, 0, 0, /* RESERVED [4] */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* SEL_ETH [1] */ FN_SEL_ETH_0, FN_SEL_ETH_1, /* RESERVED [1] */ - 0, 0, /* SEL_IC200 [3] */ FN_SEL_I2C00_0, FN_SEL_I2C00_1, FN_SEL_I2C00_2, FN_SEL_I2C00_3, FN_SEL_I2C00_4, 0, 0, 0, @@ -5454,12 +5425,11 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_SEL_I2C04_4, 0, 0, 0, /* SEL_I2C05 [2] */ FN_SEL_I2C05_0, FN_SEL_I2C05_1, FN_SEL_I2C05_2, FN_SEL_I2C05_3, - /* RESERVED [1] */ - 0, 0, )) + /* RESERVED [1] */ )) }, { PINMUX_CFG_REG_VAR("MOD_SEL2", 0xE6060094, 32, GROUP(2, 2, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, - 2, 2, 1, 1, 2, 2, 2, 1, 1, 2), + 2, 2, -1, 1, 2, 2, 2, 1, 1, -2), GROUP( /* SEL_IEB [2] */ FN_SEL_IEB_0, FN_SEL_IEB_1, FN_SEL_IEB_2, 0, @@ -5493,7 +5463,6 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_SEL_SCIFA5_0, FN_SEL_SCIFA5_1, FN_SEL_SCIFA5_2, FN_SEL_SCIFA5_3, /* RESERVED [1] */ - 0, 0, /* SEL_TMU [1] */ FN_SEL_TMU_0, FN_SEL_TMU_1, /* SEL_TSIF0 [2] */ @@ -5506,12 +5475,11 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_SEL_HSCIF0_0, FN_SEL_HSCIF0_1, /* SEL_HSCIF1 [1] */ FN_SEL_HSCIF1_0, FN_SEL_HSCIF1_1, - /* RESERVED [2] */ - 0, 0, 0, 0, )) + /* RESERVED [2] */ )) }, { PINMUX_CFG_REG_VAR("MOD_SEL3", 0xE6060098, 32, GROUP(2, 2, 2, 1, 3, 2, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), + 1, 1, -12), GROUP( /* SEL_SCIF0 [2] */ FN_SEL_SCIF0_0, FN_SEL_SCIF0_1, FN_SEL_SCIF0_2, FN_SEL_SCIF0_3, @@ -5542,30 +5510,7 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_SEL_SSI8_0, FN_SEL_SSI8_1, /* SEL_SSI9 [1] */ FN_SEL_SSI9_0, FN_SEL_SSI9_1, - /* RESERVED [1] */ - 0, 0, - /* RESERVED [1] */ - 0, 0, - /* RESERVED [1] */ - 0, 0, - /* RESERVED [1] */ - 0, 0, - /* RESERVED [1] */ - 0, 0, - /* RESERVED [1] */ - 0, 0, - /* RESERVED [1] */ - 0, 0, - /* RESERVED [1] */ - 0, 0, - /* RESERVED [1] */ - 0, 0, - /* RESERVED [1] */ - 0, 0, - /* RESERVED [1] */ - 0, 0, - /* RESERVED [1] */ - 0, 0, )) + /* RESERVED [12] */ )) }, { }, }; diff --git a/drivers/pinctrl/renesas/pfc-r8a77950.c b/drivers/pinctrl/renesas/pfc-r8a77950.c index 63c9f6d6468b386947bee614085af0afc8b39046..4c543ec3a8639393c6b0728d0be6c51f93cba8f3 100644 --- a/drivers/pinctrl/renesas/pfc-r8a77950.c +++ b/drivers/pinctrl/renesas/pfc-r8a77950.c @@ -4701,23 +4701,11 @@ static const struct sh_pfc_function pinmux_functions[] = { static const struct pinmux_cfg_reg pinmux_config_regs[] = { #define F_(x, y) FN_##y #define FM(x) FN_##x - { PINMUX_CFG_REG("GPSR0", 0xe6060100, 32, 1, GROUP( - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("GPSR0", 0xe6060100, 32, + GROUP(-16, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1), + GROUP( + /* GP0_31_16 RESERVED */ GP_0_15_FN, GPSR0_15, GP_0_14_FN, GPSR0_14, GP_0_13_FN, GPSR0_13, @@ -4769,24 +4757,11 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { GP_1_1_FN, GPSR1_1, GP_1_0_FN, GPSR1_0, )) }, - { PINMUX_CFG_REG("GPSR2", 0xe6060108, 32, 1, GROUP( - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("GPSR2", 0xe6060108, 32, + GROUP(-17, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1), + GROUP( + /* GP2_31_15 RESERVED */ GP_2_14_FN, GPSR2_14, GP_2_13_FN, GPSR2_13, GP_2_12_FN, GPSR2_12, @@ -4803,23 +4778,11 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { GP_2_1_FN, GPSR2_1, GP_2_0_FN, GPSR2_0, )) }, - { PINMUX_CFG_REG("GPSR3", 0xe606010c, 32, 1, GROUP( - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("GPSR3", 0xe606010c, 32, + GROUP(-16, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1), + GROUP( + /* GP3_31_16 RESERVED */ GP_3_15_FN, GPSR3_15, GP_3_14_FN, GPSR3_14, GP_3_13_FN, GPSR3_13, @@ -4837,21 +4800,11 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { GP_3_1_FN, GPSR3_1, GP_3_0_FN, GPSR3_0, )) }, - { PINMUX_CFG_REG("GPSR4", 0xe6060110, 32, 1, GROUP( - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("GPSR4", 0xe6060110, 32, + GROUP(-14, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1), + GROUP( + /* GP4_31_18 RESERVED */ GP_4_17_FN, GPSR4_17, GP_4_16_FN, GPSR4_16, GP_4_15_FN, GPSR4_15, @@ -4939,35 +4892,10 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { GP_6_1_FN, GPSR6_1, GP_6_0_FN, GPSR6_0, )) }, - { PINMUX_CFG_REG("GPSR7", 0xe606011c, 32, 1, GROUP( - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("GPSR7", 0xe606011c, 32, + GROUP(-28, 1, 1, 1, 1), + GROUP( + /* GP7_31_4 RESERVED */ GP_7_3_FN, GPSR7_3, GP_7_2_FN, GPSR7_2, GP_7_1_FN, GPSR7_1, @@ -5148,13 +5076,10 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { IP16_7_4 IP16_3_0 )) }, - { PINMUX_CFG_REG("IPSR17", 0xe6060244, 32, 4, GROUP( - /* IP17_31_28 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* IP17_27_24 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* IP17_23_20 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* IP17_19_16 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* IP17_15_12 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* IP17_11_8 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + { PINMUX_CFG_REG_VAR("IPSR17", 0xe6060244, 32, + GROUP(-24, 4, 4), + GROUP( + /* IP17_31_8 RESERVED */ IP17_7_4 IP17_3_0 )) }, @@ -5164,10 +5089,10 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { #define F_(x, y) x, #define FM(x) FN_##x, { PINMUX_CFG_REG_VAR("MOD_SEL0", 0xe6060500, 32, - GROUP(1, 2, 2, 3, 1, 1, 2, 1, 1, 1, 2, 1, - 1, 1, 1, 1, 1, 1, 2, 2, 1, 2, 1), + GROUP(-1, 2, 2, 3, 1, 1, 2, 1, 1, 1, 2, 1, + 1, 1, 1, 1, 1, 1, 2, 2, 1, 2, -1), GROUP( - 0, 0, /* RESERVED 31 */ + /* RESERVED 31 */ MOD_SEL0_30_29 MOD_SEL0_28_27 MOD_SEL0_26_25_24 @@ -5189,11 +5114,11 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { MOD_SEL0_5_4 MOD_SEL0_3 MOD_SEL0_2_1 - 0, 0, /* RESERVED 0 */ )) + /* RESERVED 0 */ )) }, { PINMUX_CFG_REG_VAR("MOD_SEL1", 0xe6060504, 32, GROUP(2, 3, 1, 2, 3, 1, 1, 2, 1, 2, 1, 1, - 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1), + 1, 1, 1, -2, 1, 1, 1, 1, 1, 1, 1), GROUP( MOD_SEL1_31_30 MOD_SEL1_29_28_27 @@ -5210,7 +5135,7 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { MOD_SEL1_11 MOD_SEL1_10 MOD_SEL1_9 - 0, 0, 0, 0, /* RESERVED 8, 7 */ + /* RESERVED 8, 7 */ MOD_SEL1_6 MOD_SEL1_5 MOD_SEL1_4 @@ -5220,35 +5145,12 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { MOD_SEL1_0 )) }, { PINMUX_CFG_REG_VAR("MOD_SEL2", 0xe6060508, 32, - GROUP(1, 1, 1, 1, 4, 4, 4, 4, 4, 4, 1, 2, 1), + GROUP(1, 1, 1, -28, 1), GROUP( MOD_SEL2_31 MOD_SEL2_30 MOD_SEL2_29 - /* RESERVED 28 */ - 0, 0, - /* RESERVED 27, 26, 25, 24 */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - /* RESERVED 23, 22, 21, 20 */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - /* RESERVED 19, 18, 17, 16 */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - /* RESERVED 15, 14, 13, 12 */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - /* RESERVED 11, 10, 9, 8 */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - /* RESERVED 7, 6, 5, 4 */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - /* RESERVED 3 */ - 0, 0, - /* RESERVED 2, 1 */ - 0, 0, 0, 0, + /* RESERVED 28-1 */ MOD_SEL2_0 )) }, { }, diff --git a/drivers/pinctrl/renesas/pfc-r8a77951.c b/drivers/pinctrl/renesas/pfc-r8a77951.c index 9d6eef4e9d1885b957d0fe9d236a0d1516e459f8..d4d271dff055462da019d45ef97412b1375ebba5 100644 --- a/drivers/pinctrl/renesas/pfc-r8a77951.c +++ b/drivers/pinctrl/renesas/pfc-r8a77951.c @@ -5139,23 +5139,11 @@ static const struct { static const struct pinmux_cfg_reg pinmux_config_regs[] = { #define F_(x, y) FN_##y #define FM(x) FN_##x - { PINMUX_CFG_REG("GPSR0", 0xe6060100, 32, 1, GROUP( - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("GPSR0", 0xe6060100, 32, + GROUP(-16, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1), + GROUP( + /* GP0_31_16 RESERVED */ GP_0_15_FN, GPSR0_15, GP_0_14_FN, GPSR0_14, GP_0_13_FN, GPSR0_13, @@ -5207,24 +5195,11 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { GP_1_1_FN, GPSR1_1, GP_1_0_FN, GPSR1_0, )) }, - { PINMUX_CFG_REG("GPSR2", 0xe6060108, 32, 1, GROUP( - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("GPSR2", 0xe6060108, 32, + GROUP(-17, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1), + GROUP( + /* GP2_31_15 RESERVED */ GP_2_14_FN, GPSR2_14, GP_2_13_FN, GPSR2_13, GP_2_12_FN, GPSR2_12, @@ -5241,23 +5216,11 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { GP_2_1_FN, GPSR2_1, GP_2_0_FN, GPSR2_0, )) }, - { PINMUX_CFG_REG("GPSR3", 0xe606010c, 32, 1, GROUP( - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("GPSR3", 0xe606010c, 32, + GROUP(-16, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1), + GROUP( + /* GP3_31_16 RESERVED */ GP_3_15_FN, GPSR3_15, GP_3_14_FN, GPSR3_14, GP_3_13_FN, GPSR3_13, @@ -5275,21 +5238,11 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { GP_3_1_FN, GPSR3_1, GP_3_0_FN, GPSR3_0, )) }, - { PINMUX_CFG_REG("GPSR4", 0xe6060110, 32, 1, GROUP( - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("GPSR4", 0xe6060110, 32, + GROUP(-14, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1), + GROUP( + /* GP4_31_18 RESERVED */ GP_4_17_FN, GPSR4_17, GP_4_16_FN, GPSR4_16, GP_4_15_FN, GPSR4_15, @@ -5377,35 +5330,10 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { GP_6_1_FN, GPSR6_1, GP_6_0_FN, GPSR6_0, )) }, - { PINMUX_CFG_REG("GPSR7", 0xe606011c, 32, 1, GROUP( - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("GPSR7", 0xe606011c, 32, + GROUP(-28, 1, 1, 1, 1), + GROUP( + /* GP7_31_4 RESERVED */ GP_7_3_FN, GPSR7_3, GP_7_2_FN, GPSR7_2, GP_7_1_FN, GPSR7_1, @@ -5486,12 +5414,14 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { IP6_7_4 IP6_3_0 )) }, - { PINMUX_CFG_REG("IPSR7", 0xe606021c, 32, 4, GROUP( + { PINMUX_CFG_REG_VAR("IPSR7", 0xe606021c, 32, + GROUP(4, 4, 4, 4, -4, 4, 4, 4), + GROUP( IP7_31_28 IP7_27_24 IP7_23_20 IP7_19_16 - /* IP7_15_12 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* IP7_15_12 RESERVED */ IP7_11_8 IP7_7_4 IP7_3_0 )) @@ -5596,13 +5526,10 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { IP17_7_4 IP17_3_0 )) }, - { PINMUX_CFG_REG("IPSR18", 0xe6060248, 32, 4, GROUP( - /* IP18_31_28 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* IP18_27_24 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* IP18_23_20 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* IP18_19_16 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* IP18_15_12 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* IP18_11_8 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + { PINMUX_CFG_REG_VAR("IPSR18", 0xe6060248, 32, + GROUP(-24, 4, 4), + GROUP( + /* IP18_31_8 RESERVED */ IP18_7_4 IP18_3_0 )) }, @@ -5612,8 +5539,8 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { #define F_(x, y) x, #define FM(x) FN_##x, { PINMUX_CFG_REG_VAR("MOD_SEL0", 0xe6060500, 32, - GROUP(3, 2, 3, 1, 1, 1, 1, 1, 2, 1, 1, 2, - 1, 1, 1, 2, 2, 1, 2, 3), + GROUP(3, 2, 3, 1, 1, 1, 1, 1, 2, 1, -1, 2, + 1, 1, 1, 2, 2, 1, 2, -3), GROUP( MOD_SEL0_31_30_29 MOD_SEL0_28_27 @@ -5625,7 +5552,7 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { MOD_SEL0_19 MOD_SEL0_18_17 MOD_SEL0_16 - 0, 0, /* RESERVED 15 */ + /* RESERVED 15 */ MOD_SEL0_14_13 MOD_SEL0_12 MOD_SEL0_11 @@ -5634,12 +5561,11 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { MOD_SEL0_7_6 MOD_SEL0_5 MOD_SEL0_4_3 - /* RESERVED 2, 1, 0 */ - 0, 0, 0, 0, 0, 0, 0, 0 )) + /* RESERVED 2, 1, 0 */ )) }, { PINMUX_CFG_REG_VAR("MOD_SEL1", 0xe6060504, 32, GROUP(2, 3, 1, 2, 3, 1, 1, 2, 1, 2, 1, 1, - 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1), + 1, 1, 1, -2, 1, 1, 1, 1, 1, 1, 1), GROUP( MOD_SEL1_31_30 MOD_SEL1_29_28_27 @@ -5656,7 +5582,7 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { MOD_SEL1_11 MOD_SEL1_10 MOD_SEL1_9 - 0, 0, 0, 0, /* RESERVED 8, 7 */ + /* RESERVED 8, 7 */ MOD_SEL1_6 MOD_SEL1_5 MOD_SEL1_4 @@ -5666,8 +5592,8 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { MOD_SEL1_0 )) }, { PINMUX_CFG_REG_VAR("MOD_SEL2", 0xe6060508, 32, - GROUP(1, 1, 1, 2, 1, 3, 1, 1, 1, 1, 1, 1, - 1, 4, 4, 4, 3, 1), + GROUP(1, 1, 1, 2, 1, 3, -1, 1, 1, 1, 1, 1, + -16, 1), GROUP( MOD_SEL2_31 MOD_SEL2_30 @@ -5676,25 +5602,12 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { MOD_SEL2_26 MOD_SEL2_25_24_23 /* RESERVED 22 */ - 0, 0, MOD_SEL2_21 MOD_SEL2_20 MOD_SEL2_19 MOD_SEL2_18 MOD_SEL2_17 - /* RESERVED 16 */ - 0, 0, - /* RESERVED 15, 14, 13, 12 */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - /* RESERVED 11, 10, 9, 8 */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - /* RESERVED 7, 6, 5, 4 */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - /* RESERVED 3, 2, 1 */ - 0, 0, 0, 0, 0, 0, 0, 0, + /* RESERVED 16-1 */ MOD_SEL2_0 )) }, { }, diff --git a/drivers/pinctrl/renesas/pfc-r8a7796.c b/drivers/pinctrl/renesas/pfc-r8a7796.c index 75ea36829a70e0246a6d3a55f92c0a8bbde894c4..a0096ef5e68dc6d64dc9b95b36575ada9f28af16 100644 --- a/drivers/pinctrl/renesas/pfc-r8a7796.c +++ b/drivers/pinctrl/renesas/pfc-r8a7796.c @@ -5094,23 +5094,11 @@ static const struct { static const struct pinmux_cfg_reg pinmux_config_regs[] = { #define F_(x, y) FN_##y #define FM(x) FN_##x - { PINMUX_CFG_REG("GPSR0", 0xe6060100, 32, 1, GROUP( - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("GPSR0", 0xe6060100, 32, + GROUP(-16, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1), + GROUP( + /* GP0_31_16 RESERVED */ GP_0_15_FN, GPSR0_15, GP_0_14_FN, GPSR0_14, GP_0_13_FN, GPSR0_13, @@ -5162,24 +5150,11 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { GP_1_1_FN, GPSR1_1, GP_1_0_FN, GPSR1_0, )) }, - { PINMUX_CFG_REG("GPSR2", 0xe6060108, 32, 1, GROUP( - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("GPSR2", 0xe6060108, 32, + GROUP(-17, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1), + GROUP( + /* GP2_31_15 RESERVED */ GP_2_14_FN, GPSR2_14, GP_2_13_FN, GPSR2_13, GP_2_12_FN, GPSR2_12, @@ -5196,23 +5171,11 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { GP_2_1_FN, GPSR2_1, GP_2_0_FN, GPSR2_0, )) }, - { PINMUX_CFG_REG("GPSR3", 0xe606010c, 32, 1, GROUP( - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("GPSR3", 0xe606010c, 32, + GROUP(-16, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1), + GROUP( + /* GP3_31_16 RESERVED */ GP_3_15_FN, GPSR3_15, GP_3_14_FN, GPSR3_14, GP_3_13_FN, GPSR3_13, @@ -5230,21 +5193,11 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { GP_3_1_FN, GPSR3_1, GP_3_0_FN, GPSR3_0, )) }, - { PINMUX_CFG_REG("GPSR4", 0xe6060110, 32, 1, GROUP( - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("GPSR4", 0xe6060110, 32, + GROUP(-14, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1), + GROUP( + /* GP4_31_18 RESERVED */ GP_4_17_FN, GPSR4_17, GP_4_16_FN, GPSR4_16, GP_4_15_FN, GPSR4_15, @@ -5332,35 +5285,10 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { GP_6_1_FN, GPSR6_1, GP_6_0_FN, GPSR6_0, )) }, - { PINMUX_CFG_REG("GPSR7", 0xe606011c, 32, 1, GROUP( - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("GPSR7", 0xe606011c, 32, + GROUP(-28, 1, 1, 1, 1), + GROUP( + /* GP7_31_4 RESERVED */ GP_7_3_FN, GPSR7_3, GP_7_2_FN, GPSR7_2, GP_7_1_FN, GPSR7_1, @@ -5441,12 +5369,14 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { IP6_7_4 IP6_3_0 )) }, - { PINMUX_CFG_REG("IPSR7", 0xe606021c, 32, 4, GROUP( + { PINMUX_CFG_REG_VAR("IPSR7", 0xe606021c, 32, + GROUP(4, 4, 4, 4, -4, 4, 4, 4), + GROUP( IP7_31_28 IP7_27_24 IP7_23_20 IP7_19_16 - /* IP7_15_12 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* IP7_15_12 RESERVED */ IP7_11_8 IP7_7_4 IP7_3_0 )) @@ -5551,13 +5481,10 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { IP17_7_4 IP17_3_0 )) }, - { PINMUX_CFG_REG("IPSR18", 0xe6060248, 32, 4, GROUP( - /* IP18_31_28 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* IP18_27_24 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* IP18_23_20 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* IP18_19_16 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* IP18_15_12 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* IP18_11_8 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + { PINMUX_CFG_REG_VAR("IPSR18", 0xe6060248, 32, + GROUP(-24, 4, 4), + GROUP( + /* IP18_31_8 RESERVED */ IP18_7_4 IP18_3_0 )) }, @@ -5567,8 +5494,8 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { #define F_(x, y) x, #define FM(x) FN_##x, { PINMUX_CFG_REG_VAR("MOD_SEL0", 0xe6060500, 32, - GROUP(3, 2, 3, 1, 1, 1, 1, 1, 2, 1, 1, 2, - 1, 1, 1, 2, 2, 1, 2, 3), + GROUP(3, 2, 3, 1, 1, 1, 1, 1, 2, 1, -1, 2, + 1, 1, 1, 2, 2, 1, 2, -3), GROUP( MOD_SEL0_31_30_29 MOD_SEL0_28_27 @@ -5580,7 +5507,7 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { MOD_SEL0_19 MOD_SEL0_18_17 MOD_SEL0_16 - 0, 0, /* RESERVED 15 */ + /* RESERVED 15 */ MOD_SEL0_14_13 MOD_SEL0_12 MOD_SEL0_11 @@ -5589,12 +5516,11 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { MOD_SEL0_7_6 MOD_SEL0_5 MOD_SEL0_4_3 - /* RESERVED 2, 1, 0 */ - 0, 0, 0, 0, 0, 0, 0, 0 )) + /* RESERVED 2, 1, 0 */ )) }, { PINMUX_CFG_REG_VAR("MOD_SEL1", 0xe6060504, 32, GROUP(2, 3, 1, 2, 3, 1, 1, 2, 1, 2, 1, 1, - 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1), + 1, 1, 1, -2, 1, 1, 1, 1, 1, 1, 1), GROUP( MOD_SEL1_31_30 MOD_SEL1_29_28_27 @@ -5611,7 +5537,7 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { MOD_SEL1_11 MOD_SEL1_10 MOD_SEL1_9 - 0, 0, 0, 0, /* RESERVED 8, 7 */ + /* RESERVED 8, 7 */ MOD_SEL1_6 MOD_SEL1_5 MOD_SEL1_4 @@ -5622,7 +5548,7 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { }, { PINMUX_CFG_REG_VAR("MOD_SEL2", 0xe6060508, 32, GROUP(1, 1, 1, 2, 1, 3, 1, 1, 1, 1, 1, 1, - 1, 4, 4, 4, 3, 1), + -16, 1), GROUP( MOD_SEL2_31 MOD_SEL2_30 @@ -5636,19 +5562,7 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { MOD_SEL2_19 MOD_SEL2_18 MOD_SEL2_17 - /* RESERVED 16 */ - 0, 0, - /* RESERVED 15, 14, 13, 12 */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - /* RESERVED 11, 10, 9, 8 */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - /* RESERVED 7, 6, 5, 4 */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - /* RESERVED 3, 2, 1 */ - 0, 0, 0, 0, 0, 0, 0, 0, + /* RESERVED 16-1 */ MOD_SEL2_0 )) }, { }, diff --git a/drivers/pinctrl/renesas/pfc-r8a77965.c b/drivers/pinctrl/renesas/pfc-r8a77965.c index 6bb7f7543c37ca8de901fa6363779f164a4aaad5..acd0bdf1301844ef1923c787626302921c727b45 100644 --- a/drivers/pinctrl/renesas/pfc-r8a77965.c +++ b/drivers/pinctrl/renesas/pfc-r8a77965.c @@ -5335,23 +5335,11 @@ static const struct { static const struct pinmux_cfg_reg pinmux_config_regs[] = { #define F_(x, y) FN_##y #define FM(x) FN_##x - { PINMUX_CFG_REG("GPSR0", 0xe6060100, 32, 1, GROUP( - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("GPSR0", 0xe6060100, 32, + GROUP(-16, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1), + GROUP( + /* GP0_31_16 RESERVED */ GP_0_15_FN, GPSR0_15, GP_0_14_FN, GPSR0_14, GP_0_13_FN, GPSR0_13, @@ -5403,24 +5391,11 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { GP_1_1_FN, GPSR1_1, GP_1_0_FN, GPSR1_0, )) }, - { PINMUX_CFG_REG("GPSR2", 0xe6060108, 32, 1, GROUP( - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("GPSR2", 0xe6060108, 32, + GROUP(-17, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1), + GROUP( + /* GP2_31_15 RESERVED */ GP_2_14_FN, GPSR2_14, GP_2_13_FN, GPSR2_13, GP_2_12_FN, GPSR2_12, @@ -5437,23 +5412,11 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { GP_2_1_FN, GPSR2_1, GP_2_0_FN, GPSR2_0, )) }, - { PINMUX_CFG_REG("GPSR3", 0xe606010c, 32, 1, GROUP( - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("GPSR3", 0xe606010c, 32, + GROUP(-16, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1), + GROUP( + /* GP3_31_16 RESERVED */ GP_3_15_FN, GPSR3_15, GP_3_14_FN, GPSR3_14, GP_3_13_FN, GPSR3_13, @@ -5471,21 +5434,11 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { GP_3_1_FN, GPSR3_1, GP_3_0_FN, GPSR3_0, )) }, - { PINMUX_CFG_REG("GPSR4", 0xe6060110, 32, 1, GROUP( - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("GPSR4", 0xe6060110, 32, + GROUP(-14, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1), + GROUP( + /* GP4_31_18 RESERVED */ GP_4_17_FN, GPSR4_17, GP_4_16_FN, GPSR4_16, GP_4_15_FN, GPSR4_15, @@ -5573,35 +5526,10 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { GP_6_1_FN, GPSR6_1, GP_6_0_FN, GPSR6_0, )) }, - { PINMUX_CFG_REG("GPSR7", 0xe606011c, 32, 1, GROUP( - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("GPSR7", 0xe606011c, 32, + GROUP(-28, 1, 1, 1, 1), + GROUP( + /* GP7_31_4 RESERVED */ GP_7_3_FN, GPSR7_3, GP_7_2_FN, GPSR7_2, GP_7_1_FN, GPSR7_1, @@ -5682,12 +5610,14 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { IP6_7_4 IP6_3_0 )) }, - { PINMUX_CFG_REG("IPSR7", 0xe606021c, 32, 4, GROUP( + { PINMUX_CFG_REG_VAR("IPSR7", 0xe606021c, 32, + GROUP(4, 4, 4, 4, -4, 4, 4, 4), + GROUP( IP7_31_28 IP7_27_24 IP7_23_20 IP7_19_16 - /* IP7_15_12 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* IP7_15_12 RESERVED */ IP7_11_8 IP7_7_4 IP7_3_0 )) @@ -5792,13 +5722,10 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { IP17_7_4 IP17_3_0 )) }, - { PINMUX_CFG_REG("IPSR18", 0xe6060248, 32, 4, GROUP( - /* IP18_31_28 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* IP18_27_24 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* IP18_23_20 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* IP18_19_16 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* IP18_15_12 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* IP18_11_8 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + { PINMUX_CFG_REG_VAR("IPSR18", 0xe6060248, 32, + GROUP(-24, 4, 4), + GROUP( + /* IP18_31_8 RESERVED */ IP18_7_4 IP18_3_0 )) }, @@ -5808,8 +5735,8 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { #define F_(x, y) x, #define FM(x) FN_##x, { PINMUX_CFG_REG_VAR("MOD_SEL0", 0xe6060500, 32, - GROUP(3, 2, 3, 1, 1, 1, 1, 1, 2, 1, 1, 2, - 1, 1, 1, 2, 2, 1, 2, 3), + GROUP(3, 2, 3, 1, 1, 1, 1, 1, 2, 1, -1, 2, + 1, 1, 1, 2, 2, 1, 2, -3), GROUP( MOD_SEL0_31_30_29 MOD_SEL0_28_27 @@ -5821,7 +5748,7 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { MOD_SEL0_19 MOD_SEL0_18_17 MOD_SEL0_16 - 0, 0, /* RESERVED 15 */ + /* RESERVED 15 */ MOD_SEL0_14_13 MOD_SEL0_12 MOD_SEL0_11 @@ -5830,12 +5757,11 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { MOD_SEL0_7_6 MOD_SEL0_5 MOD_SEL0_4_3 - /* RESERVED 2, 1, 0 */ - 0, 0, 0, 0, 0, 0, 0, 0 )) + /* RESERVED 2, 1, 0 */ )) }, { PINMUX_CFG_REG_VAR("MOD_SEL1", 0xe6060504, 32, GROUP(2, 3, 1, 2, 3, 1, 1, 2, 1, 2, 1, 1, - 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1), + 1, 1, 1, -2, 1, 1, 1, 1, 1, 1, 1), GROUP( MOD_SEL1_31_30 MOD_SEL1_29_28_27 @@ -5852,7 +5778,7 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { MOD_SEL1_11 MOD_SEL1_10 MOD_SEL1_9 - 0, 0, 0, 0, /* RESERVED 8, 7 */ + /* RESERVED 8, 7 */ MOD_SEL1_6 MOD_SEL1_5 MOD_SEL1_4 @@ -5863,7 +5789,7 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { }, { PINMUX_CFG_REG_VAR("MOD_SEL2", 0xe6060508, 32, GROUP(1, 1, 1, 2, 1, 3, 1, 1, 1, 1, 1, 1, - 1, 4, 4, 4, 3, 1), + -16, 1), GROUP( MOD_SEL2_31 MOD_SEL2_30 @@ -5877,19 +5803,7 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { MOD_SEL2_19 MOD_SEL2_18 MOD_SEL2_17 - /* RESERVED 16 */ - 0, 0, - /* RESERVED 15, 14, 13, 12 */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - /* RESERVED 11, 10, 9, 8 */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - /* RESERVED 7, 6, 5, 4 */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - /* RESERVED 3, 2, 1 */ - 0, 0, 0, 0, 0, 0, 0, 0, + /* RESERVED 16-1 */ MOD_SEL2_0 )) }, { }, diff --git a/drivers/pinctrl/renesas/pfc-r8a77970.c b/drivers/pinctrl/renesas/pfc-r8a77970.c index 94f90c13989eceb9411fb2086fab8bc35149ccac..4a7803eaafaa8abf54ebf0074b6dc9b124609e81 100644 --- a/drivers/pinctrl/renesas/pfc-r8a77970.c +++ b/drivers/pinctrl/renesas/pfc-r8a77970.c @@ -231,7 +231,6 @@ #define IP8_19_16 FM(CANFD_CLK_A) FM(CLK_EXTFXR) FM(PWM4_B) FM(SPEEDIN_B) FM(SCIF_CLK_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP8_23_20 FM(DIGRF_CLKIN) FM(DIGRF_CLKEN_IN) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP8_27_24 FM(DIGRF_CLKOUT) FM(DIGRF_CLKEN_OUT) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP8_31_28 F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define PINMUX_GPSR \ \ @@ -290,8 +289,7 @@ FM(IP8_11_8) IP8_11_8 \ FM(IP8_15_12) IP8_15_12 \ FM(IP8_19_16) IP8_19_16 \ FM(IP8_23_20) IP8_23_20 \ -FM(IP8_27_24) IP8_27_24 \ -FM(IP8_31_28) IP8_31_28 +FM(IP8_27_24) IP8_27_24 /* MOD_SEL0 */ /* 0 */ /* 1 */ #define MOD_SEL0_11 FM(SEL_I2C3_0) FM(SEL_I2C3_1) @@ -2085,17 +2083,11 @@ static const struct sh_pfc_function pinmux_functions[] = { static const struct pinmux_cfg_reg pinmux_config_regs[] = { #define F_(x, y) FN_##y #define FM(x) FN_##x - { PINMUX_CFG_REG("GPSR0", 0xe6060100, 32, 1, GROUP( - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("GPSR0", 0xe6060100, 32, + GROUP(-10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), + GROUP( + /* GP0_31_22 RESERVED */ GP_0_21_FN, GPSR0_21, GP_0_20_FN, GPSR0_20, GP_0_19_FN, GPSR0_19, @@ -2153,22 +2145,11 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { GP_1_1_FN, GPSR1_1, GP_1_0_FN, GPSR1_0, )) }, - { PINMUX_CFG_REG("GPSR2", 0xe6060108, 32, 1, GROUP( - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("GPSR2", 0xe6060108, 32, + GROUP(-15, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1), + GROUP( + /* GP2_31_17 RESERVED */ GP_2_16_FN, GPSR2_16, GP_2_15_FN, GPSR2_15, GP_2_14_FN, GPSR2_14, @@ -2187,22 +2168,11 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { GP_2_1_FN, GPSR2_1, GP_2_0_FN, GPSR2_0, )) }, - { PINMUX_CFG_REG("GPSR3", 0xe606010c, 32, 1, GROUP( - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("GPSR3", 0xe606010c, 32, + GROUP(-15, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1), + GROUP( + /* GP3_31_17 RESERVED */ GP_3_16_FN, GPSR3_16, GP_3_15_FN, GPSR3_15, GP_3_14_FN, GPSR3_14, @@ -2221,33 +2191,10 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { GP_3_1_FN, GPSR3_1, GP_3_0_FN, GPSR3_0, )) }, - { PINMUX_CFG_REG("GPSR4", 0xe6060110, 32, 1, GROUP( - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("GPSR4", 0xe6060110, 32, + GROUP(-26, 1, 1, 1, 1, 1, 1), + GROUP( + /* GP4_31_6 RESERVED */ GP_4_5_FN, GPSR4_5, GP_4_4_FN, GPSR4_4, GP_4_3_FN, GPSR4_3, @@ -2255,24 +2202,11 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { GP_4_1_FN, GPSR4_1, GP_4_0_FN, GPSR4_0, )) }, - { PINMUX_CFG_REG("GPSR5", 0xe6060114, 32, 1, GROUP( - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("GPSR5", 0xe6060114, 32, + GROUP(-17, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1), + GROUP( + /* GP5_31_15 RESERVED */ GP_5_14_FN, GPSR5_14, GP_5_13_FN, GPSR5_13, GP_5_12_FN, GPSR5_12, @@ -2374,8 +2308,10 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { IP7_7_4 IP7_3_0 )) }, - { PINMUX_CFG_REG("IPSR8", 0xe6060220, 32, 4, GROUP( - IP8_31_28 + { PINMUX_CFG_REG_VAR("IPSR8", 0xe6060220, 32, + GROUP(-4, 4, 4, 4, 4, 4, 4, 4), + GROUP( + /* IP8_31_28 RESERVED */ IP8_27_24 IP8_23_20 IP8_19_16 @@ -2390,19 +2326,9 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { #define F_(x, y) x, #define FM(x) FN_##x, { PINMUX_CFG_REG_VAR("MOD_SEL0", 0xe6060500, 32, - GROUP(4, 4, 4, 4, 4, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1), + GROUP(-20, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), GROUP( - /* RESERVED 31, 30, 29, 28 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* RESERVED 27, 26, 25, 24 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* RESERVED 23, 22, 21, 20 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* RESERVED 19, 18, 17, 16 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* RESERVED 15, 14, 13, 12 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* RESERVED 31-12 */ MOD_SEL0_11 MOD_SEL0_10 MOD_SEL0_9 diff --git a/drivers/pinctrl/renesas/pfc-r8a77980.c b/drivers/pinctrl/renesas/pfc-r8a77980.c index c229a5d8fa5738161c3c2eeb8b5d312c40ce304e..ac03309c5c0c9756778f3d448be3c1519ba85c5a 100644 --- a/drivers/pinctrl/renesas/pfc-r8a77980.c +++ b/drivers/pinctrl/renesas/pfc-r8a77980.c @@ -278,9 +278,6 @@ #define IP10_11_8 FM(FSO_CFE_0_N) F_(0, 0) F_(0, 0) FM(VI0_DATA22) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP10_15_12 FM(FSO_CFE_1_N) F_(0, 0) F_(0, 0) FM(VI0_DATA23) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP10_19_16 FM(FSO_TOE_N) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP10_23_20 F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP10_27_24 F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP10_31_28 F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define PINMUX_GPSR \ \ @@ -340,9 +337,9 @@ FM(IP8_7_4) IP8_7_4 FM(IP9_7_4) IP9_7_4 FM(IP10_7_4) IP10_7_4 \ FM(IP8_11_8) IP8_11_8 FM(IP9_11_8) IP9_11_8 FM(IP10_11_8) IP10_11_8 \ FM(IP8_15_12) IP8_15_12 FM(IP9_15_12) IP9_15_12 FM(IP10_15_12) IP10_15_12 \ FM(IP8_19_16) IP8_19_16 FM(IP9_19_16) IP9_19_16 FM(IP10_19_16) IP10_19_16 \ -FM(IP8_23_20) IP8_23_20 FM(IP9_23_20) IP9_23_20 FM(IP10_23_20) IP10_23_20 \ -FM(IP8_27_24) IP8_27_24 FM(IP9_27_24) IP9_27_24 FM(IP10_27_24) IP10_27_24 \ -FM(IP8_31_28) IP8_31_28 FM(IP9_31_28) IP9_31_28 FM(IP10_31_28) IP10_31_28 +FM(IP8_23_20) IP8_23_20 FM(IP9_23_20) IP9_23_20 \ +FM(IP8_27_24) IP8_27_24 FM(IP9_27_24) IP9_27_24 \ +FM(IP8_31_28) IP8_31_28 FM(IP9_31_28) IP9_31_28 /* MOD_SEL0 */ /* 0 */ /* 1 */ #define MOD_SEL0_11 FM(SEL_CANFD0_0) FM(SEL_CANFD0_1) @@ -2507,17 +2504,11 @@ static const struct sh_pfc_function pinmux_functions[] = { static const struct pinmux_cfg_reg pinmux_config_regs[] = { #define F_(x, y) FN_##y #define FM(x) FN_##x - { PINMUX_CFG_REG("GPSR0", 0xe6060100, 32, 1, GROUP( - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("GPSR0", 0xe6060100, 32, + GROUP(-10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), + GROUP( + /* GP0_31_22 RESERVED */ GP_0_21_FN, GPSR0_21, GP_0_20_FN, GPSR0_20, GP_0_19_FN, GPSR0_19, @@ -2609,22 +2600,11 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { GP_2_1_FN, GPSR2_1, GP_2_0_FN, GPSR2_0, )) }, - { PINMUX_CFG_REG("GPSR3", 0xe606010c, 32, 1, GROUP( - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("GPSR3", 0xe606010c, 32, + GROUP(-15, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1), + GROUP( + /* GP3_31_17 RESERVED */ GP_3_16_FN, GPSR3_16, GP_3_15_FN, GPSR3_15, GP_3_14_FN, GPSR3_14, @@ -2643,14 +2623,12 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { GP_3_1_FN, GPSR3_1, GP_3_0_FN, GPSR3_0, )) }, - { PINMUX_CFG_REG("GPSR4", 0xe6060110, 32, 1, GROUP( - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("GPSR4", 0xe6060110, 32, + GROUP(-7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1), + GROUP( + /* GP4_31_25 RESERVED */ GP_4_24_FN, GPSR4_24, GP_4_23_FN, GPSR4_23, GP_4_22_FN, GPSR4_22, @@ -2677,24 +2655,11 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { GP_4_1_FN, GPSR4_1, GP_4_0_FN, GPSR4_0, )) }, - { PINMUX_CFG_REG("GPSR5", 0xe6060114, 32, 1, GROUP( - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("GPSR5", 0xe6060114, 32, + GROUP(-17, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1), + GROUP( + /* GP5_31_15 RESERVED */ GP_5_14_FN, GPSR5_14, GP_5_13_FN, GPSR5_13, GP_5_12_FN, GPSR5_12, @@ -2816,10 +2781,10 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { IP9_7_4 IP9_3_0 )) }, - { PINMUX_CFG_REG("IPSR10", 0xe6060228, 32, 4, GROUP( - IP10_31_28 - IP10_27_24 - IP10_23_20 + { PINMUX_CFG_REG_VAR("IPSR10", 0xe6060228, 32, + GROUP(-12, 4, 4, 4, 4, 4), + GROUP( + /* IP10_31_20 RESERVED */ IP10_19_16 IP10_15_12 IP10_11_8 @@ -2832,19 +2797,9 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { #define F_(x, y) x, #define FM(x) FN_##x, { PINMUX_CFG_REG_VAR("MOD_SEL0", 0xe6060500, 32, - GROUP(4, 4, 4, 4, 4, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1), + GROUP(-20, 1, 1, 1, 1, 1, 1, 1, 1, -1, 1, 1, 1), GROUP( - /* RESERVED 31, 30, 29, 28 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* RESERVED 27, 26, 25, 24 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* RESERVED 23, 22, 21, 20 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* RESERVED 19, 18, 17, 16 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* RESERVED 15, 14, 13, 12 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* RESERVED 31-12 */ MOD_SEL0_11 MOD_SEL0_10 MOD_SEL0_9 @@ -2853,7 +2808,7 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { MOD_SEL0_6 MOD_SEL0_5 MOD_SEL0_4 - 0, 0, + /* RESERVED 3 */ MOD_SEL0_2 MOD_SEL0_1 MOD_SEL0_0 )) diff --git a/drivers/pinctrl/renesas/pfc-r8a77990.c b/drivers/pinctrl/renesas/pfc-r8a77990.c index 6c4ba9e16058ff22801fa8f3eb499b741a0a9450..b0936962fad709f1c5bb50ca493e83c35eedb104 100644 --- a/drivers/pinctrl/renesas/pfc-r8a77990.c +++ b/drivers/pinctrl/renesas/pfc-r8a77990.c @@ -22,12 +22,12 @@ PORT_GP_CFG_18(0, fn, sfx, CFG_FLAGS), \ PORT_GP_CFG_23(1, fn, sfx, CFG_FLAGS), \ PORT_GP_CFG_26(2, fn, sfx, CFG_FLAGS), \ - PORT_GP_CFG_12(3, fn, sfx, CFG_FLAGS | SH_PFC_PIN_CFG_IO_VOLTAGE), \ + PORT_GP_CFG_12(3, fn, sfx, CFG_FLAGS | SH_PFC_PIN_CFG_IO_VOLTAGE | SH_PFC_PIN_CFG_DRIVE_STRENGTH), \ PORT_GP_CFG_1(3, 12, fn, sfx, CFG_FLAGS), \ PORT_GP_CFG_1(3, 13, fn, sfx, CFG_FLAGS), \ PORT_GP_CFG_1(3, 14, fn, sfx, CFG_FLAGS), \ PORT_GP_CFG_1(3, 15, fn, sfx, CFG_FLAGS), \ - PORT_GP_CFG_11(4, fn, sfx, CFG_FLAGS | SH_PFC_PIN_CFG_IO_VOLTAGE), \ + PORT_GP_CFG_11(4, fn, sfx, CFG_FLAGS | SH_PFC_PIN_CFG_IO_VOLTAGE | SH_PFC_PIN_CFG_DRIVE_STRENGTH), \ PORT_GP_CFG_20(5, fn, sfx, CFG_FLAGS), \ PORT_GP_CFG_9(6, fn, sfx, CFG_FLAGS), \ PORT_GP_CFG_1(6, 9, fn, sfx, SH_PFC_PIN_CFG_PULL_UP), \ @@ -2827,16 +2827,6 @@ static const unsigned int qspi0_ctrl_pins[] = { static const unsigned int qspi0_ctrl_mux[] = { QSPI0_SPCLK_MARK, QSPI0_SSL_MARK, }; -static const unsigned int qspi0_data_pins[] = { - /* QSPI0_MOSI_IO0, QSPI0_MISO_IO1 */ - RCAR_GP_PIN(2, 1), RCAR_GP_PIN(2, 2), - /* QSPI0_IO2, QSPI0_IO3 */ - RCAR_GP_PIN(2, 3), RCAR_GP_PIN(2, 4), -}; -static const unsigned int qspi0_data_mux[] = { - QSPI0_MOSI_IO0_MARK, QSPI0_MISO_IO1_MARK, - QSPI0_IO2_MARK, QSPI0_IO3_MARK, -}; /* - QSPI1 ------------------------------------------------------------------ */ static const unsigned int qspi1_ctrl_pins[] = { /* QSPI1_SPCLK, QSPI1_SSL */ @@ -2845,16 +2835,51 @@ static const unsigned int qspi1_ctrl_pins[] = { static const unsigned int qspi1_ctrl_mux[] = { QSPI1_SPCLK_MARK, QSPI1_SSL_MARK, }; -static const unsigned int qspi1_data_pins[] = { - /* QSPI1_MOSI_IO0, QSPI1_MISO_IO1 */ + +/* - RPC -------------------------------------------------------------------- */ +static const unsigned int rpc_clk_pins[] = { + /* Octal-SPI flash: C/SCLK */ + /* HyperFlash: CK, CK# */ + RCAR_GP_PIN(2, 0), RCAR_GP_PIN(2, 6), +}; +static const unsigned int rpc_clk_mux[] = { + QSPI0_SPCLK_MARK, QSPI1_SPCLK_MARK, +}; +static const unsigned int rpc_ctrl_pins[] = { + /* Octal-SPI flash: S#/CS, DQS */ + /* HyperFlash: CS#, RDS */ + RCAR_GP_PIN(2, 5), RCAR_GP_PIN(2, 11), +}; +static const unsigned int rpc_ctrl_mux[] = { + QSPI0_SSL_MARK, QSPI1_SSL_MARK, +}; +static const unsigned int rpc_data_pins[] = { + /* DQ[0:7] */ + RCAR_GP_PIN(2, 1), RCAR_GP_PIN(2, 2), + RCAR_GP_PIN(2, 3), RCAR_GP_PIN(2, 4), RCAR_GP_PIN(2, 7), RCAR_GP_PIN(2, 8), - /* QSPI1_IO2, QSPI1_IO3 */ RCAR_GP_PIN(2, 9), RCAR_GP_PIN(2, 10), }; -static const unsigned int qspi1_data_mux[] = { +static const unsigned int rpc_data_mux[] = { + QSPI0_MOSI_IO0_MARK, QSPI0_MISO_IO1_MARK, + QSPI0_IO2_MARK, QSPI0_IO3_MARK, QSPI1_MOSI_IO0_MARK, QSPI1_MISO_IO1_MARK, QSPI1_IO2_MARK, QSPI1_IO3_MARK, }; +static const unsigned int rpc_reset_pins[] = { + /* RPC_RESET# */ + RCAR_GP_PIN(2, 13), +}; +static const unsigned int rpc_reset_mux[] = { + RPC_RESET_N_MARK, +}; +static const unsigned int rpc_int_pins[] = { + /* RPC_INT# */ + RCAR_GP_PIN(2, 12), +}; +static const unsigned int rpc_int_mux[] = { + RPC_INT_N_MARK, +}; /* - SCIF0 ------------------------------------------------------------------ */ static const unsigned int scif0_data_a_pins[] = { @@ -3758,7 +3783,7 @@ static const unsigned int vin5_clk_b_mux[] = { }; static const struct { - struct sh_pfc_pin_group common[255]; + struct sh_pfc_pin_group common[261]; #ifdef CONFIG_PINCTRL_PFC_R8A77990 struct sh_pfc_pin_group automotive[22]; #endif @@ -3907,11 +3932,17 @@ static const struct { SH_PFC_PIN_GROUP(pwm6_a), SH_PFC_PIN_GROUP(pwm6_b), SH_PFC_PIN_GROUP(qspi0_ctrl), - BUS_DATA_PIN_GROUP(qspi0_data, 2), - BUS_DATA_PIN_GROUP(qspi0_data, 4), + SH_PFC_PIN_GROUP_SUBSET(qspi0_data2, rpc_data, 0, 2), + SH_PFC_PIN_GROUP_SUBSET(qspi0_data4, rpc_data, 0, 4), SH_PFC_PIN_GROUP(qspi1_ctrl), - BUS_DATA_PIN_GROUP(qspi1_data, 2), - BUS_DATA_PIN_GROUP(qspi1_data, 4), + SH_PFC_PIN_GROUP_SUBSET(qspi1_data2, rpc_data, 4, 2), + SH_PFC_PIN_GROUP_SUBSET(qspi1_data4, rpc_data, 4, 4), + BUS_DATA_PIN_GROUP(rpc_clk, 1), + BUS_DATA_PIN_GROUP(rpc_clk, 2), + SH_PFC_PIN_GROUP(rpc_ctrl), + SH_PFC_PIN_GROUP(rpc_data), + SH_PFC_PIN_GROUP(rpc_reset), + SH_PFC_PIN_GROUP(rpc_int), SH_PFC_PIN_GROUP(scif0_data_a), SH_PFC_PIN_GROUP(scif0_clk_a), SH_PFC_PIN_GROUP(scif0_ctrl_a), @@ -4336,6 +4367,15 @@ static const char * const qspi1_groups[] = { "qspi1_data4", }; +static const char * const rpc_groups[] = { + "rpc_clk1", + "rpc_clk2", + "rpc_ctrl", + "rpc_data", + "rpc_reset", + "rpc_int", +}; + static const char * const scif0_groups[] = { "scif0_data_a", "scif0_clk_a", @@ -4492,7 +4532,7 @@ static const char * const vin5_groups[] = { }; static const struct { - struct sh_pfc_function common[49]; + struct sh_pfc_function common[50]; #ifdef CONFIG_PINCTRL_PFC_R8A77990 struct sh_pfc_function automotive[5]; #endif @@ -4531,6 +4571,7 @@ static const struct { SH_PFC_FUNCTION(pwm6), SH_PFC_FUNCTION(qspi0), SH_PFC_FUNCTION(qspi1), + SH_PFC_FUNCTION(rpc), SH_PFC_FUNCTION(scif0), SH_PFC_FUNCTION(scif1), SH_PFC_FUNCTION(scif2), @@ -4562,21 +4603,11 @@ static const struct { static const struct pinmux_cfg_reg pinmux_config_regs[] = { #define F_(x, y) FN_##y #define FM(x) FN_##x - { PINMUX_CFG_REG("GPSR0", 0xe6060100, 32, 1, GROUP( - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("GPSR0", 0xe6060100, 32, + GROUP(-14, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1), + GROUP( + /* GP0_31_18 RESERVED */ GP_0_17_FN, GPSR0_17, GP_0_16_FN, GPSR0_16, GP_0_15_FN, GPSR0_15, @@ -4596,16 +4627,11 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { GP_0_1_FN, GPSR0_1, GP_0_0_FN, GPSR0_0, )) }, - { PINMUX_CFG_REG("GPSR1", 0xe6060104, 32, 1, GROUP( - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("GPSR1", 0xe6060104, 32, + GROUP(-9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), + GROUP( + /* GP1_31_23 RESERVED */ GP_1_22_FN, GPSR1_22, GP_1_21_FN, GPSR1_21, GP_1_20_FN, GPSR1_20, @@ -4664,23 +4690,11 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { GP_2_1_FN, GPSR2_1, GP_2_0_FN, GPSR2_0, )) }, - { PINMUX_CFG_REG("GPSR3", 0xe606010c, 32, 1, GROUP( - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("GPSR3", 0xe606010c, 32, + GROUP(-16, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1), + GROUP( + /* GP3_31_16 RESERVED */ GP_3_15_FN, GPSR3_15, GP_3_14_FN, GPSR3_14, GP_3_13_FN, GPSR3_13, @@ -4698,28 +4712,10 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { GP_3_1_FN, GPSR3_1, GP_3_0_FN, GPSR3_0, )) }, - { PINMUX_CFG_REG("GPSR4", 0xe6060110, 32, 1, GROUP( - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("GPSR4", 0xe6060110, 32, + GROUP(-21, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), + GROUP( + /* GP4_31_11 RESERVED */ GP_4_10_FN, GPSR4_10, GP_4_9_FN, GPSR4_9, GP_4_8_FN, GPSR4_8, @@ -4732,19 +4728,11 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { GP_4_1_FN, GPSR4_1, GP_4_0_FN, GPSR4_0, )) }, - { PINMUX_CFG_REG("GPSR5", 0xe6060114, 32, 1, GROUP( - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("GPSR5", 0xe6060114, 32, + GROUP(-12, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1), + GROUP( + /* GP5_31_20 RESERVED */ GP_5_19_FN, GPSR5_19, GP_5_18_FN, GPSR5_18, GP_5_17_FN, GPSR5_17, @@ -4766,21 +4754,11 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { GP_5_1_FN, GPSR5_1, GP_5_0_FN, GPSR5_0, )) }, - { PINMUX_CFG_REG("GPSR6", 0xe6060118, 32, 1, GROUP( - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("GPSR6", 0xe6060118, 32, + GROUP(-14, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1), + GROUP( + /* GP6_31_18 RESERVED */ GP_6_17_FN, GPSR6_17, GP_6_16_FN, GPSR6_16, GP_6_15_FN, GPSR6_15, @@ -4971,11 +4949,10 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { #define F_(x, y) x, #define FM(x) FN_##x, { PINMUX_CFG_REG_VAR("MOD_SEL0", 0xe6060500, 32, - GROUP(1, 2, 1, 2, 1, 1, 1, 1, 2, 3, 1, 1, + GROUP(-1, 2, 1, 2, 1, 1, 1, 1, 2, 3, 1, 1, 1, 2, 2, 1, 1, 1, 2, 1, 1, 1, 2), GROUP( /* RESERVED 31 */ - 0, 0, MOD_SEL0_30_29 MOD_SEL0_28 MOD_SEL0_27_26 @@ -5000,15 +4977,14 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { MOD_SEL0_1_0 )) }, { PINMUX_CFG_REG_VAR("MOD_SEL1", 0xe6060504, 32, - GROUP(1, 1, 1, 1, 1, 1, 1, 3, 3, 1, 1, 1, - 1, 2, 2, 2, 1, 1, 2, 1, 4), + GROUP(1, 1, 1, 1, -1, 1, 1, 3, 3, 1, 1, 1, + 1, 2, 2, 2, 1, 1, 2, 1, -4), GROUP( MOD_SEL1_31 MOD_SEL1_30 MOD_SEL1_29 MOD_SEL1_28 /* RESERVED 27 */ - 0, 0, MOD_SEL1_26 MOD_SEL1_25 MOD_SEL1_24_23_22 @@ -5024,12 +5000,44 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { MOD_SEL1_7 MOD_SEL1_6_5 MOD_SEL1_4 - /* RESERVED 3, 2, 1, 0 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 )) + /* RESERVED 3, 2, 1, 0 */ )) }, { }, }; +static const struct pinmux_drive_reg pinmux_drive_regs[] = { + { PINMUX_DRIVE_REG("DRVCTRL8", 0xe6060320) { + { RCAR_GP_PIN(3, 0), 18, 2 }, /* SD0_CLK */ + { RCAR_GP_PIN(3, 1), 15, 2 }, /* SD0_CMD */ + { RCAR_GP_PIN(3, 2), 12, 2 }, /* SD0_DAT0 */ + { RCAR_GP_PIN(3, 3), 9, 2 }, /* SD0_DAT1 */ + { RCAR_GP_PIN(3, 4), 6, 2 }, /* SD0_DAT2 */ + { RCAR_GP_PIN(3, 5), 3, 2 }, /* SD0_DAT3 */ + { RCAR_GP_PIN(3, 6), 0, 2 }, /* SD1_CLK */ + } }, + { PINMUX_DRIVE_REG("DRVCTRL9", 0xe6060324) { + { RCAR_GP_PIN(3, 7), 29, 2 }, /* SD1_CMD */ + { RCAR_GP_PIN(3, 8), 26, 2 }, /* SD1_DAT0 */ + { RCAR_GP_PIN(3, 9), 23, 2 }, /* SD1_DAT1 */ + { RCAR_GP_PIN(3, 10), 20, 2 }, /* SD1_DAT2 */ + { RCAR_GP_PIN(3, 11), 17, 2 }, /* SD1_DAT3 */ + { RCAR_GP_PIN(4, 0), 14, 2 }, /* SD3_CLK */ + { RCAR_GP_PIN(4, 1), 11, 2 }, /* SD3_CMD */ + { RCAR_GP_PIN(4, 2), 8, 2 }, /* SD3_DAT0 */ + { RCAR_GP_PIN(4, 3), 5, 2 }, /* SD3_DAT1 */ + { RCAR_GP_PIN(4, 4), 2, 2 }, /* SD3_DAT2 */ + } }, + { PINMUX_DRIVE_REG("DRVCTRL10", 0xe6060328) { + { RCAR_GP_PIN(4, 5), 29, 2 }, /* SD3_DAT3 */ + { RCAR_GP_PIN(4, 6), 26, 2 }, /* SD3_DAT4 */ + { RCAR_GP_PIN(4, 7), 23, 2 }, /* SD3_DAT5 */ + { RCAR_GP_PIN(4, 8), 20, 2 }, /* SD3_DAT6 */ + { RCAR_GP_PIN(4, 9), 17, 2 }, /* SD3_DAT7 */ + { RCAR_GP_PIN(4, 10), 14, 2 }, /* SD3_DS */ + } }, + { }, +}; + enum ioctrl_regs { POCCTRL0, TDSELCTRL, @@ -5286,6 +5294,7 @@ const struct sh_pfc_soc_info r8a774c0_pinmux_info = { .nr_functions = ARRAY_SIZE(pinmux_functions.common), .cfg_regs = pinmux_config_regs, + .drive_regs = pinmux_drive_regs, .bias_regs = pinmux_bias_regs, .ioctrl_regs = pinmux_ioctrl_regs, @@ -5312,6 +5321,7 @@ const struct sh_pfc_soc_info r8a77990_pinmux_info = { ARRAY_SIZE(pinmux_functions.automotive), .cfg_regs = pinmux_config_regs, + .drive_regs = pinmux_drive_regs, .bias_regs = pinmux_bias_regs, .ioctrl_regs = pinmux_ioctrl_regs, diff --git a/drivers/pinctrl/renesas/pfc-r8a77995.c b/drivers/pinctrl/renesas/pfc-r8a77995.c index 445c903a121acedddeddd2fb044702b1e0b2cef9..d949ae59c757924d07b13b3ed15d38d040e66b91 100644 --- a/drivers/pinctrl/renesas/pfc-r8a77995.c +++ b/drivers/pinctrl/renesas/pfc-r8a77995.c @@ -1682,6 +1682,68 @@ static const unsigned int pwm3_c_mux[] = { PWM3_C_MARK, }; +/* - QSPI0 ------------------------------------------------------------------ */ +static const unsigned int qspi0_ctrl_pins[] = { + /* QSPI0_SPCLK, QSPI0_SSL */ + RCAR_GP_PIN(6, 0), RCAR_GP_PIN(6, 5), +}; +static const unsigned int qspi0_ctrl_mux[] = { + QSPI0_SPCLK_MARK, QSPI0_SSL_MARK, +}; +/* - QSPI1 ------------------------------------------------------------------ */ +static const unsigned int qspi1_ctrl_pins[] = { + /* QSPI1_SPCLK, QSPI1_SSL */ + RCAR_GP_PIN(6, 6), RCAR_GP_PIN(6, 11), +}; +static const unsigned int qspi1_ctrl_mux[] = { + QSPI1_SPCLK_MARK, QSPI1_SSL_MARK, +}; + +/* - RPC -------------------------------------------------------------------- */ +static const unsigned int rpc_clk_pins[] = { + /* Octal-SPI flash: C/SCLK */ + /* HyperFlash: CK, CK# */ + RCAR_GP_PIN(6, 0), RCAR_GP_PIN(6, 6), +}; +static const unsigned int rpc_clk_mux[] = { + QSPI0_SPCLK_MARK, QSPI1_SPCLK_MARK, +}; +static const unsigned int rpc_ctrl_pins[] = { + /* Octal-SPI flash: S#/CS, DQS */ + /* HyperFlash: CS#, RDS */ + RCAR_GP_PIN(6, 5), RCAR_GP_PIN(6, 11), +}; +static const unsigned int rpc_ctrl_mux[] = { + QSPI0_SSL_MARK, QSPI1_SSL_MARK, +}; +static const unsigned int rpc_data_pins[] = { + /* DQ[0:7] */ + RCAR_GP_PIN(6, 1), RCAR_GP_PIN(6, 2), + RCAR_GP_PIN(6, 3), RCAR_GP_PIN(6, 4), + RCAR_GP_PIN(6, 7), RCAR_GP_PIN(6, 8), + RCAR_GP_PIN(6, 9), RCAR_GP_PIN(6, 10), +}; +static const unsigned int rpc_data_mux[] = { + QSPI0_MOSI_IO0_MARK, QSPI0_MISO_IO1_MARK, + QSPI0_IO2_MARK, QSPI0_IO3_MARK, + QSPI1_MOSI_IO0_MARK, QSPI1_MISO_IO1_MARK, + QSPI1_IO2_MARK, QSPI1_IO3_MARK, +}; +static const unsigned int rpc_reset_pins[] = { + /* RPC_RESET# */ + RCAR_GP_PIN(6, 12), +}; +static const unsigned int rpc_reset_mux[] = { + RPC_RESET_N_MARK, +}; +static const unsigned int rpc_int_pins[] = { + /* RPC_INT# */ + RCAR_GP_PIN(6, 13), +}; +static const unsigned int rpc_int_mux[] = { + RPC_INT_N_MARK, +}; + /* - SCIF0 ------------------------------------------------------------------ */ static const unsigned int scif0_data_a_pins[] = { /* RX, TX */ @@ -2085,6 +2147,18 @@ static const struct sh_pfc_pin_group pinmux_groups[] = { SH_PFC_PIN_GROUP(pwm3_a), SH_PFC_PIN_GROUP(pwm3_b), SH_PFC_PIN_GROUP(pwm3_c), + SH_PFC_PIN_GROUP(qspi0_ctrl), + SH_PFC_PIN_GROUP_SUBSET(qspi0_data2, rpc_data, 0, 2), + SH_PFC_PIN_GROUP_SUBSET(qspi0_data4, rpc_data, 0, 4), + SH_PFC_PIN_GROUP(qspi1_ctrl), + SH_PFC_PIN_GROUP_SUBSET(qspi1_data2, rpc_data, 4, 2), + SH_PFC_PIN_GROUP_SUBSET(qspi1_data4, rpc_data, 4, 4), + BUS_DATA_PIN_GROUP(rpc_clk, 1), + BUS_DATA_PIN_GROUP(rpc_clk, 2), + SH_PFC_PIN_GROUP(rpc_ctrl), + SH_PFC_PIN_GROUP(rpc_data), + SH_PFC_PIN_GROUP(rpc_reset), + SH_PFC_PIN_GROUP(rpc_int), SH_PFC_PIN_GROUP(scif0_data_a), SH_PFC_PIN_GROUP(scif0_clk_a), SH_PFC_PIN_GROUP(scif0_data_b), @@ -2277,6 +2351,27 @@ static const char * const pwm3_groups[] = { "pwm3_c", }; +static const char * const qspi0_groups[] = { + "qspi0_ctrl", + "qspi0_data2", + "qspi0_data4", +}; + +static const char * const qspi1_groups[] = { + "qspi1_ctrl", + "qspi1_data2", + "qspi1_data4", +}; + +static const char * const rpc_groups[] = { + "rpc_clk1", + "rpc_clk2", + "rpc_ctrl", + "rpc_data", + "rpc_reset", + "rpc_int", +}; + static const char * const scif0_groups[] = { "scif0_data_a", "scif0_clk_a", @@ -2373,6 +2468,9 @@ static const struct sh_pfc_function pinmux_functions[] = { SH_PFC_FUNCTION(pwm1), SH_PFC_FUNCTION(pwm2), SH_PFC_FUNCTION(pwm3), + SH_PFC_FUNCTION(qspi0), + SH_PFC_FUNCTION(qspi1), + SH_PFC_FUNCTION(rpc), SH_PFC_FUNCTION(scif0), SH_PFC_FUNCTION(scif1), SH_PFC_FUNCTION(scif2), @@ -2388,30 +2486,10 @@ static const struct sh_pfc_function pinmux_functions[] = { static const struct pinmux_cfg_reg pinmux_config_regs[] = { #define F_(x, y) FN_##y #define FM(x) FN_##x - { PINMUX_CFG_REG("GPSR0", 0xe6060100, 32, 1, GROUP( - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("GPSR0", 0xe6060100, 32, + GROUP(-23, 1, 1, 1, 1, 1, 1, 1, 1, 1), + GROUP( + /* GP0_31_9 RESERVED */ GP_0_8_FN, GPSR0_8, GP_0_7_FN, GPSR0_7, GP_0_6_FN, GPSR0_6, @@ -2490,29 +2568,10 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { GP_2_1_FN, GPSR2_1, GP_2_0_FN, GPSR2_0, )) }, - { PINMUX_CFG_REG("GPSR3", 0xe606010c, 32, 1, GROUP( - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("GPSR3", 0xe606010c, 32, + GROUP(-22, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), + GROUP( + /* GP3_31_10 RESERVED */ GP_3_9_FN, GPSR3_9, GP_3_8_FN, GPSR3_8, GP_3_7_FN, GPSR3_7, @@ -2558,18 +2617,11 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { GP_4_1_FN, GPSR4_1, GP_4_0_FN, GPSR4_0, )) }, - { PINMUX_CFG_REG("GPSR5", 0xe6060114, 32, 1, GROUP( - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("GPSR5", 0xe6060114, 32, + GROUP(-11, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), + GROUP( + /* GP5_31_21 RESERVED */ GP_5_20_FN, GPSR5_20, GP_5_19_FN, GPSR5_19, GP_5_18_FN, GPSR5_18, @@ -2592,25 +2644,11 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { GP_5_1_FN, GPSR5_1, GP_5_0_FN, GPSR5_0, )) }, - { PINMUX_CFG_REG("GPSR6", 0xe6060118, 32, 1, GROUP( - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("GPSR6", 0xe6060118, 32, + GROUP(-18, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1), + GROUP( + /* GP6_31_14 RESERVED */ GP_6_13_FN, GPSR6_13, GP_6_12_FN, GPSR6_12, GP_6_11_FN, GPSR6_11, @@ -2761,13 +2799,10 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { IP12_7_4 IP12_3_0 )) }, - { PINMUX_CFG_REG("IPSR13", 0xe6060234, 32, 4, GROUP( - /* IP13_31_28 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* IP13_27_24 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* IP13_23_20 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* IP13_19_16 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* IP13_15_12 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* IP13_11_8 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + { PINMUX_CFG_REG_VAR("IPSR13", 0xe6060234, 32, + GROUP(-24, 4, 4), + GROUP( + /* IP13_31_8 RESERVED */ IP13_7_4 IP13_3_0 )) }, @@ -2777,11 +2812,10 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { #define F_(x, y) x, #define FM(x) FN_##x, { PINMUX_CFG_REG_VAR("MOD_SEL0", 0xe6060500, 32, - GROUP(1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 1, - 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, 1, 1, 1), + GROUP(-1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, -1, + 1, 1, 1, 1, 1, 1, -4, 1, 1, 1, 1, 1, 1), GROUP( /* RESERVED 31 */ - 0, 0, MOD_SEL0_30 MOD_SEL0_29 MOD_SEL0_28 @@ -2793,7 +2827,6 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { MOD_SEL0_20_19 MOD_SEL0_18_17 /* RESERVED 16 */ - 0, 0, MOD_SEL0_15 MOD_SEL0_14 MOD_SEL0_13 @@ -2801,7 +2834,6 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { MOD_SEL0_11 MOD_SEL0_10 /* RESERVED 9, 8, 7, 6 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, MOD_SEL0_5 MOD_SEL0_4 MOD_SEL0_3 @@ -2810,7 +2842,7 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { MOD_SEL0_0 )) }, { PINMUX_CFG_REG_VAR("MOD_SEL1", 0xe6060504, 32, - GROUP(1, 1, 1, 1, 1, 1, 2, 4, 4, 4, 4, 4, 4), + GROUP(1, 1, 1, 1, 1, 1, -26), GROUP( MOD_SEL1_31 MOD_SEL1_30 @@ -2818,20 +2850,7 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { MOD_SEL1_28 MOD_SEL1_27 MOD_SEL1_26 - /* RESERVED 25, 24 */ - 0, 0, 0, 0, - /* RESERVED 23, 22, 21, 20 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* RESERVED 19, 18, 17, 16 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* RESERVED 15, 14, 13, 12 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* RESERVED 11, 10, 9, 8 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* RESERVED 7, 6, 5, 4 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* RESERVED 3, 2, 1, 0 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 )) + /* RESERVED 25-0 */ )) }, { }, }; diff --git a/drivers/pinctrl/renesas/pfc-r8a779a0.c b/drivers/pinctrl/renesas/pfc-r8a779a0.c index 4a668a04b7ca6820f75bc338c808b9a95ed05a13..760c83a8740bd8b3dfd173c69b495d75743bc56e 100644 --- a/drivers/pinctrl/renesas/pfc-r8a779a0.c +++ b/drivers/pinctrl/renesas/pfc-r8a779a0.c @@ -389,7 +389,6 @@ #define IP3SR1_19_16 FM(GP1_28) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) FM(D0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP3SR1_23_20 FM(GP1_29) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) FM(D1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP3SR1_27_24 FM(GP1_30) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) FM(D2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP3SR1_31_28 F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) /* IP0SR2 */ /* 0 */ /* 1 */ /* 2 */ /* 3 */ /* 4 */ /* 5 */ /* 6 - F */ #define IP0SR2_3_0 FM(IPC_CLKIN) FM(IPC_CLKEN_IN) F_(0, 0) F_(0, 0) FM(DU_DOTCLKIN) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) @@ -420,11 +419,8 @@ #define IP2SR2_31_28 FM(TCLK1_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) FM(EX_WAIT0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) /* IP0SR3 */ /* 0 */ /* 1 */ /* 2 */ /* 3 */ /* 4 */ /* 5 */ /* 6 - F */ -#define IP0SR3_3_0 F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP0SR3_7_4 FM(CANFD0_TX) FM(FXR_TXDA_B) FM(TX1_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP0SR3_11_8 FM(CANFD0_RX) FM(RXDA_EXTFXR_B) FM(RX1_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP0SR3_15_12 F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP0SR3_19_16 F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP0SR3_23_20 FM(CANFD2_TX) FM(TPU0TO2) FM(PWM0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP0SR3_27_24 FM(CANFD2_RX) FM(TPU0TO3) FM(PWM1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP0SR3_31_28 FM(CANFD3_TX) F_(0, 0) FM(PWM2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) @@ -435,8 +431,6 @@ #define IP1SR3_15_12 FM(CANFD5_TX) F_(0, 0) F_(0, 0) FM(FXR_TXENA_N) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP1SR3_19_16 FM(CANFD5_RX) F_(0, 0) F_(0, 0) FM(FXR_TXENB_N) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP1SR3_23_20 FM(CANFD6_TX) F_(0, 0) F_(0, 0) FM(STPWT_EXTFXR) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP1SR3_27_24 F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP1SR3_31_28 F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) /* IP0SR4 */ /* 0 */ /* 1 */ /* 2 */ /* 3 */ /* 4 */ /* 5 */ /* 6 - F */ #define IP0SR4_3_0 FM(AVB0_RX_CTL) FM(AVB0_MII_RX_DV) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) @@ -457,14 +451,10 @@ #define IP1SR4_27_24 FM(AVB0_MDC) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP1SR4_31_28 FM(AVB0_MAGIC) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) /* IP2SR4 */ /* 0 */ /* 1 */ /* 2 */ /* 3 */ /* 4 */ /* 5 */ /* 6 - F */ -#define IP2SR4_3_0 F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP2SR4_7_4 FM(AVB0_LINK) FM(AVB0_MII_TX_ER) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP2SR4_11_8 FM(AVB0_AVTP_MATCH) FM(AVB0_MII_RX_ER) FM(CC5_OSCOUT) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP2SR4_15_12 FM(AVB0_AVTP_CAPTURE) FM(AVB0_MII_CRS) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP2SR4_19_16 FM(AVB0_AVTP_PPS) FM(AVB0_MII_COL) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP2SR4_23_20 F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP2SR4_27_24 F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP2SR4_31_28 F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) /* IP0SR5 */ /* 0 */ /* 1 */ /* 2 */ /* 3 */ /* 4 */ /* 5 */ /* 6 - F */ #define IP0SR5_3_0 FM(AVB1_RX_CTL) FM(AVB1_MII_RX_DV) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) @@ -485,14 +475,10 @@ #define IP1SR5_27_24 FM(AVB1_MDC) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP1SR5_31_28 FM(AVB1_MAGIC) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) /* IP2SR5 */ /* 0 */ /* 1 */ /* 2 */ /* 3 */ /* 4 */ /* 5 */ /* 6 - F */ -#define IP2SR5_3_0 F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP2SR5_7_4 FM(AVB1_LINK) FM(AVB1_MII_TX_ER) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP2SR5_11_8 FM(AVB1_AVTP_MATCH) FM(AVB1_MII_RX_ER) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP2SR5_15_12 FM(AVB1_AVTP_CAPTURE) FM(AVB1_MII_CRS) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP2SR5_19_16 FM(AVB1_AVTP_PPS) FM(AVB1_MII_COL) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP2SR5_23_20 F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP2SR5_27_24 F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP2SR5_31_28 F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define PINMUX_GPSR \ \ @@ -537,7 +523,7 @@ FM(IP0SR1_15_12) IP0SR1_15_12 FM(IP1SR1_15_12) IP1SR1_15_12 FM(IP2SR1_15_12) IP2 FM(IP0SR1_19_16) IP0SR1_19_16 FM(IP1SR1_19_16) IP1SR1_19_16 FM(IP2SR1_19_16) IP2SR1_19_16 FM(IP3SR1_19_16) IP3SR1_19_16 \ FM(IP0SR1_23_20) IP0SR1_23_20 FM(IP1SR1_23_20) IP1SR1_23_20 FM(IP2SR1_23_20) IP2SR1_23_20 FM(IP3SR1_23_20) IP3SR1_23_20 \ FM(IP0SR1_27_24) IP0SR1_27_24 FM(IP1SR1_27_24) IP1SR1_27_24 FM(IP2SR1_27_24) IP2SR1_27_24 FM(IP3SR1_27_24) IP3SR1_27_24 \ -FM(IP0SR1_31_28) IP0SR1_31_28 FM(IP1SR1_31_28) IP1SR1_31_28 FM(IP2SR1_31_28) IP2SR1_31_28 FM(IP3SR1_31_28) IP3SR1_31_28 \ +FM(IP0SR1_31_28) IP0SR1_31_28 FM(IP1SR1_31_28) IP1SR1_31_28 FM(IP2SR1_31_28) IP2SR1_31_28 \ \ FM(IP0SR2_3_0) IP0SR2_3_0 FM(IP1SR2_3_0) IP1SR2_3_0 FM(IP2SR2_3_0) IP2SR2_3_0 \ FM(IP0SR2_7_4) IP0SR2_7_4 FM(IP1SR2_7_4) IP1SR2_7_4 FM(IP2SR2_7_4) IP2SR2_7_4 \ @@ -548,32 +534,32 @@ FM(IP0SR2_23_20) IP0SR2_23_20 FM(IP1SR2_23_20) IP1SR2_23_20 FM(IP2SR2_23_20) IP2 FM(IP0SR2_27_24) IP0SR2_27_24 FM(IP1SR2_27_24) IP1SR2_27_24 FM(IP2SR2_27_24) IP2SR2_27_24 \ FM(IP0SR2_31_28) IP0SR2_31_28 FM(IP1SR2_31_28) IP1SR2_31_28 FM(IP2SR2_31_28) IP2SR2_31_28 \ \ -FM(IP0SR3_3_0) IP0SR3_3_0 FM(IP1SR3_3_0) IP1SR3_3_0 \ + FM(IP1SR3_3_0) IP1SR3_3_0 \ FM(IP0SR3_7_4) IP0SR3_7_4 FM(IP1SR3_7_4) IP1SR3_7_4 \ FM(IP0SR3_11_8) IP0SR3_11_8 FM(IP1SR3_11_8) IP1SR3_11_8 \ -FM(IP0SR3_15_12) IP0SR3_15_12 FM(IP1SR3_15_12) IP1SR3_15_12 \ -FM(IP0SR3_19_16) IP0SR3_19_16 FM(IP1SR3_19_16) IP1SR3_19_16 \ + FM(IP1SR3_15_12) IP1SR3_15_12 \ + FM(IP1SR3_19_16) IP1SR3_19_16 \ FM(IP0SR3_23_20) IP0SR3_23_20 FM(IP1SR3_23_20) IP1SR3_23_20 \ -FM(IP0SR3_27_24) IP0SR3_27_24 FM(IP1SR3_27_24) IP1SR3_27_24 \ -FM(IP0SR3_31_28) IP0SR3_31_28 FM(IP1SR3_31_28) IP1SR3_31_28 \ +FM(IP0SR3_27_24) IP0SR3_27_24 \ +FM(IP0SR3_31_28) IP0SR3_31_28 \ \ -FM(IP0SR4_3_0) IP0SR4_3_0 FM(IP1SR4_3_0) IP1SR4_3_0 FM(IP2SR4_3_0) IP2SR4_3_0 \ +FM(IP0SR4_3_0) IP0SR4_3_0 FM(IP1SR4_3_0) IP1SR4_3_0 \ FM(IP0SR4_7_4) IP0SR4_7_4 FM(IP1SR4_7_4) IP1SR4_7_4 FM(IP2SR4_7_4) IP2SR4_7_4 \ FM(IP0SR4_11_8) IP0SR4_11_8 FM(IP1SR4_11_8) IP1SR4_11_8 FM(IP2SR4_11_8) IP2SR4_11_8 \ FM(IP0SR4_15_12) IP0SR4_15_12 FM(IP1SR4_15_12) IP1SR4_15_12 FM(IP2SR4_15_12) IP2SR4_15_12 \ FM(IP0SR4_19_16) IP0SR4_19_16 FM(IP1SR4_19_16) IP1SR4_19_16 FM(IP2SR4_19_16) IP2SR4_19_16 \ -FM(IP0SR4_23_20) IP0SR4_23_20 FM(IP1SR4_23_20) IP1SR4_23_20 FM(IP2SR4_23_20) IP2SR4_23_20 \ -FM(IP0SR4_27_24) IP0SR4_27_24 FM(IP1SR4_27_24) IP1SR4_27_24 FM(IP2SR4_27_24) IP2SR4_27_24 \ -FM(IP0SR4_31_28) IP0SR4_31_28 FM(IP1SR4_31_28) IP1SR4_31_28 FM(IP2SR4_31_28) IP2SR4_31_28 \ +FM(IP0SR4_23_20) IP0SR4_23_20 FM(IP1SR4_23_20) IP1SR4_23_20 \ +FM(IP0SR4_27_24) IP0SR4_27_24 FM(IP1SR4_27_24) IP1SR4_27_24 \ +FM(IP0SR4_31_28) IP0SR4_31_28 FM(IP1SR4_31_28) IP1SR4_31_28 \ \ -FM(IP0SR5_3_0) IP0SR5_3_0 FM(IP1SR5_3_0) IP1SR5_3_0 FM(IP2SR5_3_0) IP2SR5_3_0 \ +FM(IP0SR5_3_0) IP0SR5_3_0 FM(IP1SR5_3_0) IP1SR5_3_0 \ FM(IP0SR5_7_4) IP0SR5_7_4 FM(IP1SR5_7_4) IP1SR5_7_4 FM(IP2SR5_7_4) IP2SR5_7_4 \ FM(IP0SR5_11_8) IP0SR5_11_8 FM(IP1SR5_11_8) IP1SR5_11_8 FM(IP2SR5_11_8) IP2SR5_11_8 \ FM(IP0SR5_15_12) IP0SR5_15_12 FM(IP1SR5_15_12) IP1SR5_15_12 FM(IP2SR5_15_12) IP2SR5_15_12 \ FM(IP0SR5_19_16) IP0SR5_19_16 FM(IP1SR5_19_16) IP1SR5_19_16 FM(IP2SR5_19_16) IP2SR5_19_16 \ -FM(IP0SR5_23_20) IP0SR5_23_20 FM(IP1SR5_23_20) IP1SR5_23_20 FM(IP2SR5_23_20) IP2SR5_23_20 \ -FM(IP0SR5_27_24) IP0SR5_27_24 FM(IP1SR5_27_24) IP1SR5_27_24 FM(IP2SR5_27_24) IP2SR5_27_24 \ -FM(IP0SR5_31_28) IP0SR5_31_28 FM(IP1SR5_31_28) IP1SR5_31_28 FM(IP2SR5_31_28) IP2SR5_31_28 +FM(IP0SR5_23_20) IP0SR5_23_20 FM(IP1SR5_23_20) IP1SR5_23_20 \ +FM(IP0SR5_27_24) IP0SR5_27_24 FM(IP1SR5_27_24) IP1SR5_27_24 \ +FM(IP0SR5_31_28) IP0SR5_31_28 FM(IP1SR5_31_28) IP1SR5_31_28 /* MOD_SEL2 */ /* 0 */ /* 1 */ /* 2 */ /* 3 */ #define MOD_SEL2_15_14 FM(SEL_I2C6_0) F_(0, 0) F_(0, 0) FM(SEL_I2C6_3) @@ -629,7 +615,36 @@ enum { }; static const u16 pinmux_data[] = { +/* Using GP_2_[2-15] requires disabling I2C in MOD_SEL2 */ +#define GP_2_2_FN GP_2_2_FN, FN_SEL_I2C0_0 +#define GP_2_3_FN GP_2_3_FN, FN_SEL_I2C0_0 +#define GP_2_4_FN GP_2_4_FN, FN_SEL_I2C1_0 +#define GP_2_5_FN GP_2_5_FN, FN_SEL_I2C1_0 +#define GP_2_6_FN GP_2_6_FN, FN_SEL_I2C2_0 +#define GP_2_7_FN GP_2_7_FN, FN_SEL_I2C2_0 +#define GP_2_8_FN GP_2_8_FN, FN_SEL_I2C3_0 +#define GP_2_9_FN GP_2_9_FN, FN_SEL_I2C3_0 +#define GP_2_10_FN GP_2_10_FN, FN_SEL_I2C4_0 +#define GP_2_11_FN GP_2_11_FN, FN_SEL_I2C4_0 +#define GP_2_12_FN GP_2_12_FN, FN_SEL_I2C5_0 +#define GP_2_13_FN GP_2_13_FN, FN_SEL_I2C5_0 +#define GP_2_14_FN GP_2_14_FN, FN_SEL_I2C6_0 +#define GP_2_15_FN GP_2_15_FN, FN_SEL_I2C6_0 PINMUX_DATA_GP_ALL(), +#undef GP_2_2_FN +#undef GP_2_3_FN +#undef GP_2_4_FN +#undef GP_2_5_FN +#undef GP_2_6_FN +#undef GP_2_7_FN +#undef GP_2_8_FN +#undef GP_2_9_FN +#undef GP_2_10_FN +#undef GP_2_11_FN +#undef GP_2_12_FN +#undef GP_2_13_FN +#undef GP_2_14_FN +#undef GP_2_15_FN PINMUX_SINGLE(MMC_D7), PINMUX_SINGLE(MMC_D6), @@ -3223,14 +3238,11 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { GP_1_1_FN, GPSR1_1, GP_1_0_FN, GPSR1_0, )) }, - { PINMUX_CFG_REG("GPSR2", 0xe6050840, 32, 1, GROUP( - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("GPSR2", 0xe6050840, 32, + GROUP(-7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), + GROUP( + /* GP2_31_25 RESERVED */ GP_2_24_FN, GPSR2_24, GP_2_23_FN, GPSR2_23, GP_2_22_FN, GPSR2_22, @@ -3257,22 +3269,11 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { GP_2_1_FN, GPSR2_1, GP_2_0_FN, GPSR2_0, )) }, - { PINMUX_CFG_REG("GPSR3", 0xe6058840, 32, 1, GROUP( - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("GPSR3", 0xe6058840, 32, + GROUP(-15, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1), + GROUP( + /* GP3_31_17 RESERVED */ GP_3_16_FN, GPSR3_16, GP_3_15_FN, GPSR3_15, GP_3_14_FN, GPSR3_14, @@ -3325,18 +3326,11 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { GP_4_1_FN, GPSR4_1, GP_4_0_FN, GPSR4_0, )) }, - { PINMUX_CFG_REG("GPSR5", 0xe6060840, 32, 1, GROUP( - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("GPSR5", 0xe6060840, 32, + GROUP(-11, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), + GROUP( + /* GP5_31_21 RESERVED */ GP_5_20_FN, GPSR5_20, GP_5_19_FN, GPSR5_19, GP_5_18_FN, GPSR5_18, @@ -3359,18 +3353,11 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { GP_5_1_FN, GPSR5_1, GP_5_0_FN, GPSR5_0, )) }, - { PINMUX_CFG_REG("GPSR6", 0xe6068040, 32, 1, GROUP( - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("GPSR6", 0xe6068040, 32, + GROUP(-11, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), + GROUP( + /* GP6_31_21 RESERVED */ GP_6_20_FN, GPSR6_20, GP_6_19_FN, GPSR6_19, GP_6_18_FN, GPSR6_18, @@ -3393,18 +3380,11 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { GP_6_1_FN, GPSR6_1, GP_6_0_FN, GPSR6_0, )) }, - { PINMUX_CFG_REG("GPSR7", 0xe6068840, 32, 1, GROUP( - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("GPSR7", 0xe6068840, 32, + GROUP(-11, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), + GROUP( + /* GP7_31_21 RESERVED */ GP_7_20_FN, GPSR7_20, GP_7_19_FN, GPSR7_19, GP_7_18_FN, GPSR7_18, @@ -3427,18 +3407,11 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { GP_7_1_FN, GPSR7_1, GP_7_0_FN, GPSR7_0, )) }, - { PINMUX_CFG_REG("GPSR8", 0xe6069040, 32, 1, GROUP( - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("GPSR8", 0xe6069040, 32, + GROUP(-11, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), + GROUP( + /* GP8_31_21 RESERVED */ GP_8_20_FN, GPSR8_20, GP_8_19_FN, GPSR8_19, GP_8_18_FN, GPSR8_18, @@ -3461,18 +3434,11 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { GP_8_1_FN, GPSR8_1, GP_8_0_FN, GPSR8_0, )) }, - { PINMUX_CFG_REG("GPSR9", 0xe6069840, 32, 1, GROUP( - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("GPSR9", 0xe6069840, 32, + GROUP(-11, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), + GROUP( + /* GP9_31_21 RESERVED */ GP_9_20_FN, GPSR9_20, GP_9_19_FN, GPSR9_19, GP_9_18_FN, GPSR9_18, @@ -3530,8 +3496,10 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { IP2SR1_7_4 IP2SR1_3_0)) }, - { PINMUX_CFG_REG("IP3SR1", 0xe605006c, 32, 4, GROUP( - IP3SR1_31_28 + { PINMUX_CFG_REG_VAR("IP3SR1", 0xe605006c, 32, + GROUP(-4, 4, 4, 4, 4, 4, 4, 4), + GROUP( + /* IP3SR1_31_28 RESERVED */ IP3SR1_27_24 IP3SR1_23_20 IP3SR1_19_16 @@ -3570,19 +3538,21 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { IP2SR2_7_4 IP2SR2_3_0)) }, - { PINMUX_CFG_REG("IP0SR3", 0xe6058860, 32, 4, GROUP( + { PINMUX_CFG_REG_VAR("IP0SR3", 0xe6058860, 32, + GROUP(4, 4, 4, -8, 4, 4, -4), + GROUP( IP0SR3_31_28 IP0SR3_27_24 IP0SR3_23_20 - IP0SR3_19_16 - IP0SR3_15_12 + /* IP0SR3_19_12 RESERVED */ IP0SR3_11_8 IP0SR3_7_4 - IP0SR3_3_0)) + /* IP0SR3_3_0 RESERVED */ )) }, - { PINMUX_CFG_REG("IP1SR3", 0xe6058864, 32, 4, GROUP( - IP1SR3_31_28 - IP1SR3_27_24 + { PINMUX_CFG_REG_VAR("IP1SR3", 0xe6058864, 32, + GROUP(-8, 4, 4, 4, 4, 4, 4), + GROUP( + /* IP1SR3_31_24 RESERVED */ IP1SR3_23_20 IP1SR3_19_16 IP1SR3_15_12 @@ -3610,15 +3580,15 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { IP1SR4_7_4 IP1SR4_3_0)) }, - { PINMUX_CFG_REG("IP2SR4", 0xe6060068, 32, 4, GROUP( - IP2SR4_31_28 - IP2SR4_27_24 - IP2SR4_23_20 + { PINMUX_CFG_REG_VAR("IP2SR4", 0xe6060068, 32, + GROUP(-12, 4, 4, 4, 4, -4), + GROUP( + /* IP2SR4_31_20 RESERVED */ IP2SR4_19_16 IP2SR4_15_12 IP2SR4_11_8 IP2SR4_7_4 - IP2SR4_3_0)) + /* IP2SR4_3_0 RESERVED */ )) }, { PINMUX_CFG_REG("IP0SR5", 0xe6060860, 32, 4, GROUP( IP0SR5_31_28 @@ -3640,15 +3610,15 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { IP1SR5_7_4 IP1SR5_3_0)) }, - { PINMUX_CFG_REG("IP2SR5", 0xe6060868, 32, 4, GROUP( - IP2SR5_31_28 - IP2SR5_27_24 - IP2SR5_23_20 + { PINMUX_CFG_REG_VAR("IP2SR5", 0xe6060868, 32, + GROUP(-12, 4, 4, 4, 4, -4), + GROUP( + /* IP2SR5_31_20 RESERVED */ IP2SR5_19_16 IP2SR5_15_12 IP2SR5_11_8 IP2SR5_7_4 - IP2SR5_3_0)) + /* IP2SR5_3_0 RESERVED */ )) }, #undef F_ #undef FM @@ -3656,16 +3626,9 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { #define F_(x, y) x, #define FM(x) FN_##x, { PINMUX_CFG_REG_VAR("MOD_SEL2", 0xe6050900, 32, - GROUP(4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 1, 1), + GROUP(-16, 2, 2, 2, 2, 2, 2, 2, -2), GROUP( - /* RESERVED 31, 30, 29, 28 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* RESERVED 27, 26, 25, 24 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* RESERVED 23, 22, 21, 20 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* RESERVED 19, 18, 17, 16 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* RESERVED 31-16 */ MOD_SEL2_15_14 MOD_SEL2_13_12 MOD_SEL2_11_10 @@ -3673,8 +3636,7 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { MOD_SEL2_7_6 MOD_SEL2_5_4 MOD_SEL2_3_2 - 0, 0, - 0, 0, )) + /* RESERVED 1-0 */ )) }, { }, }; diff --git a/drivers/pinctrl/renesas/pfc-r8a779f0.c b/drivers/pinctrl/renesas/pfc-r8a779f0.c index 91860608242c503b1d4e850115a5d80d9337d1c1..aaca4ee2af5554c790748fc3a07649f49c1b82f7 100644 --- a/drivers/pinctrl/renesas/pfc-r8a779f0.c +++ b/drivers/pinctrl/renesas/pfc-r8a779f0.c @@ -144,9 +144,6 @@ #define IP2SR0_11_8 FM(IRQ1) F_(0, 0) F_(0, 0) FM(MSIOF1_SS2) F_(0, 0) FM(TSN0_PHY_INT_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP2SR0_15_12 FM(IRQ2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) FM(TSN1_PHY_INT_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) #define IP2SR0_19_16 FM(IRQ3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) FM(TSN2_PHY_INT_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP2SR0_23_20 F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP2SR0_27_24 F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) -#define IP2SR0_31_28 F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) /* IP0SR1 */ /* 0 */ /* 1 */ /* 2 */ /* 3 */ /* 4 */ /* 5 */ /* 6 */ /* 7 - F */ #define IP0SR1_3_0 FM(GP1_00) FM(TCLK1) FM(HSCK2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) @@ -192,9 +189,9 @@ FM(IP0SR0_7_4) IP0SR0_7_4 FM(IP1SR0_7_4) IP1SR0_7_4 FM(IP2SR0_7_4) IP2SR0_7_4 FM(IP0SR0_11_8) IP0SR0_11_8 FM(IP1SR0_11_8) IP1SR0_11_8 FM(IP2SR0_11_8) IP2SR0_11_8 \ FM(IP0SR0_15_12) IP0SR0_15_12 FM(IP1SR0_15_12) IP1SR0_15_12 FM(IP2SR0_15_12) IP2SR0_15_12 \ FM(IP0SR0_19_16) IP0SR0_19_16 FM(IP1SR0_19_16) IP1SR0_19_16 FM(IP2SR0_19_16) IP2SR0_19_16 \ -FM(IP0SR0_23_20) IP0SR0_23_20 FM(IP1SR0_23_20) IP1SR0_23_20 FM(IP2SR0_23_20) IP2SR0_23_20 \ -FM(IP0SR0_27_24) IP0SR0_27_24 FM(IP1SR0_27_24) IP1SR0_27_24 FM(IP2SR0_27_24) IP2SR0_27_24 \ -FM(IP0SR0_31_28) IP0SR0_31_28 FM(IP1SR0_31_28) IP1SR0_31_28 FM(IP2SR0_31_28) IP2SR0_31_28 \ +FM(IP0SR0_23_20) IP0SR0_23_20 FM(IP1SR0_23_20) IP1SR0_23_20 \ +FM(IP0SR0_27_24) IP0SR0_27_24 FM(IP1SR0_27_24) IP1SR0_27_24 \ +FM(IP0SR0_31_28) IP0SR0_31_28 FM(IP1SR0_31_28) IP1SR0_31_28 \ \ FM(IP0SR1_3_0) IP0SR1_3_0 \ FM(IP0SR1_7_4) IP0SR1_7_4 \ @@ -257,7 +254,28 @@ enum { }; static const u16 pinmux_data[] = { +/* Using GP_1_[0-9] requires disabling I2C in MOD_SEL1 */ +#define GP_1_0_FN GP_1_0_FN, FN_SEL_I2C0_0 +#define GP_1_1_FN GP_1_1_FN, FN_SEL_I2C0_0 +#define GP_1_2_FN GP_1_2_FN, FN_SEL_I2C1_0 +#define GP_1_3_FN GP_1_3_FN, FN_SEL_I2C1_0 +#define GP_1_4_FN GP_1_4_FN, FN_SEL_I2C2_0 +#define GP_1_5_FN GP_1_5_FN, FN_SEL_I2C2_0 +#define GP_1_6_FN GP_1_6_FN, FN_SEL_I2C3_0 +#define GP_1_7_FN GP_1_7_FN, FN_SEL_I2C3_0 +#define GP_1_8_FN GP_1_8_FN, FN_SEL_I2C4_0 +#define GP_1_9_FN GP_1_9_FN, FN_SEL_I2C4_0 PINMUX_DATA_GP_ALL(), +#undef GP_1_0_FN +#undef GP_1_1_FN +#undef GP_1_2_FN +#undef GP_1_3_FN +#undef GP_1_4_FN +#undef GP_1_5_FN +#undef GP_1_6_FN +#undef GP_1_7_FN +#undef GP_1_8_FN +#undef GP_1_9_FN PINMUX_SINGLE(SD_WP), PINMUX_SINGLE(SD_CD), @@ -1599,18 +1617,11 @@ static const struct sh_pfc_function pinmux_functions[] = { static const struct pinmux_cfg_reg pinmux_config_regs[] = { #define F_(x, y) FN_##y #define FM(x) FN_##x - { PINMUX_CFG_REG("GPSR0", 0xe6050040, 32, 1, GROUP( - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("GPSR0", 0xe6050040, 32, + GROUP(-11, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), + GROUP( + /* GP0_31_21 RESERVED */ GP_0_20_FN, GPSR0_20, GP_0_19_FN, GPSR0_19, GP_0_18_FN, GPSR0_18, @@ -1633,14 +1644,11 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { GP_0_1_FN, GPSR0_1, GP_0_0_FN, GPSR0_0, )) }, - { PINMUX_CFG_REG("GPSR1", 0xe6050840, 32, 1, GROUP( - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("GPSR1", 0xe6050840, 32, + GROUP(-7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), + GROUP( + /* GP1_31_25 RESERVED */ GP_1_24_FN, GPSR1_24, GP_1_23_FN, GPSR1_23, GP_1_22_FN, GPSR1_22, @@ -1667,22 +1675,11 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { GP_1_1_FN, GPSR1_1, GP_1_0_FN, GPSR1_0, )) }, - { PINMUX_CFG_REG("GPSR2", 0xe6051040, 32, 1, GROUP( - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("GPSR2", 0xe6051040, 32, + GROUP(-15, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1), + GROUP( + /* GP2_31_17 RESERVED */ GP_2_16_FN, GPSR2_16, GP_2_15_FN, GPSR2_15, GP_2_14_FN, GPSR2_14, @@ -1701,20 +1698,11 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { GP_2_1_FN, GPSR2_1, GP_2_0_FN, GPSR2_0, )) }, - { PINMUX_CFG_REG("GPSR3", 0xe6051840, 32, 1, GROUP( - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("GPSR3", 0xe6051840, 32, + GROUP(-13, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1), + GROUP( + /* GP3_31_19 RESERVED */ GP_3_18_FN, GPSR3_18, GP_3_17_FN, GPSR3_17, GP_3_16_FN, GPSR3_16, @@ -1760,10 +1748,10 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { IP1SR0_7_4 IP1SR0_3_0)) }, - { PINMUX_CFG_REG("IP2SR0", 0xe6050068, 32, 4, GROUP( - IP2SR0_31_28 - IP2SR0_27_24 - IP2SR0_23_20 + { PINMUX_CFG_REG_VAR("IP2SR0", 0xe6050068, 32, + GROUP(-12, 4, 4, 4, 4, 4), + GROUP( + /* IP2SR0_31_20 RESERVED */ IP2SR0_19_16 IP2SR0_15_12 IP2SR0_11_8 @@ -1786,18 +1774,9 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { #define F_(x, y) x, #define FM(x) FN_##x, { PINMUX_CFG_REG_VAR("MOD_SEL1", 0xe6050900, 32, - GROUP(4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2), + GROUP(-20, 2, 2, 2, 2, 2, 2), GROUP( - /* RESERVED 31, 30, 29, 28 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* RESERVED 27, 26, 25, 24 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* RESERVED 23, 22, 21, 20 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* RESERVED 19, 18, 17, 16 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* RESERVED 15, 14, 13, 12 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* RESERVED 31-12 */ MOD_SEL1_11_10 MOD_SEL1_9_8 MOD_SEL1_7_6 diff --git a/drivers/pinctrl/renesas/pfc-sh7203.c b/drivers/pinctrl/renesas/pfc-sh7203.c index 3986802b448a265c8061cb11ff26fabe7cdb90c0..19735746b1bb215749f780adffe1a82825840bca 100644 --- a/drivers/pinctrl/renesas/pfc-sh7203.c +++ b/drivers/pinctrl/renesas/pfc-sh7203.c @@ -1072,31 +1072,20 @@ static const struct pinmux_func pinmux_func_gpios[] = { }; static const struct pinmux_cfg_reg pinmux_config_regs[] = { - { PINMUX_CFG_REG("PBIORL", 0xfffe3886, 16, 1, GROUP( - 0, 0, - 0, 0, - 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("PBIORL", 0xfffe3886, 16, + GROUP(-4, 1, 1, 1, 1, -8), + GROUP( + /* RESERVED [4] */ PB11_IN, PB11_OUT, PB10_IN, PB10_OUT, PB9_IN, PB9_OUT, PB8_IN, PB8_OUT, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0 )) + /* RESERVED [8] */ )) }, - { PINMUX_CFG_REG("PBCRL4", 0xfffe3890, 16, 4, GROUP( - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - + { PINMUX_CFG_REG_VAR("PBCRL4", 0xfffe3890, 16, + GROUP(-12, 4), + GROUP( + /* RESERVED [12] */ PB12MD_00, PB12MD_01, PB12MD_10, PB12MD_11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 )) }, @@ -1139,13 +1128,10 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { PB0MD_00, PB0MD_01, PB0MD_10, PB0MD_11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 )) }, - { PINMUX_CFG_REG("IFCR", 0xfffe38a2, 16, 4, GROUP( - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - + { PINMUX_CFG_REG_VAR("IFCR", 0xfffe38a2, 16, + GROUP(-12, 4), + GROUP( + /* RESERVED [12] */ PB12IRQ_00, PB12IRQ_01, PB12IRQ_10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 )) }, @@ -1167,9 +1153,10 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { PC1_IN, PC1_OUT, PC0_IN, PC0_OUT )) }, - { PINMUX_CFG_REG("PCCRL4", 0xfffe3910, 16, 4, GROUP( - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - + { PINMUX_CFG_REG_VAR("PCCRL4", 0xfffe3910, 16, + GROUP(-4, 4, 4, 4), + GROUP( + /* RESERVED [4] */ PC14MD_0, PC14MD_1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -1417,8 +1404,10 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { PF1_IN, PF1_OUT, PF0_IN, PF0_OUT )) }, - { PINMUX_CFG_REG("PFCRH4", 0xfffe3a88, 16, 4, GROUP( - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + { PINMUX_CFG_REG_VAR("PFCRH4", 0xfffe3a88, 16, + GROUP(-4, 4, 4, 4), + GROUP( + /* RESERVED [4] */ PF30MD_0, PF30MD_1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, diff --git a/drivers/pinctrl/renesas/pfc-sh7264.c b/drivers/pinctrl/renesas/pfc-sh7264.c index 7476b982101d6518f7b28b4705abe7c922df7e4e..30096925a70c5d88501978e388eeae4548bed3c9 100644 --- a/drivers/pinctrl/renesas/pfc-sh7264.c +++ b/drivers/pinctrl/renesas/pfc-sh7264.c @@ -1464,19 +1464,20 @@ static const struct pinmux_func pinmux_func_gpios[] = { }; static const struct pinmux_cfg_reg pinmux_config_regs[] = { - { PINMUX_CFG_REG("PAIOR0", 0xfffe3812, 16, 1, GROUP( - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, + { PINMUX_CFG_REG_VAR("PAIOR0", 0xfffe3812, 16, + GROUP(-12, 1, 1, 1, 1), + GROUP( + /* RESERVED [12] */ PA3_IN, PA3_OUT, PA2_IN, PA2_OUT, PA1_IN, PA1_OUT, PA0_IN, PA0_OUT )) }, - { PINMUX_CFG_REG("PBCR5", 0xfffe3824, 16, 4, GROUP( - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, + { PINMUX_CFG_REG_VAR("PBCR5", 0xfffe3824, 16, + GROUP(-4, 4, 4, 4), + GROUP( + /* RESERVED [4] */ PB22MD_00, PB22MD_01, PB22MD_10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, PB21MD_0, PB21MD_1, 0, 0, 0, 0, 0, 0, @@ -1525,21 +1526,22 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { 0, PB4MD_01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 )) }, - { PINMUX_CFG_REG("PBCR0", 0xfffe382e, 16, 4, GROUP( + { PINMUX_CFG_REG_VAR("PBCR0", 0xfffe382e, 16, + GROUP(4, 4, 4, -4), + GROUP( 0, PB3MD_1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, PB2MD_1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, PB1MD_1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0 )) + /* RESERVED [4] */ )) }, - { PINMUX_CFG_REG("PBIOR1", 0xfffe3830, 16, 1, GROUP( - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("PBIOR1", 0xfffe3830, 16, + GROUP(-9, 1, 1, 1, 1, 1, 1, 1), + GROUP( + /* RESERVED [9] */ PB22_IN, PB22_OUT, PB21_IN, PB21_OUT, PB20_IN, PB20_OUT, @@ -1568,9 +1570,10 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { 0, 0 )) }, - { PINMUX_CFG_REG("PCCR2", 0xfffe384a, 16, 4, GROUP( - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, + { PINMUX_CFG_REG_VAR("PCCR2", 0xfffe384a, 16, + GROUP(-4, 4, 4, 4), + GROUP( + /* RESERVED [4] */ PC10MD_0, PC10MD_1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, PC9MD_0, PC9MD_1, 0, 0, 0, 0, 0, 0, @@ -1599,8 +1602,10 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { 0, 0, 0, 0, 0, 0, 0, 0 )) }, - { PINMUX_CFG_REG("PCIOR0", 0xfffe3852, 16, 1, GROUP( - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + { PINMUX_CFG_REG_VAR("PCIOR0", 0xfffe3852, 16, + GROUP(-5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), + GROUP( + /* RESERVED [5] */ PC10_IN, PC10_OUT, PC9_IN, PC9_OUT, PC8_IN, PC8_OUT, @@ -1675,11 +1680,10 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { PD0_IN, PD0_OUT )) }, - { PINMUX_CFG_REG("PECR1", 0xfffe388c, 16, 4, GROUP( - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, + { PINMUX_CFG_REG_VAR("PECR1", 0xfffe388c, 16, + GROUP(-8, 4, 4), + GROUP( + /* RESERVED [8] */ PE5MD_00, PE5MD_01, 0, PE5MD_11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, PE4MD_00, PE4MD_01, 0, PE4MD_11, 0, 0, 0, 0, @@ -1698,10 +1702,10 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { 0, 0, 0, 0, 0, 0, 0, 0 )) }, - { PINMUX_CFG_REG("PEIOR0", 0xfffe3892, 16, 1, GROUP( - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, + { PINMUX_CFG_REG_VAR("PEIOR0", 0xfffe3892, 16, + GROUP(-10, 1, 1, 1, 1, 1, 1), + GROUP( + /* RESERVED [10] */ PE5_IN, PE5_OUT, PE4_IN, PE4_OUT, PE3_IN, PE3_OUT, @@ -1710,10 +1714,10 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { PE0_IN, PE0_OUT )) }, - { PINMUX_CFG_REG("PFCR3", 0xfffe38a8, 16, 4, GROUP( - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + { PINMUX_CFG_REG_VAR("PFCR3", 0xfffe38a8, 16, + GROUP(-12, 4), + GROUP( + /* RESERVED [12] */ PF12MD_000, PF12MD_001, 0, PF12MD_011, PF12MD_100, PF12MD_101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 )) @@ -1780,25 +1784,19 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { PF0_IN, PF0_OUT )) }, - { PINMUX_CFG_REG("PGCR7", 0xfffe38c0, 16, 4, GROUP( - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, + { PINMUX_CFG_REG_VAR("PGCR7", 0xfffe38c0, 16, + GROUP(-12, 4), + GROUP( + /* RESERVED [12] */ PG0MD_000, PG0MD_001, PG0MD_010, PG0MD_011, PG0MD_100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 )) }, - { PINMUX_CFG_REG("PGCR6", 0xfffe38c2, 16, 4, GROUP( - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, + { PINMUX_CFG_REG_VAR("PGCR6", 0xfffe38c2, 16, + GROUP(-12, 4), + GROUP( + /* RESERVED [12] */ PG24MD_00, PG24MD_01, PG24MD_10, PG24MD_11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 )) }, @@ -1869,19 +1867,21 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { PG4MD_00, PG4MD_01, PG4MD_10, PG4MD_11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 )) }, - { PINMUX_CFG_REG("PGCR0", 0xfffe38ce, 16, 4, GROUP( + { PINMUX_CFG_REG_VAR("PGCR0", 0xfffe38ce, 16, + GROUP(4, 4, 4, -4), + GROUP( PG3MD_00, PG3MD_01, PG3MD_10, PG3MD_11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, PG2MD_00, PG2MD_01, PG2MD_10, PG2MD_11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, PG1MD_00, PG1MD_01, PG1MD_10, PG1MD_11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0 )) + /* RESERVED [4] */ )) }, - { PINMUX_CFG_REG("PGIOR1", 0xfffe38d0, 16, 1, GROUP( - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, + { PINMUX_CFG_REG_VAR("PGIOR1", 0xfffe38d0, 16, + GROUP(-7, 1, 1, 1, 1, 1, 1, 1, 1, 1), + GROUP( + /* RESERVED [7] */ PG24_IN, PG24_OUT, PG23_IN, PG23_OUT, PG22_IN, PG22_OUT, diff --git a/drivers/pinctrl/renesas/pfc-sh7269.c b/drivers/pinctrl/renesas/pfc-sh7269.c index 733a2c114ca26ea04fc26adfadbec452a5dad660..f59f558d75ae253e0cb0b8fdd03378589b9370dd 100644 --- a/drivers/pinctrl/renesas/pfc-sh7269.c +++ b/drivers/pinctrl/renesas/pfc-sh7269.c @@ -1966,15 +1966,18 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { * mode registers and modes are described in assending order [0..15] */ - { PINMUX_CFG_REG("PAIOR0", 0xfffe3812, 16, 1, GROUP( - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, PA1_IN, PA1_OUT, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, PA0_IN, PA0_OUT )) + { PINMUX_CFG_REG_VAR("PAIOR0", 0xfffe3812, 16, + GROUP(-7, 1, -7, 1), + GROUP( + /* RESERVED [7] */ + PA1_IN, PA1_OUT, + /* RESERVED [7] */ + PA0_IN, PA0_OUT )) }, - { PINMUX_CFG_REG("PBCR5", 0xfffe3824, 16, 4, GROUP( - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - + { PINMUX_CFG_REG_VAR("PBCR5", 0xfffe3824, 16, + GROUP(-4, 4, 4, 4), + GROUP( + /* RESERVED [4] */ PB22MD_000, PB22MD_001, PB22MD_010, PB22MD_011, PB22MD_100, PB22MD_101, PB22MD_110, PB22MD_111, 0, 0, 0, 0, 0, 0, 0, 0, @@ -2045,7 +2048,9 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { PB4MD_00, PB4MD_01, PB4MD_10, PB4MD_11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 )) }, - { PINMUX_CFG_REG("PBCR0", 0xfffe382e, 16, 4, GROUP( + { PINMUX_CFG_REG_VAR("PBCR0", 0xfffe382e, 16, + GROUP(4, 4, 4, -4), + GROUP( PB3MD_00, PB3MD_01, PB3MD_10, PB3MD_11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -2055,13 +2060,13 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { PB1MD_00, PB1MD_01, PB1MD_10, PB1MD_11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 )) + /* RESERVED [4] */ )) }, - { PINMUX_CFG_REG("PBIOR1", 0xfffe3830, 16, 1, GROUP( - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("PBIOR1", 0xfffe3830, 16, + GROUP(-9, 1, 1, 1, 1, 1, 1, 1), + GROUP( + /* RESERVED [9] */ PB22_IN, PB22_OUT, PB21_IN, PB21_OUT, PB20_IN, PB20_OUT, @@ -2089,13 +2094,10 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { 0, 0 )) }, - { PINMUX_CFG_REG("PCCR2", 0xfffe384a, 16, 4, GROUP( - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - + { PINMUX_CFG_REG_VAR("PCCR2", 0xfffe384a, 16, + GROUP(-12, 4), + GROUP( + /* RESERVED [12] */ PC8MD_000, PC8MD_001, PC8MD_010, PC8MD_011, PC8MD_100, PC8MD_101, PC8MD_110, PC8MD_111, 0, 0, 0, 0, 0, 0, 0, 0 )) @@ -2130,8 +2132,10 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { 0, 0, 0, 0, 0, 0, 0, 0 )) }, - { PINMUX_CFG_REG("PCIOR0", 0xfffe3852, 16, 1, GROUP( - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + { PINMUX_CFG_REG_VAR("PCIOR0", 0xfffe3852, 16, + GROUP(-7, 1, 1, 1, 1, 1, 1, 1, 1, 1), + GROUP( + /* RESERVED [7] */ PC8_IN, PC8_OUT, PC7_IN, PC7_OUT, PC6_IN, PC6_OUT, @@ -2244,9 +2248,10 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { PE0MD_00, PE0MD_01, PE0MD_10, PE0MD_11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 )) }, - { PINMUX_CFG_REG("PEIOR0", 0xfffe3892, 16, 1, GROUP( - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, + { PINMUX_CFG_REG_VAR("PEIOR0", 0xfffe3892, 16, + GROUP(-8, 1, 1, 1, 1, 1, 1, 1, 1), + GROUP( + /* RESERVED [8] */ PE7_IN, PE7_OUT, PE6_IN, PE6_OUT, PE5_IN, PE5_OUT, @@ -2291,20 +2296,18 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { PF16MD_100, PF16MD_101, PF16MD_110, PF16MD_111, 0, 0, 0, 0, 0, 0, 0, 0 )) }, - { PINMUX_CFG_REG("PFCR4", 0xfffe38a6, 16, 4, GROUP( - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - + { PINMUX_CFG_REG_VAR("PFCR4", 0xfffe38a6, 16, + GROUP(-12, 4), + GROUP( + /* RESERVED [12] */ PF15MD_000, PF15MD_001, PF15MD_010, PF15MD_011, PF15MD_100, PF15MD_101, PF15MD_110, PF15MD_111, 0, 0, 0, 0, 0, 0, 0, 0 )) }, - { PINMUX_CFG_REG("PFCR3", 0xfffe38a8, 16, 4, GROUP( - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - + { PINMUX_CFG_REG_VAR("PFCR3", 0xfffe38a8, 16, + GROUP(-4, 4, 4, 4), + GROUP( + /* RESERVED [4] */ PF14MD_000, PF14MD_001, PF14MD_010, PF14MD_011, PF14MD_100, PF14MD_101, PF14MD_110, PF14MD_111, 0, 0, 0, 0, 0, 0, 0, 0, @@ -2369,9 +2372,10 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { 0, 0, 0, 0, 0, 0, 0, 0 )) }, - { PINMUX_CFG_REG("PFIOR1", 0xfffe38b0, 16, 1, GROUP( - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, + { PINMUX_CFG_REG_VAR("PFIOR1", 0xfffe38b0, 16, + GROUP(-8, 1, 1, 1, 1, 1, 1, 1, 1), + GROUP( + /* RESERVED [8] */ PF23_IN, PF23_OUT, PF22_IN, PF22_OUT, PF21_IN, PF21_OUT, diff --git a/drivers/pinctrl/renesas/pfc-sh73a0.c b/drivers/pinctrl/renesas/pfc-sh73a0.c index 5d8a0179fd60fee4762a48b757779414bd179c35..4f54dfd5a9674916e3ee66a1d5cb07bb7d7ac8b7 100644 --- a/drivers/pinctrl/renesas/pfc-sh73a0.c +++ b/drivers/pinctrl/renesas/pfc-sh73a0.c @@ -3798,24 +3798,16 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { PORTCR(308, 0xe6052134), /* PORT308CR */ PORTCR(309, 0xe6052135), /* PORT309CR */ - { PINMUX_CFG_REG("MSEL2CR", 0xe605801c, 32, 1, GROUP( - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("MSEL2CR", 0xe605801c, 32, + GROUP(-12, 1, 1, 1, 1, -1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1), + GROUP( + /* RESERVED [12] */ MSEL2CR_MSEL19_0, MSEL2CR_MSEL19_1, MSEL2CR_MSEL18_0, MSEL2CR_MSEL18_1, MSEL2CR_MSEL17_0, MSEL2CR_MSEL17_1, MSEL2CR_MSEL16_0, MSEL2CR_MSEL16_1, - 0, 0, + /* RESERVED [1] */ MSEL2CR_MSEL14_0, MSEL2CR_MSEL14_1, MSEL2CR_MSEL13_0, MSEL2CR_MSEL13_1, MSEL2CR_MSEL12_0, MSEL2CR_MSEL12_1, @@ -3833,60 +3825,43 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { MSEL2CR_MSEL0_0, MSEL2CR_MSEL0_1, )) }, - { PINMUX_CFG_REG("MSEL3CR", 0xe6058020, 32, 1, GROUP( - 0, 0, - 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("MSEL3CR", 0xe6058020, 32, + GROUP(-3, 1, -12, 1, -3, 1, -1, 1, -2, 1, -3, 1, + -2), + GROUP( + /* RESERVED [3] */ MSEL3CR_MSEL28_0, MSEL3CR_MSEL28_1, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + /* RESERVED [12] */ MSEL3CR_MSEL15_0, MSEL3CR_MSEL15_1, - 0, 0, - 0, 0, - 0, 0, + /* RESERVED [3] */ MSEL3CR_MSEL11_0, MSEL3CR_MSEL11_1, - 0, 0, + /* RESERVED [1] */ MSEL3CR_MSEL9_0, MSEL3CR_MSEL9_1, - 0, 0, - 0, 0, + /* RESERVED [2] */ MSEL3CR_MSEL6_0, MSEL3CR_MSEL6_1, - 0, 0, - 0, 0, - 0, 0, + /* RESERVED [3] */ MSEL3CR_MSEL2_0, MSEL3CR_MSEL2_1, - 0, 0, - 0, 0, + /* RESERVED [2] */ )) }, - { PINMUX_CFG_REG("MSEL4CR", 0xe6058024, 32, 1, GROUP( - 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("MSEL4CR", 0xe6058024, 32, + GROUP(-2, 1, -1, 1, 1, -3, 1, 1, 1, 1, -3, 1, + -1, 1, 1, 1, 1, 1, 1, 1, -2, 1, -2, 1, + -1), + GROUP( + /* RESERVED [2] */ MSEL4CR_MSEL29_0, MSEL4CR_MSEL29_1, - 0, 0, + /* RESERVED [1] */ MSEL4CR_MSEL27_0, MSEL4CR_MSEL27_1, MSEL4CR_MSEL26_0, MSEL4CR_MSEL26_1, - 0, 0, - 0, 0, - 0, 0, + /* RESERVED [3] */ MSEL4CR_MSEL22_0, MSEL4CR_MSEL22_1, MSEL4CR_MSEL21_0, MSEL4CR_MSEL21_1, MSEL4CR_MSEL20_0, MSEL4CR_MSEL20_1, MSEL4CR_MSEL19_0, MSEL4CR_MSEL19_1, - 0, 0, - 0, 0, - 0, 0, + /* RESERVED [3] */ MSEL4CR_MSEL15_0, MSEL4CR_MSEL15_1, - 0, 0, + /* RESERVED [1] */ MSEL4CR_MSEL13_0, MSEL4CR_MSEL13_1, MSEL4CR_MSEL12_0, MSEL4CR_MSEL12_1, MSEL4CR_MSEL11_0, MSEL4CR_MSEL11_1, @@ -3894,13 +3869,11 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { MSEL4CR_MSEL9_0, MSEL4CR_MSEL9_1, MSEL4CR_MSEL8_0, MSEL4CR_MSEL8_1, MSEL4CR_MSEL7_0, MSEL4CR_MSEL7_1, - 0, 0, - 0, 0, + /* RESERVED [2] */ MSEL4CR_MSEL4_0, MSEL4CR_MSEL4_1, - 0, 0, - 0, 0, + /* RESERVED [2] */ MSEL4CR_MSEL1_0, MSEL4CR_MSEL1_1, - 0, 0, + /* RESERVED [1] */ )) }, { }, diff --git a/drivers/pinctrl/renesas/pfc-sh7720.c b/drivers/pinctrl/renesas/pfc-sh7720.c index 7071ef52449d6ccfb4d3770c4eb33f67d2a14e4d..6eedcc5bbb4d6705dbf762024d1ba55a6c23bbfb 100644 --- a/drivers/pinctrl/renesas/pfc-sh7720.c +++ b/drivers/pinctrl/renesas/pfc-sh7720.c @@ -1014,25 +1014,24 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { PTJ1_FN, PTJ1_OUT, 0, PTJ1_IN, PTJ0_FN, PTJ0_OUT, 0, PTJ0_IN )) }, - { PINMUX_CFG_REG("PKCR", 0xa4050112, 16, 2, GROUP( - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, + { PINMUX_CFG_REG_VAR("PKCR", 0xa4050112, 16, + GROUP(-8, 2, 2, 2, 2), + GROUP( + /* RESERVED [8] */ PTK3_FN, PTK3_OUT, 0, PTK3_IN, PTK2_FN, PTK2_OUT, 0, PTK2_IN, PTK1_FN, PTK1_OUT, 0, PTK1_IN, PTK0_FN, PTK0_OUT, 0, PTK0_IN )) }, - { PINMUX_CFG_REG("PLCR", 0xa4050114, 16, 2, GROUP( + { PINMUX_CFG_REG_VAR("PLCR", 0xa4050114, 16, + GROUP(2, 2, 2, 2, 2, -6), + GROUP( PTL7_FN, PTL7_OUT, 0, PTL7_IN, PTL6_FN, PTL6_OUT, 0, PTL6_IN, PTL5_FN, PTL5_OUT, 0, PTL5_IN, PTL4_FN, PTL4_OUT, 0, PTL4_IN, PTL3_FN, PTL3_OUT, 0, PTL3_IN, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0 )) + /* RESERVED [6] */ )) }, { PINMUX_CFG_REG("PMCR", 0xa4050116, 16, 2, GROUP( PTM7_FN, PTM7_OUT, 0, PTM7_IN, @@ -1044,10 +1043,10 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { PTM1_FN, PTM1_OUT, 0, PTM1_IN, PTM0_FN, PTM0_OUT, 0, PTM0_IN )) }, - { PINMUX_CFG_REG("PPCR", 0xa4050118, 16, 2, GROUP( - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, + { PINMUX_CFG_REG_VAR("PPCR", 0xa4050118, 16, + GROUP(-6, 2, 2, 2, 2, 2), + GROUP( + /* RESERVED [6] */ PTP4_FN, PTP4_OUT, 0, PTP4_IN, PTP3_FN, PTP3_OUT, 0, PTP3_IN, PTP2_FN, PTP2_OUT, 0, PTP2_IN, @@ -1064,40 +1063,40 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { PTR1_FN, PTR1_OUT, 0, PTR1_IN, PTR0_FN, PTR0_OUT, 0, PTR0_IN )) }, - { PINMUX_CFG_REG("PSCR", 0xa405011c, 16, 2, GROUP( - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, + { PINMUX_CFG_REG_VAR("PSCR", 0xa405011c, 16, + GROUP(-6, 2, 2, 2, 2, 2), + GROUP( + /* RESERVED [6] */ PTS4_FN, PTS4_OUT, 0, PTS4_IN, PTS3_FN, PTS3_OUT, 0, PTS3_IN, PTS2_FN, PTS2_OUT, 0, PTS2_IN, PTS1_FN, PTS1_OUT, 0, PTS1_IN, PTS0_FN, PTS0_OUT, 0, PTS0_IN )) }, - { PINMUX_CFG_REG("PTCR", 0xa405011e, 16, 2, GROUP( - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, + { PINMUX_CFG_REG_VAR("PTCR", 0xa405011e, 16, + GROUP(-6, 2, 2, 2, 2, 2), + GROUP( + /* RESERVED [6] */ PTT4_FN, PTT4_OUT, 0, PTT4_IN, PTT3_FN, PTT3_OUT, 0, PTT3_IN, PTT2_FN, PTT2_OUT, 0, PTT2_IN, PTT1_FN, PTT1_OUT, 0, PTT1_IN, PTT0_FN, PTT0_OUT, 0, PTT0_IN )) }, - { PINMUX_CFG_REG("PUCR", 0xa4050120, 16, 2, GROUP( - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, + { PINMUX_CFG_REG_VAR("PUCR", 0xa4050120, 16, + GROUP(-6, 2, 2, 2, 2, 2), + GROUP( + /* RESERVED [6] */ PTU4_FN, PTU4_OUT, 0, PTU4_IN, PTU3_FN, PTU3_OUT, 0, PTU3_IN, PTU2_FN, PTU2_OUT, 0, PTU2_IN, PTU1_FN, PTU1_OUT, 0, PTU1_IN, PTU0_FN, PTU0_OUT, 0, PTU0_IN )) }, - { PINMUX_CFG_REG("PVCR", 0xa4050122, 16, 2, GROUP( - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, + { PINMUX_CFG_REG_VAR("PVCR", 0xa4050122, 16, + GROUP(-6, 2, 2, 2, 2, 2), + GROUP( + /* RESERVED [6] */ PTV4_FN, PTV4_OUT, 0, PTV4_IN, PTV3_FN, PTV3_OUT, 0, PTV3_IN, PTV2_FN, PTV2_OUT, 0, PTV2_IN, diff --git a/drivers/pinctrl/renesas/pfc-sh7722.c b/drivers/pinctrl/renesas/pfc-sh7722.c index 13d9967dce592d8ef409564e358f819f0045986d..4b82ac2c5e91d787eeca8daca48d640e1d995db1 100644 --- a/drivers/pinctrl/renesas/pfc-sh7722.c +++ b/drivers/pinctrl/renesas/pfc-sh7722.c @@ -1,5 +1,4 @@ // SPDX-License-Identifier: GPL-2.0 -#include #include #include @@ -1256,14 +1255,16 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { HPD49, PTB1_OUT, 0, PTB1_IN, HPD48, PTB0_OUT, 0, PTB0_IN )) }, - { PINMUX_CFG_REG("PCCR", 0xa4050104, 16, 2, GROUP( + { PINMUX_CFG_REG_VAR("PCCR", 0xa4050104, 16, + GROUP(2, -2, 2, 2, 2, 2, -2, 2), + GROUP( 0, 0, 0, PTC7_IN, - 0, 0, 0, 0, + /* RESERVED [2] */ IOIS16, 0, 0, PTC5_IN, HPDQM7, PTC4_OUT, 0, PTC4_IN, HPDQM6, PTC3_OUT, 0, PTC3_IN, HPDQM5, PTC2_OUT, 0, PTC2_IN, - 0, 0, 0, 0, + /* RESERVED [2] */ HPDQM4, PTC0_OUT, 0, PTC0_IN )) }, { PINMUX_CFG_REG("PDCR", 0xa4050106, 16, 2, GROUP( @@ -1276,13 +1277,14 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { SDHICMD, PTD1_OUT, 0, PTD1_IN, SDHICLK, PTD0_OUT, 0, 0 )) }, - { PINMUX_CFG_REG("PECR", 0xa4050108, 16, 2, GROUP( + { PINMUX_CFG_REG_VAR("PECR", 0xa4050108, 16, + GROUP(2, 2, 2, 2, -4, 2, 2), + GROUP( A25, PTE7_OUT, 0, PTE7_IN, A24, PTE6_OUT, 0, PTE6_IN, A23, PTE5_OUT, 0, PTE5_IN, A22, PTE4_OUT, 0, PTE4_IN, - 0, 0, 0, 0, - 0, 0, 0, 0, + /* RESERVED [4] */ IRQ5, PTE1_OUT, 0, PTE1_IN, IRQ4_BS, PTE0_OUT, 0, PTE0_IN )) }, @@ -1296,10 +1298,10 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { SIORXD_SIUBISLD, 0, 0, PTF1_IN, SIOTXD_SIUBOSLD, PTF0_OUT, 0, 0 )) }, - { PINMUX_CFG_REG("PGCR", 0xa405010c, 16, 2, GROUP( - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, + { PINMUX_CFG_REG_VAR("PGCR", 0xa405010c, 16, + GROUP(-6, 2, 2, 2, 2, 2), + GROUP( + /* RESERVED [6] */ AUDSYNC, PTG4_OUT, 0, 0, AUDATA3, PTG3_OUT, 0, 0, AUDATA2, PTG2_OUT, 0, 0, @@ -1316,13 +1318,13 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { LCDD17_DV_HSYNC, PTH1_OUT, 0, PTH1_IN, LCDD16_DV_VSYNC, PTH0_OUT, 0, PTH0_IN )) }, - { PINMUX_CFG_REG("PJCR", 0xa4050110, 16, 2, GROUP( + { PINMUX_CFG_REG_VAR("PJCR", 0xa4050110, 16, + GROUP(2, 2, 2, -6, 2, 2), + GROUP( STATUS0, PTJ7_OUT, 0, 0, 0, PTJ6_OUT, 0, 0, PDSTATUS, PTJ5_OUT, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, + /* RESERVED [6] */ IRQ1, PTJ1_OUT, 0, PTJ1_IN, IRQ0, PTJ0_OUT, 0, PTJ0_IN )) }, @@ -1376,50 +1378,50 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { PTQ1, PTQ1_OUT, 0, 0, PTQ0, PTQ0_OUT, 0, PTQ0_IN )) }, - { PINMUX_CFG_REG("PRCR", 0xa405011c, 16, 2, GROUP( - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, + { PINMUX_CFG_REG_VAR("PRCR", 0xa405011c, 16, + GROUP(-6, 2, 2, 2, 2, 2), + GROUP( + /* RESERVED [6] */ LCDRD, PTR4_OUT, 0, 0, CS6B_CE1B_LCDCS2, PTR3_OUT, 0, 0, WAIT, 0, 0, PTR2_IN, LCDDCK_LCDWR, PTR1_OUT, 0, 0, LCDVEPWC_LCDVEPWC2, PTR0_OUT, 0, 0 )) }, - { PINMUX_CFG_REG("PSCR", 0xa405011e, 16, 2, GROUP( - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, + { PINMUX_CFG_REG_VAR("PSCR", 0xa405011e, 16, + GROUP(-6, 2, 2, 2, 2, 2), + GROUP( + /* RESERVED [6] */ SCIF0_CTS_SIUAISPD, 0, 0, PTS4_IN, SCIF0_RTS_SIUAOSPD, PTS3_OUT, 0, 0, SCIF0_SCK_TPUTO, PTS2_OUT, 0, PTS2_IN, SCIF0_RXD, 0, 0, PTS1_IN, SCIF0_TXD, PTS0_OUT, 0, 0 )) }, - { PINMUX_CFG_REG("PTCR", 0xa4050140, 16, 2, GROUP( - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, + { PINMUX_CFG_REG_VAR("PTCR", 0xa4050140, 16, + GROUP(-6, 2, 2, 2, 2, 2), + GROUP( + /* RESERVED [6] */ FOE_VIO_VD2, PTT4_OUT, 0, PTT4_IN, FWE, PTT3_OUT, 0, PTT3_IN, FSC, PTT2_OUT, 0, PTT2_IN, DREQ0, 0, 0, PTT1_IN, FCDE, PTT0_OUT, 0, 0 )) }, - { PINMUX_CFG_REG("PUCR", 0xa4050142, 16, 2, GROUP( - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, + { PINMUX_CFG_REG_VAR("PUCR", 0xa4050142, 16, + GROUP(-6, 2, 2, 2, 2, 2), + GROUP( + /* RESERVED [6] */ NAF2_VIO_D10, PTU4_OUT, 0, PTU4_IN, NAF1_VIO_D9, PTU3_OUT, 0, PTU3_IN, NAF0_VIO_D8, PTU2_OUT, 0, PTU2_IN, FRB_VIO_CLK2, 0, 0, PTU1_IN, FCE_VIO_HD2, PTU0_OUT, 0, PTU0_IN )) }, - { PINMUX_CFG_REG("PVCR", 0xa4050144, 16, 2, GROUP( - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, + { PINMUX_CFG_REG_VAR("PVCR", 0xa4050144, 16, + GROUP(-6, 2, 2, 2, 2, 2), + GROUP( + /* RESERVED [6] */ NAF7_VIO_D15, PTV4_OUT, 0, PTV4_IN, NAF6_VIO_D14, PTV3_OUT, 0, PTV3_IN, NAF5_VIO_D13, PTV2_OUT, 0, PTV2_IN, @@ -1446,9 +1448,10 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { LCDD19_DV_CLKI, PTX1_OUT, 0, PTX1_IN, LCDD18_DV_CLK, PTX0_OUT, 0, PTX0_IN )) }, - { PINMUX_CFG_REG("PYCR", 0xa405014a, 16, 2, GROUP( - 0, 0, 0, 0, - 0, 0, 0, 0, + { PINMUX_CFG_REG_VAR("PYCR", 0xa405014a, 16, + GROUP(-4, 2, 2, 2, 2, 2, 2), + GROUP( + /* RESERVED [4] */ KEYOUT5_IN5, PTY5_OUT, 0, PTY5_IN, KEYOUT4_IN6, PTY4_OUT, 0, PTY4_IN, KEYOUT3, PTY3_OUT, 0, PTY3_IN, @@ -1456,33 +1459,27 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { KEYOUT1, PTY1_OUT, 0, 0, KEYOUT0, PTY0_OUT, 0, PTY0_IN )) }, - { PINMUX_CFG_REG("PZCR", 0xa405014c, 16, 2, GROUP( - 0, 0, 0, 0, - 0, 0, 0, 0, + { PINMUX_CFG_REG_VAR("PZCR", 0xa405014c, 16, + GROUP(-4, 2, 2, 2, 2, 2, -2), + GROUP( + /* RESERVED [4] */ KEYIN4_IRQ7, 0, 0, PTZ5_IN, KEYIN3, 0, 0, PTZ4_IN, KEYIN2, 0, 0, PTZ3_IN, KEYIN1, 0, 0, PTZ2_IN, KEYIN0_IRQ6, 0, 0, PTZ1_IN, - 0, 0, 0, 0 )) + /* RESERVED [2] */ )) }, - { PINMUX_CFG_REG("PSELA", 0xa405014e, 16, 1, GROUP( + { PINMUX_CFG_REG_VAR("PSELA", 0xa405014e, 16, + GROUP(1, 1, -4, 1, -4, 1, -4), + GROUP( PSA15_KEYIN0, PSA15_IRQ6, PSA14_KEYIN4, PSA14_IRQ7, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + /* RESERVED [4] */ PSA9_IRQ4, PSA9_BS, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + /* RESERVED [4] */ PSA4_IRQ2, PSA4_SDHID2, - 0, 0, - 0, 0, - 0, 0, - 0, 0 )) + /* RESERVED [4] */ )) }, { PINMUX_CFG_REG("PSELB", 0xa4050150, 16, 1, GROUP( PSB15_SIOTXD, PSB15_SIUBOSLD, @@ -1502,22 +1499,15 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { PSB1_SIUMCKA, PSB1_SIOF1_MCK, PSB0_SIUAOSLD, PSB0_SIOF1_TXD )) }, - { PINMUX_CFG_REG("PSELC", 0xa4050152, 16, 1, GROUP( + { PINMUX_CFG_REG_VAR("PSELC", 0xa4050152, 16, + GROUP(1, 1, 1, 1, 1, -10, 1), + GROUP( PSC15_SIUAISLD, PSC15_SIOF1_RXD, PSC14_SIUAOBT, PSC14_SIOF1_SCK, PSC13_SIUAOLR, PSC13_SIOF1_SYNC, PSC12_SIUAIBT, PSC12_SIOF1_SS1, PSC11_SIUAILR, PSC11_SIOF1_SS2, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + /* RESERVED [10] */ PSC0_NAF, PSC0_VIO )) }, { PINMUX_CFG_REG("PSELD", 0xa4050154, 16, 1, GROUP( @@ -1538,61 +1528,45 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { 0, 0, PSD0_LCDD19_LCDD0, PSD0_DV )) }, - { PINMUX_CFG_REG("PSELE", 0xa4050156, 16, 1, GROUP( + { PINMUX_CFG_REG_VAR("PSELE", 0xa4050156, 16, + GROUP(1, 1, 1, 1, 1, -7, 1, 1, 1, 1), + GROUP( PSE15_SIOF0_MCK_IRQ3, PSE15_SIM_D, PSE14_SIOF0_TXD_IRDA_OUT, PSE14_SIM_CLK, PSE13_SIOF0_RXD_IRDA_IN, PSE13_TS_SDAT, PSE12_LCDVSYN2, PSE12_DACK, PSE11_SIUMCKA_SIOF1_MCK, PSE11_SIUFCKA, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + /* RESERVED [7] */ PSE3_FLCTL, PSE3_VIO, PSE2_NAF2, PSE2_VIO_D10, PSE1_NAF1, PSE1_VIO_D9, PSE0_NAF0, PSE0_VIO_D8 )) }, - { PINMUX_CFG_REG("HIZCRA", 0xa4050158, 16, 1, GROUP( - 0, 0, + { PINMUX_CFG_REG_VAR("HIZCRA", 0xa4050158, 16, + GROUP(-1, 1, -3, 1, 1, 1, 1, 1, -6), + GROUP( + /* RESERVED [1] */ HIZA14_KEYSC, HIZA14_HIZ, - 0, 0, - 0, 0, - 0, 0, + /* RESERVED [3] */ HIZA10_NAF, HIZA10_HIZ, HIZA9_VIO, HIZA9_HIZ, HIZA8_LCDC, HIZA8_HIZ, HIZA7_LCDC, HIZA7_HIZ, HIZA6_LCDC, HIZA6_HIZ, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0 )) + /* RESERVED [6] */ )) }, - { PINMUX_CFG_REG("HIZCRB", 0xa405015a, 16, 1, GROUP( - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("HIZCRB", 0xa405015a, 16, + GROUP(-11, 1, -2, 1, 1), + GROUP( + /* RESERVED [11] */ HIZB4_SIUA, HIZB4_HIZ, - 0, 0, - 0, 0, + /* RESERVED [2] */ HIZB1_VIO, HIZB1_HIZ, HIZB0_VIO, HIZB0_HIZ )) }, - { PINMUX_CFG_REG("HIZCRC", 0xa405015c, 16, 1, GROUP( + { PINMUX_CFG_REG_VAR("HIZCRC", 0xa405015c, 16, + GROUP(1, 1, 1, 1, 1, 1, 1, 1, -8), + GROUP( HIZC15_IRQ7, HIZC15_HIZ, HIZC14_IRQ6, HIZC14_HIZ, HIZC13_IRQ5, HIZC13_HIZ, @@ -1601,32 +1575,15 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { HIZC10_IRQ2, HIZC10_HIZ, HIZC9_IRQ1, HIZC9_HIZ, HIZC8_IRQ0, HIZC8_HIZ, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0 )) + /* RESERVED [8] */ )) }, - { PINMUX_CFG_REG("MSELCRB", 0xa4050182, 16, 1, GROUP( - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("MSELCRB", 0xa4050182, 16, + GROUP(-6, 1, 1, -8), + GROUP( + /* RESERVED [6] */ MSELB9_VIO, MSELB9_VIO2, MSELB8_RGB, MSELB8_SYS, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0 )) + /* RESERVED [8] */ )) }, {} }; diff --git a/drivers/pinctrl/renesas/pfc-sh7723.c b/drivers/pinctrl/renesas/pfc-sh7723.c index 6f08f527c01081c32d509a9b068c1b761a309f52..95344281966e6eb09514cdad655418097b1c44d1 100644 --- a/drivers/pinctrl/renesas/pfc-sh7723.c +++ b/drivers/pinctrl/renesas/pfc-sh7723.c @@ -5,7 +5,6 @@ * Copyright (C) 2008 Magnus Damm */ -#include #include #include @@ -1547,9 +1546,10 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { PTD1_FN, PTD1_OUT, 0, PTD1_IN, PTD0_FN, PTD0_OUT, 0, PTD0_IN )) }, - { PINMUX_CFG_REG("PECR", 0xa4050108, 16, 2, GROUP( - 0, 0, 0, 0, - 0, 0, 0, 0, + { PINMUX_CFG_REG_VAR("PECR", 0xa4050108, 16, + GROUP(-4, 2, 2, 2, 2, 2, 2), + GROUP( + /* RESERVED [4] */ PTE5_FN, PTE5_OUT, 0, PTE5_IN, PTE4_FN, PTE4_OUT, 0, PTE4_IN, PTE3_FN, PTE3_OUT, 0, PTE3_IN, @@ -1567,9 +1567,10 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { PTF1_FN, PTF1_OUT, 0, PTF1_IN, PTF0_FN, PTF0_OUT, 0, PTF0_IN )) }, - { PINMUX_CFG_REG("PGCR", 0xa405010c, 16, 2, GROUP( - 0, 0, 0, 0, - 0, 0, 0, 0, + { PINMUX_CFG_REG_VAR("PGCR", 0xa405010c, 16, + GROUP(-4, 2, 2, 2, 2, 2, 2), + GROUP( + /* RESERVED [4] */ PTG5_FN, PTG5_OUT, 0, 0, PTG4_FN, PTG4_OUT, 0, 0, PTG3_FN, PTG3_OUT, 0, 0, @@ -1587,11 +1588,13 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { PTH1_FN, PTH1_OUT, 0, PTH1_IN, PTH0_FN, PTH0_OUT, 0, PTH0_IN )) }, - { PINMUX_CFG_REG("PJCR", 0xa4050110, 16, 2, GROUP( + { PINMUX_CFG_REG_VAR("PJCR", 0xa4050110, 16, + GROUP(2, -2, 2, -2, 2, 2, 2, 2), + GROUP( PTJ7_FN, PTJ7_OUT, 0, 0, - 0, 0, 0, 0, + /* RESERVED [2] */ PTJ5_FN, PTJ5_OUT, 0, 0, - 0, 0, 0, 0, + /* RESERVED [2] */ PTJ3_FN, PTJ3_OUT, 0, PTJ3_IN, PTJ2_FN, PTJ2_OUT, 0, PTJ2_IN, PTJ1_FN, PTJ1_OUT, 0, PTJ1_IN, @@ -1637,11 +1640,10 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { PTN1_FN, PTN1_OUT, 0, PTN1_IN, PTN0_FN, PTN0_OUT, 0, PTN0_IN )) }, - { PINMUX_CFG_REG("PQCR", 0xa405011a, 16, 2, GROUP( - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, + { PINMUX_CFG_REG_VAR("PQCR", 0xa405011a, 16, + GROUP(-8, 2, 2, 2, 2), + GROUP( + /* RESERVED [8] */ PTQ3_FN, 0, 0, PTQ3_IN, PTQ2_FN, 0, 0, PTQ2_IN, PTQ1_FN, 0, 0, PTQ1_IN, @@ -1667,9 +1669,10 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { PTS1_FN, PTS1_OUT, 0, PTS1_IN, PTS0_FN, PTS0_OUT, 0, PTS0_IN )) }, - { PINMUX_CFG_REG("PTCR", 0xa4050140, 16, 2, GROUP( - 0, 0, 0, 0, - 0, 0, 0, 0, + { PINMUX_CFG_REG_VAR("PTCR", 0xa4050140, 16, + GROUP(-4, 2, 2, 2, 2, 2, 2), + GROUP( + /* RESERVED [4] */ PTT5_FN, PTT5_OUT, 0, PTT5_IN, PTT4_FN, PTT4_OUT, 0, PTT4_IN, PTT3_FN, PTT3_OUT, 0, PTT3_IN, @@ -1677,9 +1680,10 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { PTT1_FN, PTT1_OUT, 0, PTT1_IN, PTT0_FN, PTT0_OUT, 0, PTT0_IN )) }, - { PINMUX_CFG_REG("PUCR", 0xa4050142, 16, 2, GROUP( - 0, 0, 0, 0, - 0, 0, 0, 0, + { PINMUX_CFG_REG_VAR("PUCR", 0xa4050142, 16, + GROUP(-4, 2, 2, 2, 2, 2, 2), + GROUP( + /* RESERVED [4] */ PTU5_FN, PTU5_OUT, 0, PTU5_IN, PTU4_FN, PTU4_OUT, 0, PTU4_IN, PTU3_FN, PTU3_OUT, 0, PTU3_IN, @@ -1737,35 +1741,38 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { PTZ1_FN, PTZ1_OUT, 0, PTZ1_IN, PTZ0_FN, PTZ0_OUT, 0, PTZ0_IN )) }, - { PINMUX_CFG_REG("PSELA", 0xa405014e, 16, 2, GROUP( + { PINMUX_CFG_REG_VAR("PSELA", 0xa405014e, 16, + GROUP(2, 2, 2, -4, 2, 2, -2), + GROUP( PSA15_PSA14_FN1, PSA15_PSA14_FN2, 0, 0, PSA13_PSA12_FN1, PSA13_PSA12_FN2, 0, 0, PSA11_PSA10_FN1, PSA11_PSA10_FN2, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, + /* RESERVED [4] */ PSA5_PSA4_FN1, PSA5_PSA4_FN2, PSA5_PSA4_FN3, 0, PSA3_PSA2_FN1, PSA3_PSA2_FN2, 0, 0, - 0, 0, 0, 0 )) + /* RESERVED [2] */ )) }, - { PINMUX_CFG_REG("PSELB", 0xa4050150, 16, 2, GROUP( + { PINMUX_CFG_REG_VAR("PSELB", 0xa4050150, 16, + GROUP(2, 2, -2, 2, 2, 2, 2, -2), + GROUP( PSB15_PSB14_FN1, PSB15_PSB14_FN2, 0, 0, PSB13_PSB12_LCDC_RGB, PSB13_PSB12_LCDC_SYS, 0, 0, - 0, 0, 0, 0, + /* RESERVED [2] */ PSB9_PSB8_FN1, PSB9_PSB8_FN2, PSB9_PSB8_FN3, 0, PSB7_PSB6_FN1, PSB7_PSB6_FN2, 0, 0, PSB5_PSB4_FN1, PSB5_PSB4_FN2, 0, 0, PSB3_PSB2_FN1, PSB3_PSB2_FN2, 0, 0, - 0, 0, 0, 0 )) + /* RESERVED [2] */ )) }, - { PINMUX_CFG_REG("PSELC", 0xa4050152, 16, 2, GROUP( + { PINMUX_CFG_REG_VAR("PSELC", 0xa4050152, 16, + GROUP(2, 2, 2, 2, 2, -6), + GROUP( PSC15_PSC14_FN1, PSC15_PSC14_FN2, 0, 0, PSC13_PSC12_FN1, PSC13_PSC12_FN2, 0, 0, PSC11_PSC10_FN1, PSC11_PSC10_FN2, PSC11_PSC10_FN3, 0, PSC9_PSC8_FN1, PSC9_PSC8_FN2, 0, 0, PSC7_PSC6_FN1, PSC7_PSC6_FN2, PSC7_PSC6_FN3, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0 )) + /* RESERVED [3] */ )) }, { PINMUX_CFG_REG("PSELD", 0xa4050154, 16, 2, GROUP( PSD15_PSD14_FN1, PSD15_PSD14_FN2, 0, 0, diff --git a/drivers/pinctrl/renesas/pfc-sh7724.c b/drivers/pinctrl/renesas/pfc-sh7724.c index 7a18afecda2c2799dc50b50c5d9ccf5535379f29..26517ad26a0fd1b849f9de3a518e1419e8f2f233 100644 --- a/drivers/pinctrl/renesas/pfc-sh7724.c +++ b/drivers/pinctrl/renesas/pfc-sh7724.c @@ -10,7 +10,6 @@ * Copyright (C) 2008 Magnus Damm */ -#include #include #include @@ -1799,9 +1798,10 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { PTF1_FN, PTF1_OUT, 0, PTF1_IN, PTF0_FN, PTF0_OUT, 0, PTF0_IN )) }, - { PINMUX_CFG_REG("PGCR", 0xa405010c, 16, 2, GROUP( - 0, 0, 0, 0, - 0, 0, 0, 0, + { PINMUX_CFG_REG_VAR("PGCR", 0xa405010c, 16, + GROUP(-4, 2, 2, 2, 2, 2, 2), + GROUP( + /* RESERVED [4] */ PTG5_FN, PTG5_OUT, 0, 0, PTG4_FN, PTG4_OUT, 0, 0, PTG3_FN, PTG3_OUT, 0, 0, diff --git a/drivers/pinctrl/renesas/pfc-sh7734.c b/drivers/pinctrl/renesas/pfc-sh7734.c index dbc36079c3811cdec734378e5f3dbe5f9d62f8a3..106a500ad13d160e1fb848a7a44a538e9debc4b1 100644 --- a/drivers/pinctrl/renesas/pfc-sh7734.c +++ b/drivers/pinctrl/renesas/pfc-sh7734.c @@ -5,7 +5,6 @@ * Copyright (C) 2012 Renesas Solutions Corp. * Copyright (C) 2012 Nobuhiro Iwamatsu */ -#include #include #include @@ -1806,16 +1805,13 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { GP_4_1_FN, FN_IP9_21_20, GP_4_0_FN, FN_IP9_19_18 )) }, - { PINMUX_CFG_REG("GPSR5", 0xFFFC0018, 32, 1, GROUP( - 0, 0, 0, 0, 0, 0, 0, 0, /* 31 - 28 */ - 0, 0, 0, 0, 0, 0, 0, 0, /* 27 - 24 */ - 0, 0, 0, 0, 0, 0, 0, 0, /* 23 - 20 */ - 0, 0, 0, 0, 0, 0, 0, 0, /* 19 - 16 */ - 0, 0, 0, 0, 0, 0, 0, 0, /* 15 - 12 */ + { PINMUX_CFG_REG_VAR("GPSR5", 0xFFFC0018, 32, + GROUP(-20, 1, 1, -6, 1, 1, 1, 1), + GROUP( + /* GP5_31_12 RESERVED */ GP_5_11_FN, FN_IP10_29_28, GP_5_10_FN, FN_IP10_27_26, - 0, 0, 0, 0, 0, 0, 0, 0, /* 9 - 6 */ - 0, 0, 0, 0, /* 5, 4 */ + /* GP5_9_4 RESERVED */ GP_5_3_FN, FN_IRQ3_B, GP_5_2_FN, FN_IRQ2_B, GP_5_1_FN, FN_IP11_3, @@ -1896,10 +1892,9 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_A16, FN_ST0_PWM, FN_LCD_DON_A, FN_TIOC4A_C )) }, { PINMUX_CFG_REG_VAR("IPSR2", 0xFFFC0024, 32, - GROUP(1, 3, 3, 2, 3, 3, 3, 3, 3, 3, 2, 3), + GROUP(-1, 3, 3, 2, 3, 3, 3, 3, 3, 3, 2, 3), GROUP( - /* IP2_31 [1] */ - 0, 0, + /* IP2_31 [1] RESERVED */ /* IP2_30_28 [3] */ FN_D14, FN_TX2_B, 0, FN_FSE_A, FN_ET0_TX_CLK_B, 0, 0, 0, @@ -1933,10 +1928,9 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_FD4_A, 0, 0, 0 )) }, { PINMUX_CFG_REG_VAR("IPSR3", 0xFFFC0028, 32, - GROUP(2, 3, 3, 3, 1, 2, 3, 3, 3, 3, 3, 1, 2), + GROUP(-2, 3, 3, 3, 1, 2, 3, 3, 3, 3, 3, 1, 2), GROUP( - /* IP3_31_30 [2] */ - 0, 0, 0, 0, + /* IP3_31_30 [2] RESERVED */ /* IP3_29_27 [3] */ FN_DRACK0, FN_SD1_DAT2_A, FN_ATAG, FN_TCLK1_A, FN_ET0_ETXD7, 0, 0, 0, @@ -2007,19 +2001,9 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_ET0_ERXD7, 0, 0, 0 )) }, { PINMUX_CFG_REG_VAR("IPSR5", 0xFFFC0030, 32, - GROUP(1, 1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3, - 3, 3, 3), + GROUP(-5, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3), GROUP( - /* IP5_31 [1] */ - 0, 0, - /* IP5_30 [1] */ - 0, 0, - /* IP5_29 [1] */ - 0, 0, - /* IP5_28 [1] */ - 0, 0, - /* IP5_27 [1] */ - 0, 0, + /* IP5_31_27 [5] RESERVED */ /* IP5_26_25 [2] */ FN_REF50CK, FN_CTS1_E, FN_HCTS0_D, 0, /* IP5_24_23 [2] */ @@ -2049,25 +2033,9 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_ET0_RX_CLK_B, 0, 0, 0 )) }, { PINMUX_CFG_REG_VAR("IPSR6", 0xFFFC0034, 32, - GROUP(1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 2, 2, - 2, 2, 2, 2, 3, 3), + GROUP(-8, 3, 3, 2, 2, 2, 2, 2, 2, 3, 3), GROUP( - /* IP5_31 [1] */ - 0, 0, - /* IP6_30 [1] */ - 0, 0, - /* IP6_29 [1] */ - 0, 0, - /* IP6_28 [1] */ - 0, 0, - /* IP6_27 [1] */ - 0, 0, - /* IP6_26 [1] */ - 0, 0, - /* IP6_25 [1] */ - 0, 0, - /* IP6_24 [1] */ - 0, 0, + /* IP5_31_24 [8] RESERVED */ /* IP6_23_21 [3] */ FN_DU0_DG1, FN_CTS1_C, FN_HRTS0_D, FN_TIOC1B_A, FN_HIFD09, 0, 0, 0, @@ -2094,10 +2062,9 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_TCLKA_A, FN_HIFD00, 0, 0 )) }, { PINMUX_CFG_REG_VAR("IPSR7", 0xFFFC0038, 32, - GROUP(1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3), + GROUP(-1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3), GROUP( - /* IP7_31 [1] */ - 0, 0, + /* IP7_31 [1] RESERVED */ /* IP7_30_29 [2] */ FN_DU0_DB4, 0, FN_HIFINT, 0, /* IP7_28_27 [2] */ @@ -2131,11 +2098,10 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_HIFD10, 0, 0, 0 )) }, { PINMUX_CFG_REG_VAR("IPSR8", 0xFFFC003C, 32, - GROUP(2, 2, 2, 3, 3, 2, 2, 2, 2, 2, 2, 2, + GROUP(-2, 2, 2, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2), GROUP( - /* IP9_31_30 [2] */ - 0, 0, 0, 0, + /* IP9_31_30 [2] RESERVED */ /* IP8_29_28 [2] */ FN_IRQ3_A, FN_RTS0_A, FN_HRTS0_B, FN_ET0_ERXD3_A, /* IP8_27_26 [2] */ @@ -2169,11 +2135,10 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_DU0_DB5, 0, FN_HIFDREQ, 0 )) }, { PINMUX_CFG_REG_VAR("IPSR9", 0xFFFC0040, 32, - GROUP(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + GROUP(-2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2), GROUP( - /* IP9_31_30 [2] */ - 0, 0, 0, 0, + /* IP9_31_30 [2] RESERVED */ /* IP9_29_28 [2] */ FN_SSI_SDATA1_A, FN_VI1_3_B, FN_LCD_DATA14_B, 0, /* IP9_27_26 [2] */ @@ -2206,10 +2171,9 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_VI1_CLK_A, 0, FN_FD0_B, FN_LCD_DATA0_B )) }, { PINMUX_CFG_REG_VAR("IPSR10", 0xFFFC0044, 32, - GROUP(2, 2, 2, 1, 2, 1, 3, 3, 1, 3, 3, 3, 3, 3), + GROUP(-2, 2, 2, 1, 2, 1, 3, 3, 1, 3, 3, 3, 3, 3), GROUP( - /* IP9_31_30 [2] */ - 0, 0, 0, 0, + /* IP9_31_30 [2] RESERVED */ /* IP10_29_28 [2] */ FN_CAN1_TX_A, FN_TX5_C, FN_MLB_DAT, 0, /* IP10_27_26 [2] */ @@ -2245,11 +2209,10 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_LCD_DATA15_B, 0, 0, 0 )) }, { PINMUX_CFG_REG_VAR("IPSR11", 0xFFFC0048, 32, - GROUP(3, 1, 2, 3, 2, 2, 3, 3, 1, 2, 3, 3, + GROUP(-3, 1, 2, 3, 2, 2, 3, 3, 1, 2, 3, 3, 1, 1, 1, 1), GROUP( - /* IP11_31_29 [3] */ - 0, 0, 0, 0, 0, 0, 0, 0, + /* IP11_31_29 [3] RESERVED */ /* IP11_28 [1] */ FN_PRESETOUT, FN_ST_CLKOUT, /* IP11_27_26 [2] */ @@ -2287,11 +2250,10 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_SCL1, FN_SCIF_CLK_C )) }, { PINMUX_CFG_REG_VAR("MOD_SEL1", 0xFFFC004C, 32, - GROUP(3, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 2, + GROUP(-3, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 2, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), GROUP( - /* SEL1_31_29 [3] */ - 0, 0, 0, 0, 0, 0, 0, 0, + /* SEL1_31_29 [3] RESERVED */ /* SEL1_28 [1] */ FN_SEL_IEBUS_0, FN_SEL_IEBUS_1, /* SEL1_27 [1] */ @@ -2344,25 +2306,9 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { FN_SEL_INTC_0, FN_SEL_INTC_1 )) }, { PINMUX_CFG_REG_VAR("MOD_SEL2", 0xFFFC0050, 32, - GROUP(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, - 2, 1, 2, 2, 3, 2, 3, 2, 2), + GROUP(-8, 1, 1, 1, 2, 2, 1, 2, 2, 3, 2, 3, 2, 2), GROUP( - /* SEL2_31 [1] */ - 0, 0, - /* SEL2_30 [1] */ - 0, 0, - /* SEL2_29 [1] */ - 0, 0, - /* SEL2_28 [1] */ - 0, 0, - /* SEL2_27 [1] */ - 0, 0, - /* SEL2_26 [1] */ - 0, 0, - /* SEL2_25 [1] */ - 0, 0, - /* SEL2_24 [1] */ - 0, 0, + /* SEL2_31_24 [8] RESERVED */ /* SEL2_23 [1] */ FN_SEL_MTU2_CLK_0, FN_SEL_MTU2_CLK_1, /* SEL2_22 [1] */ @@ -2403,10 +2349,10 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { }, { PINMUX_CFG_REG("INOUTSEL4", 0xFFC44004, 32, 1, GROUP(GP_INOUTSEL(4))) }, - { PINMUX_CFG_REG("INOUTSEL5", 0xffc45004, 32, 1, GROUP( - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 31 - 24 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 23 - 16 */ - 0, 0, 0, 0, 0, 0, 0, 0, /* 15 - 12 */ + { PINMUX_CFG_REG_VAR("INOUTSEL5", 0xffc45004, 32, + GROUP(-20, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), + GROUP( + /* GP5_31_12 RESERVED */ GP_5_11_IN, GP_5_11_OUT, GP_5_10_IN, GP_5_10_OUT, GP_5_9_IN, GP_5_9_OUT, diff --git a/drivers/pinctrl/renesas/pfc-sh7757.c b/drivers/pinctrl/renesas/pfc-sh7757.c index 064e987b09cbf5b93244107c553f823244e3a89c..0d7857d7efefb47b7dcc48b1dfb46e8bc56740d4 100644 --- a/drivers/pinctrl/renesas/pfc-sh7757.c +++ b/drivers/pinctrl/renesas/pfc-sh7757.c @@ -10,7 +10,6 @@ * Copyright (C) 2008 Magnus Damm */ -#include #include #include @@ -1964,43 +1963,35 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { 0, 0, 0, 0, )) }, - { PINMUX_CFG_REG("PSEL1", 0xffec0072, 16, 1, GROUP( - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("PSEL1", 0xffec0072, 16, + GROUP(-5, 1, 1, 1, -5, 1, -2), + GROUP( + /* RESERVED [5] */ PS1_10_FN1, PS1_10_FN2, PS1_9_FN1, PS1_9_FN2, PS1_8_FN1, PS1_8_FN2, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + /* RESERVED [5] */ PS1_2_FN1, PS1_2_FN2, - 0, 0, - 0, 0, )) + /* RESERVED [2] */ )) }, - { PINMUX_CFG_REG("PSEL2", 0xffec0074, 16, 1, GROUP( - 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("PSEL2", 0xffec0074, 16, + GROUP(-2, 1, 1, -4, 1, 1, 1, 1, -1, 1, -2), + GROUP( + /* RESERVED [2] */ PS2_13_FN1, PS2_13_FN2, PS2_12_FN1, PS2_12_FN2, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + /* RESERVED [4] */ PS2_7_FN1, PS2_7_FN2, PS2_6_FN1, PS2_6_FN2, PS2_5_FN1, PS2_5_FN2, PS2_4_FN1, PS2_4_FN2, - 0, 0, + /* RESERVED [1] */ PS2_2_FN1, PS2_2_FN2, - 0, 0, - 0, 0, )) + /* RESERVED [2] */ )) }, - { PINMUX_CFG_REG("PSEL3", 0xffec0076, 16, 1, GROUP( + { PINMUX_CFG_REG_VAR("PSEL3", 0xffec0076, 16, + GROUP(1, 1, 1, 1, 1, 1, 1, 1, 1, -4, 1, 1, -1), + GROUP( PS3_15_FN1, PS3_15_FN2, PS3_14_FN1, PS3_14_FN2, PS3_13_FN1, PS3_13_FN2, @@ -2010,38 +2001,35 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { PS3_9_FN1, PS3_9_FN2, PS3_8_FN1, PS3_8_FN2, PS3_7_FN1, PS3_7_FN2, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + /* RESERVED [4] */ PS3_2_FN1, PS3_2_FN2, PS3_1_FN1, PS3_1_FN2, - 0, 0, )) + /* RESERVED [1] */ )) }, - { PINMUX_CFG_REG("PSEL4", 0xffec0078, 16, 1, GROUP( - 0, 0, + { PINMUX_CFG_REG_VAR("PSEL4", 0xffec0078, 16, + GROUP(-1, 1, 1, 1, -1, 1, 1, 1, -3, 1, 1, 1, + 1, 1), + GROUP( + /* RESERVED [1] */ PS4_14_FN1, PS4_14_FN2, PS4_13_FN1, PS4_13_FN2, PS4_12_FN1, PS4_12_FN2, - 0, 0, + /* RESERVED [1] */ PS4_10_FN1, PS4_10_FN2, PS4_9_FN1, PS4_9_FN2, PS4_8_FN1, PS4_8_FN2, - 0, 0, - 0, 0, - 0, 0, + /* RESERVED [3] */ PS4_4_FN1, PS4_4_FN2, PS4_3_FN1, PS4_3_FN2, PS4_2_FN1, PS4_2_FN2, PS4_1_FN1, PS4_1_FN2, PS4_0_FN1, PS4_0_FN2, )) }, - { PINMUX_CFG_REG("PSEL5", 0xffec007a, 16, 1, GROUP( - 0, 0, - 0, 0, - 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("PSEL5", 0xffec007a, 16, + GROUP(-4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -2), + GROUP( + /* RESERVED [4] */ PS5_11_FN1, PS5_11_FN2, PS5_10_FN1, PS5_10_FN2, PS5_9_FN1, PS5_9_FN2, @@ -2052,8 +2040,7 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { PS5_4_FN1, PS5_4_FN2, PS5_3_FN1, PS5_3_FN2, PS5_2_FN1, PS5_2_FN2, - 0, 0, - 0, 0, )) + /* RESERVED [2] */ )) }, { PINMUX_CFG_REG("PSEL6", 0xffec007c, 16, 1, GROUP( PS6_15_FN1, PS6_15_FN2, @@ -2073,7 +2060,9 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { PS6_1_FN1, PS6_1_FN2, PS6_0_FN1, PS6_0_FN2, )) }, - { PINMUX_CFG_REG("PSEL7", 0xffec0082, 16, 1, GROUP( + { PINMUX_CFG_REG_VAR("PSEL7", 0xffec0082, 16, + GROUP(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -5), + GROUP( PS7_15_FN1, PS7_15_FN2, PS7_14_FN1, PS7_14_FN2, PS7_13_FN1, PS7_13_FN2, @@ -2085,13 +2074,11 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { PS7_7_FN1, PS7_7_FN2, PS7_6_FN1, PS7_6_FN2, PS7_5_FN1, PS7_5_FN2, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, )) + /* RESERVED [5] */ )) }, - { PINMUX_CFG_REG("PSEL8", 0xffec0084, 16, 1, GROUP( + { PINMUX_CFG_REG_VAR("PSEL8", 0xffec0084, 16, + GROUP(1, 1, 1, 1, 1, 1, 1, 1, -8), + GROUP( PS8_15_FN1, PS8_15_FN2, PS8_14_FN1, PS8_14_FN2, PS8_13_FN1, PS8_13_FN2, @@ -2100,14 +2087,7 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { PS8_10_FN1, PS8_10_FN2, PS8_9_FN1, PS8_9_FN2, PS8_8_FN1, PS8_8_FN2, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, )) + /* RESERVED [8] */ )) }, {} }; diff --git a/drivers/pinctrl/renesas/pfc-sh7785.c b/drivers/pinctrl/renesas/pfc-sh7785.c index c4c1e288c53e6a63212a047dd46d6f274319e361..126b663bb6eb3abe6ccab4c5d34b4723e68066fe 100644 --- a/drivers/pinctrl/renesas/pfc-sh7785.c +++ b/drivers/pinctrl/renesas/pfc-sh7785.c @@ -5,7 +5,6 @@ * Copyright (C) 2008 Magnus Damm */ -#include #include #include @@ -1025,9 +1024,10 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { PD1_FN, PD1_OUT, PD1_IN, 0, PD0_FN, PD0_OUT, PD0_IN, 0 )) }, - { PINMUX_CFG_REG("PECR", 0xffe70008, 16, 2, GROUP( - 0, 0, 0, 0, - 0, 0, 0, 0, + { PINMUX_CFG_REG_VAR("PECR", 0xffe70008, 16, + GROUP(-4, 2, 2, 2, 2, 2, 2), + GROUP( + /* RESERVED [4] */ PE5_FN, PE5_OUT, PE5_IN, 0, PE4_FN, PE4_OUT, PE4_IN, 0, PE3_FN, PE3_OUT, PE3_IN, 0, @@ -1095,13 +1095,10 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { PL1_FN, PL1_OUT, PL1_IN, 0, PL0_FN, PL0_OUT, PL0_IN, 0 )) }, - { PINMUX_CFG_REG("PMCR", 0xffe70016, 16, 2, GROUP( - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, + { PINMUX_CFG_REG_VAR("PMCR", 0xffe70016, 16, + GROUP(-12, 2, 2), + GROUP( + /* RESERVED [12] */ PM1_FN, PM1_OUT, PM1_IN, 0, PM0_FN, PM0_OUT, PM0_IN, 0 )) }, @@ -1115,9 +1112,10 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { PN1_FN, PN1_OUT, PN1_IN, 0, PN0_FN, PN0_OUT, PN0_IN, 0 )) }, - { PINMUX_CFG_REG("PPCR", 0xffe7001a, 16, 2, GROUP( - 0, 0, 0, 0, - 0, 0, 0, 0, + { PINMUX_CFG_REG_VAR("PPCR", 0xffe7001a, 16, + GROUP(-4, 2, 2, 2, 2, 2, 2), + GROUP( + /* RESERVED [4] */ PP5_FN, PP5_OUT, PP5_IN, 0, PP4_FN, PP4_OUT, PP4_IN, 0, PP3_FN, PP3_OUT, PP3_IN, 0, @@ -1125,21 +1123,20 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { PP1_FN, PP1_OUT, PP1_IN, 0, PP0_FN, PP0_OUT, PP0_IN, 0 )) }, - { PINMUX_CFG_REG("PQCR", 0xffe7001c, 16, 2, GROUP( - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, + { PINMUX_CFG_REG_VAR("PQCR", 0xffe7001c, 16, + GROUP(-6, 2, 2, 2, 2, 2), + GROUP( + /* RESERVED [6] */ PQ4_FN, PQ4_OUT, PQ4_IN, 0, PQ3_FN, PQ3_OUT, PQ3_IN, 0, PQ2_FN, PQ2_OUT, PQ2_IN, 0, PQ1_FN, PQ1_OUT, PQ1_IN, 0, PQ0_FN, PQ0_OUT, PQ0_IN, 0 )) }, - { PINMUX_CFG_REG("PRCR", 0xffe7001e, 16, 2, GROUP( - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, + { PINMUX_CFG_REG_VAR("PRCR", 0xffe7001e, 16, + GROUP(-8, 2, 2, 2, 2), + GROUP( + /* RESERVED [8] */ PR3_FN, PR3_OUT, PR3_IN, 0, PR2_FN, PR2_OUT, PR2_IN, 0, PR1_FN, PR1_OUT, PR1_IN, 0, @@ -1163,20 +1160,10 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { P1MSEL1_0, P1MSEL1_1, P1MSEL0_0, P1MSEL0_1 )) }, - { PINMUX_CFG_REG("P2MSELR", 0xffe70082, 16, 1, GROUP( - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, + { PINMUX_CFG_REG_VAR("P2MSELR", 0xffe70082, 16, + GROUP(-13, 1, 1, 1), + GROUP( + /* RESERVED [13] */ P2MSEL2_0, P2MSEL2_1, P2MSEL1_0, P2MSEL1_1, P2MSEL0_0, P2MSEL0_1 )) diff --git a/drivers/pinctrl/renesas/pfc-sh7786.c b/drivers/pinctrl/renesas/pfc-sh7786.c index b8a098cd7721872885a0d4f985c83e43802bf4e9..f09f4a76901088b4c42fd46162717d662feeee6e 100644 --- a/drivers/pinctrl/renesas/pfc-sh7786.c +++ b/drivers/pinctrl/renesas/pfc-sh7786.c @@ -10,7 +10,6 @@ * Copyright (C) 2008 Magnus Damm */ -#include #include #include @@ -667,15 +666,12 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { PD1_FN, PD1_OUT, PD1_IN, 0, PD0_FN, PD0_OUT, PD0_IN, 0 )) }, - { PINMUX_CFG_REG("PECR", 0xffcc0008, 16, 2, GROUP( + { PINMUX_CFG_REG_VAR("PECR", 0xffcc0008, 16, + GROUP(2, 2, -12), + GROUP( PE7_FN, PE7_OUT, PE7_IN, 0, PE6_FN, PE6_OUT, PE6_IN, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, )) + /* RESERVED [12] */ )) }, { PINMUX_CFG_REG("PFCR", 0xffcc000a, 16, 2, GROUP( PF7_FN, PF7_OUT, PF7_IN, 0, @@ -687,15 +683,13 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { PF1_FN, PF1_OUT, PF1_IN, 0, PF0_FN, PF0_OUT, PF0_IN, 0 )) }, - { PINMUX_CFG_REG("PGCR", 0xffcc000c, 16, 2, GROUP( + { PINMUX_CFG_REG_VAR("PGCR", 0xffcc000c, 16, + GROUP(2, 2, 2, -10), + GROUP( PG7_FN, PG7_OUT, PG7_IN, 0, PG6_FN, PG6_OUT, PG6_IN, 0, PG5_FN, PG5_OUT, PG5_IN, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, )) + /* RESERVED [10] */ )) }, { PINMUX_CFG_REG("PHCR", 0xffcc000e, 16, 2, GROUP( PH7_FN, PH7_OUT, PH7_IN, 0, diff --git a/drivers/pinctrl/renesas/pfc-shx3.c b/drivers/pinctrl/renesas/pfc-shx3.c index 22e812850964e795ba0d0915077c675fb3abfbcb..96a65d83774f16a7d845c2c0594a288b9f7df2a5 100644 --- a/drivers/pinctrl/renesas/pfc-shx3.c +++ b/drivers/pinctrl/renesas/pfc-shx3.c @@ -4,7 +4,6 @@ * * Copyright (C) 2010 Paul Mundt */ -#include #include #include diff --git a/drivers/pinctrl/renesas/pinctrl-rzg2l.c b/drivers/pinctrl/renesas/pinctrl-rzg2l.c index cb805502fb0f5ea7722a9f3b4eb299fa638419bd..a48cac55152cefa37b26803d28a9084716bdeb47 100644 --- a/drivers/pinctrl/renesas/pinctrl-rzg2l.c +++ b/drivers/pinctrl/renesas/pinctrl-rzg2l.c @@ -996,83 +996,112 @@ static const u32 rzg2l_gpio_configs[] = { RZG2L_GPIO_PORT_PACK(5, 0x40, RZG2L_MPXED_PIN_FUNCS), }; -static struct rzg2l_dedicated_configs rzg2l_dedicated_pins[] = { - { "NMI", RZG2L_SINGLE_PIN_PACK(0x1, 0, - (PIN_CFG_FILONOFF | PIN_CFG_FILNUM | PIN_CFG_FILCLKSEL)) }, - { "TMS/SWDIO", RZG2L_SINGLE_PIN_PACK(0x2, 0, - (PIN_CFG_SR | PIN_CFG_IOLH_A | PIN_CFG_IEN)) }, - { "TDO", RZG2L_SINGLE_PIN_PACK(0x3, 0, - (PIN_CFG_IOLH_A | PIN_CFG_SR | PIN_CFG_IEN)) }, - { "AUDIO_CLK1", RZG2L_SINGLE_PIN_PACK(0x4, 0, PIN_CFG_IEN) }, - { "AUDIO_CLK2", RZG2L_SINGLE_PIN_PACK(0x4, 1, PIN_CFG_IEN) }, - { "SD0_CLK", RZG2L_SINGLE_PIN_PACK(0x6, 0, - (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_SD0)) }, - { "SD0_CMD", RZG2L_SINGLE_PIN_PACK(0x6, 1, - (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD0)) }, - { "SD0_RST#", RZG2L_SINGLE_PIN_PACK(0x6, 2, - (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_SD0)) }, - { "SD0_DATA0", RZG2L_SINGLE_PIN_PACK(0x7, 0, - (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD0)) }, - { "SD0_DATA1", RZG2L_SINGLE_PIN_PACK(0x7, 1, - (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD0)) }, - { "SD0_DATA2", RZG2L_SINGLE_PIN_PACK(0x7, 2, - (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD0)) }, - { "SD0_DATA3", RZG2L_SINGLE_PIN_PACK(0x7, 3, - (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD0)) }, - { "SD0_DATA4", RZG2L_SINGLE_PIN_PACK(0x7, 4, - (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD0)) }, - { "SD0_DATA5", RZG2L_SINGLE_PIN_PACK(0x7, 5, - (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD0)) }, - { "SD0_DATA6", RZG2L_SINGLE_PIN_PACK(0x7, 6, - (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD0)) }, - { "SD0_DATA7", RZG2L_SINGLE_PIN_PACK(0x7, 7, - (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD0)) }, - { "SD1_CLK", RZG2L_SINGLE_PIN_PACK(0x8, 0, - (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_SD1)) }, - { "SD1_CMD", RZG2L_SINGLE_PIN_PACK(0x8, 1, - (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD1)) }, - { "SD1_DATA0", RZG2L_SINGLE_PIN_PACK(0x9, 0, - (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD1)) }, - { "SD1_DATA1", RZG2L_SINGLE_PIN_PACK(0x9, 1, - (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD1)) }, - { "SD1_DATA2", RZG2L_SINGLE_PIN_PACK(0x9, 2, - (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD1)) }, - { "SD1_DATA3", RZG2L_SINGLE_PIN_PACK(0x9, 3, - (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD1)) }, - { "QSPI0_SPCLK", RZG2L_SINGLE_PIN_PACK(0xa, 0, - (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) }, - { "QSPI0_IO0", RZG2L_SINGLE_PIN_PACK(0xa, 1, - (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) }, - { "QSPI0_IO1", RZG2L_SINGLE_PIN_PACK(0xa, 2, - (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) }, - { "QSPI0_IO2", RZG2L_SINGLE_PIN_PACK(0xa, 3, - (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) }, - { "QSPI0_IO3", RZG2L_SINGLE_PIN_PACK(0xa, 4, - (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) }, - { "QSPI0_SSL", RZG2L_SINGLE_PIN_PACK(0xa, 5, - (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) }, - { "QSPI1_SPCLK", RZG2L_SINGLE_PIN_PACK(0xb, 0, - (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) }, - { "QSPI1_IO0", RZG2L_SINGLE_PIN_PACK(0xb, 1, - (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) }, - { "QSPI1_IO1", RZG2L_SINGLE_PIN_PACK(0xb, 2, - (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) }, - { "QSPI1_IO2", RZG2L_SINGLE_PIN_PACK(0xb, 3, - (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) }, - { "QSPI1_IO3", RZG2L_SINGLE_PIN_PACK(0xb, 4, - (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) }, - { "QSPI1_SSL", RZG2L_SINGLE_PIN_PACK(0xb, 5, - (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) }, - { "QSPI_RESET#", RZG2L_SINGLE_PIN_PACK(0xc, 0, - (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) }, - { "QSPI_WP#", RZG2L_SINGLE_PIN_PACK(0xc, 1, - (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) }, - { "QSPI_INT#", RZG2L_SINGLE_PIN_PACK(0xc, 2, (PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) }, - { "WDTOVF_PERROUT#", RZG2L_SINGLE_PIN_PACK(0xd, 0, (PIN_CFG_IOLH_A | PIN_CFG_SR)) }, - { "RIIC0_SDA", RZG2L_SINGLE_PIN_PACK(0xe, 0, PIN_CFG_IEN) }, - { "RIIC0_SCL", RZG2L_SINGLE_PIN_PACK(0xe, 1, PIN_CFG_IEN) }, - { "RIIC1_SDA", RZG2L_SINGLE_PIN_PACK(0xe, 2, PIN_CFG_IEN) }, - { "RIIC1_SCL", RZG2L_SINGLE_PIN_PACK(0xe, 3, PIN_CFG_IEN) }, +static const u32 r9a07g043_gpio_configs[] = { + RZG2L_GPIO_PORT_PACK(4, 0x10, RZG2L_MPXED_PIN_FUNCS), + RZG2L_GPIO_PORT_PACK(5, 0x11, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH0)), + RZG2L_GPIO_PORT_PACK(4, 0x12, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH0)), + RZG2L_GPIO_PORT_PACK(4, 0x13, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH0)), + RZG2L_GPIO_PORT_PACK(6, 0x14, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH0)), + RZG2L_GPIO_PORT_PACK(5, 0x15, RZG2L_MPXED_PIN_FUNCS), + RZG2L_GPIO_PORT_PACK(5, 0x16, RZG2L_MPXED_PIN_FUNCS), + RZG2L_GPIO_PORT_PACK(5, 0x17, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH1)), + RZG2L_GPIO_PORT_PACK(5, 0x18, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH1)), + RZG2L_GPIO_PORT_PACK(4, 0x19, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH1)), + RZG2L_GPIO_PORT_PACK(5, 0x1a, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH1)), + RZG2L_GPIO_PORT_PACK(4, 0x1b, RZG2L_MPXED_PIN_FUNCS), + RZG2L_GPIO_PORT_PACK(2, 0x1c, RZG2L_MPXED_PIN_FUNCS), + RZG2L_GPIO_PORT_PACK(5, 0x1d, RZG2L_MPXED_PIN_FUNCS), + RZG2L_GPIO_PORT_PACK(3, 0x1e, RZG2L_MPXED_PIN_FUNCS), + RZG2L_GPIO_PORT_PACK(4, 0x1f, RZG2L_MPXED_PIN_FUNCS), + RZG2L_GPIO_PORT_PACK(2, 0x20, RZG2L_MPXED_PIN_FUNCS), + RZG2L_GPIO_PORT_PACK(4, 0x21, RZG2L_MPXED_PIN_FUNCS), + RZG2L_GPIO_PORT_PACK(6, 0x22, RZG2L_MPXED_PIN_FUNCS), +}; + +static struct { + struct rzg2l_dedicated_configs common[35]; + struct rzg2l_dedicated_configs rzg2l_pins[7]; +} rzg2l_dedicated_pins = { + .common = { + { "NMI", RZG2L_SINGLE_PIN_PACK(0x1, 0, + (PIN_CFG_FILONOFF | PIN_CFG_FILNUM | PIN_CFG_FILCLKSEL)) }, + { "TMS/SWDIO", RZG2L_SINGLE_PIN_PACK(0x2, 0, + (PIN_CFG_IOLH_A | PIN_CFG_SR | PIN_CFG_IEN)) }, + { "TDO", RZG2L_SINGLE_PIN_PACK(0x3, 0, + (PIN_CFG_IOLH_A | PIN_CFG_SR | PIN_CFG_IEN)) }, + { "AUDIO_CLK1", RZG2L_SINGLE_PIN_PACK(0x4, 0, PIN_CFG_IEN) }, + { "AUDIO_CLK2", RZG2L_SINGLE_PIN_PACK(0x4, 1, PIN_CFG_IEN) }, + { "SD0_CLK", RZG2L_SINGLE_PIN_PACK(0x6, 0, + (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_SD0)) }, + { "SD0_CMD", RZG2L_SINGLE_PIN_PACK(0x6, 1, + (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD0)) }, + { "SD0_RST#", RZG2L_SINGLE_PIN_PACK(0x6, 2, + (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_SD0)) }, + { "SD0_DATA0", RZG2L_SINGLE_PIN_PACK(0x7, 0, + (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD0)) }, + { "SD0_DATA1", RZG2L_SINGLE_PIN_PACK(0x7, 1, + (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD0)) }, + { "SD0_DATA2", RZG2L_SINGLE_PIN_PACK(0x7, 2, + (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD0)) }, + { "SD0_DATA3", RZG2L_SINGLE_PIN_PACK(0x7, 3, + (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD0)) }, + { "SD0_DATA4", RZG2L_SINGLE_PIN_PACK(0x7, 4, + (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD0)) }, + { "SD0_DATA5", RZG2L_SINGLE_PIN_PACK(0x7, 5, + (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD0)) }, + { "SD0_DATA6", RZG2L_SINGLE_PIN_PACK(0x7, 6, + (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD0)) }, + { "SD0_DATA7", RZG2L_SINGLE_PIN_PACK(0x7, 7, + (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD0)) }, + { "SD1_CLK", RZG2L_SINGLE_PIN_PACK(0x8, 0, + (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_SD1)) }, + { "SD1_CMD", RZG2L_SINGLE_PIN_PACK(0x8, 1, + (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD1)) }, + { "SD1_DATA0", RZG2L_SINGLE_PIN_PACK(0x9, 0, + (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD1)) }, + { "SD1_DATA1", RZG2L_SINGLE_PIN_PACK(0x9, 1, + (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD1)) }, + { "SD1_DATA2", RZG2L_SINGLE_PIN_PACK(0x9, 2, + (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD1)) }, + { "SD1_DATA3", RZG2L_SINGLE_PIN_PACK(0x9, 3, + (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD1)) }, + { "QSPI0_SPCLK", RZG2L_SINGLE_PIN_PACK(0xa, 0, + (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) }, + { "QSPI0_IO0", RZG2L_SINGLE_PIN_PACK(0xa, 1, + (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) }, + { "QSPI0_IO1", RZG2L_SINGLE_PIN_PACK(0xa, 2, + (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) }, + { "QSPI0_IO2", RZG2L_SINGLE_PIN_PACK(0xa, 3, + (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) }, + { "QSPI0_IO3", RZG2L_SINGLE_PIN_PACK(0xa, 4, + (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) }, + { "QSPI0_SSL", RZG2L_SINGLE_PIN_PACK(0xa, 5, + (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) }, + { "QSPI_RESET#", RZG2L_SINGLE_PIN_PACK(0xc, 0, + (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) }, + { "QSPI_WP#", RZG2L_SINGLE_PIN_PACK(0xc, 1, + (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) }, + { "WDTOVF_PERROUT#", RZG2L_SINGLE_PIN_PACK(0xd, 0, (PIN_CFG_IOLH_A | PIN_CFG_SR)) }, + { "RIIC0_SDA", RZG2L_SINGLE_PIN_PACK(0xe, 0, PIN_CFG_IEN) }, + { "RIIC0_SCL", RZG2L_SINGLE_PIN_PACK(0xe, 1, PIN_CFG_IEN) }, + { "RIIC1_SDA", RZG2L_SINGLE_PIN_PACK(0xe, 2, PIN_CFG_IEN) }, + { "RIIC1_SCL", RZG2L_SINGLE_PIN_PACK(0xe, 3, PIN_CFG_IEN) }, + }, + .rzg2l_pins = { + { "QSPI_INT#", RZG2L_SINGLE_PIN_PACK(0xc, 2, (PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) }, + { "QSPI1_SPCLK", RZG2L_SINGLE_PIN_PACK(0xb, 0, + (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) }, + { "QSPI1_IO0", RZG2L_SINGLE_PIN_PACK(0xb, 1, + (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) }, + { "QSPI1_IO1", RZG2L_SINGLE_PIN_PACK(0xb, 2, + (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) }, + { "QSPI1_IO2", RZG2L_SINGLE_PIN_PACK(0xb, 3, + (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) }, + { "QSPI1_IO3", RZG2L_SINGLE_PIN_PACK(0xb, 4, + (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) }, + { "QSPI1_SSL", RZG2L_SINGLE_PIN_PACK(0xb, 5, + (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) }, + } }; static int rzg2l_gpio_register(struct rzg2l_pinctrl *pctrl) @@ -1250,15 +1279,28 @@ static int rzg2l_pinctrl_probe(struct platform_device *pdev) return 0; } +static struct rzg2l_pinctrl_data r9a07g043_data = { + .port_pins = rzg2l_gpio_names, + .port_pin_configs = r9a07g043_gpio_configs, + .dedicated_pins = rzg2l_dedicated_pins.common, + .n_port_pins = ARRAY_SIZE(r9a07g043_gpio_configs) * RZG2L_PINS_PER_PORT, + .n_dedicated_pins = ARRAY_SIZE(rzg2l_dedicated_pins.common), +}; + static struct rzg2l_pinctrl_data r9a07g044_data = { .port_pins = rzg2l_gpio_names, .port_pin_configs = rzg2l_gpio_configs, - .dedicated_pins = rzg2l_dedicated_pins, + .dedicated_pins = rzg2l_dedicated_pins.common, .n_port_pins = ARRAY_SIZE(rzg2l_gpio_names), - .n_dedicated_pins = ARRAY_SIZE(rzg2l_dedicated_pins), + .n_dedicated_pins = ARRAY_SIZE(rzg2l_dedicated_pins.common) + + ARRAY_SIZE(rzg2l_dedicated_pins.rzg2l_pins), }; static const struct of_device_id rzg2l_pinctrl_of_table[] = { + { + .compatible = "renesas,r9a07g043-pinctrl", + .data = &r9a07g043_data, + }, { .compatible = "renesas,r9a07g044-pinctrl", .data = &r9a07g044_data, diff --git a/drivers/pinctrl/renesas/pinctrl-rzn1.c b/drivers/pinctrl/renesas/pinctrl-rzn1.c index ef5fb25b6016dd3136cf1ea38fa9b1edbcf6ccff..849d091205d4d545509a22ab03bef0db4434209e 100644 --- a/drivers/pinctrl/renesas/pinctrl-rzn1.c +++ b/drivers/pinctrl/renesas/pinctrl-rzn1.c @@ -865,17 +865,15 @@ static int rzn1_pinctrl_probe(struct platform_device *pdev) ipctl->mdio_func[0] = -1; ipctl->mdio_func[1] = -1; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - ipctl->lev1_protect_phys = (u32)res->start + 0x400; - ipctl->lev1 = devm_ioremap_resource(&pdev->dev, res); + ipctl->lev1 = devm_platform_get_and_ioremap_resource(pdev, 0, &res); if (IS_ERR(ipctl->lev1)) return PTR_ERR(ipctl->lev1); + ipctl->lev1_protect_phys = (u32)res->start + 0x400; - res = platform_get_resource(pdev, IORESOURCE_MEM, 1); - ipctl->lev2_protect_phys = (u32)res->start + 0x400; - ipctl->lev2 = devm_ioremap_resource(&pdev->dev, res); + ipctl->lev2 = devm_platform_get_and_ioremap_resource(pdev, 1, &res); if (IS_ERR(ipctl->lev2)) return PTR_ERR(ipctl->lev2); + ipctl->lev2_protect_phys = (u32)res->start + 0x400; ipctl->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(ipctl->clk)) diff --git a/drivers/pinctrl/renesas/pinctrl.c b/drivers/pinctrl/renesas/pinctrl.c index 4c37aebc75b82e1f8c7271ba88c2168c1a0acae9..b438d24c13b5c9110d7ad772e485cc16acccffc0 100644 --- a/drivers/pinctrl/renesas/pinctrl.c +++ b/drivers/pinctrl/renesas/pinctrl.c @@ -9,7 +9,6 @@ #include #include -#include #include #include #include diff --git a/drivers/pinctrl/renesas/sh_pfc.h b/drivers/pinctrl/renesas/sh_pfc.h index 6b5836ea47de224cf7544181ff117b6ad09db59e..12bc279f573311d558ce639e8887acc99206d2a1 100644 --- a/drivers/pinctrl/renesas/sh_pfc.h +++ b/drivers/pinctrl/renesas/sh_pfc.h @@ -112,7 +112,7 @@ struct pinmux_cfg_reg { #define SET_NR_ENUM_IDS(n) #endif const u16 *enum_ids; - const u8 *var_field_width; + const s8 *var_field_width; }; #define GROUP(...) __VA_ARGS__ @@ -132,9 +132,8 @@ struct pinmux_cfg_reg { .reg = r, .reg_width = r_width, \ .field_width = f_width + BUILD_BUG_ON_ZERO(r_width % f_width) + \ BUILD_BUG_ON_ZERO(sizeof((const u16 []) { ids }) / sizeof(u16) != \ - (r_width / f_width) * (1 << f_width)), \ - .enum_ids = (const u16 [(r_width / f_width) * (1 << f_width)]) \ - { ids } + (r_width / f_width) << f_width), \ + .enum_ids = (const u16 [(r_width / f_width) << f_width]) { ids } /* * Describe a config register consisting of several fields of different widths @@ -143,14 +142,15 @@ struct pinmux_cfg_reg { * - r_width: Width of the register (in bits) * - f_widths: List of widths of the register fields (in bits), from left * to right (i.e. MSB to LSB), wrapped using the GROUP() macro. - * - ids: For each register field (from left to right, i.e. MSB to LSB), - * 2^f_widths[i] enum IDs must be specified, one for each possible - * combination of the register field bit values, all wrapped using - * the GROUP() macro. + * Reserved fields are indicated by negating the field width. + * - ids: For each non-reserved register field (from left to right, i.e. MSB + * to LSB), 2^f_widths[i] enum IDs must be specified, one for each + * possible combination of the register field bit values, all wrapped + * using the GROUP() macro. */ #define PINMUX_CFG_REG_VAR(name, r, r_width, f_widths, ids) \ .reg = r, .reg_width = r_width, \ - .var_field_width = (const u8 []) { f_widths, 0 }, \ + .var_field_width = (const s8 []) { f_widths, 0 }, \ SET_NR_ENUM_IDS(sizeof((const u16 []) { ids }) / sizeof(u16)) \ .enum_ids = (const u16 []) { ids } @@ -162,7 +162,7 @@ struct pinmux_drive_reg_field { struct pinmux_drive_reg { u32 reg; - const struct pinmux_drive_reg_field fields[8]; + const struct pinmux_drive_reg_field fields[10]; }; #define PINMUX_DRIVE_REG(name, r) \ @@ -739,14 +739,12 @@ extern const struct sh_pfc_soc_info shx3_pinmux_info; * PORTnCR helper macro for SH-Mobile/R-Mobile */ #define PORTCR(nr, reg) { \ - PINMUX_CFG_REG_VAR("PORT" nr "CR", reg, 8, GROUP(2, 2, 1, 3), \ + PINMUX_CFG_REG_VAR("PORT" nr "CR", reg, 8, GROUP(-2, 2, -1, 3), \ GROUP( \ /* PULMD[1:0], handled by .set_bias() */ \ - 0, 0, 0, 0, \ /* IE and OE */ \ 0, PORT##nr##_OUT, PORT##nr##_IN, 0, \ /* SEC, not supported */ \ - 0, 0, \ /* PTMD[2:0] */ \ PORT##nr##_FN0, PORT##nr##_FN1, \ PORT##nr##_FN2, PORT##nr##_FN3, \ diff --git a/drivers/pinctrl/stm32/pinctrl-stm32.c b/drivers/pinctrl/stm32/pinctrl-stm32.c index 7aecd0efde075ede49a9efa75a2b2578507ba1fb..57a33fb0f2d7d6955dcf812f4ba9cf9a932825db 100644 --- a/drivers/pinctrl/stm32/pinctrl-stm32.c +++ b/drivers/pinctrl/stm32/pinctrl-stm32.c @@ -44,6 +44,7 @@ #define STM32_GPIO_LCKR 0x1c #define STM32_GPIO_AFRL 0x20 #define STM32_GPIO_AFRH 0x24 +#define STM32_GPIO_SECCFGR 0x30 /* custom bitfield to backup pin status */ #define STM32_GPIO_BKP_MODE_SHIFT 0 @@ -95,6 +96,7 @@ struct stm32_gpio_bank { u32 bank_ioport_nr; u32 pin_backup[STM32_GPIO_PINS_PER_BANK]; u8 irq_type[STM32_GPIO_PINS_PER_BANK]; + bool secure_control; }; struct stm32_pinctrl { @@ -198,11 +200,7 @@ static inline void __stm32_gpio_set(struct stm32_gpio_bank *bank, if (!value) offset += STM32_GPIO_PINS_PER_BANK; - clk_enable(bank->clk); - writel_relaxed(BIT(offset), bank->base + STM32_GPIO_BSRR); - - clk_disable(bank->clk); } static int stm32_gpio_request(struct gpio_chip *chip, unsigned offset) @@ -226,25 +224,11 @@ static void stm32_gpio_free(struct gpio_chip *chip, unsigned offset) pinctrl_gpio_free(chip->base + offset); } -static int stm32_gpio_get_noclk(struct gpio_chip *chip, unsigned int offset) -{ - struct stm32_gpio_bank *bank = gpiochip_get_data(chip); - - return !!(readl_relaxed(bank->base + STM32_GPIO_IDR) & BIT(offset)); -} - static int stm32_gpio_get(struct gpio_chip *chip, unsigned offset) { struct stm32_gpio_bank *bank = gpiochip_get_data(chip); - int ret; - - clk_enable(bank->clk); - - ret = stm32_gpio_get_noclk(chip, offset); - clk_disable(bank->clk); - - return ret; + return !!(readl_relaxed(bank->base + STM32_GPIO_IDR) & BIT(offset)); } static void stm32_gpio_set(struct gpio_chip *chip, unsigned offset, int value) @@ -302,6 +286,33 @@ static int stm32_gpio_get_direction(struct gpio_chip *chip, unsigned int offset) return ret; } +static int stm32_gpio_init_valid_mask(struct gpio_chip *chip, + unsigned long *valid_mask, + unsigned int ngpios) +{ + struct stm32_gpio_bank *bank = gpiochip_get_data(chip); + struct stm32_pinctrl *pctl = dev_get_drvdata(bank->gpio_chip.parent); + unsigned int i; + u32 sec; + + /* All gpio are valid per default */ + bitmap_fill(valid_mask, ngpios); + + if (bank->secure_control) { + /* Tag secured pins as invalid */ + sec = readl_relaxed(bank->base + STM32_GPIO_SECCFGR); + + for (i = 0; i < ngpios; i++) { + if (sec & BIT(i)) { + clear_bit(i, valid_mask); + dev_dbg(pctl->dev, "No access to gpio %d - %d\n", bank->bank_nr, i); + } + } + } + + return 0; +} + static const struct gpio_chip stm32_gpio_template = { .request = stm32_gpio_request, .free = stm32_gpio_free, @@ -312,6 +323,7 @@ static const struct gpio_chip stm32_gpio_template = { .to_irq = stm32_gpio_to_irq, .get_direction = stm32_gpio_get_direction, .set_config = gpiochip_generic_config, + .init_valid_mask = stm32_gpio_init_valid_mask, }; static void stm32_gpio_irq_trigger(struct irq_data *d) @@ -324,7 +336,7 @@ static void stm32_gpio_irq_trigger(struct irq_data *d) return; /* If level interrupt type then retrig */ - level = stm32_gpio_get_noclk(&bank->gpio_chip, d->hwirq); + level = stm32_gpio_get(&bank->gpio_chip, d->hwirq); if ((level == 0 && bank->irq_type[d->hwirq] == IRQ_TYPE_LEVEL_LOW) || (level == 1 && bank->irq_type[d->hwirq] == IRQ_TYPE_LEVEL_HIGH)) irq_chip_retrigger_hierarchy(d); @@ -366,7 +378,6 @@ static int stm32_gpio_irq_request_resources(struct irq_data *irq_data) { struct stm32_gpio_bank *bank = irq_data->domain->host_data; struct stm32_pinctrl *pctl = dev_get_drvdata(bank->gpio_chip.parent); - unsigned long flags; int ret; ret = stm32_gpio_direction_input(&bank->gpio_chip, irq_data->hwirq); @@ -380,10 +391,6 @@ static int stm32_gpio_irq_request_resources(struct irq_data *irq_data) return ret; } - flags = irqd_get_trigger_type(irq_data); - if (flags & IRQ_TYPE_LEVEL_MASK) - clk_enable(bank->clk); - return 0; } @@ -391,9 +398,6 @@ static void stm32_gpio_irq_release_resources(struct irq_data *irq_data) { struct stm32_gpio_bank *bank = irq_data->domain->host_data; - if (bank->irq_type[irq_data->hwirq] & IRQ_TYPE_LEVEL_MASK) - clk_disable(bank->clk); - gpiochip_unlock_as_irq(&bank->gpio_chip, irq_data->hwirq); } @@ -534,7 +538,7 @@ stm32_pctrl_find_group_by_pin(struct stm32_pinctrl *pctl, u32 pin) static bool stm32_pctrl_is_function_valid(struct stm32_pinctrl *pctl, u32 pin_num, u32 fnum) { - int i; + int i, k; for (i = 0; i < pctl->npins; i++) { const struct stm32_desc_pin *pin = pctl->pins + i; @@ -543,7 +547,7 @@ static bool stm32_pctrl_is_function_valid(struct stm32_pinctrl *pctl, if (pin->pin.number != pin_num) continue; - while (func && func->name) { + for (k = 0; k < STM32_CONFIG_NUM; k++) { if (func->num == fnum) return true; func++; @@ -770,7 +774,6 @@ static int stm32_pmx_set_mode(struct stm32_gpio_bank *bank, unsigned long flags; int err = 0; - clk_enable(bank->clk); spin_lock_irqsave(&bank->lock, flags); if (pctl->hwlock) { @@ -799,7 +802,6 @@ static int stm32_pmx_set_mode(struct stm32_gpio_bank *bank, unlock: spin_unlock_irqrestore(&bank->lock, flags); - clk_disable(bank->clk); return err; } @@ -812,7 +814,6 @@ void stm32_pmx_get_mode(struct stm32_gpio_bank *bank, int pin, u32 *mode, int alt_offset = STM32_GPIO_AFRL + (pin / 8) * 4; unsigned long flags; - clk_enable(bank->clk); spin_lock_irqsave(&bank->lock, flags); val = readl_relaxed(bank->base + alt_offset); @@ -824,7 +825,6 @@ void stm32_pmx_get_mode(struct stm32_gpio_bank *bank, int pin, u32 *mode, *mode = val >> (pin * 2); spin_unlock_irqrestore(&bank->lock, flags); - clk_disable(bank->clk); } static int stm32_pmx_set_mux(struct pinctrl_dev *pctldev, @@ -868,12 +868,32 @@ static int stm32_pmx_gpio_set_direction(struct pinctrl_dev *pctldev, return stm32_pmx_set_mode(bank, pin, !input, 0); } +static int stm32_pmx_request(struct pinctrl_dev *pctldev, unsigned int gpio) +{ + struct stm32_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); + struct pinctrl_gpio_range *range; + + range = pinctrl_find_gpio_range_from_pin_nolock(pctldev, gpio); + if (!range) { + dev_err(pctl->dev, "No gpio range defined.\n"); + return -EINVAL; + } + + if (!gpiochip_line_is_valid(range->gc, stm32_gpio_pin(gpio))) { + dev_warn(pctl->dev, "Can't access gpio %d\n", gpio); + return -EACCES; + } + + return 0; +} + static const struct pinmux_ops stm32_pmx_ops = { .get_functions_count = stm32_pmx_get_funcs_cnt, .get_function_name = stm32_pmx_get_func_name, .get_function_groups = stm32_pmx_get_func_groups, .set_mux = stm32_pmx_set_mux, .gpio_set_direction = stm32_pmx_gpio_set_direction, + .request = stm32_pmx_request, .strict = true, }; @@ -887,7 +907,6 @@ static int stm32_pconf_set_driving(struct stm32_gpio_bank *bank, u32 val; int err = 0; - clk_enable(bank->clk); spin_lock_irqsave(&bank->lock, flags); if (pctl->hwlock) { @@ -911,7 +930,6 @@ static int stm32_pconf_set_driving(struct stm32_gpio_bank *bank, unlock: spin_unlock_irqrestore(&bank->lock, flags); - clk_disable(bank->clk); return err; } @@ -922,14 +940,12 @@ static u32 stm32_pconf_get_driving(struct stm32_gpio_bank *bank, unsigned long flags; u32 val; - clk_enable(bank->clk); spin_lock_irqsave(&bank->lock, flags); val = readl_relaxed(bank->base + STM32_GPIO_TYPER); val &= BIT(offset); spin_unlock_irqrestore(&bank->lock, flags); - clk_disable(bank->clk); return (val >> offset); } @@ -942,7 +958,6 @@ static int stm32_pconf_set_speed(struct stm32_gpio_bank *bank, u32 val; int err = 0; - clk_enable(bank->clk); spin_lock_irqsave(&bank->lock, flags); if (pctl->hwlock) { @@ -966,7 +981,6 @@ static int stm32_pconf_set_speed(struct stm32_gpio_bank *bank, unlock: spin_unlock_irqrestore(&bank->lock, flags); - clk_disable(bank->clk); return err; } @@ -977,14 +991,12 @@ static u32 stm32_pconf_get_speed(struct stm32_gpio_bank *bank, unsigned long flags; u32 val; - clk_enable(bank->clk); spin_lock_irqsave(&bank->lock, flags); val = readl_relaxed(bank->base + STM32_GPIO_SPEEDR); val &= GENMASK(offset * 2 + 1, offset * 2); spin_unlock_irqrestore(&bank->lock, flags); - clk_disable(bank->clk); return (val >> (offset * 2)); } @@ -997,7 +1009,6 @@ static int stm32_pconf_set_bias(struct stm32_gpio_bank *bank, u32 val; int err = 0; - clk_enable(bank->clk); spin_lock_irqsave(&bank->lock, flags); if (pctl->hwlock) { @@ -1021,7 +1032,6 @@ static int stm32_pconf_set_bias(struct stm32_gpio_bank *bank, unlock: spin_unlock_irqrestore(&bank->lock, flags); - clk_disable(bank->clk); return err; } @@ -1032,14 +1042,12 @@ static u32 stm32_pconf_get_bias(struct stm32_gpio_bank *bank, unsigned long flags; u32 val; - clk_enable(bank->clk); spin_lock_irqsave(&bank->lock, flags); val = readl_relaxed(bank->base + STM32_GPIO_PUPDR); val &= GENMASK(offset * 2 + 1, offset * 2); spin_unlock_irqrestore(&bank->lock, flags); - clk_disable(bank->clk); return (val >> (offset * 2)); } @@ -1050,7 +1058,6 @@ static bool stm32_pconf_get(struct stm32_gpio_bank *bank, unsigned long flags; u32 val; - clk_enable(bank->clk); spin_lock_irqsave(&bank->lock, flags); if (dir) @@ -1061,7 +1068,6 @@ static bool stm32_pconf_get(struct stm32_gpio_bank *bank, BIT(offset)); spin_unlock_irqrestore(&bank->lock, flags); - clk_disable(bank->clk); return val; } @@ -1084,6 +1090,11 @@ static int stm32_pconf_parse_conf(struct pinctrl_dev *pctldev, bank = gpiochip_get_data(range->gc); offset = stm32_gpio_pin(pin); + if (!gpiochip_line_is_valid(range->gc, offset)) { + dev_warn(pctl->dev, "Can't access gpio %d\n", pin); + return -EACCES; + } + switch (param) { case PIN_CONFIG_DRIVE_PUSH_PULL: ret = stm32_pconf_set_driving(bank, offset, 0); @@ -1163,10 +1174,27 @@ static int stm32_pconf_set(struct pinctrl_dev *pctldev, unsigned int pin, return 0; } +static struct stm32_desc_pin * +stm32_pconf_get_pin_desc_by_pin_number(struct stm32_pinctrl *pctl, + unsigned int pin_number) +{ + struct stm32_desc_pin *pins = pctl->pins; + int i; + + for (i = 0; i < pctl->npins; i++) { + if (pins->pin.number == pin_number) + return pins; + pins++; + } + return NULL; +} + static void stm32_pconf_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s, unsigned int pin) { + struct stm32_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); + const struct stm32_desc_pin *pin_desc; struct pinctrl_gpio_range *range; struct stm32_gpio_bank *bank; int offset; @@ -1186,6 +1214,11 @@ static void stm32_pconf_dbg_show(struct pinctrl_dev *pctldev, bank = gpiochip_get_data(range->gc); offset = stm32_gpio_pin(pin); + if (!gpiochip_line_is_valid(range->gc, offset)) { + seq_puts(s, "NO ACCESS"); + return; + } + stm32_pmx_get_mode(bank, offset, &mode, &alt); bias = stm32_pconf_get_bias(bank, offset); @@ -1216,7 +1249,12 @@ static void stm32_pconf_dbg_show(struct pinctrl_dev *pctldev, case 2: drive = stm32_pconf_get_driving(bank, offset); speed = stm32_pconf_get_speed(bank, offset); - seq_printf(s, "%d - %s - %s - %s %s", alt, + pin_desc = stm32_pconf_get_pin_desc_by_pin_number(pctl, pin); + if (!pin_desc) + return; + + seq_printf(s, "%d (%s) - %s - %s - %s %s", alt, + pin_desc->functions[alt + 1].name, drive ? "open drain" : "push pull", biasing[bias], speeds[speed], "speed"); @@ -1256,9 +1294,9 @@ static int stm32_gpiolib_register_bank(struct stm32_pinctrl *pctl, struct fwnode if (IS_ERR(bank->base)) return PTR_ERR(bank->base); - err = clk_prepare(bank->clk); + err = clk_prepare_enable(bank->clk); if (err) { - dev_err(dev, "failed to prepare clk (%d)\n", err); + dev_err(dev, "failed to prepare_enable clk (%d)\n", err); return err; } @@ -1297,6 +1335,7 @@ static int stm32_gpiolib_register_bank(struct stm32_pinctrl *pctl, struct fwnode bank->gpio_chip.parent = dev; bank->bank_nr = bank_nr; bank->bank_ioport_nr = bank_ioport_nr; + bank->secure_control = pctl->match_data->secure_control; spin_lock_init(&bank->lock); /* create irq hierarchical domain */ @@ -1306,21 +1345,28 @@ static int stm32_gpiolib_register_bank(struct stm32_pinctrl *pctl, struct fwnode STM32_GPIO_IRQ_LINE, bank->fwnode, &stm32_gpio_domain_ops, bank); - if (!bank->domain) - return -ENODEV; + if (!bank->domain) { + err = -ENODEV; + goto err_clk; + } err = gpiochip_add_data(&bank->gpio_chip, bank); if (err) { dev_err(dev, "Failed to add gpiochip(%d)!\n", bank_nr); - return err; + goto err_clk; } dev_info(dev, "%s bank added\n", bank->gpio_chip.label); return 0; + +err_clk: + clk_disable_unprepare(bank->clk); + return err; } -static struct irq_domain *stm32_pctrl_get_irq_domain(struct device_node *np) +static struct irq_domain *stm32_pctrl_get_irq_domain(struct platform_device *pdev) { + struct device_node *np = pdev->dev.of_node; struct device_node *parent; struct irq_domain *domain; @@ -1424,7 +1470,8 @@ static int stm32_pctrl_create_pins_tab(struct stm32_pinctrl *pctl, if (pctl->pkg && !(pctl->pkg & p->pkg)) continue; pins->pin = p->pin; - pins->functions = p->functions; + memcpy((struct stm32_desc_pin *)pins->functions, p->functions, + STM32_CONFIG_NUM * sizeof(struct stm32_desc_function)); pins++; nb_pins_available++; } @@ -1436,23 +1483,19 @@ static int stm32_pctrl_create_pins_tab(struct stm32_pinctrl *pctl, int stm32_pctl_probe(struct platform_device *pdev) { - struct device_node *np = pdev->dev.of_node; + const struct stm32_pinctrl_match_data *match_data; struct fwnode_handle *child; - const struct of_device_id *match; struct device *dev = &pdev->dev; struct stm32_pinctrl *pctl; struct pinctrl_pin_desc *pins; int i, ret, hwlock_id; unsigned int banks; - if (!np) + match_data = device_get_match_data(dev); + if (!match_data) return -EINVAL; - match = of_match_device(dev->driver->of_match_table, dev); - if (!match || !match->data) - return -EINVAL; - - if (!of_find_property(np, "pins-are-numbered", NULL)) { + if (!device_property_present(dev, "pins-are-numbered")) { dev_err(dev, "only support pins-are-numbered format\n"); return -EINVAL; } @@ -1464,7 +1507,7 @@ int stm32_pctl_probe(struct platform_device *pdev) platform_set_drvdata(pdev, pctl); /* check for IRQ controller (may require deferred probe) */ - pctl->domain = stm32_pctrl_get_irq_domain(np); + pctl->domain = stm32_pctrl_get_irq_domain(pdev); if (IS_ERR(pctl->domain)) return PTR_ERR(pctl->domain); @@ -1480,10 +1523,10 @@ int stm32_pctl_probe(struct platform_device *pdev) spin_lock_init(&pctl->irqmux_lock); pctl->dev = dev; - pctl->match_data = match->data; + pctl->match_data = match_data; /* get optional package information */ - if (!of_property_read_u32(np, "st,package", &pctl->pkg)) + if (!device_property_read_u32(dev, "st,package", &pctl->pkg)) dev_dbg(pctl->dev, "package detected: %x\n", pctl->pkg); pctl->pins = devm_kcalloc(pctl->dev, pctl->match_data->npins, @@ -1568,6 +1611,10 @@ int stm32_pctl_probe(struct platform_device *pdev) ret = stm32_gpiolib_register_bank(pctl, child); if (ret) { fwnode_handle_put(child); + + for (i = 0; i < pctl->nbanks; i++) + clk_disable_unprepare(pctl->banks[i].clk); + return ret; } @@ -1593,6 +1640,9 @@ static int __maybe_unused stm32_pinctrl_restore_gpio_regs( if (!range) return 0; + if (!gpiochip_line_is_valid(range->gc, offset)) + return 0; + pin_is_irq = gpiochip_line_is_irq(range->gc, offset); if (!desc || (!pin_is_irq && !desc->gpio_owner)) @@ -1639,12 +1689,26 @@ static int __maybe_unused stm32_pinctrl_restore_gpio_regs( return 0; } +int __maybe_unused stm32_pinctrl_suspend(struct device *dev) +{ + struct stm32_pinctrl *pctl = dev_get_drvdata(dev); + int i; + + for (i = 0; i < pctl->nbanks; i++) + clk_disable(pctl->banks[i].clk); + + return 0; +} + int __maybe_unused stm32_pinctrl_resume(struct device *dev) { struct stm32_pinctrl *pctl = dev_get_drvdata(dev); struct stm32_pinctrl_group *g = pctl->groups; int i; + for (i = 0; i < pctl->nbanks; i++) + clk_enable(pctl->banks[i].clk); + for (i = 0; i < pctl->ngroups; i++, g++) stm32_pinctrl_restore_gpio_regs(pctl, g->pin); diff --git a/drivers/pinctrl/stm32/pinctrl-stm32.h b/drivers/pinctrl/stm32/pinctrl-stm32.h index b0882d1207658a6262d8cd9906ac5bf88b60fbc4..e0c31c4c8bca8fa4e0e7015838a444b2d19c9887 100644 --- a/drivers/pinctrl/stm32/pinctrl-stm32.h +++ b/drivers/pinctrl/stm32/pinctrl-stm32.h @@ -17,6 +17,7 @@ #define STM32_PIN_GPIO 0 #define STM32_PIN_AF(x) ((x) + 1) #define STM32_PIN_ANALOG (STM32_PIN_AF(15) + 1) +#define STM32_CONFIG_NUM (STM32_PIN_ANALOG + 1) /* package information */ #define STM32MP_PKG_AA BIT(0) @@ -31,26 +32,26 @@ struct stm32_desc_function { struct stm32_desc_pin { struct pinctrl_pin_desc pin; - const struct stm32_desc_function *functions; + const struct stm32_desc_function functions[STM32_CONFIG_NUM]; const unsigned int pkg; }; #define STM32_PIN(_pin, ...) \ { \ .pin = _pin, \ - .functions = (struct stm32_desc_function[]){ \ - __VA_ARGS__, { } }, \ + .functions = { \ + __VA_ARGS__}, \ } #define STM32_PIN_PKG(_pin, _pkg, ...) \ { \ .pin = _pin, \ .pkg = _pkg, \ - .functions = (struct stm32_desc_function[]){ \ - __VA_ARGS__, { } }, \ + .functions = { \ + __VA_ARGS__}, \ } #define STM32_FUNCTION(_num, _name) \ - { \ + [_num] = { \ .num = _num, \ .name = _name, \ } @@ -58,6 +59,7 @@ struct stm32_desc_pin { struct stm32_pinctrl_match_data { const struct stm32_desc_pin *pins; const unsigned int npins; + bool secure_control; }; struct stm32_gpio_bank; @@ -65,6 +67,7 @@ struct stm32_gpio_bank; int stm32_pctl_probe(struct platform_device *pdev); void stm32_pmx_get_mode(struct stm32_gpio_bank *bank, int pin, u32 *mode, u32 *alt); +int stm32_pinctrl_suspend(struct device *dev); int stm32_pinctrl_resume(struct device *dev); #endif /* __PINCTRL_STM32_H */ diff --git a/drivers/pinctrl/stm32/pinctrl-stm32mp135.c b/drivers/pinctrl/stm32/pinctrl-stm32mp135.c index 4ab03520c4077734dff8c7607b32d10bece4a7fe..fde1df191c2474906da291a9831febbc1fcbff31 100644 --- a/drivers/pinctrl/stm32/pinctrl-stm32mp135.c +++ b/drivers/pinctrl/stm32/pinctrl-stm32mp135.c @@ -1649,6 +1649,7 @@ static const struct stm32_desc_pin stm32mp135_pins[] = { static struct stm32_pinctrl_match_data stm32mp135_match_data = { .pins = stm32mp135_pins, .npins = ARRAY_SIZE(stm32mp135_pins), + .secure_control = true, }; static const struct of_device_id stm32mp135_pctrl_match[] = { @@ -1660,7 +1661,7 @@ static const struct of_device_id stm32mp135_pctrl_match[] = { }; static const struct dev_pm_ops stm32_pinctrl_dev_pm_ops = { - SET_LATE_SYSTEM_SLEEP_PM_OPS(NULL, stm32_pinctrl_resume) + SET_LATE_SYSTEM_SLEEP_PM_OPS(stm32_pinctrl_suspend, stm32_pinctrl_resume) }; static struct platform_driver stm32mp135_pinctrl_driver = { diff --git a/drivers/pinctrl/stm32/pinctrl-stm32mp157.c b/drivers/pinctrl/stm32/pinctrl-stm32mp157.c index 2ccb99d64df8372ccb4a12a8df18c5bf548d2650..91b2fc8ddbdbc7d417fd5788f7d9b5343553e115 100644 --- a/drivers/pinctrl/stm32/pinctrl-stm32mp157.c +++ b/drivers/pinctrl/stm32/pinctrl-stm32mp157.c @@ -2343,7 +2343,7 @@ static const struct of_device_id stm32mp157_pctrl_match[] = { }; static const struct dev_pm_ops stm32_pinctrl_dev_pm_ops = { - SET_LATE_SYSTEM_SLEEP_PM_OPS(NULL, stm32_pinctrl_resume) + SET_LATE_SYSTEM_SLEEP_PM_OPS(stm32_pinctrl_suspend, stm32_pinctrl_resume) }; static struct platform_driver stm32mp157_pinctrl_driver = { diff --git a/drivers/pinctrl/tegra/pinctrl-tegra194.c b/drivers/pinctrl/tegra/pinctrl-tegra194.c index 5c1dfcb46749d0485da289d952ac25eb347af759..f6c5d5e6dbb68311d1ff3d59de634e72b5919795 100644 --- a/drivers/pinctrl/tegra/pinctrl-tegra194.c +++ b/drivers/pinctrl/tegra/pinctrl-tegra194.c @@ -1110,24 +1110,15 @@ static const unsigned int sdmmc4_dat0_pins[] = { static const unsigned int sdmmc1_comp_pins[] = { TEGRA_PIN_SDMMC1_COMP, }; -static const unsigned int sdmmc1_hv_trim_pins[] = { - TEGRA_PIN_SDMMC1_HV_TRIM, -}; static const unsigned int sdmmc3_comp_pins[] = { TEGRA_PIN_SDMMC3_COMP, }; -static const unsigned int sdmmc3_hv_trim_pins[] = { - TEGRA_PIN_SDMMC3_HV_TRIM, -}; static const unsigned int eqos_comp_pins[] = { TEGRA_PIN_EQOS_COMP, }; static const unsigned int qspi_comp_pins[] = { TEGRA_PIN_QSPI_COMP, }; -static const unsigned int sys_reset_n_pins[] = { - TEGRA_PIN_SYS_RESET_N, -}; static const unsigned int shutdown_n_pins[] = { TEGRA_PIN_SHUTDOWN_N, }; diff --git a/drivers/platform/mips/cpu_hwmon.c b/drivers/platform/mips/cpu_hwmon.c index 386389ffec4198a15d85784ed26d9139e8aaaa03..d8c5f9195f85f5d436a4065aee16a380627ba50a 100644 --- a/drivers/platform/mips/cpu_hwmon.c +++ b/drivers/platform/mips/cpu_hwmon.c @@ -55,55 +55,6 @@ out: static int nr_packages; static struct device *cpu_hwmon_dev; -static SENSOR_DEVICE_ATTR(name, 0444, NULL, NULL, 0); - -static struct attribute *cpu_hwmon_attributes[] = { - &sensor_dev_attr_name.dev_attr.attr, - NULL -}; - -/* Hwmon device attribute group */ -static struct attribute_group cpu_hwmon_attribute_group = { - .attrs = cpu_hwmon_attributes, -}; - -static ssize_t get_cpu_temp(struct device *dev, - struct device_attribute *attr, char *buf); -static ssize_t cpu_temp_label(struct device *dev, - struct device_attribute *attr, char *buf); - -static SENSOR_DEVICE_ATTR(temp1_input, 0444, get_cpu_temp, NULL, 1); -static SENSOR_DEVICE_ATTR(temp1_label, 0444, cpu_temp_label, NULL, 1); -static SENSOR_DEVICE_ATTR(temp2_input, 0444, get_cpu_temp, NULL, 2); -static SENSOR_DEVICE_ATTR(temp2_label, 0444, cpu_temp_label, NULL, 2); -static SENSOR_DEVICE_ATTR(temp3_input, 0444, get_cpu_temp, NULL, 3); -static SENSOR_DEVICE_ATTR(temp3_label, 0444, cpu_temp_label, NULL, 3); -static SENSOR_DEVICE_ATTR(temp4_input, 0444, get_cpu_temp, NULL, 4); -static SENSOR_DEVICE_ATTR(temp4_label, 0444, cpu_temp_label, NULL, 4); - -static const struct attribute *hwmon_cputemp[4][3] = { - { - &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_temp1_label.dev_attr.attr, - NULL - }, - { - &sensor_dev_attr_temp2_input.dev_attr.attr, - &sensor_dev_attr_temp2_label.dev_attr.attr, - NULL - }, - { - &sensor_dev_attr_temp3_input.dev_attr.attr, - &sensor_dev_attr_temp3_label.dev_attr.attr, - NULL - }, - { - &sensor_dev_attr_temp4_input.dev_attr.attr, - &sensor_dev_attr_temp4_label.dev_attr.attr, - NULL - } -}; - static ssize_t cpu_temp_label(struct device *dev, struct device_attribute *attr, char *buf) { @@ -121,24 +72,47 @@ static ssize_t get_cpu_temp(struct device *dev, return sprintf(buf, "%d\n", value); } -static int create_sysfs_cputemp_files(struct kobject *kobj) -{ - int i, ret = 0; - - for (i = 0; i < nr_packages; i++) - ret = sysfs_create_files(kobj, hwmon_cputemp[i]); +static SENSOR_DEVICE_ATTR(temp1_input, 0444, get_cpu_temp, NULL, 1); +static SENSOR_DEVICE_ATTR(temp1_label, 0444, cpu_temp_label, NULL, 1); +static SENSOR_DEVICE_ATTR(temp2_input, 0444, get_cpu_temp, NULL, 2); +static SENSOR_DEVICE_ATTR(temp2_label, 0444, cpu_temp_label, NULL, 2); +static SENSOR_DEVICE_ATTR(temp3_input, 0444, get_cpu_temp, NULL, 3); +static SENSOR_DEVICE_ATTR(temp3_label, 0444, cpu_temp_label, NULL, 3); +static SENSOR_DEVICE_ATTR(temp4_input, 0444, get_cpu_temp, NULL, 4); +static SENSOR_DEVICE_ATTR(temp4_label, 0444, cpu_temp_label, NULL, 4); - return ret; -} +static struct attribute *cpu_hwmon_attributes[] = { + &sensor_dev_attr_temp1_input.dev_attr.attr, + &sensor_dev_attr_temp1_label.dev_attr.attr, + &sensor_dev_attr_temp2_input.dev_attr.attr, + &sensor_dev_attr_temp2_label.dev_attr.attr, + &sensor_dev_attr_temp3_input.dev_attr.attr, + &sensor_dev_attr_temp3_label.dev_attr.attr, + &sensor_dev_attr_temp4_input.dev_attr.attr, + &sensor_dev_attr_temp4_label.dev_attr.attr, + NULL +}; -static void remove_sysfs_cputemp_files(struct kobject *kobj) +static umode_t cpu_hwmon_is_visible(struct kobject *kobj, + struct attribute *attr, int i) { - int i; + int id = i / 2; - for (i = 0; i < nr_packages; i++) - sysfs_remove_files(kobj, hwmon_cputemp[i]); + if (id < nr_packages) + return attr->mode; + return 0; } +static struct attribute_group cpu_hwmon_group = { + .attrs = cpu_hwmon_attributes, + .is_visible = cpu_hwmon_is_visible, +}; + +static const struct attribute_group *cpu_hwmon_groups[] = { + &cpu_hwmon_group, + NULL +}; + #define CPU_THERMAL_THRESHOLD 90000 static struct delayed_work thermal_work; @@ -159,50 +133,31 @@ static void do_thermal_timer(struct work_struct *work) static int __init loongson_hwmon_init(void) { - int ret; - pr_info("Loongson Hwmon Enter...\n"); if (cpu_has_csr()) csr_temp_enable = csr_readl(LOONGSON_CSR_FEATURES) & LOONGSON_CSRF_TEMP; - cpu_hwmon_dev = hwmon_device_register_with_info(NULL, "cpu_hwmon", NULL, NULL, NULL); - if (IS_ERR(cpu_hwmon_dev)) { - ret = PTR_ERR(cpu_hwmon_dev); - pr_err("hwmon_device_register fail!\n"); - goto fail_hwmon_device_register; - } - nr_packages = loongson_sysconf.nr_cpus / loongson_sysconf.cores_per_package; - ret = create_sysfs_cputemp_files(&cpu_hwmon_dev->kobj); - if (ret) { - pr_err("fail to create cpu temperature interface!\n"); - goto fail_create_sysfs_cputemp_files; + cpu_hwmon_dev = hwmon_device_register_with_groups(NULL, "cpu_hwmon", + NULL, cpu_hwmon_groups); + if (IS_ERR(cpu_hwmon_dev)) { + pr_err("hwmon_device_register fail!\n"); + return PTR_ERR(cpu_hwmon_dev); } INIT_DEFERRABLE_WORK(&thermal_work, do_thermal_timer); schedule_delayed_work(&thermal_work, msecs_to_jiffies(20000)); - return ret; - -fail_create_sysfs_cputemp_files: - sysfs_remove_group(&cpu_hwmon_dev->kobj, - &cpu_hwmon_attribute_group); - hwmon_device_unregister(cpu_hwmon_dev); - -fail_hwmon_device_register: - return ret; + return 0; } static void __exit loongson_hwmon_exit(void) { cancel_delayed_work_sync(&thermal_work); - remove_sysfs_cputemp_files(&cpu_hwmon_dev->kobj); - sysfs_remove_group(&cpu_hwmon_dev->kobj, - &cpu_hwmon_attribute_group); hwmon_device_unregister(cpu_hwmon_dev); } diff --git a/drivers/regulator/pfuze100-regulator.c b/drivers/regulator/pfuze100-regulator.c index aa55cfca9e4005dfc4b87cdfa0a660275a7b2280..6b617024a67d1b048bf4df59806826e26ef8dd47 100644 --- a/drivers/regulator/pfuze100-regulator.c +++ b/drivers/regulator/pfuze100-regulator.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -571,10 +572,10 @@ static inline struct device_node *match_of_node(int index) return pfuze_matches[index].of_node; } -static struct pfuze_chip *syspm_pfuze_chip; - -static void pfuze_power_off_prepare(void) +static int pfuze_power_off_prepare(struct sys_off_data *data) { + struct pfuze_chip *syspm_pfuze_chip = data->cb_data; + dev_info(syspm_pfuze_chip->dev, "Configure standby mode for power off"); /* Switch from default mode: APS/APS to APS/Off */ @@ -609,28 +610,30 @@ static void pfuze_power_off_prepare(void) regmap_update_bits(syspm_pfuze_chip->regmap, PFUZE100_VGEN6VOL, PFUZE100_VGENxLPWR | PFUZE100_VGENxSTBY, PFUZE100_VGENxSTBY); + + return NOTIFY_DONE; } static int pfuze_power_off_prepare_init(struct pfuze_chip *pfuze_chip) { + int err; + if (pfuze_chip->chip_id != PFUZE100) { dev_warn(pfuze_chip->dev, "Requested pm_power_off_prepare handler for not supported chip\n"); return -ENODEV; } - if (pm_power_off_prepare) { - dev_warn(pfuze_chip->dev, "pm_power_off_prepare is already registered.\n"); - return -EBUSY; + err = devm_register_sys_off_handler(pfuze_chip->dev, + SYS_OFF_MODE_POWER_OFF_PREPARE, + SYS_OFF_PRIO_DEFAULT, + pfuze_power_off_prepare, + pfuze_chip); + if (err) { + dev_err(pfuze_chip->dev, "failed to register sys-off handler: %d\n", + err); + return err; } - if (syspm_pfuze_chip) { - dev_warn(pfuze_chip->dev, "syspm_pfuze_chip is already set.\n"); - return -EBUSY; - } - - syspm_pfuze_chip = pfuze_chip; - pm_power_off_prepare = pfuze_power_off_prepare; - return 0; } @@ -839,23 +842,12 @@ static int pfuze100_regulator_probe(struct i2c_client *client, return 0; } -static int pfuze100_regulator_remove(struct i2c_client *client) -{ - if (syspm_pfuze_chip) { - syspm_pfuze_chip = NULL; - pm_power_off_prepare = NULL; - } - - return 0; -} - static struct i2c_driver pfuze_driver = { .driver = { .name = "pfuze100-regulator", .of_match_table = pfuze_dt_ids, }, .probe = pfuze100_regulator_probe, - .remove = pfuze100_regulator_remove, }; module_i2c_driver(pfuze_driver); diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c index d614843caf6cc95a34f18d6e9b9f8f6299c84e41..8d0d0eaa30594556f879275d6852f18c8f9bfe20 100644 --- a/drivers/s390/block/dcssblk.c +++ b/drivers/s390/block/dcssblk.c @@ -32,7 +32,8 @@ static int dcssblk_open(struct block_device *bdev, fmode_t mode); static void dcssblk_release(struct gendisk *disk, fmode_t mode); static void dcssblk_submit_bio(struct bio *bio); static long dcssblk_dax_direct_access(struct dax_device *dax_dev, pgoff_t pgoff, - long nr_pages, void **kaddr, pfn_t *pfn); + long nr_pages, enum dax_access_mode mode, void **kaddr, + pfn_t *pfn); static char dcssblk_segments[DCSSBLK_PARM_LEN] = "\0"; @@ -50,7 +51,8 @@ static int dcssblk_dax_zero_page_range(struct dax_device *dax_dev, long rc; void *kaddr; - rc = dax_direct_access(dax_dev, pgoff, nr_pages, &kaddr, NULL); + rc = dax_direct_access(dax_dev, pgoff, nr_pages, DAX_ACCESS, + &kaddr, NULL); if (rc < 0) return rc; memset(kaddr, 0, nr_pages << PAGE_SHIFT); @@ -927,7 +929,8 @@ __dcssblk_direct_access(struct dcssblk_dev_info *dev_info, pgoff_t pgoff, static long dcssblk_dax_direct_access(struct dax_device *dax_dev, pgoff_t pgoff, - long nr_pages, void **kaddr, pfn_t *pfn) + long nr_pages, enum dax_access_mode mode, void **kaddr, + pfn_t *pfn) { struct dcssblk_dev_info *dev_info = dax_get_private(dax_dev); diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 9a0bba5a51a717d2aef47f3a737f56fcc59db08a..08ed059a738b92065f7fd0f91608e043267c72a6 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -54,7 +54,6 @@ #define VMSTOR_PROTO_VERSION(MAJOR_, MINOR_) ((((MAJOR_) & 0xff) << 8) | \ (((MINOR_) & 0xff))) - #define VMSTOR_PROTO_VERSION_WIN6 VMSTOR_PROTO_VERSION(2, 0) #define VMSTOR_PROTO_VERSION_WIN7 VMSTOR_PROTO_VERSION(4, 2) #define VMSTOR_PROTO_VERSION_WIN8 VMSTOR_PROTO_VERSION(5, 1) @@ -136,20 +135,10 @@ struct hv_fc_wwn_packet { */ #define STORVSC_MAX_CMD_LEN 0x10 -#define POST_WIN7_STORVSC_SENSE_BUFFER_SIZE 0x14 -#define PRE_WIN8_STORVSC_SENSE_BUFFER_SIZE 0x12 - +/* Sense buffer size is the same for all versions since Windows 8 */ #define STORVSC_SENSE_BUFFER_SIZE 0x14 #define STORVSC_MAX_BUF_LEN_WITH_PADDING 0x14 -/* - * Sense buffer size changed in win8; have a run-time - * variable to track the size we should use. This value will - * likely change during protocol negotiation but it is valid - * to start by assuming pre-Win8. - */ -static int sense_buffer_size = PRE_WIN8_STORVSC_SENSE_BUFFER_SIZE; - /* * The storage protocol version is determined during the * initial exchange with the host. It will indicate which @@ -177,18 +166,6 @@ do { \ dev_warn(&(dev)->device, fmt, ##__VA_ARGS__); \ } while (0) -struct vmscsi_win8_extension { - /* - * The following were added in Windows 8 - */ - u16 reserve; - u8 queue_tag; - u8 queue_action; - u32 srb_flags; - u32 time_out_value; - u32 queue_sort_ey; -} __packed; - struct vmscsi_request { u16 length; u8 srb_status; @@ -214,46 +191,23 @@ struct vmscsi_request { /* * The following was added in win8. */ - struct vmscsi_win8_extension win8_extension; + u16 reserve; + u8 queue_tag; + u8 queue_action; + u32 srb_flags; + u32 time_out_value; + u32 queue_sort_ey; } __attribute((packed)); /* - * The list of storage protocols in order of preference. + * The list of windows version in order of preference. */ -struct vmstor_protocol { - int protocol_version; - int sense_buffer_size; - int vmscsi_size_delta; -}; - -static const struct vmstor_protocol vmstor_protocols[] = { - { +static const int protocol_version[] = { VMSTOR_PROTO_VERSION_WIN10, - POST_WIN7_STORVSC_SENSE_BUFFER_SIZE, - 0 - }, - { VMSTOR_PROTO_VERSION_WIN8_1, - POST_WIN7_STORVSC_SENSE_BUFFER_SIZE, - 0 - }, - { VMSTOR_PROTO_VERSION_WIN8, - POST_WIN7_STORVSC_SENSE_BUFFER_SIZE, - 0 - }, - { - VMSTOR_PROTO_VERSION_WIN7, - PRE_WIN8_STORVSC_SENSE_BUFFER_SIZE, - sizeof(struct vmscsi_win8_extension), - }, - { - VMSTOR_PROTO_VERSION_WIN6, - PRE_WIN8_STORVSC_SENSE_BUFFER_SIZE, - sizeof(struct vmscsi_win8_extension), - } }; @@ -409,9 +363,7 @@ static void storvsc_on_channel_callback(void *context); #define STORVSC_IDE_MAX_CHANNELS 1 /* - * Upper bound on the size of a storvsc packet. vmscsi_size_delta is not - * included in the calculation because it is set after STORVSC_MAX_PKT_SIZE - * is used in storvsc_connect_to_vsp + * Upper bound on the size of a storvsc packet. */ #define STORVSC_MAX_PKT_SIZE (sizeof(struct vmpacket_descriptor) +\ sizeof(struct vstor_packet)) @@ -452,17 +404,6 @@ struct storvsc_device { unsigned char path_id; unsigned char target_id; - /* - * The size of the vmscsi_request has changed in win8. The - * additional size is because of new elements added to the - * structure. These elements are valid only when we are talking - * to a win8 host. - * Track the correction to size we need to apply. This value - * will likely change during protocol negotiation but it is - * valid to start by assuming pre-Win8. - */ - int vmscsi_size_delta; - /* * Max I/O, the device can support. */ @@ -795,8 +736,7 @@ static void handle_multichannel_storage(struct hv_device *device, int max_chns) vstor_packet->sub_channel_count = num_sc; ret = vmbus_sendpacket(device->channel, vstor_packet, - (sizeof(struct vstor_packet) - - stor_device->vmscsi_size_delta), + sizeof(struct vstor_packet), VMBUS_RQST_INIT, VM_PKT_DATA_INBAND, VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); @@ -864,8 +804,7 @@ static int storvsc_execute_vstor_op(struct hv_device *device, vstor_packet->flags = REQUEST_COMPLETION_FLAG; ret = vmbus_sendpacket(device->channel, vstor_packet, - (sizeof(struct vstor_packet) - - stor_device->vmscsi_size_delta), + sizeof(struct vstor_packet), VMBUS_RQST_INIT, VM_PKT_DATA_INBAND, VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); @@ -915,14 +854,13 @@ static int storvsc_channel_init(struct hv_device *device, bool is_fc) * Query host supported protocol version. */ - for (i = 0; i < ARRAY_SIZE(vmstor_protocols); i++) { + for (i = 0; i < ARRAY_SIZE(protocol_version); i++) { /* reuse the packet for version range supported */ memset(vstor_packet, 0, sizeof(struct vstor_packet)); vstor_packet->operation = VSTOR_OPERATION_QUERY_PROTOCOL_VERSION; - vstor_packet->version.major_minor = - vmstor_protocols[i].protocol_version; + vstor_packet->version.major_minor = protocol_version[i]; /* * The revision number is only used in Windows; set it to 0. @@ -936,21 +874,16 @@ static int storvsc_channel_init(struct hv_device *device, bool is_fc) return -EINVAL; if (vstor_packet->status == 0) { - vmstor_proto_version = - vmstor_protocols[i].protocol_version; - - sense_buffer_size = - vmstor_protocols[i].sense_buffer_size; - - stor_device->vmscsi_size_delta = - vmstor_protocols[i].vmscsi_size_delta; + vmstor_proto_version = protocol_version[i]; break; } } - if (vstor_packet->status != 0) + if (vstor_packet->status != 0) { + dev_err(&device->device, "Obsolete Hyper-V version\n"); return -EINVAL; + } memset(vstor_packet, 0, sizeof(struct vstor_packet)); @@ -986,11 +919,10 @@ static int storvsc_channel_init(struct hv_device *device, bool is_fc) cpumask_set_cpu(device->channel->target_cpu, &stor_device->alloced_cpus); - if (vmstor_proto_version >= VMSTOR_PROTO_VERSION_WIN8) { - if (vstor_packet->storage_channel_properties.flags & - STORAGE_CHANNEL_SUPPORTS_MULTI_CHANNEL) - process_sub_channels = true; - } + if (vstor_packet->storage_channel_properties.flags & + STORAGE_CHANNEL_SUPPORTS_MULTI_CHANNEL) + process_sub_channels = true; + stor_device->max_transfer_bytes = vstor_packet->storage_channel_properties.max_transfer_bytes; @@ -1197,7 +1129,7 @@ static void storvsc_on_io_completion(struct storvsc_device *stor_device, * Copy over the sense_info_length, but limit to the known max * size if Hyper-V returns a bad value. */ - stor_pkt->vm_srb.sense_info_length = min_t(u8, sense_buffer_size, + stor_pkt->vm_srb.sense_info_length = min_t(u8, STORVSC_SENSE_BUFFER_SIZE, vstor_packet->vm_srb.sense_info_length); if (vstor_packet->vm_srb.scsi_status != 0 || @@ -1289,8 +1221,8 @@ static void storvsc_on_channel_callback(void *context) struct storvsc_cmd_request *request = NULL; u32 pktlen = hv_pkt_datalen(desc); u64 rqst_id = desc->trans_id; - u32 minlen = rqst_id ? sizeof(struct vstor_packet) - - stor_device->vmscsi_size_delta : sizeof(enum vstor_packet_operation); + u32 minlen = rqst_id ? sizeof(struct vstor_packet) : + sizeof(enum vstor_packet_operation); if (pktlen < minlen) { dev_err(&device->device, @@ -1346,7 +1278,7 @@ static void storvsc_on_channel_callback(void *context) } memcpy(&request->vstor_packet, packet, - (sizeof(struct vstor_packet) - stor_device->vmscsi_size_delta)); + sizeof(struct vstor_packet)); complete(&request->wait_event); } } @@ -1557,11 +1489,10 @@ static int storvsc_do_io(struct hv_device *device, found_channel: vstor_packet->flags |= REQUEST_COMPLETION_FLAG; - vstor_packet->vm_srb.length = (sizeof(struct vmscsi_request) - - stor_device->vmscsi_size_delta); + vstor_packet->vm_srb.length = sizeof(struct vmscsi_request); - vstor_packet->vm_srb.sense_info_length = sense_buffer_size; + vstor_packet->vm_srb.sense_info_length = STORVSC_SENSE_BUFFER_SIZE; vstor_packet->vm_srb.data_transfer_length = @@ -1574,13 +1505,11 @@ found_channel: ret = vmbus_sendpacket_mpb_desc(outgoing_channel, request->payload, request->payload_sz, vstor_packet, - (sizeof(struct vstor_packet) - - stor_device->vmscsi_size_delta), + sizeof(struct vstor_packet), (unsigned long)request); } else { ret = vmbus_sendpacket(outgoing_channel, vstor_packet, - (sizeof(struct vstor_packet) - - stor_device->vmscsi_size_delta), + sizeof(struct vstor_packet), (unsigned long)request, VM_PKT_DATA_INBAND, VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); @@ -1684,8 +1613,7 @@ static int storvsc_host_reset_handler(struct scsi_cmnd *scmnd) vstor_packet->vm_srb.path_id = stor_device->path_id; ret = vmbus_sendpacket(device->channel, vstor_packet, - (sizeof(struct vstor_packet) - - stor_device->vmscsi_size_delta), + sizeof(struct vstor_packet), VMBUS_RQST_RESET, VM_PKT_DATA_INBAND, VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); @@ -1778,31 +1706,31 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd) memset(&cmd_request->vstor_packet, 0, sizeof(struct vstor_packet)); vm_srb = &cmd_request->vstor_packet.vm_srb; - vm_srb->win8_extension.time_out_value = 60; + vm_srb->time_out_value = 60; - vm_srb->win8_extension.srb_flags |= + vm_srb->srb_flags |= SRB_FLAGS_DISABLE_SYNCH_TRANSFER; if (scmnd->device->tagged_supported) { - vm_srb->win8_extension.srb_flags |= + vm_srb->srb_flags |= (SRB_FLAGS_QUEUE_ACTION_ENABLE | SRB_FLAGS_NO_QUEUE_FREEZE); - vm_srb->win8_extension.queue_tag = SP_UNTAGGED; - vm_srb->win8_extension.queue_action = SRB_SIMPLE_TAG_REQUEST; + vm_srb->queue_tag = SP_UNTAGGED; + vm_srb->queue_action = SRB_SIMPLE_TAG_REQUEST; } /* Build the SRB */ switch (scmnd->sc_data_direction) { case DMA_TO_DEVICE: vm_srb->data_in = WRITE_TYPE; - vm_srb->win8_extension.srb_flags |= SRB_FLAGS_DATA_OUT; + vm_srb->srb_flags |= SRB_FLAGS_DATA_OUT; break; case DMA_FROM_DEVICE: vm_srb->data_in = READ_TYPE; - vm_srb->win8_extension.srb_flags |= SRB_FLAGS_DATA_IN; + vm_srb->srb_flags |= SRB_FLAGS_DATA_IN; break; case DMA_NONE: vm_srb->data_in = UNKNOWN_TYPE; - vm_srb->win8_extension.srb_flags |= SRB_FLAGS_NO_DATA_TRANSFER; + vm_srb->srb_flags |= SRB_FLAGS_NO_DATA_TRANSFER; break; default: /* @@ -1966,34 +1894,16 @@ static int storvsc_probe(struct hv_device *device, bool is_fc = ((dev_id->driver_data == SFC_GUID) ? true : false); int target = 0; struct storvsc_device *stor_device; - int max_luns_per_target; - int max_targets; - int max_channels; int max_sub_channels = 0; /* - * Based on the windows host we are running on, - * set state to properly communicate with the host. + * We support sub-channels for storage on SCSI and FC controllers. + * The number of sub-channels offerred is based on the number of + * VCPUs in the guest. */ - - if (vmbus_proto_version < VERSION_WIN8) { - max_luns_per_target = STORVSC_IDE_MAX_LUNS_PER_TARGET; - max_targets = STORVSC_IDE_MAX_TARGETS; - max_channels = STORVSC_IDE_MAX_CHANNELS; - } else { - max_luns_per_target = STORVSC_MAX_LUNS_PER_TARGET; - max_targets = STORVSC_MAX_TARGETS; - max_channels = STORVSC_MAX_CHANNELS; - /* - * On Windows8 and above, we support sub-channels for storage - * on SCSI and FC controllers. - * The number of sub-channels offerred is based on the number of - * VCPUs in the guest. - */ - if (!dev_is_ide) - max_sub_channels = - (num_cpus - 1) / storvsc_vcpus_per_sub_channel; - } + if (!dev_is_ide) + max_sub_channels = + (num_cpus - 1) / storvsc_vcpus_per_sub_channel; scsi_driver.can_queue = max_outstanding_req_per_channel * (max_sub_channels + 1) * @@ -2022,7 +1932,6 @@ static int storvsc_probe(struct hv_device *device, init_waitqueue_head(&stor_device->waiting_to_drain); stor_device->device = device; stor_device->host = host; - stor_device->vmscsi_size_delta = sizeof(struct vmscsi_win8_extension); spin_lock_init(&stor_device->lock); hv_set_drvdata(device, stor_device); dma_set_min_align_mask(&device->device, HV_HYP_PAGE_SIZE - 1); @@ -2046,9 +1955,9 @@ static int storvsc_probe(struct hv_device *device, break; case SCSI_GUID: - host->max_lun = max_luns_per_target; - host->max_id = max_targets; - host->max_channel = max_channels - 1; + host->max_lun = STORVSC_MAX_LUNS_PER_TARGET; + host->max_id = STORVSC_MAX_TARGETS; + host->max_channel = STORVSC_MAX_CHANNELS - 1; break; default: @@ -2235,10 +2144,6 @@ static int __init storvsc_drv_init(void) * than the ring buffer size since that page is reserved for * the ring buffer indices) by the max request size (which is * vmbus_channel_packet_multipage_buffer + struct vstor_packet + u64) - * - * The computation underestimates max_outstanding_req_per_channel - * for Win7 and older hosts because it does not take into account - * the vmscsi_size_delta correction to the max request size. */ max_outstanding_req_per_channel = ((storvsc_ringbuffer_size - PAGE_SIZE) / diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c index c77ecf61818bae1849789eb24869e7870fd4d5b3..5611d14d3ba2adbaa9eb17aaed30855fdce52a8a 100644 --- a/drivers/soc/tegra/pmc.c +++ b/drivers/soc/tegra/pmc.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -108,6 +109,7 @@ #define PMC_USB_DEBOUNCE_DEL 0xec #define PMC_USB_AO 0xf0 +#define PMC_SCRATCH37 0x130 #define PMC_SCRATCH41 0x140 #define PMC_WAKE2_MASK 0x160 @@ -1101,8 +1103,7 @@ static struct notifier_block tegra_pmc_reboot_notifier = { .notifier_call = tegra_pmc_reboot_notify, }; -static int tegra_pmc_restart_notify(struct notifier_block *this, - unsigned long action, void *data) +static void tegra_pmc_restart(void) { u32 value; @@ -1110,14 +1111,31 @@ static int tegra_pmc_restart_notify(struct notifier_block *this, value = tegra_pmc_readl(pmc, PMC_CNTRL); value |= PMC_CNTRL_MAIN_RST; tegra_pmc_writel(pmc, value, PMC_CNTRL); +} + +static int tegra_pmc_restart_handler(struct sys_off_data *data) +{ + tegra_pmc_restart(); return NOTIFY_DONE; } -static struct notifier_block tegra_pmc_restart_handler = { - .notifier_call = tegra_pmc_restart_notify, - .priority = 128, -}; +static int tegra_pmc_power_off_handler(struct sys_off_data *data) +{ + /* + * Reboot Nexus 7 into special bootloader mode if USB cable is + * connected in order to display battery status and power off. + */ + if (of_machine_is_compatible("asus,grouper") && + power_supply_is_system_supplied()) { + const u32 go_to_charger_mode = 0xa5a55a5a; + + tegra_pmc_writel(pmc, go_to_charger_mode, PMC_SCRATCH37); + tegra_pmc_restart(); + } + + return NOTIFY_DONE; +} static int powergate_show(struct seq_file *s, void *data) { @@ -2879,6 +2897,42 @@ static int tegra_pmc_probe(struct platform_device *pdev) pmc->clk = NULL; } + /* + * PMC should be last resort for restarting since it soft-resets + * CPU without resetting everything else. + */ + err = devm_register_reboot_notifier(&pdev->dev, + &tegra_pmc_reboot_notifier); + if (err) { + dev_err(&pdev->dev, "unable to register reboot notifier, %d\n", + err); + return err; + } + + err = devm_register_sys_off_handler(&pdev->dev, + SYS_OFF_MODE_RESTART, + SYS_OFF_PRIO_LOW, + tegra_pmc_restart_handler, NULL); + if (err) { + dev_err(&pdev->dev, "failed to register sys-off handler: %d\n", + err); + return err; + } + + /* + * PMC should be primary power-off method if it soft-resets CPU, + * asking bootloader to shutdown hardware. + */ + err = devm_register_sys_off_handler(&pdev->dev, + SYS_OFF_MODE_POWER_OFF, + SYS_OFF_PRIO_FIRMWARE, + tegra_pmc_power_off_handler, NULL); + if (err) { + dev_err(&pdev->dev, "failed to register sys-off handler: %d\n", + err); + return err; + } + /* * PCLK clock rate can't be retrieved using CLK API because it * causes lockup if CPU enters LP2 idle state from some other @@ -2910,28 +2964,13 @@ static int tegra_pmc_probe(struct platform_device *pdev) goto cleanup_sysfs; } - err = devm_register_reboot_notifier(&pdev->dev, - &tegra_pmc_reboot_notifier); - if (err) { - dev_err(&pdev->dev, "unable to register reboot notifier, %d\n", - err); - goto cleanup_debugfs; - } - - err = register_restart_handler(&tegra_pmc_restart_handler); - if (err) { - dev_err(&pdev->dev, "unable to register restart handler, %d\n", - err); - goto cleanup_debugfs; - } - err = tegra_pmc_pinctrl_init(pmc); if (err) - goto cleanup_restart_handler; + goto cleanup_debugfs; err = tegra_pmc_regmap_init(pmc); if (err < 0) - goto cleanup_restart_handler; + goto cleanup_debugfs; err = tegra_powergate_init(pmc, pdev->dev.of_node); if (err < 0) @@ -2954,8 +2993,6 @@ static int tegra_pmc_probe(struct platform_device *pdev) cleanup_powergates: tegra_powergate_remove_all(pdev->dev.of_node); -cleanup_restart_handler: - unregister_restart_handler(&tegra_pmc_restart_handler); cleanup_debugfs: debugfs_remove(pmc->debugfs); cleanup_sysfs: diff --git a/drivers/thermal/intel/int340x_thermal/int3400_thermal.c b/drivers/thermal/intel/int340x_thermal/int3400_thermal.c index 770d2b0299c37ca9d84a8afe5df8a2d22803b5d7..80d4e0676083ac56ade7bea96834203f1d95eed0 100644 --- a/drivers/thermal/intel/int340x_thermal/int3400_thermal.c +++ b/drivers/thermal/intel/int340x_thermal/int3400_thermal.c @@ -663,6 +663,7 @@ static const struct acpi_device_id int3400_thermal_match[] = { {"INT3400", 0}, {"INTC1040", 0}, {"INTC1041", 0}, + {"INTC1042", 0}, {"INTC10A0", 0}, {} }; diff --git a/drivers/thermal/intel/int340x_thermal/int3403_thermal.c b/drivers/thermal/intel/int340x_thermal/int3403_thermal.c index 07e25321dfe3bd911e0e2a99f4b008163e1f09e8..71d084c4c456dd41df7f13f2f9b51db4aa8f5ffd 100644 --- a/drivers/thermal/intel/int340x_thermal/int3403_thermal.c +++ b/drivers/thermal/intel/int340x_thermal/int3403_thermal.c @@ -285,6 +285,7 @@ static const struct acpi_device_id int3403_device_ids[] = { {"INT3403", 0}, {"INTC1043", 0}, {"INTC1046", 0}, + {"INTC1062", 0}, {"INTC10A1", 0}, {"", 0}, }; diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_device.h b/drivers/thermal/intel/int340x_thermal/processor_thermal_device.h index 49932a68abac4df77e855490cf088f0de057a18d..7d52fcff4937b097444c46570849a03c5b940824 100644 --- a/drivers/thermal/intel/int340x_thermal/processor_thermal_device.h +++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_device.h @@ -24,6 +24,7 @@ #define PCI_DEVICE_ID_INTEL_HSB_THERMAL 0x0A03 #define PCI_DEVICE_ID_INTEL_ICL_THERMAL 0x8a03 #define PCI_DEVICE_ID_INTEL_JSL_THERMAL 0x4E03 +#define PCI_DEVICE_ID_INTEL_MTLP_THERMAL 0x7D03 #define PCI_DEVICE_ID_INTEL_RPL_THERMAL 0xA71D #define PCI_DEVICE_ID_INTEL_SKL_THERMAL 0x1903 #define PCI_DEVICE_ID_INTEL_TGL_THERMAL 0x9A03 diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c b/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c index ca40b0967cdda92f5884dc000eeae1201965c983..c2dc4c158b9dcca6fb0d1c5e0a0c03a221a4ac18 100644 --- a/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c +++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c @@ -358,6 +358,7 @@ static SIMPLE_DEV_PM_OPS(proc_thermal_pci_pm, proc_thermal_pci_suspend, static const struct pci_device_id proc_thermal_pci_ids[] = { { PCI_DEVICE_DATA(INTEL, ADL_THERMAL, PROC_THERMAL_FEATURE_RAPL | PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_MBOX) }, + { PCI_DEVICE_DATA(INTEL, MTLP_THERMAL, PROC_THERMAL_FEATURE_RAPL | PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_MBOX) }, { PCI_DEVICE_DATA(INTEL, RPL_THERMAL, PROC_THERMAL_FEATURE_RAPL | PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_MBOX) }, { }, }; diff --git a/drivers/thunderbolt/domain.c b/drivers/thunderbolt/domain.c index 7018d959f7758dcbbe4ddb7783936ac5dfe34977..2889a214dadcb6e16e9e244620c820f435bacda5 100644 --- a/drivers/thunderbolt/domain.c +++ b/drivers/thunderbolt/domain.c @@ -7,9 +7,7 @@ */ #include -#include #include -#include #include #include #include @@ -257,13 +255,9 @@ static ssize_t iommu_dma_protection_show(struct device *dev, struct device_attribute *attr, char *buf) { - /* - * Kernel DMA protection is a feature where Thunderbolt security is - * handled natively using IOMMU. It is enabled when IOMMU is - * enabled and ACPI DMAR table has DMAR_PLATFORM_OPT_IN set. - */ - return sprintf(buf, "%d\n", - iommu_present(&pci_bus_type) && dmar_platform_optin()); + struct tb *tb = container_of(dev, struct tb, dev); + + return sysfs_emit(buf, "%d\n", tb->nhi->iommu_dma_protection); } static DEVICE_ATTR_RO(iommu_dma_protection); diff --git a/drivers/thunderbolt/nhi.c b/drivers/thunderbolt/nhi.c index 4a582183f67570e1e55a77cd93c7c13c28ff7500..4bc87b0f003aa5a5793334687ced91da695e4e83 100644 --- a/drivers/thunderbolt/nhi.c +++ b/drivers/thunderbolt/nhi.c @@ -15,9 +15,11 @@ #include #include #include +#include #include #include #include +#include #include "nhi.h" #include "nhi_regs.h" @@ -1103,6 +1105,47 @@ static void nhi_check_quirks(struct tb_nhi *nhi) nhi->quirks |= QUIRK_AUTO_CLEAR_INT; } +static int nhi_check_iommu_pdev(struct pci_dev *pdev, void *data) +{ + if (!pdev->external_facing || + !device_iommu_capable(&pdev->dev, IOMMU_CAP_PRE_BOOT_PROTECTION)) + return 0; + *(bool *)data = true; + return 1; /* Stop walking */ +} + +static void nhi_check_iommu(struct tb_nhi *nhi) +{ + struct pci_bus *bus = nhi->pdev->bus; + bool port_ok = false; + + /* + * Ideally what we'd do here is grab every PCI device that + * represents a tunnelling adapter for this NHI and check their + * status directly, but unfortunately USB4 seems to make it + * obnoxiously difficult to reliably make any correlation. + * + * So for now we'll have to bodge it... Hoping that the system + * is at least sane enough that an adapter is in the same PCI + * segment as its NHI, if we can find *something* on that segment + * which meets the requirements for Kernel DMA Protection, we'll + * take that to imply that firmware is aware and has (hopefully) + * done the right thing in general. We need to know that the PCI + * layer has seen the ExternalFacingPort property which will then + * inform the IOMMU layer to enforce the complete "untrusted DMA" + * flow, but also that the IOMMU driver itself can be trusted not + * to have been subverted by a pre-boot DMA attack. + */ + while (bus->parent) + bus = bus->parent; + + pci_walk_bus(bus, nhi_check_iommu_pdev, &port_ok); + + nhi->iommu_dma_protection = port_ok; + dev_dbg(&nhi->pdev->dev, "IOMMU DMA protection is %s\n", + str_enabled_disabled(port_ok)); +} + static int nhi_init_msi(struct tb_nhi *nhi) { struct pci_dev *pdev = nhi->pdev; @@ -1220,6 +1263,7 @@ static int nhi_probe(struct pci_dev *pdev, const struct pci_device_id *id) return -ENOMEM; nhi_check_quirks(nhi); + nhi_check_iommu(nhi); res = nhi_init_msi(nhi); if (res) { diff --git a/drivers/usb/typec/ucsi/ucsi_acpi.c b/drivers/usb/typec/ucsi/ucsi_acpi.c index 6771f05e32c290cb12f033b31ce49002a0f5b1c6..8873c1644a2953d008f52f69f5435cc28d7778eb 100644 --- a/drivers/usb/typec/ucsi/ucsi_acpi.c +++ b/drivers/usb/typec/ucsi/ucsi_acpi.c @@ -19,7 +19,7 @@ struct ucsi_acpi { struct device *dev; struct ucsi *ucsi; - void __iomem *base; + void *base; struct completion complete; unsigned long flags; guid_t guid; @@ -51,7 +51,7 @@ static int ucsi_acpi_read(struct ucsi *ucsi, unsigned int offset, if (ret) return ret; - memcpy(val, (const void __force *)(ua->base + offset), val_len); + memcpy(val, ua->base + offset, val_len); return 0; } @@ -61,7 +61,7 @@ static int ucsi_acpi_async_write(struct ucsi *ucsi, unsigned int offset, { struct ucsi_acpi *ua = ucsi_get_drvdata(ucsi); - memcpy((void __force *)(ua->base + offset), val, val_len); + memcpy(ua->base + offset, val, val_len); return ucsi_acpi_dsm(ua, UCSI_DSM_FUNC_WRITE); } @@ -132,20 +132,9 @@ static int ucsi_acpi_probe(struct platform_device *pdev) return -ENODEV; } - /* This will make sure we can use ioremap() */ - status = acpi_release_memory(ACPI_HANDLE(&pdev->dev), res, 1); - if (ACPI_FAILURE(status)) - return -ENOMEM; - - /* - * NOTE: The memory region for the data structures is used also in an - * operation region, which means ACPI has already reserved it. Therefore - * it can not be requested here, and we can not use - * devm_ioremap_resource(). - */ - ua->base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); - if (!ua->base) - return -ENOMEM; + ua->base = devm_memremap(&pdev->dev, res->start, resource_size(res), MEMREMAP_WB); + if (IS_ERR(ua->base)) + return PTR_ERR(ua->base); ret = guid_parse(UCSI_DSM_UUID, &ua->guid); if (ret) diff --git a/drivers/vfio/fsl-mc/vfio_fsl_mc.c b/drivers/vfio/fsl-mc/vfio_fsl_mc.c index 6e2e62c6f47aebff90a0e853a62d1d35ac6d2a6a..3feff729f3ce825cf759421241bdabe08e6d29a8 100644 --- a/drivers/vfio/fsl-mc/vfio_fsl_mc.c +++ b/drivers/vfio/fsl-mc/vfio_fsl_mc.c @@ -588,6 +588,7 @@ static struct fsl_mc_driver vfio_fsl_mc_driver = { .name = "vfio-fsl-mc", .owner = THIS_MODULE, }, + .driver_managed_dma = true, }; static int __init vfio_fsl_mc_driver_init(void) diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c index 2b047469e02feea48b0bbea808fd119d1eeefcfe..58839206d1ca7f229c7d90f12a149e8f2c3a24eb 100644 --- a/drivers/vfio/pci/vfio_pci.c +++ b/drivers/vfio/pci/vfio_pci.c @@ -194,6 +194,7 @@ static struct pci_driver vfio_pci_driver = { .remove = vfio_pci_remove, .sriov_configure = vfio_pci_sriov_configure, .err_handler = &vfio_pci_core_err_handlers, + .driver_managed_dma = true, }; static void __init vfio_pci_fill_ids(void) diff --git a/drivers/vfio/platform/vfio_amba.c b/drivers/vfio/platform/vfio_amba.c index badfffea14fbdc2018dbb6c4490fcff387756f13..1aaa4f721bd2ce13f0332aa5c72934997182a4fe 100644 --- a/drivers/vfio/platform/vfio_amba.c +++ b/drivers/vfio/platform/vfio_amba.c @@ -95,6 +95,7 @@ static struct amba_driver vfio_amba_driver = { .name = "vfio-amba", .owner = THIS_MODULE, }, + .driver_managed_dma = true, }; module_amba_driver(vfio_amba_driver); diff --git a/drivers/vfio/platform/vfio_platform.c b/drivers/vfio/platform/vfio_platform.c index 68a1c87066d7604e5cbf8cce44dbde228ecb7b5d..04f40c5acfd673d8f087a0c10505ab837c9ffc0b 100644 --- a/drivers/vfio/platform/vfio_platform.c +++ b/drivers/vfio/platform/vfio_platform.c @@ -76,6 +76,7 @@ static struct platform_driver vfio_platform_driver = { .driver = { .name = "vfio-platform", }, + .driver_managed_dma = true, }; module_platform_driver(vfio_platform_driver); diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c index a4555014bd1e72b2ee5852cf4987901eda481fb6..6a7fb8d91aaa8f79970886a1cf328d3a4c6b5e19 100644 --- a/drivers/vfio/vfio.c +++ b/drivers/vfio/vfio.c @@ -62,11 +62,6 @@ struct vfio_container { bool noiommu; }; -struct vfio_unbound_dev { - struct device *dev; - struct list_head unbound_next; -}; - struct vfio_group { struct device dev; struct cdev cdev; @@ -76,11 +71,8 @@ struct vfio_group { struct vfio_container *container; struct list_head device_list; struct mutex device_lock; - struct notifier_block nb; struct list_head vfio_next; struct list_head container_next; - struct list_head unbound_list; - struct mutex unbound_lock; atomic_t opened; wait_queue_head_t container_q; enum vfio_group_type type; @@ -281,8 +273,6 @@ void vfio_unregister_iommu_driver(const struct vfio_iommu_driver_ops *ops) } EXPORT_SYMBOL_GPL(vfio_unregister_iommu_driver); -static int vfio_iommu_group_notifier(struct notifier_block *nb, - unsigned long action, void *data); static void vfio_group_get(struct vfio_group *group); /* @@ -340,16 +330,8 @@ vfio_group_get_from_iommu(struct iommu_group *iommu_group) static void vfio_group_release(struct device *dev) { struct vfio_group *group = container_of(dev, struct vfio_group, dev); - struct vfio_unbound_dev *unbound, *tmp; - - list_for_each_entry_safe(unbound, tmp, - &group->unbound_list, unbound_next) { - list_del(&unbound->unbound_next); - kfree(unbound); - } mutex_destroy(&group->device_lock); - mutex_destroy(&group->unbound_lock); iommu_group_put(group->iommu_group); ida_free(&vfio.group_ida, MINOR(group->dev.devt)); kfree(group); @@ -381,8 +363,6 @@ static struct vfio_group *vfio_group_alloc(struct iommu_group *iommu_group, refcount_set(&group->users, 1); INIT_LIST_HEAD(&group->device_list); mutex_init(&group->device_lock); - INIT_LIST_HEAD(&group->unbound_list); - mutex_init(&group->unbound_lock); init_waitqueue_head(&group->container_q); group->iommu_group = iommu_group; /* put in vfio_group_release() */ @@ -412,13 +392,6 @@ static struct vfio_group *vfio_create_group(struct iommu_group *iommu_group, goto err_put; } - group->nb.notifier_call = vfio_iommu_group_notifier; - err = iommu_group_register_notifier(iommu_group, &group->nb); - if (err) { - ret = ERR_PTR(err); - goto err_put; - } - mutex_lock(&vfio.group_lock); /* Did we race creating this group? */ @@ -439,7 +412,6 @@ static struct vfio_group *vfio_create_group(struct iommu_group *iommu_group, err_unlock: mutex_unlock(&vfio.group_lock); - iommu_group_unregister_notifier(group->iommu_group, &group->nb); err_put: put_device(&group->dev); return ret; @@ -464,7 +436,6 @@ static void vfio_group_put(struct vfio_group *group) cdev_device_del(&group->cdev, &group->dev); mutex_unlock(&vfio.group_lock); - iommu_group_unregister_notifier(group->iommu_group, &group->nb); put_device(&group->dev); } @@ -520,175 +491,6 @@ static struct vfio_device *vfio_group_get_device(struct vfio_group *group, return NULL; } -/* - * Some drivers, like pci-stub, are only used to prevent other drivers from - * claiming a device and are therefore perfectly legitimate for a user owned - * group. The pci-stub driver has no dependencies on DMA or the IOVA mapping - * of the device, but it does prevent the user from having direct access to - * the device, which is useful in some circumstances. - * - * We also assume that we can include PCI interconnect devices, ie. bridges. - * IOMMU grouping on PCI necessitates that if we lack isolation on a bridge - * then all of the downstream devices will be part of the same IOMMU group as - * the bridge. Thus, if placing the bridge into the user owned IOVA space - * breaks anything, it only does so for user owned devices downstream. Note - * that error notification via MSI can be affected for platforms that handle - * MSI within the same IOVA space as DMA. - */ -static const char * const vfio_driver_allowed[] = { "pci-stub" }; - -static bool vfio_dev_driver_allowed(struct device *dev, - struct device_driver *drv) -{ - if (dev_is_pci(dev)) { - struct pci_dev *pdev = to_pci_dev(dev); - - if (pdev->hdr_type != PCI_HEADER_TYPE_NORMAL) - return true; - } - - return match_string(vfio_driver_allowed, - ARRAY_SIZE(vfio_driver_allowed), - drv->name) >= 0; -} - -/* - * A vfio group is viable for use by userspace if all devices are in - * one of the following states: - * - driver-less - * - bound to a vfio driver - * - bound to an otherwise allowed driver - * - a PCI interconnect device - * - * We use two methods to determine whether a device is bound to a vfio - * driver. The first is to test whether the device exists in the vfio - * group. The second is to test if the device exists on the group - * unbound_list, indicating it's in the middle of transitioning from - * a vfio driver to driver-less. - */ -static int vfio_dev_viable(struct device *dev, void *data) -{ - struct vfio_group *group = data; - struct vfio_device *device; - struct device_driver *drv = READ_ONCE(dev->driver); - struct vfio_unbound_dev *unbound; - int ret = -EINVAL; - - mutex_lock(&group->unbound_lock); - list_for_each_entry(unbound, &group->unbound_list, unbound_next) { - if (dev == unbound->dev) { - ret = 0; - break; - } - } - mutex_unlock(&group->unbound_lock); - - if (!ret || !drv || vfio_dev_driver_allowed(dev, drv)) - return 0; - - device = vfio_group_get_device(group, dev); - if (device) { - vfio_device_put(device); - return 0; - } - - return ret; -} - -/* - * Async device support - */ -static int vfio_group_nb_add_dev(struct vfio_group *group, struct device *dev) -{ - struct vfio_device *device; - - /* Do we already know about it? We shouldn't */ - device = vfio_group_get_device(group, dev); - if (WARN_ON_ONCE(device)) { - vfio_device_put(device); - return 0; - } - - /* Nothing to do for idle groups */ - if (!atomic_read(&group->container_users)) - return 0; - - /* TODO Prevent device auto probing */ - dev_WARN(dev, "Device added to live group %d!\n", - iommu_group_id(group->iommu_group)); - - return 0; -} - -static int vfio_group_nb_verify(struct vfio_group *group, struct device *dev) -{ - /* We don't care what happens when the group isn't in use */ - if (!atomic_read(&group->container_users)) - return 0; - - return vfio_dev_viable(dev, group); -} - -static int vfio_iommu_group_notifier(struct notifier_block *nb, - unsigned long action, void *data) -{ - struct vfio_group *group = container_of(nb, struct vfio_group, nb); - struct device *dev = data; - struct vfio_unbound_dev *unbound; - - switch (action) { - case IOMMU_GROUP_NOTIFY_ADD_DEVICE: - vfio_group_nb_add_dev(group, dev); - break; - case IOMMU_GROUP_NOTIFY_DEL_DEVICE: - /* - * Nothing to do here. If the device is in use, then the - * vfio sub-driver should block the remove callback until - * it is unused. If the device is unused or attached to a - * stub driver, then it should be released and we don't - * care that it will be going away. - */ - break; - case IOMMU_GROUP_NOTIFY_BIND_DRIVER: - dev_dbg(dev, "%s: group %d binding to driver\n", __func__, - iommu_group_id(group->iommu_group)); - break; - case IOMMU_GROUP_NOTIFY_BOUND_DRIVER: - dev_dbg(dev, "%s: group %d bound to driver %s\n", __func__, - iommu_group_id(group->iommu_group), dev->driver->name); - BUG_ON(vfio_group_nb_verify(group, dev)); - break; - case IOMMU_GROUP_NOTIFY_UNBIND_DRIVER: - dev_dbg(dev, "%s: group %d unbinding from driver %s\n", - __func__, iommu_group_id(group->iommu_group), - dev->driver->name); - break; - case IOMMU_GROUP_NOTIFY_UNBOUND_DRIVER: - dev_dbg(dev, "%s: group %d unbound from driver\n", __func__, - iommu_group_id(group->iommu_group)); - /* - * XXX An unbound device in a live group is ok, but we'd - * really like to avoid the above BUG_ON by preventing other - * drivers from binding to it. Once that occurs, we have to - * stop the system to maintain isolation. At a minimum, we'd - * want a toggle to disable driver auto probe for this device. - */ - - mutex_lock(&group->unbound_lock); - list_for_each_entry(unbound, - &group->unbound_list, unbound_next) { - if (dev == unbound->dev) { - list_del(&unbound->unbound_next); - kfree(unbound); - break; - } - } - mutex_unlock(&group->unbound_lock); - break; - } - return NOTIFY_OK; -} - /* * VFIO driver API */ @@ -815,6 +617,13 @@ static int __vfio_register_dev(struct vfio_device *device, int vfio_register_group_dev(struct vfio_device *device) { + /* + * VFIO always sets IOMMU_CACHE because we offer no way for userspace to + * restore cache coherency. + */ + if (!iommu_capable(device->dev->bus, IOMMU_CAP_CACHE_COHERENCY)) + return -EINVAL; + return __vfio_register_dev(device, vfio_group_find_or_alloc(device->dev)); } @@ -889,29 +698,10 @@ static struct vfio_device *vfio_device_get_from_name(struct vfio_group *group, void vfio_unregister_group_dev(struct vfio_device *device) { struct vfio_group *group = device->group; - struct vfio_unbound_dev *unbound; unsigned int i = 0; bool interrupted = false; long rc; - /* - * When the device is removed from the group, the group suddenly - * becomes non-viable; the device has a driver (until the unbind - * completes), but it's not present in the group. This is bad news - * for any external users that need to re-acquire a group reference - * in order to match and release their existing reference. To - * solve this, we track such devices on the unbound_list to bridge - * the gap until they're fully unbound. - */ - unbound = kzalloc(sizeof(*unbound), GFP_KERNEL); - if (unbound) { - unbound->dev = device->dev; - mutex_lock(&group->unbound_lock); - list_add(&unbound->unbound_next, &group->unbound_list); - mutex_unlock(&group->unbound_lock); - } - WARN_ON(!unbound); - vfio_device_put(device); rc = try_wait_for_completion(&device->comp); while (rc <= 0) { @@ -1198,6 +988,8 @@ static void __vfio_group_unset_container(struct vfio_group *group) driver->ops->detach_group(container->iommu_data, group->iommu_group); + iommu_group_release_dma_owner(group->iommu_group); + group->container = NULL; wake_up(&group->container_q); list_del(&group->container_next); @@ -1282,13 +1074,19 @@ static int vfio_group_set_container(struct vfio_group *group, int container_fd) goto unlock_out; } + ret = iommu_group_claim_dma_owner(group->iommu_group, f.file); + if (ret) + goto unlock_out; + driver = container->iommu_driver; if (driver) { ret = driver->ops->attach_group(container->iommu_data, group->iommu_group, group->type); - if (ret) + if (ret) { + iommu_group_release_dma_owner(group->iommu_group); goto unlock_out; + } } group->container = container; @@ -1305,12 +1103,6 @@ unlock_out: return ret; } -static bool vfio_group_viable(struct vfio_group *group) -{ - return (iommu_group_for_each_dev(group->iommu_group, - group, vfio_dev_viable) == 0); -} - static int vfio_group_add_container_user(struct vfio_group *group) { if (!atomic_inc_not_zero(&group->container_users)) @@ -1320,7 +1112,7 @@ static int vfio_group_add_container_user(struct vfio_group *group) atomic_dec(&group->container_users); return -EPERM; } - if (!group->container->iommu_driver || !vfio_group_viable(group)) { + if (!group->container->iommu_driver) { atomic_dec(&group->container_users); return -EINVAL; } @@ -1338,7 +1130,7 @@ static int vfio_group_get_device_fd(struct vfio_group *group, char *buf) int ret = 0; if (0 == atomic_read(&group->container_users) || - !group->container->iommu_driver || !vfio_group_viable(group)) + !group->container->iommu_driver) return -EINVAL; if (group->type == VFIO_NO_IOMMU && !capable(CAP_SYS_RAWIO)) @@ -1430,11 +1222,11 @@ static long vfio_group_fops_unl_ioctl(struct file *filep, status.flags = 0; - if (vfio_group_viable(group)) - status.flags |= VFIO_GROUP_FLAGS_VIABLE; - if (group->container) - status.flags |= VFIO_GROUP_FLAGS_CONTAINER_SET; + status.flags |= VFIO_GROUP_FLAGS_CONTAINER_SET | + VFIO_GROUP_FLAGS_VIABLE; + else if (!iommu_group_dma_owner_claimed(group->iommu_group)) + status.flags |= VFIO_GROUP_FLAGS_VIABLE; if (copy_to_user((void __user *)arg, &status, minsz)) return -EFAULT; diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c index 9394aa9444c10c565ce2ffa2aefcfd6b39048f8b..c13b9290e357594575086e71ddf6d997c3f8ba65 100644 --- a/drivers/vfio/vfio_iommu_type1.c +++ b/drivers/vfio/vfio_iommu_type1.c @@ -84,8 +84,8 @@ struct vfio_domain { struct iommu_domain *domain; struct list_head next; struct list_head group_list; - int prot; /* IOMMU_CACHE */ - bool fgsp; /* Fine-grained super pages */ + bool fgsp : 1; /* Fine-grained super pages */ + bool enforce_cache_coherency : 1; }; struct vfio_dma { @@ -1461,7 +1461,7 @@ static int vfio_iommu_map(struct vfio_iommu *iommu, dma_addr_t iova, list_for_each_entry(d, &iommu->domain_list, next) { ret = iommu_map(d->domain, iova, (phys_addr_t)pfn << PAGE_SHIFT, - npage << PAGE_SHIFT, prot | d->prot); + npage << PAGE_SHIFT, prot | IOMMU_CACHE); if (ret) goto unwind; @@ -1771,7 +1771,7 @@ static int vfio_iommu_replay(struct vfio_iommu *iommu, } ret = iommu_map(domain->domain, iova, phys, - size, dma->prot | domain->prot); + size, dma->prot | IOMMU_CACHE); if (ret) { if (!dma->iommu_mapped) { vfio_unpin_pages_remote(dma, iova, @@ -1859,7 +1859,7 @@ static void vfio_test_domain_fgsp(struct vfio_domain *domain) return; ret = iommu_map(domain->domain, 0, page_to_phys(pages), PAGE_SIZE * 2, - IOMMU_READ | IOMMU_WRITE | domain->prot); + IOMMU_READ | IOMMU_WRITE | IOMMU_CACHE); if (!ret) { size_t unmapped = iommu_unmap(domain->domain, 0, PAGE_SIZE); @@ -2267,8 +2267,15 @@ static int vfio_iommu_type1_attach_group(void *iommu_data, goto out_detach; } - if (iommu_capable(bus, IOMMU_CAP_CACHE_COHERENCY)) - domain->prot |= IOMMU_CACHE; + /* + * If the IOMMU can block non-coherent operations (ie PCIe TLPs with + * no-snoop set) then VFIO always turns this feature on because on Intel + * platforms it optimizes KVM to disable wbinvd emulation. + */ + if (domain->domain->ops->enforce_cache_coherency) + domain->enforce_cache_coherency = + domain->domain->ops->enforce_cache_coherency( + domain->domain); /* * Try to match an existing compatible domain. We don't want to @@ -2279,7 +2286,8 @@ static int vfio_iommu_type1_attach_group(void *iommu_data, */ list_for_each_entry(d, &iommu->domain_list, next) { if (d->domain->ops == domain->domain->ops && - d->prot == domain->prot) { + d->enforce_cache_coherency == + domain->enforce_cache_coherency) { iommu_detach_group(domain->domain, group->iommu_group); if (!iommu_attach_group(d->domain, group->iommu_group)) { @@ -2611,14 +2619,14 @@ static void vfio_iommu_type1_release(void *iommu_data) kfree(iommu); } -static int vfio_domains_have_iommu_cache(struct vfio_iommu *iommu) +static int vfio_domains_have_enforce_cache_coherency(struct vfio_iommu *iommu) { struct vfio_domain *domain; int ret = 1; mutex_lock(&iommu->lock); list_for_each_entry(domain, &iommu->domain_list, next) { - if (!(domain->prot & IOMMU_CACHE)) { + if (!(domain->enforce_cache_coherency)) { ret = 0; break; } @@ -2641,7 +2649,7 @@ static int vfio_iommu_type1_check_extension(struct vfio_iommu *iommu, case VFIO_DMA_CC_IOMMU: if (!iommu) return 0; - return vfio_domains_have_iommu_cache(iommu); + return vfio_domains_have_enforce_cache_coherency(iommu); default: return 0; } diff --git a/drivers/video/console/sticore.c b/drivers/video/console/sticore.c index f869b723494f1c276ded7fb643f8da3ce1b6e97c..837011be9978bf606b3bcc7845db1f0e22bfc16f 100644 --- a/drivers/video/console/sticore.c +++ b/drivers/video/console/sticore.c @@ -549,6 +549,26 @@ sti_select_fbfont(struct sti_cooked_rom *cooked_rom, const char *fbfont_name) } #endif +static void sti_dump_font(struct sti_cooked_font *font) +{ +#ifdef STI_DUMP_FONT + unsigned char *p = (unsigned char *)font->raw; + int n; + + p += sizeof(struct sti_rom_font); + pr_debug(" w %d h %d bpc %d\n", font->width, font->height, + font->raw->bytes_per_char); + + for (n = 0; n < 256 * font->raw->bytes_per_char; n += 16, p += 16) { + pr_debug(" 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x," + " 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x," + " 0x%02x, 0x%02x, 0x%02x, 0x%02x,\n", + p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], + p[9], p[10], p[11], p[12], p[13], p[14], p[15]); + } +#endif +} + static int sti_search_font(struct sti_cooked_rom *rom, int height, int width) { struct sti_cooked_font *font; @@ -796,6 +816,7 @@ static int sti_read_rom(int wordmode, struct sti_struct *sti, sti->font->width = sti->font->raw->width; sti->font->height = sti->font->raw->height; sti_font_convert_bytemode(sti, sti->font); + sti_dump_font(sti->font); sti->sti_mem_request = raw->sti_mem_req; sti->graphics_id[0] = raw->graphics_id[0]; diff --git a/drivers/video/fbdev/amba-clcd.c b/drivers/video/fbdev/amba-clcd.c index 9ec969e136bfd6517e2590b539a5822a92fc2f7b..8080116aea844d5556a4b0f22cad92ce5a7f5d6e 100644 --- a/drivers/video/fbdev/amba-clcd.c +++ b/drivers/video/fbdev/amba-clcd.c @@ -758,12 +758,15 @@ static int clcdfb_of_vram_setup(struct clcd_fb *fb) return -ENODEV; fb->fb.screen_base = of_iomap(memory, 0); - if (!fb->fb.screen_base) + if (!fb->fb.screen_base) { + of_node_put(memory); return -ENOMEM; + } fb->fb.fix.smem_start = of_translate_address(memory, of_get_address(memory, 0, &size, NULL)); fb->fb.fix.smem_len = size; + of_node_put(memory); return 0; } diff --git a/drivers/video/fbdev/hyperv_fb.c b/drivers/video/fbdev/hyperv_fb.c index 8359a513b600f1ab02b536994df6fb4992d081d0..886c564787f152f8eef16d0990bf9242662bdc88 100644 --- a/drivers/video/fbdev/hyperv_fb.c +++ b/drivers/video/fbdev/hyperv_fb.c @@ -63,6 +63,7 @@ #define MAX_VMBUS_PKT_SIZE 0x4000 #define SYNTHVID_VERSION(major, minor) ((minor) << 16 | (major)) +/* Support for VERSION_WIN7 is removed. #define is retained for reference. */ #define SYNTHVID_VERSION_WIN7 SYNTHVID_VERSION(3, 0) #define SYNTHVID_VERSION_WIN8 SYNTHVID_VERSION(3, 2) #define SYNTHVID_VERSION_WIN10 SYNTHVID_VERSION(3, 5) @@ -70,13 +71,7 @@ #define SYNTHVID_VER_GET_MAJOR(ver) (ver & 0x0000ffff) #define SYNTHVID_VER_GET_MINOR(ver) ((ver & 0xffff0000) >> 16) -#define SYNTHVID_DEPTH_WIN7 16 #define SYNTHVID_DEPTH_WIN8 32 - -#define SYNTHVID_FB_SIZE_WIN7 (4 * 1024 * 1024) -#define SYNTHVID_WIDTH_MAX_WIN7 1600 -#define SYNTHVID_HEIGHT_MAX_WIN7 1200 - #define SYNTHVID_FB_SIZE_WIN8 (8 * 1024 * 1024) #define PCI_VENDOR_ID_MICROSOFT 0x1414 @@ -643,12 +638,6 @@ static int synthvid_connect_vsp(struct hv_device *hdev) case VERSION_WIN8: case VERSION_WIN8_1: ret = synthvid_negotiate_ver(hdev, SYNTHVID_VERSION_WIN8); - if (!ret) - break; - fallthrough; - case VERSION_WS2008: - case VERSION_WIN7: - ret = synthvid_negotiate_ver(hdev, SYNTHVID_VERSION_WIN7); break; default: ret = synthvid_negotiate_ver(hdev, SYNTHVID_VERSION_WIN10); @@ -660,11 +649,7 @@ static int synthvid_connect_vsp(struct hv_device *hdev) goto error; } - if (par->synthvid_version == SYNTHVID_VERSION_WIN7) - screen_depth = SYNTHVID_DEPTH_WIN7; - else - screen_depth = SYNTHVID_DEPTH_WIN8; - + screen_depth = SYNTHVID_DEPTH_WIN8; if (synthvid_ver_ge(par->synthvid_version, SYNTHVID_VERSION_WIN10)) { ret = synthvid_get_supported_resolution(hdev); if (ret) @@ -933,9 +918,7 @@ static void hvfb_get_option(struct fb_info *info) (synthvid_ver_ge(par->synthvid_version, SYNTHVID_VERSION_WIN10) && (x * y * screen_depth / 8 > screen_fb_size)) || (par->synthvid_version == SYNTHVID_VERSION_WIN8 && - x * y * screen_depth / 8 > SYNTHVID_FB_SIZE_WIN8) || - (par->synthvid_version == SYNTHVID_VERSION_WIN7 && - (x > SYNTHVID_WIDTH_MAX_WIN7 || y > SYNTHVID_HEIGHT_MAX_WIN7))) { + x * y * screen_depth / 8 > SYNTHVID_FB_SIZE_WIN8)) { pr_err("Screen resolution option is out of range: skipped\n"); return; } @@ -1009,7 +992,6 @@ static int hvfb_getmem(struct hv_device *hdev, struct fb_info *info) struct pci_dev *pdev = NULL; void __iomem *fb_virt; int gen2vm = efi_enabled(EFI_BOOT); - resource_size_t pot_start, pot_end; phys_addr_t paddr; int ret; @@ -1060,23 +1042,7 @@ static int hvfb_getmem(struct hv_device *hdev, struct fb_info *info) dio_fb_size = screen_width * screen_height * screen_depth / 8; - if (gen2vm) { - pot_start = 0; - pot_end = -1; - } else { - if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM) || - pci_resource_len(pdev, 0) < screen_fb_size) { - pr_err("Resource not available or (0x%lx < 0x%lx)\n", - (unsigned long) pci_resource_len(pdev, 0), - (unsigned long) screen_fb_size); - goto err1; - } - - pot_end = pci_resource_end(pdev, 0); - pot_start = pot_end - screen_fb_size + 1; - } - - ret = vmbus_allocate_mmio(&par->mem, hdev, pot_start, pot_end, + ret = vmbus_allocate_mmio(&par->mem, hdev, 0, -1, screen_fb_size, 0x100000, true); if (ret != 0) { pr_err("Unable to allocate framebuffer memory\n"); diff --git a/drivers/video/fbdev/omap/omapfb.h b/drivers/video/fbdev/omap/omapfb.h index 313a051fe7a42c98a765e1681f164c8d5be748e4..beb841ccb99cd7528f06f2a4dc539766384514c3 100644 --- a/drivers/video/fbdev/omap/omapfb.h +++ b/drivers/video/fbdev/omap/omapfb.h @@ -231,5 +231,9 @@ extern int omapfb_update_window_async(struct fb_info *fbi, struct omapfb_update_window *win, void (*callback)(void *), void *callback_data); +extern int hwa742_update_window_async(struct fb_info *fbi, + struct omapfb_update_window *win, + void (*callback)(void *), + void *callback_data); #endif /* __OMAPFB_H */ diff --git a/drivers/video/fbdev/omap2/omapfb/displays/panel-nec-nl8048hl11.c b/drivers/video/fbdev/omap2/omapfb/displays/panel-nec-nl8048hl11.c index be9910ff6e62d410b90d77a39337083317443c85..b407173e27b1f166486b3c21d9be37c51a1b6f61 100644 --- a/drivers/video/fbdev/omap2/omapfb/displays/panel-nec-nl8048hl11.c +++ b/drivers/video/fbdev/omap2/omapfb/displays/panel-nec-nl8048hl11.c @@ -117,16 +117,11 @@ static int nec_8048_connect(struct omap_dss_device *dssdev) { struct panel_drv_data *ddata = to_panel_data(dssdev); struct omap_dss_device *in = ddata->in; - int r; if (omapdss_device_is_connected(dssdev)) return 0; - r = in->ops.dpi->connect(in, dssdev); - if (r) - return r; - - return 0; + return in->ops.dpi->connect(in, dssdev); } static void nec_8048_disconnect(struct omap_dss_device *dssdev) diff --git a/drivers/video/fbdev/omap2/omapfb/dss/hdmi_pll.c b/drivers/video/fbdev/omap2/omapfb/dss/hdmi_pll.c index c5f89129dcddd08d5d3bd3abd4f997b4ea0a5ec6..531b36d2232b8cabe2fe3398009384b65d1008aa 100644 --- a/drivers/video/fbdev/omap2/omapfb/dss/hdmi_pll.c +++ b/drivers/video/fbdev/omap2/omapfb/dss/hdmi_pll.c @@ -173,7 +173,6 @@ static int dsi_init_pll_data(struct platform_device *pdev, struct hdmi_pll_data { struct dss_pll *pll = &hpll->pll; struct clk *clk; - int r; clk = devm_clk_get(&pdev->dev, "sys_clk"); if (IS_ERR(clk)) { @@ -203,12 +202,7 @@ static int dsi_init_pll_data(struct platform_device *pdev, struct hdmi_pll_data } pll->ops = &dsi_pll_ops; - - r = dss_pll_register(pll); - if (r) - return r; - - return 0; + return dss_pll_register(pll); } int hdmi_pll_init(struct platform_device *pdev, struct hdmi_pll_data *pll, diff --git a/drivers/video/fbdev/pxa3xx-gcu.c b/drivers/video/fbdev/pxa3xx-gcu.c index 350b3139c863ec6616276c466a638e51bcdfc58a..043cc8f9ef1c73d0022d7bd1e7bf0b0ee5b4d388 100644 --- a/drivers/video/fbdev/pxa3xx-gcu.c +++ b/drivers/video/fbdev/pxa3xx-gcu.c @@ -646,6 +646,7 @@ static int pxa3xx_gcu_probe(struct platform_device *pdev) for (i = 0; i < 8; i++) { ret = pxa3xx_gcu_add_buffer(dev, priv); if (ret) { + pxa3xx_gcu_free_buffers(dev, priv); dev_err(dev, "failed to allocate DMA memory\n"); goto err_disable_clk; } @@ -662,15 +663,15 @@ static int pxa3xx_gcu_probe(struct platform_device *pdev) SHARED_SIZE, irq); return 0; -err_free_dma: - dma_free_coherent(dev, SHARED_SIZE, - priv->shared, priv->shared_phys); +err_disable_clk: + clk_disable_unprepare(priv->clk); err_misc_deregister: misc_deregister(&priv->misc_dev); -err_disable_clk: - clk_disable_unprepare(priv->clk); +err_free_dma: + dma_free_coherent(dev, SHARED_SIZE, + priv->shared, priv->shared_phys); return ret; } @@ -683,6 +684,7 @@ static int pxa3xx_gcu_remove(struct platform_device *pdev) pxa3xx_gcu_wait_idle(priv); misc_deregister(&priv->misc_dev); dma_free_coherent(dev, SHARED_SIZE, priv->shared, priv->shared_phys); + clk_disable_unprepare(priv->clk); pxa3xx_gcu_free_buffers(dev, priv); return 0; diff --git a/drivers/video/fbdev/vesafb.c b/drivers/video/fbdev/vesafb.c index e25e8de5ff672de983837762f39ef9f8034a7a6f..929d4775cb4bcc73048d6a342c116dc422b71238 100644 --- a/drivers/video/fbdev/vesafb.c +++ b/drivers/video/fbdev/vesafb.c @@ -490,11 +490,12 @@ static int vesafb_remove(struct platform_device *pdev) { struct fb_info *info = platform_get_drvdata(pdev); - /* vesafb_destroy takes care of info cleanup */ - unregister_framebuffer(info); if (((struct vesafb_par *)(info->par))->region) release_region(0x3c0, 32); + /* vesafb_destroy takes care of info cleanup */ + unregister_framebuffer(info); + return 0; } diff --git a/drivers/video/fbdev/xen-fbfront.c b/drivers/video/fbdev/xen-fbfront.c index 3bed357a98703e30db607325deab3e5c6cb1e411..4d2694d904aab6b065b9f64c5530693a5b11e77d 100644 --- a/drivers/video/fbdev/xen-fbfront.c +++ b/drivers/video/fbdev/xen-fbfront.c @@ -223,7 +223,6 @@ static int xenfb_setcolreg(unsigned regno, unsigned red, unsigned green, red = CNVT_TOHW(red, info->var.red.length); green = CNVT_TOHW(green, info->var.green.length); blue = CNVT_TOHW(blue, info->var.blue.length); - transp = CNVT_TOHW(transp, info->var.transp.length); #undef CNVT_TOHW v = (red << info->var.red.offset) | diff --git a/fs/Kconfig.binfmt b/fs/Kconfig.binfmt index 32dff7ba3ddaaf12ff34505c679c62fda5a2d738..21e154516bf297e35bfbd9884731110609315698 100644 --- a/fs/Kconfig.binfmt +++ b/fs/Kconfig.binfmt @@ -58,7 +58,7 @@ config ARCH_USE_GNU_PROPERTY config BINFMT_ELF_FDPIC bool "Kernel support for FDPIC ELF binaries" default y if !BINFMT_ELF - depends on (ARM || (SUPERH && !MMU)) + depends on ARM || ((M68K || SUPERH) && !MMU) select ELFCORE help ELF FDPIC binaries are based on ELF, but allow the individual load diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c index 9d334816eac074a5edc2233d44a2008e1956a376..1dd995efd5b8623b5f4eb79bd16bc9cd5abbc25c 100644 --- a/fs/cifs/cifs_debug.c +++ b/fs/cifs/cifs_debug.c @@ -116,7 +116,8 @@ static void cifs_debug_tcon(struct seq_file *m, struct cifs_tcon *tcon) tcon->ses->server->ops->dump_share_caps(m, tcon); if (tcon->use_witness) seq_puts(m, " Witness"); - + if (tcon->broken_sparse_sup) + seq_puts(m, " nosparse"); if (tcon->need_reconnect) seq_puts(m, "\tDISCONNECTED "); seq_putc(m, '\n'); @@ -386,7 +387,7 @@ skip_rdma: (ses->serverNOS == NULL)) { seq_printf(m, "\n\t%d) Address: %s Uses: %d Capability: 0x%x\tSession Status: %d ", i, ses->ip_addr, ses->ses_count, - ses->capabilities, ses->status); + ses->capabilities, ses->ses_status); if (ses->session_flags & SMB2_SESSION_FLAG_IS_GUEST) seq_printf(m, "Guest "); else if (ses->session_flags & SMB2_SESSION_FLAG_IS_NULL) @@ -398,7 +399,7 @@ skip_rdma: "\n\tSMB session status: %d ", i, ses->ip_addr, ses->serverDomain, ses->ses_count, ses->serverOS, ses->serverNOS, - ses->capabilities, ses->status); + ses->capabilities, ses->ses_status); } seq_printf(m, "\n\tSecurity type: %s ", @@ -418,6 +419,8 @@ skip_rdma: spin_lock(&ses->chan_lock); if (CIFS_CHAN_NEEDS_RECONNECT(ses, 0)) seq_puts(m, "\tPrimary channel: DISCONNECTED "); + if (CIFS_CHAN_IN_RECONNECT(ses, 0)) + seq_puts(m, "\t[RECONNECTING] "); if (ses->chan_count > 1) { seq_printf(m, "\n\n\tExtra Channels: %zu ", @@ -426,6 +429,8 @@ skip_rdma: cifs_dump_channel(m, j, &ses->chans[j]); if (CIFS_CHAN_NEEDS_RECONNECT(ses, j)) seq_puts(m, "\tDISCONNECTED "); + if (CIFS_CHAN_IN_RECONNECT(ses, j)) + seq_puts(m, "\t[RECONNECTING] "); } } spin_unlock(&ses->chan_lock); diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 2b1a1c029c75ec19376a7250fb806b516e59ad03..f539a39d47f50ca6ce78f5eb3cf9fddcc8490040 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -582,6 +582,8 @@ cifs_show_options(struct seq_file *s, struct dentry *root) seq_puts(s, ",nocase"); if (tcon->nodelete) seq_puts(s, ",nodelete"); + if (cifs_sb->ctx->no_sparse) + seq_puts(s, ",nosparse"); if (tcon->local_lease) seq_puts(s, ",locallease"); if (tcon->retry) diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 8de977c359b1132462c533996187d1cb1b00a873..68da230c7f11284ecb7444805e63c5ae4a24944e 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -106,7 +106,7 @@ * CIFS vfs client Status information (based on what we know.) */ -/* associated with each tcp and smb session */ +/* associated with each connection */ enum statusEnum { CifsNew = 0, CifsGood, @@ -114,8 +114,15 @@ enum statusEnum { CifsNeedReconnect, CifsNeedNegotiate, CifsInNegotiate, - CifsNeedSessSetup, - CifsInSessSetup, +}; + +/* associated with each smb session */ +enum ses_status_enum { + SES_NEW = 0, + SES_GOOD, + SES_EXITING, + SES_NEED_RECON, + SES_IN_SETUP }; /* associated with each tree connection to the server */ @@ -915,6 +922,7 @@ struct cifs_server_iface { }; struct cifs_chan { + unsigned int in_reconnect : 1; /* if session setup in progress for this channel */ struct TCP_Server_Info *server; __u8 signkey[SMB3_SIGN_KEY_SIZE]; }; @@ -930,7 +938,7 @@ struct cifs_ses { struct mutex session_mutex; struct TCP_Server_Info *server; /* pointer to server info */ int ses_count; /* reference counter */ - enum statusEnum status; /* updates protected by cifs_tcp_ses_lock */ + enum ses_status_enum ses_status; /* updates protected by cifs_tcp_ses_lock */ unsigned overrideSecFlg; /* if non-zero override global sec flags */ char *serverOS; /* name of operating system underlying server */ char *serverNOS; /* name of network operating system of server */ @@ -944,7 +952,7 @@ struct cifs_ses { and after mount option parsing we fill it */ char *domainName; char *password; - char *workstation_name; + char workstation_name[CIFS_MAX_WORKSTATION_LEN]; struct session_key auth_key; struct ntlmssp_auth *ntlmssp; /* ciphertext, flags, server challenge */ enum securityEnum sectype; /* what security flavor was specified? */ @@ -977,12 +985,16 @@ struct cifs_ses { #define CIFS_MAX_CHANNELS 16 #define CIFS_ALL_CHANNELS_SET(ses) \ ((1UL << (ses)->chan_count) - 1) +#define CIFS_ALL_CHANS_GOOD(ses) \ + (!(ses)->chans_need_reconnect) #define CIFS_ALL_CHANS_NEED_RECONNECT(ses) \ ((ses)->chans_need_reconnect == CIFS_ALL_CHANNELS_SET(ses)) #define CIFS_SET_ALL_CHANS_NEED_RECONNECT(ses) \ ((ses)->chans_need_reconnect = CIFS_ALL_CHANNELS_SET(ses)) #define CIFS_CHAN_NEEDS_RECONNECT(ses, index) \ test_bit((index), &(ses)->chans_need_reconnect) +#define CIFS_CHAN_IN_RECONNECT(ses, index) \ + ((ses)->chans[(index)].in_reconnect) struct cifs_chan chans[CIFS_MAX_CHANNELS]; size_t chan_count; @@ -1009,6 +1021,58 @@ cap_unix(struct cifs_ses *ses) return ses->server->vals->cap_unix & ses->capabilities; } +/* + * common struct for holding inode info when searching for or updating an + * inode with new info + */ + +#define CIFS_FATTR_DFS_REFERRAL 0x1 +#define CIFS_FATTR_DELETE_PENDING 0x2 +#define CIFS_FATTR_NEED_REVAL 0x4 +#define CIFS_FATTR_INO_COLLISION 0x8 +#define CIFS_FATTR_UNKNOWN_NLINK 0x10 +#define CIFS_FATTR_FAKE_ROOT_INO 0x20 + +struct cifs_fattr { + u32 cf_flags; + u32 cf_cifsattrs; + u64 cf_uniqueid; + u64 cf_eof; + u64 cf_bytes; + u64 cf_createtime; + kuid_t cf_uid; + kgid_t cf_gid; + umode_t cf_mode; + dev_t cf_rdev; + unsigned int cf_nlink; + unsigned int cf_dtype; + struct timespec64 cf_atime; + struct timespec64 cf_mtime; + struct timespec64 cf_ctime; + u32 cf_cifstag; +}; + +struct cached_dirent { + struct list_head entry; + char *name; + int namelen; + loff_t pos; + + struct cifs_fattr fattr; +}; + +struct cached_dirents { + bool is_valid:1; + bool is_failed:1; + struct dir_context *ctx; /* + * Only used to make sure we only take entries + * from a single context. Never dereferenced. + */ + struct mutex de_mutex; + int pos; /* Expected ctx->pos */ + struct list_head entries; +}; + struct cached_fid { bool is_valid:1; /* Do we have a useable root fid */ bool file_all_info_is_valid:1; @@ -1021,6 +1085,7 @@ struct cached_fid { struct dentry *dentry; struct work_struct lease_break; struct smb2_file_all_info file_all_info; + struct cached_dirents dirents; }; /* @@ -1641,37 +1706,6 @@ struct file_list { struct cifsFileInfo *cfile; }; -/* - * common struct for holding inode info when searching for or updating an - * inode with new info - */ - -#define CIFS_FATTR_DFS_REFERRAL 0x1 -#define CIFS_FATTR_DELETE_PENDING 0x2 -#define CIFS_FATTR_NEED_REVAL 0x4 -#define CIFS_FATTR_INO_COLLISION 0x8 -#define CIFS_FATTR_UNKNOWN_NLINK 0x10 -#define CIFS_FATTR_FAKE_ROOT_INO 0x20 - -struct cifs_fattr { - u32 cf_flags; - u32 cf_cifsattrs; - u64 cf_uniqueid; - u64 cf_eof; - u64 cf_bytes; - u64 cf_createtime; - kuid_t cf_uid; - kgid_t cf_gid; - umode_t cf_mode; - dev_t cf_rdev; - unsigned int cf_nlink; - unsigned int cf_dtype; - struct timespec64 cf_atime; - struct timespec64 cf_mtime; - struct timespec64 cf_ctime; - u32 cf_cifstag; -}; - static inline void free_dfs_info_param(struct dfs_info3_param *param) { if (param) { @@ -1979,4 +2013,22 @@ static inline bool cifs_is_referral_server(struct cifs_tcon *tcon, return is_tcon_dfs(tcon) || (ref && (ref->flags & DFSREF_REFERRAL_SERVER)); } +static inline u64 cifs_flock_len(struct file_lock *fl) +{ + return fl->fl_end == OFFSET_MAX ? 0 : fl->fl_end - fl->fl_start + 1; +} + +static inline size_t ntlmssp_workstation_name_size(const struct cifs_ses *ses) +{ + if (WARN_ON_ONCE(!ses || !ses->server)) + return 0; + /* + * Make workstation name no more than 15 chars when using insecure dialects as some legacy + * servers do require it during NTLMSSP. + */ + if (ses->server->dialect <= SMB20_PROT_ID) + return min_t(size_t, sizeof(ses->workstation_name), RFC1001_NAME_LEN_WITH_NULL); + return sizeof(ses->workstation_name); +} + #endif /* _CIFS_GLOB_H */ diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 0df3b24a0bf4cc5c36b80596618fdc1e6f0cdad4..3b7366ec03c76230ff5c28e42c5e929424bca192 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -619,6 +619,15 @@ unsigned int cifs_ses_get_chan_index(struct cifs_ses *ses, struct TCP_Server_Info *server); void +cifs_chan_set_in_reconnect(struct cifs_ses *ses, + struct TCP_Server_Info *server); +void +cifs_chan_clear_in_reconnect(struct cifs_ses *ses, + struct TCP_Server_Info *server); +bool +cifs_chan_in_reconnect(struct cifs_ses *ses, + struct TCP_Server_Info *server); +void cifs_chan_set_need_reconnect(struct cifs_ses *ses, struct TCP_Server_Info *server); void diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 47e927c4ff8de3fb2b9e87daf48873b80117a8da..6371b9eebdad82009070fc120687bef373812053 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -75,7 +75,7 @@ cifs_mark_open_files_invalid(struct cifs_tcon *tcon) /* only send once per connect */ spin_lock(&cifs_tcp_ses_lock); - if ((tcon->ses->status != CifsGood) || (tcon->status != TID_NEED_RECON)) { + if ((tcon->ses->ses_status != SES_GOOD) || (tcon->status != TID_NEED_RECON)) { spin_unlock(&cifs_tcp_ses_lock); return; } @@ -2558,7 +2558,8 @@ CIFSSMBPosixLock(const unsigned int xid, struct cifs_tcon *tcon, pLockData->fl_start = le64_to_cpu(parm_data->start); pLockData->fl_end = pLockData->fl_start + - le64_to_cpu(parm_data->length) - 1; + (le64_to_cpu(parm_data->length) ? + le64_to_cpu(parm_data->length) - 1 : 0); pLockData->fl_pid = -le32_to_cpu(parm_data->pid); } } diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 42e14f408856d6e6d40f6ecaada3e350f893b4da..53373a3649e17efbcb4e022a2685903108e12996 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -241,7 +241,7 @@ cifs_mark_tcp_ses_conns_for_reconnect(struct TCP_Server_Info *server, if (!mark_smb_session && !CIFS_ALL_CHANS_NEED_RECONNECT(ses)) goto next_session; - ses->status = CifsNeedReconnect; + ses->ses_status = SES_NEED_RECON; list_for_each_entry(tcon, &ses->tcon_list, tcon_list) { tcon->need_reconnect = true; @@ -1789,7 +1789,7 @@ cifs_setup_ipc(struct cifs_ses *ses, struct smb3_fs_context *ctx) goto out; } - cifs_dbg(FYI, "IPC tcon rc = %d ipc tid = %d\n", rc, tcon->tid); + cifs_dbg(FYI, "IPC tcon rc=%d ipc tid=0x%x\n", rc, tcon->tid); ses->tcon_ipc = tcon; out: @@ -1828,7 +1828,7 @@ cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx) spin_lock(&cifs_tcp_ses_lock); list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) { - if (ses->status == CifsExiting) + if (ses->ses_status == SES_EXITING) continue; if (!match_session(ses, ctx)) continue; @@ -1848,7 +1848,7 @@ void cifs_put_smb_ses(struct cifs_ses *ses) cifs_dbg(FYI, "%s: ses_count=%d\n", __func__, ses->ses_count); spin_lock(&cifs_tcp_ses_lock); - if (ses->status == CifsExiting) { + if (ses->ses_status == SES_EXITING) { spin_unlock(&cifs_tcp_ses_lock); return; } @@ -1864,13 +1864,13 @@ void cifs_put_smb_ses(struct cifs_ses *ses) /* ses_count can never go negative */ WARN_ON(ses->ses_count < 0); - if (ses->status == CifsGood) - ses->status = CifsExiting; + if (ses->ses_status == SES_GOOD) + ses->ses_status = SES_EXITING; spin_unlock(&cifs_tcp_ses_lock); cifs_free_ipc(ses); - if (ses->status == CifsExiting && server->ops->logoff) { + if (ses->ses_status == SES_EXITING && server->ops->logoff) { xid = get_xid(); rc = server->ops->logoff(xid, ses); if (rc) @@ -2037,18 +2037,7 @@ cifs_set_cifscreds(struct smb3_fs_context *ctx, struct cifs_ses *ses) } } - ctx->workstation_name = kstrdup(ses->workstation_name, GFP_KERNEL); - if (!ctx->workstation_name) { - cifs_dbg(FYI, "Unable to allocate memory for workstation_name\n"); - rc = -ENOMEM; - kfree(ctx->username); - ctx->username = NULL; - kfree_sensitive(ctx->password); - ctx->password = NULL; - kfree(ctx->domainname); - ctx->domainname = NULL; - goto out_key_put; - } + strscpy(ctx->workstation_name, ses->workstation_name, sizeof(ctx->workstation_name)); out_key_put: up_read(&key->sem); @@ -2090,7 +2079,7 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx) ses = cifs_find_smb_ses(server, ctx); if (ses) { cifs_dbg(FYI, "Existing smb sess found (status=%d)\n", - ses->status); + ses->ses_status); spin_lock(&ses->chan_lock); if (cifs_chan_needs_reconnect(ses, server)) { @@ -2157,12 +2146,9 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx) if (!ses->domainName) goto get_ses_fail; } - if (ctx->workstation_name) { - ses->workstation_name = kstrdup(ctx->workstation_name, - GFP_KERNEL); - if (!ses->workstation_name) - goto get_ses_fail; - } + + strscpy(ses->workstation_name, ctx->workstation_name, sizeof(ses->workstation_name)); + if (ctx->domainauto) ses->domainAuto = ctx->domainauto; ses->cred_uid = ctx->cred_uid; @@ -2509,6 +2495,7 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb3_fs_context *ctx) */ tcon->retry = ctx->retry; tcon->nocase = ctx->nocase; + tcon->broken_sparse_sup = ctx->no_sparse; if (ses->server->capabilities & SMB2_GLOBAL_CAP_DIRECTORY_LEASING) tcon->nohandlecache = ctx->nohandlecache; else @@ -3420,8 +3407,9 @@ cifs_are_all_path_components_accessible(struct TCP_Server_Info *server, } /* - * Check if path is remote (e.g. a DFS share). Return -EREMOTE if it is, - * otherwise 0. + * Check if path is remote (i.e. a DFS share). + * + * Return -EREMOTE if it is, otherwise 0 or -errno. */ static int is_path_remote(struct mount_ctx *mnt_ctx) { @@ -3432,6 +3420,9 @@ static int is_path_remote(struct mount_ctx *mnt_ctx) struct cifs_tcon *tcon = mnt_ctx->tcon; struct smb3_fs_context *ctx = mnt_ctx->fs_ctx; char *full_path; +#ifdef CONFIG_CIFS_DFS_UPCALL + bool nodfs = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS; +#endif if (!server->ops->is_path_accessible) return -EOPNOTSUPP; @@ -3449,14 +3440,20 @@ static int is_path_remote(struct mount_ctx *mnt_ctx) rc = server->ops->is_path_accessible(xid, tcon, cifs_sb, full_path); #ifdef CONFIG_CIFS_DFS_UPCALL + if (nodfs) { + if (rc == -EREMOTE) + rc = -EOPNOTSUPP; + goto out; + } + + /* path *might* exist with non-ASCII characters in DFS root + * try again with full path (only if nodfs is not set) */ if (rc == -ENOENT && is_tcon_dfs(tcon)) rc = cifs_dfs_query_info_nonascii_quirk(xid, tcon, cifs_sb, full_path); #endif - if (rc != 0 && rc != -EREMOTE) { - kfree(full_path); - return rc; - } + if (rc != 0 && rc != -EREMOTE) + goto out; if (rc != -EREMOTE) { rc = cifs_are_all_path_components_accessible(server, xid, tcon, @@ -3468,6 +3465,7 @@ static int is_path_remote(struct mount_ctx *mnt_ctx) } } +out: kfree(full_path); return rc; } @@ -3703,6 +3701,7 @@ int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb3_fs_context *ctx) if (!isdfs) goto out; + /* proceed as DFS mount */ uuid_gen(&mnt_ctx.mount_id); rc = connect_dfs_root(&mnt_ctx, &tl); dfs_cache_free_tgts(&tl); @@ -3960,7 +3959,7 @@ cifs_negotiate_protocol(const unsigned int xid, struct cifs_ses *ses, if (rc == 0) { spin_lock(&cifs_tcp_ses_lock); if (server->tcpStatus == CifsInNegotiate) - server->tcpStatus = CifsNeedSessSetup; + server->tcpStatus = CifsGood; else rc = -EHOSTDOWN; spin_unlock(&cifs_tcp_ses_lock); @@ -3982,20 +3981,31 @@ cifs_setup_session(const unsigned int xid, struct cifs_ses *ses, int rc = -ENOSYS; bool is_binding = false; - /* only send once per connect */ + spin_lock(&cifs_tcp_ses_lock); - if ((server->tcpStatus != CifsNeedSessSetup) && - (ses->status == CifsGood)) { + if (ses->ses_status != SES_GOOD && + ses->ses_status != SES_NEW && + ses->ses_status != SES_NEED_RECON) { spin_unlock(&cifs_tcp_ses_lock); return 0; } - server->tcpStatus = CifsInSessSetup; - spin_unlock(&cifs_tcp_ses_lock); + /* only send once per connect */ spin_lock(&ses->chan_lock); + if (CIFS_ALL_CHANS_GOOD(ses) || + cifs_chan_in_reconnect(ses, server)) { + spin_unlock(&ses->chan_lock); + spin_unlock(&cifs_tcp_ses_lock); + return 0; + } is_binding = !CIFS_ALL_CHANS_NEED_RECONNECT(ses); + cifs_chan_set_in_reconnect(ses, server); spin_unlock(&ses->chan_lock); + if (!is_binding) + ses->ses_status = SES_IN_SETUP; + spin_unlock(&cifs_tcp_ses_lock); + if (!is_binding) { ses->capabilities = server->capabilities; if (!linuxExtEnabled) @@ -4019,20 +4029,21 @@ cifs_setup_session(const unsigned int xid, struct cifs_ses *ses, if (rc) { cifs_server_dbg(VFS, "Send error in SessSetup = %d\n", rc); spin_lock(&cifs_tcp_ses_lock); - if (server->tcpStatus == CifsInSessSetup) - server->tcpStatus = CifsNeedSessSetup; + if (ses->ses_status == SES_IN_SETUP) + ses->ses_status = SES_NEED_RECON; + spin_lock(&ses->chan_lock); + cifs_chan_clear_in_reconnect(ses, server); + spin_unlock(&ses->chan_lock); spin_unlock(&cifs_tcp_ses_lock); } else { spin_lock(&cifs_tcp_ses_lock); - if (server->tcpStatus == CifsInSessSetup) - server->tcpStatus = CifsGood; - /* Even if one channel is active, session is in good state */ - ses->status = CifsGood; - spin_unlock(&cifs_tcp_ses_lock); - + if (ses->ses_status == SES_IN_SETUP) + ses->ses_status = SES_GOOD; spin_lock(&ses->chan_lock); + cifs_chan_clear_in_reconnect(ses, server); cifs_chan_clear_need_reconnect(ses, server); spin_unlock(&ses->chan_lock); + spin_unlock(&cifs_tcp_ses_lock); } return rc; @@ -4497,7 +4508,7 @@ int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon, const stru /* only send once per connect */ spin_lock(&cifs_tcp_ses_lock); - if (tcon->ses->status != CifsGood || + if (tcon->ses->ses_status != SES_GOOD || (tcon->status != TID_NEW && tcon->status != TID_NEED_TCON)) { spin_unlock(&cifs_tcp_ses_lock); @@ -4565,7 +4576,7 @@ int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon, const stru /* only send once per connect */ spin_lock(&cifs_tcp_ses_lock); - if (tcon->ses->status != CifsGood || + if (tcon->ses->ses_status != SES_GOOD || (tcon->status != TID_NEW && tcon->status != TID_NEED_TCON)) { spin_unlock(&cifs_tcp_ses_lock); diff --git a/fs/cifs/dfs_cache.c b/fs/cifs/dfs_cache.c index 956f8e5cf3e7423438b235a99711563c9ccbb205..c5dd6f7305bd161eac0fa34857ca62a72182cb8e 100644 --- a/fs/cifs/dfs_cache.c +++ b/fs/cifs/dfs_cache.c @@ -654,7 +654,7 @@ static struct cache_entry *__lookup_cache_entry(const char *path, unsigned int h return ce; } } - return ERR_PTR(-EEXIST); + return ERR_PTR(-ENOENT); } /* @@ -662,7 +662,7 @@ static struct cache_entry *__lookup_cache_entry(const char *path, unsigned int h * * Use whole path components in the match. Must be called with htable_rw_lock held. * - * Return ERR_PTR(-EEXIST) if the entry is not found. + * Return ERR_PTR(-ENOENT) if the entry is not found. */ static struct cache_entry *lookup_cache_entry(const char *path) { @@ -710,7 +710,7 @@ static struct cache_entry *lookup_cache_entry(const char *path) while (e > s && *e != sep) e--; } - return ERR_PTR(-EEXIST); + return ERR_PTR(-ENOENT); } /** diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 580a847aa8b52ec7d9217d3487a48f8c6a5f0095..1618e0537d58c7d0438643dd309bd21f498a8b7d 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -1395,7 +1395,7 @@ cifs_push_posix_locks(struct cifsFileInfo *cfile) cifs_dbg(VFS, "Can't push all brlocks!\n"); break; } - length = 1 + flock->fl_end - flock->fl_start; + length = cifs_flock_len(flock); if (flock->fl_type == F_RDLCK || flock->fl_type == F_SHLCK) type = CIFS_RDLCK; else @@ -1511,7 +1511,7 @@ cifs_getlk(struct file *file, struct file_lock *flock, __u32 type, bool wait_flag, bool posix_lck, unsigned int xid) { int rc = 0; - __u64 length = 1 + flock->fl_end - flock->fl_start; + __u64 length = cifs_flock_len(flock); struct cifsFileInfo *cfile = (struct cifsFileInfo *)file->private_data; struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); struct TCP_Server_Info *server = tcon->ses->server; @@ -1609,7 +1609,7 @@ cifs_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock, struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); struct cifsInodeInfo *cinode = CIFS_I(d_inode(cfile->dentry)); struct cifsLockInfo *li, *tmp; - __u64 length = 1 + flock->fl_end - flock->fl_start; + __u64 length = cifs_flock_len(flock); struct list_head tmp_llist; INIT_LIST_HEAD(&tmp_llist); @@ -1713,7 +1713,7 @@ cifs_setlk(struct file *file, struct file_lock *flock, __u32 type, unsigned int xid) { int rc = 0; - __u64 length = 1 + flock->fl_end - flock->fl_start; + __u64 length = cifs_flock_len(flock); struct cifsFileInfo *cfile = (struct cifsFileInfo *)file->private_data; struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); struct TCP_Server_Info *server = tcon->ses->server; @@ -2777,8 +2777,11 @@ int cifs_flush(struct file *file, fl_owner_t id) rc = filemap_write_and_wait(inode->i_mapping); cifs_dbg(FYI, "Flush inode %p file %p rc %d\n", inode, file, rc); - if (rc) + if (rc) { + /* get more nuanced writeback errors */ + rc = filemap_check_wb_err(file->f_mapping, 0); trace_cifs_flush_err(inode->i_ino, rc); + } return rc; } diff --git a/fs/cifs/fs_context.c b/fs/cifs/fs_context.c index a92e9eec521f35ede489af492b56a50af48b30f4..8dc0d923ef6a98bb279d883ee01f2b03b6ca2a1a 100644 --- a/fs/cifs/fs_context.c +++ b/fs/cifs/fs_context.c @@ -119,6 +119,7 @@ const struct fs_parameter_spec smb3_fs_parameters[] = { fsparam_flag_no("persistenthandles", Opt_persistent), fsparam_flag_no("resilienthandles", Opt_resilient), fsparam_flag_no("tcpnodelay", Opt_tcp_nodelay), + fsparam_flag("nosparse", Opt_nosparse), fsparam_flag("domainauto", Opt_domainauto), fsparam_flag("rdma", Opt_rdma), fsparam_flag("modesid", Opt_modesid), @@ -312,7 +313,6 @@ smb3_fs_context_dup(struct smb3_fs_context *new_ctx, struct smb3_fs_context *ctx new_ctx->password = NULL; new_ctx->server_hostname = NULL; new_ctx->domainname = NULL; - new_ctx->workstation_name = NULL; new_ctx->UNC = NULL; new_ctx->source = NULL; new_ctx->iocharset = NULL; @@ -327,7 +327,6 @@ smb3_fs_context_dup(struct smb3_fs_context *new_ctx, struct smb3_fs_context *ctx DUP_CTX_STR(UNC); DUP_CTX_STR(source); DUP_CTX_STR(domainname); - DUP_CTX_STR(workstation_name); DUP_CTX_STR(nodename); DUP_CTX_STR(iocharset); @@ -766,8 +765,7 @@ static int smb3_verify_reconfigure_ctx(struct fs_context *fc, cifs_errorf(fc, "can not change domainname during remount\n"); return -EINVAL; } - if (new_ctx->workstation_name && - (!old_ctx->workstation_name || strcmp(new_ctx->workstation_name, old_ctx->workstation_name))) { + if (strcmp(new_ctx->workstation_name, old_ctx->workstation_name)) { cifs_errorf(fc, "can not change workstation_name during remount\n"); return -EINVAL; } @@ -814,7 +812,6 @@ static int smb3_reconfigure(struct fs_context *fc) STEAL_STRING(cifs_sb, ctx, username); STEAL_STRING(cifs_sb, ctx, password); STEAL_STRING(cifs_sb, ctx, domainname); - STEAL_STRING(cifs_sb, ctx, workstation_name); STEAL_STRING(cifs_sb, ctx, nodename); STEAL_STRING(cifs_sb, ctx, iocharset); @@ -943,6 +940,9 @@ static int smb3_fs_context_parse_param(struct fs_context *fc, case Opt_nolease: ctx->no_lease = 1; break; + case Opt_nosparse: + ctx->no_sparse = 1; + break; case Opt_nodelete: ctx->nodelete = 1; break; @@ -1467,22 +1467,15 @@ static int smb3_fs_context_parse_param(struct fs_context *fc, int smb3_init_fs_context(struct fs_context *fc) { - int rc; struct smb3_fs_context *ctx; char *nodename = utsname()->nodename; int i; ctx = kzalloc(sizeof(struct smb3_fs_context), GFP_KERNEL); - if (unlikely(!ctx)) { - rc = -ENOMEM; - goto err_exit; - } + if (unlikely(!ctx)) + return -ENOMEM; - ctx->workstation_name = kstrdup(nodename, GFP_KERNEL); - if (unlikely(!ctx->workstation_name)) { - rc = -ENOMEM; - goto err_exit; - } + strscpy(ctx->workstation_name, nodename, sizeof(ctx->workstation_name)); /* * does not have to be perfect mapping since field is @@ -1555,14 +1548,6 @@ int smb3_init_fs_context(struct fs_context *fc) fc->fs_private = ctx; fc->ops = &smb3_fs_context_ops; return 0; - -err_exit: - if (ctx) { - kfree(ctx->workstation_name); - kfree(ctx); - } - - return rc; } void @@ -1588,8 +1573,6 @@ smb3_cleanup_fs_context_contents(struct smb3_fs_context *ctx) ctx->source = NULL; kfree(ctx->domainname); ctx->domainname = NULL; - kfree(ctx->workstation_name); - ctx->workstation_name = NULL; kfree(ctx->nodename); ctx->nodename = NULL; kfree(ctx->iocharset); diff --git a/fs/cifs/fs_context.h b/fs/cifs/fs_context.h index e54090d9ef368e7562b17e61384bc600df4cf815..5f093cb7e9b98ef791de8c01857c7f4136bbe9c5 100644 --- a/fs/cifs/fs_context.h +++ b/fs/cifs/fs_context.h @@ -62,6 +62,7 @@ enum cifs_param { Opt_noblocksend, Opt_noautotune, Opt_nolease, + Opt_nosparse, Opt_hard, Opt_soft, Opt_perm, @@ -170,7 +171,7 @@ struct smb3_fs_context { char *server_hostname; char *UNC; char *nodename; - char *workstation_name; + char workstation_name[CIFS_MAX_WORKSTATION_LEN]; char *iocharset; /* local code page for mapping to and from Unicode */ char source_rfc1001_name[RFC1001_NAME_LEN_WITH_NULL]; /* clnt nb name */ char target_rfc1001_name[RFC1001_NAME_LEN_WITH_NULL]; /* srvr nb name */ @@ -222,6 +223,7 @@ struct smb3_fs_context { bool noautotune:1; bool nostrictsync:1; /* do not force expensive SMBflush on every sync */ bool no_lease:1; /* disable requesting leases */ + bool no_sparse:1; /* do not attempt to set files sparse */ bool fsc:1; /* enable fscache */ bool mfsymlinks:1; /* use Minshall+French Symlinks */ bool multiuser:1; diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index afaf59c221936f3023c518be2ac6f2d95a9e1e28..35962a1a23b90f3775e58f3a642fe7a647253205 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c @@ -69,7 +69,7 @@ sesInfoAlloc(void) ret_buf = kzalloc(sizeof(struct cifs_ses), GFP_KERNEL); if (ret_buf) { atomic_inc(&sesInfoAllocCount); - ret_buf->status = CifsNew; + ret_buf->ses_status = SES_NEW; ++ret_buf->ses_count; INIT_LIST_HEAD(&ret_buf->smb_ses_list); INIT_LIST_HEAD(&ret_buf->tcon_list); @@ -95,7 +95,6 @@ sesInfoFree(struct cifs_ses *buf_to_free) kfree_sensitive(buf_to_free->password); kfree(buf_to_free->user_name); kfree(buf_to_free->domainName); - kfree(buf_to_free->workstation_name); kfree_sensitive(buf_to_free->auth_key.response); kfree(buf_to_free->iface_list); kfree_sensitive(buf_to_free); @@ -114,6 +113,8 @@ tconInfoAlloc(void) kfree(ret_buf); return NULL; } + INIT_LIST_HEAD(&ret_buf->crfid.dirents.entries); + mutex_init(&ret_buf->crfid.dirents.de_mutex); atomic_inc(&tconInfoAllocCount); ret_buf->status = TID_NEW; @@ -1309,7 +1310,7 @@ int cifs_update_super_prepath(struct cifs_sb_info *cifs_sb, char *prefix) * for "\\\" DFS reference, * where contains non-ASCII unicode symbols. * - * Check such DFS reference and emulate -ENOENT if it is actual. + * Check such DFS reference. */ int cifs_dfs_query_info_nonascii_quirk(const unsigned int xid, struct cifs_tcon *tcon, @@ -1341,10 +1342,6 @@ int cifs_dfs_query_info_nonascii_quirk(const unsigned int xid, cifs_dbg(FYI, "DFS ref '%s' is found, emulate -EREMOTE\n", dfspath); rc = -EREMOTE; - } else if (rc == -EEXIST) { - cifs_dbg(FYI, "DFS ref '%s' is not found, emulate -ENOENT\n", - dfspath); - rc = -ENOENT; } else { cifs_dbg(FYI, "%s: dfs_cache_find returned %d\n", __func__, rc); } diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index 1929e80c09ee1685e31835ad94d0f3f37a498847..384cabdf47caafab0404e1cf8150963d5db059ac 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c @@ -840,9 +840,109 @@ find_cifs_entry(const unsigned int xid, struct cifs_tcon *tcon, loff_t pos, return rc; } +static bool emit_cached_dirents(struct cached_dirents *cde, + struct dir_context *ctx) +{ + struct cached_dirent *dirent; + int rc; + + list_for_each_entry(dirent, &cde->entries, entry) { + if (ctx->pos >= dirent->pos) + continue; + ctx->pos = dirent->pos; + rc = dir_emit(ctx, dirent->name, dirent->namelen, + dirent->fattr.cf_uniqueid, + dirent->fattr.cf_dtype); + if (!rc) + return rc; + } + return true; +} + +static void update_cached_dirents_count(struct cached_dirents *cde, + struct dir_context *ctx) +{ + if (cde->ctx != ctx) + return; + if (cde->is_valid || cde->is_failed) + return; + + cde->pos++; +} + +static void finished_cached_dirents_count(struct cached_dirents *cde, + struct dir_context *ctx) +{ + if (cde->ctx != ctx) + return; + if (cde->is_valid || cde->is_failed) + return; + if (ctx->pos != cde->pos) + return; + + cde->is_valid = 1; +} + +static void add_cached_dirent(struct cached_dirents *cde, + struct dir_context *ctx, + const char *name, int namelen, + struct cifs_fattr *fattr) +{ + struct cached_dirent *de; + + if (cde->ctx != ctx) + return; + if (cde->is_valid || cde->is_failed) + return; + if (ctx->pos != cde->pos) { + cde->is_failed = 1; + return; + } + de = kzalloc(sizeof(*de), GFP_ATOMIC); + if (de == NULL) { + cde->is_failed = 1; + return; + } + de->namelen = namelen; + de->name = kstrndup(name, namelen, GFP_ATOMIC); + if (de->name == NULL) { + kfree(de); + cde->is_failed = 1; + return; + } + de->pos = ctx->pos; + + memcpy(&de->fattr, fattr, sizeof(struct cifs_fattr)); + + list_add_tail(&de->entry, &cde->entries); +} + +static bool cifs_dir_emit(struct dir_context *ctx, + const char *name, int namelen, + struct cifs_fattr *fattr, + struct cached_fid *cfid) +{ + bool rc; + ino_t ino = cifs_uniqueid_to_ino_t(fattr->cf_uniqueid); + + rc = dir_emit(ctx, name, namelen, ino, fattr->cf_dtype); + if (!rc) + return rc; + + if (cfid) { + mutex_lock(&cfid->dirents.de_mutex); + add_cached_dirent(&cfid->dirents, ctx, name, namelen, + fattr); + mutex_unlock(&cfid->dirents.de_mutex); + } + + return rc; +} + static int cifs_filldir(char *find_entry, struct file *file, - struct dir_context *ctx, - char *scratch_buf, unsigned int max_len) + struct dir_context *ctx, + char *scratch_buf, unsigned int max_len, + struct cached_fid *cfid) { struct cifsFileInfo *file_info = file->private_data; struct super_block *sb = file_inode(file)->i_sb; @@ -851,7 +951,6 @@ static int cifs_filldir(char *find_entry, struct file *file, struct cifs_fattr fattr; struct qstr name; int rc = 0; - ino_t ino; rc = cifs_fill_dirent(&de, find_entry, file_info->srch_inf.info_level, file_info->srch_inf.unicode); @@ -931,8 +1030,8 @@ static int cifs_filldir(char *find_entry, struct file *file, cifs_prime_dcache(file_dentry(file), &name, &fattr); - ino = cifs_uniqueid_to_ino_t(fattr.cf_uniqueid); - return !dir_emit(ctx, name.name, name.len, ino, fattr.cf_dtype); + return !cifs_dir_emit(ctx, name.name, name.len, + &fattr, cfid); } @@ -941,8 +1040,9 @@ int cifs_readdir(struct file *file, struct dir_context *ctx) int rc = 0; unsigned int xid; int i; + struct tcon_link *tlink = NULL; struct cifs_tcon *tcon; - struct cifsFileInfo *cifsFile = NULL; + struct cifsFileInfo *cifsFile; char *current_entry; int num_to_fill = 0; char *tmp_buf = NULL; @@ -950,6 +1050,8 @@ int cifs_readdir(struct file *file, struct dir_context *ctx) unsigned int max_len; const char *full_path; void *page = alloc_dentry_path(); + struct cached_fid *cfid = NULL; + struct cifs_sb_info *cifs_sb = CIFS_FILE_SB(file); xid = get_xid(); @@ -959,6 +1061,54 @@ int cifs_readdir(struct file *file, struct dir_context *ctx) goto rddir2_exit; } + if (file->private_data == NULL) { + tlink = cifs_sb_tlink(cifs_sb); + if (IS_ERR(tlink)) + goto cache_not_found; + tcon = tlink_tcon(tlink); + } else { + cifsFile = file->private_data; + tcon = tlink_tcon(cifsFile->tlink); + } + + rc = open_cached_dir(xid, tcon, full_path, cifs_sb, &cfid); + cifs_put_tlink(tlink); + if (rc) + goto cache_not_found; + + mutex_lock(&cfid->dirents.de_mutex); + /* + * If this was reading from the start of the directory + * we need to initialize scanning and storing the + * directory content. + */ + if (ctx->pos == 0 && cfid->dirents.ctx == NULL) { + cfid->dirents.ctx = ctx; + cfid->dirents.pos = 2; + } + /* + * If we already have the entire directory cached then + * we can just serve the cache. + */ + if (cfid->dirents.is_valid) { + if (!dir_emit_dots(file, ctx)) { + mutex_unlock(&cfid->dirents.de_mutex); + goto rddir2_exit; + } + emit_cached_dirents(&cfid->dirents, ctx); + mutex_unlock(&cfid->dirents.de_mutex); + goto rddir2_exit; + } + mutex_unlock(&cfid->dirents.de_mutex); + + /* Drop the cache while calling initiate_cifs_search and + * find_cifs_entry in case there will be reconnects during + * query_directory. + */ + close_cached_dir(cfid); + cfid = NULL; + + cache_not_found: /* * Ensure FindFirst doesn't fail before doing filldir() for '.' and * '..'. Otherwise we won't be able to notify VFS in case of failure. @@ -977,7 +1127,6 @@ int cifs_readdir(struct file *file, struct dir_context *ctx) is in current search buffer? if it before then restart search if after then keep searching till find it */ - cifsFile = file->private_data; if (cifsFile->srch_inf.endOfSearch) { if (cifsFile->srch_inf.emptyDir) { @@ -993,12 +1142,18 @@ int cifs_readdir(struct file *file, struct dir_context *ctx) tcon = tlink_tcon(cifsFile->tlink); rc = find_cifs_entry(xid, tcon, ctx->pos, file, full_path, ¤t_entry, &num_to_fill); + open_cached_dir(xid, tcon, full_path, cifs_sb, &cfid); if (rc) { cifs_dbg(FYI, "fce error %d\n", rc); goto rddir2_exit; } else if (current_entry != NULL) { cifs_dbg(FYI, "entry %lld found\n", ctx->pos); } else { + if (cfid) { + mutex_lock(&cfid->dirents.de_mutex); + finished_cached_dirents_count(&cfid->dirents, ctx); + mutex_unlock(&cfid->dirents.de_mutex); + } cifs_dbg(FYI, "Could not find entry\n"); goto rddir2_exit; } @@ -1028,7 +1183,7 @@ int cifs_readdir(struct file *file, struct dir_context *ctx) */ *tmp_buf = 0; rc = cifs_filldir(current_entry, file, ctx, - tmp_buf, max_len); + tmp_buf, max_len, cfid); if (rc) { if (rc > 0) rc = 0; @@ -1036,6 +1191,12 @@ int cifs_readdir(struct file *file, struct dir_context *ctx) } ctx->pos++; + if (cfid) { + mutex_lock(&cfid->dirents.de_mutex); + update_cached_dirents_count(&cfid->dirents, ctx); + mutex_unlock(&cfid->dirents.de_mutex); + } + if (ctx->pos == cifsFile->srch_inf.index_of_last_entry) { cifs_dbg(FYI, "last entry in buf at pos %lld %s\n", @@ -1050,6 +1211,8 @@ int cifs_readdir(struct file *file, struct dir_context *ctx) kfree(tmp_buf); rddir2_exit: + if (cfid) + close_cached_dir(cfid); free_dentry_path(page); free_xid(xid); return rc; diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c index 32f478c7a66d86242363ff664b4a632ab277bc52..c6214cfc575f3b1cd38e322e34ef04a7829591e5 100644 --- a/fs/cifs/sess.c +++ b/fs/cifs/sess.c @@ -85,6 +85,33 @@ cifs_ses_get_chan_index(struct cifs_ses *ses, return 0; } +void +cifs_chan_set_in_reconnect(struct cifs_ses *ses, + struct TCP_Server_Info *server) +{ + unsigned int chan_index = cifs_ses_get_chan_index(ses, server); + + ses->chans[chan_index].in_reconnect = true; +} + +void +cifs_chan_clear_in_reconnect(struct cifs_ses *ses, + struct TCP_Server_Info *server) +{ + unsigned int chan_index = cifs_ses_get_chan_index(ses, server); + + ses->chans[chan_index].in_reconnect = false; +} + +bool +cifs_chan_in_reconnect(struct cifs_ses *ses, + struct TCP_Server_Info *server) +{ + unsigned int chan_index = cifs_ses_get_chan_index(ses, server); + + return CIFS_CHAN_IN_RECONNECT(ses, chan_index); +} + void cifs_chan_set_need_reconnect(struct cifs_ses *ses, struct TCP_Server_Info *server) @@ -714,9 +741,9 @@ static int size_of_ntlmssp_blob(struct cifs_ses *ses, int base_size) else sz += sizeof(__le16); - if (ses->workstation_name) + if (ses->workstation_name[0]) sz += sizeof(__le16) * strnlen(ses->workstation_name, - CIFS_MAX_WORKSTATION_LEN); + ntlmssp_workstation_name_size(ses)); else sz += sizeof(__le16); @@ -960,7 +987,7 @@ int build_ntlmssp_auth_blob(unsigned char **pbuffer, cifs_security_buffer_from_str(&sec_blob->WorkstationName, ses->workstation_name, - CIFS_MAX_WORKSTATION_LEN, + ntlmssp_workstation_name_size(ses), *pbuffer, &tmp, nls_cp); diff --git a/fs/cifs/smb2inode.c b/fs/cifs/smb2inode.c index fe5bfa245fa7efc32013d9a9cc67d8a1cca96b1a..8571a459c7101ef6fd89b55f29e905767925a5e8 100644 --- a/fs/cifs/smb2inode.c +++ b/fs/cifs/smb2inode.c @@ -362,8 +362,6 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, num_rqst++; if (cfile) { - cifsFileInfo_put(cfile); - cfile = NULL; rc = compound_send_recv(xid, ses, server, flags, num_rqst - 2, &rqst[1], &resp_buftype[1], @@ -514,8 +512,11 @@ smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon, if (smb2_data == NULL) return -ENOMEM; + if (strcmp(full_path, "")) + rc = -ENOENT; + else + rc = open_cached_dir(xid, tcon, full_path, cifs_sb, &cfid); /* If it is a root and its handle is cached then use it */ - rc = open_cached_dir(xid, tcon, full_path, cifs_sb, &cfid); if (!rc) { if (tcon->crfid.file_all_info_is_valid) { move_smb2_info_to_cifs(data, diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c index 3fe47a88f47d0d0a373d4cb8ce0c13bb57b6b9d2..17813c3d0c6e0a0229f9b83f9da7ade8f38eed17 100644 --- a/fs/cifs/smb2misc.c +++ b/fs/cifs/smb2misc.c @@ -656,6 +656,12 @@ smb2_is_valid_lease_break(char *buffer) } spin_unlock(&cifs_tcp_ses_lock); cifs_dbg(FYI, "Can not process lease break - no lease matched\n"); + trace_smb3_lease_not_found(le32_to_cpu(rsp->CurrentLeaseState), + le32_to_cpu(rsp->hdr.Id.SyncId.TreeId), + le64_to_cpu(rsp->hdr.SessionId), + *((u64 *)rsp->LeaseKey), + *((u64 *)&rsp->LeaseKey[8])); + return false; } @@ -726,6 +732,10 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server) } spin_unlock(&cifs_tcp_ses_lock); cifs_dbg(FYI, "No file id matched, oplock break ignored\n"); + trace_smb3_oplock_not_found(0 /* no xid */, rsp->PersistentFid, + le32_to_cpu(rsp->hdr.Id.SyncId.TreeId), + le64_to_cpu(rsp->hdr.SessionId)); + return true; } @@ -798,7 +808,7 @@ smb2_handle_cancelled_close(struct cifs_tcon *tcon, __u64 persistent_fid, if (tcon->ses) server = tcon->ses->server; - cifs_server_dbg(FYI, "tid=%u: tcon is closing, skipping async close retry of fid %llu %llu\n", + cifs_server_dbg(FYI, "tid=0x%x: tcon is closing, skipping async close retry of fid %llu %llu\n", tcon->tid, persistent_fid, volatile_fid); return 0; diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c index d6aaeff4a30a530864211b79fbda744b87d6b720..d7ade739cde194e14b92d39674601c22071279e2 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c @@ -699,6 +699,7 @@ smb2_close_cached_fid(struct kref *ref) { struct cached_fid *cfid = container_of(ref, struct cached_fid, refcount); + struct cached_dirent *dirent, *q; if (cfid->is_valid) { cifs_dbg(FYI, "clear cached root file handle\n"); @@ -718,6 +719,21 @@ smb2_close_cached_fid(struct kref *ref) dput(cfid->dentry); cfid->dentry = NULL; } + /* + * Delete all cached dirent names + */ + mutex_lock(&cfid->dirents.de_mutex); + list_for_each_entry_safe(dirent, q, &cfid->dirents.entries, entry) { + list_del(&dirent->entry); + kfree(dirent->name); + kfree(dirent); + } + cfid->dirents.is_valid = 0; + cfid->dirents.is_failed = 0; + cfid->dirents.ctx = NULL; + cfid->dirents.pos = 0; + mutex_unlock(&cfid->dirents.de_mutex); + } void close_cached_dir(struct cached_fid *cfid) @@ -754,14 +770,15 @@ smb2_cached_lease_break(struct work_struct *work) /* * Open the and cache a directory handle. * Only supported for the root handle. + * If error then *cfid is not initialized. */ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon, const char *path, struct cifs_sb_info *cifs_sb, struct cached_fid **cfid) { - struct cifs_ses *ses = tcon->ses; - struct TCP_Server_Info *server = ses->server; + struct cifs_ses *ses; + struct TCP_Server_Info *server; struct cifs_open_parms oparms; struct smb2_create_rsp *o_rsp = NULL; struct smb2_query_info_rsp *qi_rsp = NULL; @@ -776,9 +793,13 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon, struct cifs_fid *pfid; struct dentry *dentry; - if (tcon->nohandlecache) + if (tcon == NULL || tcon->nohandlecache || + is_smb1_server(tcon->ses->server)) return -ENOTSUPP; + ses = tcon->ses; + server = ses->server; + if (cifs_sb->root == NULL) return -ENOENT; @@ -824,7 +845,7 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon, rqst[0].rq_nvec = SMB2_CREATE_IOV_SIZE; oparms.tcon = tcon; - oparms.create_options = cifs_create_options(cifs_sb, 0); + oparms.create_options = cifs_create_options(cifs_sb, CREATE_NOT_FILE); oparms.desired_access = FILE_READ_ATTRIBUTES; oparms.disposition = FILE_OPEN; oparms.fid = pfid; @@ -2695,7 +2716,8 @@ smb2_query_info_compound(const unsigned int xid, struct cifs_tcon *tcon, resp_buftype[0] = resp_buftype[1] = resp_buftype[2] = CIFS_NO_BUFFER; memset(rsp_iov, 0, sizeof(rsp_iov)); - rc = open_cached_dir(xid, tcon, path, cifs_sb, &cfid); + if (!strcmp(path, "")) + open_cached_dir(xid, tcon, path, cifs_sb, &cfid); /* cfid null if open dir failed */ memset(&open_iov, 0, sizeof(open_iov)); rqst[0].rq_iov = open_iov; diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index 1b7ad0c09566876185216446aa88f0b8f96fcd28..084be3a901980dd2cc17fef35ea2e9101dcb703b 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c @@ -179,7 +179,7 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon, } } spin_unlock(&cifs_tcp_ses_lock); - if ((!tcon->ses) || (tcon->ses->status == CifsExiting) || + if ((!tcon->ses) || (tcon->ses->ses_status == SES_EXITING) || (!tcon->ses->server) || !server) return -EIO; @@ -3899,7 +3899,8 @@ SMB2_echo(struct TCP_Server_Info *server) cifs_dbg(FYI, "In echo request for conn_id %lld\n", server->conn_id); spin_lock(&cifs_tcp_ses_lock); - if (server->tcpStatus == CifsNeedNegotiate) { + if (server->ops->need_neg && + server->ops->need_neg(server)) { spin_unlock(&cifs_tcp_ses_lock); /* No need to send echo on newly established connections */ mod_delayed_work(cifsiod_wq, &server->reconnect, 0); diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h index d8c4388b190d8eaabd16c99d83b1d68cc54a0a6d..f57881b8464fb372509b5a97b2c479c1fae52aac 100644 --- a/fs/cifs/smb2pdu.h +++ b/fs/cifs/smb2pdu.h @@ -260,28 +260,6 @@ struct get_retrieval_pointers_refcount_rsp { struct smb3_extents extents[]; } __packed; -struct fsctl_set_integrity_information_req { - __le16 ChecksumAlgorithm; - __le16 Reserved; - __le32 Flags; -} __packed; - -struct fsctl_get_integrity_information_rsp { - __le16 ChecksumAlgorithm; - __le16 Reserved; - __le32 Flags; - __le32 ChecksumChunkSizeInBytes; - __le32 ClusterSizeInBytes; -} __packed; - -/* Integrity ChecksumAlgorithm choices for above */ -#define CHECKSUM_TYPE_NONE 0x0000 -#define CHECKSUM_TYPE_CRC64 0x0002 -#define CHECKSUM_TYPE_UNCHANGED 0xFFFF /* set only */ - -/* Integrity flags for above */ -#define FSCTL_INTEGRITY_FLAG_CHECKSUM_ENFORCEMENT_OFF 0x00000001 - /* See MS-DFSC 2.2.2 */ struct fsctl_get_dfs_referral_req { __le16 MaxReferralLevel; diff --git a/fs/cifs/smb2transport.c b/fs/cifs/smb2transport.c index 2af79093b78bcc2f7a7c60a4df0fb5c1fff83bc1..55e79f6ee78d1751af8c09fb5360b74008828880 100644 --- a/fs/cifs/smb2transport.c +++ b/fs/cifs/smb2transport.c @@ -641,7 +641,8 @@ smb2_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server) if (!is_signed) return 0; spin_lock(&cifs_tcp_ses_lock); - if (server->tcpStatus == CifsNeedNegotiate) { + if (server->ops->need_neg && + server->ops->need_neg(server)) { spin_unlock(&cifs_tcp_ses_lock); return 0; } @@ -779,7 +780,7 @@ smb2_get_mid_entry(struct cifs_ses *ses, struct TCP_Server_Info *server, return -EAGAIN; } - if (ses->status == CifsNew) { + if (ses->ses_status == SES_NEW) { if ((shdr->Command != SMB2_SESSION_SETUP) && (shdr->Command != SMB2_NEGOTIATE)) { spin_unlock(&cifs_tcp_ses_lock); @@ -788,7 +789,7 @@ smb2_get_mid_entry(struct cifs_ses *ses, struct TCP_Server_Info *server, /* else ok - we are setting up session */ } - if (ses->status == CifsExiting) { + if (ses->ses_status == SES_EXITING) { if (shdr->Command != SMB2_LOGOFF) { spin_unlock(&cifs_tcp_ses_lock); return -EAGAIN; diff --git a/fs/cifs/smbdirect.c b/fs/cifs/smbdirect.c index b3a1265711cc7d4c9c8a354106ca276d438104b6..c3278db1cade12227a9b2ec6f6eb721631f565e5 100644 --- a/fs/cifs/smbdirect.c +++ b/fs/cifs/smbdirect.c @@ -1350,7 +1350,7 @@ void smbd_destroy(struct TCP_Server_Info *server) wait_event(info->wait_send_pending, atomic_read(&info->send_pending) == 0); - /* It's not posssible for upper layer to get to reassembly */ + /* It's not possible for upper layer to get to reassembly */ log_rdma_event(INFO, "drain the reassembly queue\n"); do { spin_lock_irqsave(&info->reassembly_queue_lock, flags); diff --git a/fs/cifs/trace.h b/fs/cifs/trace.h index bc279616c513a86f14c002b9b29c9e34069820b9..2be5e0c8564d1c2004aec834750ff7e767d2c38b 100644 --- a/fs/cifs/trace.h +++ b/fs/cifs/trace.h @@ -158,6 +158,7 @@ DEFINE_SMB3_FD_EVENT(flush_enter); DEFINE_SMB3_FD_EVENT(flush_done); DEFINE_SMB3_FD_EVENT(close_enter); DEFINE_SMB3_FD_EVENT(close_done); +DEFINE_SMB3_FD_EVENT(oplock_not_found); DECLARE_EVENT_CLASS(smb3_fd_err_class, TP_PROTO(unsigned int xid, @@ -814,6 +815,7 @@ DEFINE_EVENT(smb3_lease_done_class, smb3_##name, \ TP_ARGS(lease_state, tid, sesid, lease_key_low, lease_key_high)) DEFINE_SMB3_LEASE_DONE_EVENT(lease_done); +DEFINE_SMB3_LEASE_DONE_EVENT(lease_not_found); DECLARE_EVENT_CLASS(smb3_lease_err_class, TP_PROTO(__u32 lease_state, diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index c667e6ddfe2f7c52b4673a12295875f4d83ccb25..05eca41e3b1e0989172c422d68b27c6af184c04d 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c @@ -726,7 +726,7 @@ static int allocate_mid(struct cifs_ses *ses, struct smb_hdr *in_buf, struct mid_q_entry **ppmidQ) { spin_lock(&cifs_tcp_ses_lock); - if (ses->status == CifsNew) { + if (ses->ses_status == SES_NEW) { if ((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) && (in_buf->Command != SMB_COM_NEGOTIATE)) { spin_unlock(&cifs_tcp_ses_lock); @@ -735,7 +735,7 @@ static int allocate_mid(struct cifs_ses *ses, struct smb_hdr *in_buf, /* else ok - we are setting up session */ } - if (ses->status == CifsExiting) { + if (ses->ses_status == SES_EXITING) { /* check if SMB session is bad because we are setting it up */ if (in_buf->Command != SMB_COM_LOGOFF_ANDX) { spin_unlock(&cifs_tcp_ses_lock); @@ -1187,7 +1187,7 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses, * Compounding is never used during session establish. */ spin_lock(&cifs_tcp_ses_lock); - if ((ses->status == CifsNew) || (optype & CIFS_NEG_OP) || (optype & CIFS_SESS_OP)) { + if ((ses->ses_status == SES_NEW) || (optype & CIFS_NEG_OP) || (optype & CIFS_SESS_OP)) { spin_unlock(&cifs_tcp_ses_lock); mutex_lock(&server->srv_mutex); @@ -1260,7 +1260,7 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses, * Compounding is never used during session establish. */ spin_lock(&cifs_tcp_ses_lock); - if ((ses->status == CifsNew) || (optype & CIFS_NEG_OP) || (optype & CIFS_SESS_OP)) { + if ((ses->ses_status == SES_NEW) || (optype & CIFS_NEG_OP) || (optype & CIFS_SESS_OP)) { struct kvec iov = { .iov_base = resp_iov[0].iov_base, .iov_len = resp_iov[0].iov_len diff --git a/fs/dax.c b/fs/dax.c index 1ac12e877f4f3f84acd9afc715fdf67f416f5500..4155a6107fa10d20914446e5798110fcddddc08f 100644 --- a/fs/dax.c +++ b/fs/dax.c @@ -722,7 +722,8 @@ static int copy_cow_page_dax(struct vm_fault *vmf, const struct iomap_iter *iter int id; id = dax_read_lock(); - rc = dax_direct_access(iter->iomap.dax_dev, pgoff, 1, &kaddr, NULL); + rc = dax_direct_access(iter->iomap.dax_dev, pgoff, 1, DAX_ACCESS, + &kaddr, NULL); if (rc < 0) { dax_read_unlock(id); return rc; @@ -939,7 +940,7 @@ static int dax_iomap_pfn(const struct iomap *iomap, loff_t pos, size_t size, id = dax_read_lock(); length = dax_direct_access(iomap->dax_dev, pgoff, PHYS_PFN(size), - NULL, pfnp); + DAX_ACCESS, NULL, pfnp); if (length < 0) { rc = length; goto out; @@ -1048,7 +1049,7 @@ static int dax_memzero(struct dax_device *dax_dev, pgoff_t pgoff, void *kaddr; long ret; - ret = dax_direct_access(dax_dev, pgoff, 1, &kaddr, NULL); + ret = dax_direct_access(dax_dev, pgoff, 1, DAX_ACCESS, &kaddr, NULL); if (ret > 0) { memset(kaddr + offset, 0, size); dax_flush(dax_dev, kaddr + offset, size); @@ -1165,6 +1166,7 @@ static loff_t dax_iomap_iter(const struct iomap_iter *iomi, const size_t size = ALIGN(length + offset, PAGE_SIZE); pgoff_t pgoff = dax_iomap_pgoff(iomap, pos); ssize_t map_len; + bool recovery = false; void *kaddr; if (fatal_signal_pending(current)) { @@ -1173,7 +1175,14 @@ static loff_t dax_iomap_iter(const struct iomap_iter *iomi, } map_len = dax_direct_access(dax_dev, pgoff, PHYS_PFN(size), - &kaddr, NULL); + DAX_ACCESS, &kaddr, NULL); + if (map_len == -EIO && iov_iter_rw(iter) == WRITE) { + map_len = dax_direct_access(dax_dev, pgoff, + PHYS_PFN(size), DAX_RECOVERY_WRITE, + &kaddr, NULL); + if (map_len > 0) + recovery = true; + } if (map_len < 0) { ret = map_len; break; @@ -1185,7 +1194,10 @@ static loff_t dax_iomap_iter(const struct iomap_iter *iomi, if (map_len > end - pos) map_len = end - pos; - if (iov_iter_rw(iter) == WRITE) + if (recovery) + xfer = dax_recovery_write(dax_dev, pgoff, kaddr, + map_len, iter); + else if (iov_iter_rw(iter) == WRITE) xfer = dax_copy_from_iter(dax_dev, pgoff, kaddr, map_len, iter); else diff --git a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c index 0106eba46d5afcf6738dd0db21186754b7b99128..3ef80d000e13d5a46e886492583322e8344f182e 100644 --- a/fs/exportfs/expfs.c +++ b/fs/exportfs/expfs.c @@ -145,7 +145,7 @@ static struct dentry *reconnect_one(struct vfsmount *mnt, if (err) goto out_err; dprintk("%s: found name: %s\n", __func__, nbuf); - tmp = lookup_one_len_unlocked(nbuf, parent, strlen(nbuf)); + tmp = lookup_one_unlocked(mnt_user_ns(mnt), nbuf, parent, strlen(nbuf)); if (IS_ERR(tmp)) { dprintk("%s: lookup failed: %d\n", __func__, PTR_ERR(tmp)); err = PTR_ERR(tmp); @@ -525,7 +525,8 @@ exportfs_decode_fh_raw(struct vfsmount *mnt, struct fid *fid, int fh_len, } inode_lock(target_dir->d_inode); - nresult = lookup_one_len(nbuf, target_dir, strlen(nbuf)); + nresult = lookup_one(mnt_user_ns(mnt), nbuf, + target_dir, strlen(nbuf)); if (!IS_ERR(nresult)) { if (unlikely(nresult->d_inode != result->d_inode)) { dput(nresult); diff --git a/fs/fuse/dax.c b/fs/fuse/dax.c index d7d3a7f06862d85b1bed8a88f74ae42037559311..10eb50cbf398c4b0e58ac3fe7e8d110e77f31036 100644 --- a/fs/fuse/dax.c +++ b/fs/fuse/dax.c @@ -1241,8 +1241,8 @@ static int fuse_dax_mem_range_init(struct fuse_conn_dax *fcd) INIT_DELAYED_WORK(&fcd->free_work, fuse_dax_free_mem_worker); id = dax_read_lock(); - nr_pages = dax_direct_access(fcd->dev, 0, PHYS_PFN(dax_size), NULL, - NULL); + nr_pages = dax_direct_access(fcd->dev, 0, PHYS_PFN(dax_size), + DAX_ACCESS, NULL, NULL); dax_read_unlock(id); if (nr_pages < 0) { pr_debug("dax_direct_access() returned %ld\n", nr_pages); diff --git a/fs/fuse/virtio_fs.c b/fs/fuse/virtio_fs.c index 541255abf301e705f654c5bd565bbcb8b67a8198..f196b98d2daa71812549eef7d7ab3b34d7d8eafc 100644 --- a/fs/fuse/virtio_fs.c +++ b/fs/fuse/virtio_fs.c @@ -752,7 +752,8 @@ static void virtio_fs_cleanup_vqs(struct virtio_device *vdev, * offset. */ static long virtio_fs_direct_access(struct dax_device *dax_dev, pgoff_t pgoff, - long nr_pages, void **kaddr, pfn_t *pfn) + long nr_pages, enum dax_access_mode mode, + void **kaddr, pfn_t *pfn) { struct virtio_fs *fs = dax_get_private(dax_dev); phys_addr_t offset = PFN_PHYS(pgoff); @@ -772,7 +773,8 @@ static int virtio_fs_zero_page_range(struct dax_device *dax_dev, long rc; void *kaddr; - rc = dax_direct_access(dax_dev, pgoff, nr_pages, &kaddr, NULL); + rc = dax_direct_access(dax_dev, pgoff, nr_pages, DAX_ACCESS, &kaddr, + NULL); if (rc < 0) return rc; memset(kaddr, 0, nr_pages << PAGE_SHIFT); diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index 22d2b94339ed97a6616f72f6839b1feb0cf683cc..62408047e8d7bf78d23775217f475f9048db8652 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c @@ -195,7 +195,6 @@ out: * Called under mmap_write_lock(mm). */ -#ifndef HAVE_ARCH_HUGETLB_UNMAPPED_AREA static unsigned long hugetlb_get_unmapped_area_bottomup(struct file *file, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags) @@ -206,7 +205,7 @@ hugetlb_get_unmapped_area_bottomup(struct file *file, unsigned long addr, info.flags = 0; info.length = len; info.low_limit = current->mm->mmap_base; - info.high_limit = arch_get_mmap_end(addr); + info.high_limit = arch_get_mmap_end(addr, len, flags); info.align_mask = PAGE_MASK & ~huge_page_mask(h); info.align_offset = 0; return vm_unmapped_area(&info); @@ -237,21 +236,22 @@ hugetlb_get_unmapped_area_topdown(struct file *file, unsigned long addr, VM_BUG_ON(addr != -ENOMEM); info.flags = 0; info.low_limit = current->mm->mmap_base; - info.high_limit = arch_get_mmap_end(addr); + info.high_limit = arch_get_mmap_end(addr, len, flags); addr = vm_unmapped_area(&info); } return addr; } -static unsigned long -hugetlb_get_unmapped_area(struct file *file, unsigned long addr, - unsigned long len, unsigned long pgoff, unsigned long flags) +unsigned long +generic_hugetlb_get_unmapped_area(struct file *file, unsigned long addr, + unsigned long len, unsigned long pgoff, + unsigned long flags) { struct mm_struct *mm = current->mm; struct vm_area_struct *vma; struct hstate *h = hstate_file(file); - const unsigned long mmap_end = arch_get_mmap_end(addr); + const unsigned long mmap_end = arch_get_mmap_end(addr, len, flags); if (len & ~huge_page_mask(h)) return -EINVAL; @@ -283,6 +283,15 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr, return hugetlb_get_unmapped_area_bottomup(file, addr, len, pgoff, flags); } + +#ifndef HAVE_ARCH_HUGETLB_UNMAPPED_AREA +static unsigned long +hugetlb_get_unmapped_area(struct file *file, unsigned long addr, + unsigned long len, unsigned long pgoff, + unsigned long flags) +{ + return generic_hugetlb_get_unmapped_area(file, addr, len, pgoff, flags); +} #endif static size_t diff --git a/fs/jfs/Makefile b/fs/jfs/Makefile index 285ec189ed5c1c4fe9cbd44339f37c29949f3d7f..7156d2c218c7bf6a93e82767ad74f065c6279e28 100644 --- a/fs/jfs/Makefile +++ b/fs/jfs/Makefile @@ -13,5 +13,3 @@ jfs-y := super.o file.o inode.o namei.o jfs_mount.o jfs_umount.o \ resize.o xattr.o ioctl.o jfs-$(CONFIG_JFS_POSIX_ACL) += acl.o - -ccflags-y := -D_JFS_4K diff --git a/fs/jfs/inode.c b/fs/jfs/inode.c index a5dd7e53754a87b086024f0b2407ffa6f937537c..259326556ada672a1a50ea8e5d0e3358a19770a2 100644 --- a/fs/jfs/inode.c +++ b/fs/jfs/inode.c @@ -224,18 +224,9 @@ int jfs_get_block(struct inode *ip, sector_t lblock, * this as a hole */ goto unlock; -#ifdef _JFS_4K XADoffset(&xad, lblock64); XADlength(&xad, xlen); XADaddress(&xad, xaddr); -#else /* _JFS_4K */ - /* - * As long as block size = 4K, this isn't a problem. - * We should mark the whole page not ABNR, but how - * will we know to mark the other blocks BH_New? - */ - BUG(); -#endif /* _JFS_4K */ rc = extRecord(ip, &xad); if (rc) goto unlock; @@ -252,7 +243,6 @@ int jfs_get_block(struct inode *ip, sector_t lblock, /* * Allocate a new block */ -#ifdef _JFS_4K if ((rc = extHint(ip, lblock64 << ip->i_sb->s_blocksize_bits, &xad))) goto unlock; rc = extAlloc(ip, xlen, lblock64, &xad, false); @@ -263,14 +253,6 @@ int jfs_get_block(struct inode *ip, sector_t lblock, map_bh(bh_result, ip->i_sb, addressXAD(&xad)); bh_result->b_size = lengthXAD(&xad) << ip->i_blkbits; -#else /* _JFS_4K */ - /* - * We need to do whatever it takes to keep all but the last buffers - * in 4K pages - see jfs_write.c - */ - BUG(); -#endif /* _JFS_4K */ - unlock: /* * Release lock on inode diff --git a/fs/jfs/jfs_dmap.c b/fs/jfs/jfs_dmap.c index d8502f4989d9d4426a27514327407519b3446cae..6b838d3ae7c2e13ff855ea5b34a26b75c91b269d 100644 --- a/fs/jfs/jfs_dmap.c +++ b/fs/jfs/jfs_dmap.c @@ -385,7 +385,8 @@ int dbFree(struct inode *ip, s64 blkno, s64 nblocks) } /* write the last buffer. */ - write_metapage(mp); + if (mp) + write_metapage(mp); IREAD_UNLOCK(ipbmap); @@ -868,74 +869,6 @@ int dbAlloc(struct inode *ip, s64 hint, s64 nblocks, s64 * results) return (rc); } -#ifdef _NOTYET -/* - * NAME: dbAllocExact() - * - * FUNCTION: try to allocate the requested extent; - * - * PARAMETERS: - * ip - pointer to in-core inode; - * blkno - extent address; - * nblocks - extent length; - * - * RETURN VALUES: - * 0 - success - * -ENOSPC - insufficient disk resources - * -EIO - i/o error - */ -int dbAllocExact(struct inode *ip, s64 blkno, int nblocks) -{ - int rc; - struct inode *ipbmap = JFS_SBI(ip->i_sb)->ipbmap; - struct bmap *bmp = JFS_SBI(ip->i_sb)->bmap; - struct dmap *dp; - s64 lblkno; - struct metapage *mp; - - IREAD_LOCK(ipbmap, RDWRLOCK_DMAP); - - /* - * validate extent request: - * - * note: defragfs policy: - * max 64 blocks will be moved. - * allocation request size must be satisfied from a single dmap. - */ - if (nblocks <= 0 || nblocks > BPERDMAP || blkno >= bmp->db_mapsize) { - IREAD_UNLOCK(ipbmap); - return -EINVAL; - } - - if (nblocks > ((s64) 1 << bmp->db_maxfreebud)) { - /* the free space is no longer available */ - IREAD_UNLOCK(ipbmap); - return -ENOSPC; - } - - /* read in the dmap covering the extent */ - lblkno = BLKTODMAP(blkno, bmp->db_l2nbperpage); - mp = read_metapage(ipbmap, lblkno, PSIZE, 0); - if (mp == NULL) { - IREAD_UNLOCK(ipbmap); - return -EIO; - } - dp = (struct dmap *) mp->data; - - /* try to allocate the requested extent */ - rc = dbAllocNext(bmp, dp, blkno, nblocks); - - IREAD_UNLOCK(ipbmap); - - if (rc == 0) - mark_metapage_dirty(mp); - - release_metapage(mp); - - return (rc); -} -#endif /* _NOTYET */ - /* * NAME: dbReAlloc() * diff --git a/fs/jfs/jfs_dtree.c b/fs/jfs/jfs_dtree.c index 837d42f61464b3a7e06bd8cf625d8e1a96fbfd5e..92b7c533407c12f61e22823e4a4fd774d7420f67 100644 --- a/fs/jfs/jfs_dtree.c +++ b/fs/jfs/jfs_dtree.c @@ -2423,304 +2423,6 @@ static int dtDeleteUp(tid_t tid, struct inode *ip, return 0; } -#ifdef _NOTYET -/* - * NAME: dtRelocate() - * - * FUNCTION: relocate dtpage (internal or leaf) of directory; - * This function is mainly used by defragfs utility. - */ -int dtRelocate(tid_t tid, struct inode *ip, s64 lmxaddr, pxd_t * opxd, - s64 nxaddr) -{ - int rc = 0; - struct metapage *mp, *pmp, *lmp, *rmp; - dtpage_t *p, *pp, *rp = 0, *lp= 0; - s64 bn; - int index; - struct btstack btstack; - pxd_t *pxd; - s64 oxaddr, nextbn, prevbn; - int xlen, xsize; - struct tlock *tlck; - struct dt_lock *dtlck; - struct pxd_lock *pxdlock; - s8 *stbl; - struct lv *lv; - - oxaddr = addressPXD(opxd); - xlen = lengthPXD(opxd); - - jfs_info("dtRelocate: lmxaddr:%Ld xaddr:%Ld:%Ld xlen:%d", - (long long)lmxaddr, (long long)oxaddr, (long long)nxaddr, - xlen); - - /* - * 1. get the internal parent dtpage covering - * router entry for the tartget page to be relocated; - */ - rc = dtSearchNode(ip, lmxaddr, opxd, &btstack); - if (rc) - return rc; - - /* retrieve search result */ - DT_GETSEARCH(ip, btstack.top, bn, pmp, pp, index); - jfs_info("dtRelocate: parent router entry validated."); - - /* - * 2. relocate the target dtpage - */ - /* read in the target page from src extent */ - DT_GETPAGE(ip, oxaddr, mp, PSIZE, p, rc); - if (rc) { - /* release the pinned parent page */ - DT_PUTPAGE(pmp); - return rc; - } - - /* - * read in sibling pages if any to update sibling pointers; - */ - rmp = NULL; - if (p->header.next) { - nextbn = le64_to_cpu(p->header.next); - DT_GETPAGE(ip, nextbn, rmp, PSIZE, rp, rc); - if (rc) { - DT_PUTPAGE(mp); - DT_PUTPAGE(pmp); - return (rc); - } - } - - lmp = NULL; - if (p->header.prev) { - prevbn = le64_to_cpu(p->header.prev); - DT_GETPAGE(ip, prevbn, lmp, PSIZE, lp, rc); - if (rc) { - DT_PUTPAGE(mp); - DT_PUTPAGE(pmp); - if (rmp) - DT_PUTPAGE(rmp); - return (rc); - } - } - - /* at this point, all xtpages to be updated are in memory */ - - /* - * update sibling pointers of sibling dtpages if any; - */ - if (lmp) { - tlck = txLock(tid, ip, lmp, tlckDTREE | tlckRELINK); - dtlck = (struct dt_lock *) & tlck->lock; - /* linelock header */ - ASSERT(dtlck->index == 0); - lv = & dtlck->lv[0]; - lv->offset = 0; - lv->length = 1; - dtlck->index++; - - lp->header.next = cpu_to_le64(nxaddr); - DT_PUTPAGE(lmp); - } - - if (rmp) { - tlck = txLock(tid, ip, rmp, tlckDTREE | tlckRELINK); - dtlck = (struct dt_lock *) & tlck->lock; - /* linelock header */ - ASSERT(dtlck->index == 0); - lv = & dtlck->lv[0]; - lv->offset = 0; - lv->length = 1; - dtlck->index++; - - rp->header.prev = cpu_to_le64(nxaddr); - DT_PUTPAGE(rmp); - } - - /* - * update the target dtpage to be relocated - * - * write LOG_REDOPAGE of LOG_NEW type for dst page - * for the whole target page (logredo() will apply - * after image and update bmap for allocation of the - * dst extent), and update bmap for allocation of - * the dst extent; - */ - tlck = txLock(tid, ip, mp, tlckDTREE | tlckNEW); - dtlck = (struct dt_lock *) & tlck->lock; - /* linelock header */ - ASSERT(dtlck->index == 0); - lv = & dtlck->lv[0]; - - /* update the self address in the dtpage header */ - pxd = &p->header.self; - PXDaddress(pxd, nxaddr); - - /* the dst page is the same as the src page, i.e., - * linelock for afterimage of the whole page; - */ - lv->offset = 0; - lv->length = p->header.maxslot; - dtlck->index++; - - /* update the buffer extent descriptor of the dtpage */ - xsize = xlen << JFS_SBI(ip->i_sb)->l2bsize; - - /* unpin the relocated page */ - DT_PUTPAGE(mp); - jfs_info("dtRelocate: target dtpage relocated."); - - /* the moved extent is dtpage, then a LOG_NOREDOPAGE log rec - * needs to be written (in logredo(), the LOG_NOREDOPAGE log rec - * will also force a bmap update ). - */ - - /* - * 3. acquire maplock for the source extent to be freed; - */ - /* for dtpage relocation, write a LOG_NOREDOPAGE record - * for the source dtpage (logredo() will init NoRedoPage - * filter and will also update bmap for free of the source - * dtpage), and upadte bmap for free of the source dtpage; - */ - tlck = txMaplock(tid, ip, tlckDTREE | tlckFREE); - pxdlock = (struct pxd_lock *) & tlck->lock; - pxdlock->flag = mlckFREEPXD; - PXDaddress(&pxdlock->pxd, oxaddr); - PXDlength(&pxdlock->pxd, xlen); - pxdlock->index = 1; - - /* - * 4. update the parent router entry for relocation; - * - * acquire tlck for the parent entry covering the target dtpage; - * write LOG_REDOPAGE to apply after image only; - */ - jfs_info("dtRelocate: update parent router entry."); - tlck = txLock(tid, ip, pmp, tlckDTREE | tlckENTRY); - dtlck = (struct dt_lock *) & tlck->lock; - lv = & dtlck->lv[dtlck->index]; - - /* update the PXD with the new address */ - stbl = DT_GETSTBL(pp); - pxd = (pxd_t *) & pp->slot[stbl[index]]; - PXDaddress(pxd, nxaddr); - lv->offset = stbl[index]; - lv->length = 1; - dtlck->index++; - - /* unpin the parent dtpage */ - DT_PUTPAGE(pmp); - - return rc; -} - -/* - * NAME: dtSearchNode() - * - * FUNCTION: Search for an dtpage containing a specified address - * This function is mainly used by defragfs utility. - * - * NOTE: Search result on stack, the found page is pinned at exit. - * The result page must be an internal dtpage. - * lmxaddr give the address of the left most page of the - * dtree level, in which the required dtpage resides. - */ -static int dtSearchNode(struct inode *ip, s64 lmxaddr, pxd_t * kpxd, - struct btstack * btstack) -{ - int rc = 0; - s64 bn; - struct metapage *mp; - dtpage_t *p; - int psize = 288; /* initial in-line directory */ - s8 *stbl; - int i; - pxd_t *pxd; - struct btframe *btsp; - - BT_CLR(btstack); /* reset stack */ - - /* - * descend tree to the level with specified leftmost page - * - * by convention, root bn = 0. - */ - for (bn = 0;;) { - /* get/pin the page to search */ - DT_GETPAGE(ip, bn, mp, psize, p, rc); - if (rc) - return rc; - - /* does the xaddr of leftmost page of the levevl - * matches levevl search key ? - */ - if (p->header.flag & BT_ROOT) { - if (lmxaddr == 0) - break; - } else if (addressPXD(&p->header.self) == lmxaddr) - break; - - /* - * descend down to leftmost child page - */ - if (p->header.flag & BT_LEAF) { - DT_PUTPAGE(mp); - return -ESTALE; - } - - /* get the leftmost entry */ - stbl = DT_GETSTBL(p); - pxd = (pxd_t *) & p->slot[stbl[0]]; - - /* get the child page block address */ - bn = addressPXD(pxd); - psize = lengthPXD(pxd) << JFS_SBI(ip->i_sb)->l2bsize; - /* unpin the parent page */ - DT_PUTPAGE(mp); - } - - /* - * search each page at the current levevl - */ - loop: - stbl = DT_GETSTBL(p); - for (i = 0; i < p->header.nextindex; i++) { - pxd = (pxd_t *) & p->slot[stbl[i]]; - - /* found the specified router entry */ - if (addressPXD(pxd) == addressPXD(kpxd) && - lengthPXD(pxd) == lengthPXD(kpxd)) { - btsp = btstack->top; - btsp->bn = bn; - btsp->index = i; - btsp->mp = mp; - - return 0; - } - } - - /* get the right sibling page if any */ - if (p->header.next) - bn = le64_to_cpu(p->header.next); - else { - DT_PUTPAGE(mp); - return -ESTALE; - } - - /* unpin current page */ - DT_PUTPAGE(mp); - - /* get the right sibling page */ - DT_GETPAGE(ip, bn, mp, PSIZE, p, rc); - if (rc) - return rc; - - goto loop; -} -#endif /* _NOTYET */ - /* * dtRelink() * diff --git a/fs/jfs/jfs_extent.c b/fs/jfs/jfs_extent.c index bb4a342a193d4491bac4d43d8901864942641316..ae99a7e232eebd1c06aaaf4e8bc9d9ef3f9c95ec 100644 --- a/fs/jfs/jfs_extent.c +++ b/fs/jfs/jfs_extent.c @@ -16,9 +16,6 @@ * forward references */ static int extBalloc(struct inode *, s64, s64 *, s64 *); -#ifdef _NOTYET -static int extBrealloc(struct inode *, s64, s64, s64 *, s64 *); -#endif static s64 extRoundDown(s64 nb); #define DPD(a) (printk("(a): %d\n",(a))) @@ -177,162 +174,6 @@ extAlloc(struct inode *ip, s64 xlen, s64 pno, xad_t * xp, bool abnr) return (0); } - -#ifdef _NOTYET -/* - * NAME: extRealloc() - * - * FUNCTION: extend the allocation of a file extent containing a - * partial back last page. - * - * PARAMETERS: - * ip - the inode of the file. - * cp - cbuf for the partial backed last page. - * xlen - request size of the resulting extent. - * xp - pointer to an xad. on successful exit, the xad - * describes the newly allocated extent. - * abnr - bool indicating whether the newly allocated extent - * should be marked as allocated but not recorded. - * - * RETURN VALUES: - * 0 - success - * -EIO - i/o error. - * -ENOSPC - insufficient disk resources. - */ -int extRealloc(struct inode *ip, s64 nxlen, xad_t * xp, bool abnr) -{ - struct super_block *sb = ip->i_sb; - s64 xaddr, xlen, nxaddr, delta, xoff; - s64 ntail, nextend, ninsert; - int rc, nbperpage = JFS_SBI(sb)->nbperpage; - int xflag; - - /* This blocks if we are low on resources */ - txBeginAnon(ip->i_sb); - - mutex_lock(&JFS_IP(ip)->commit_mutex); - /* validate extent length */ - if (nxlen > MAXXLEN) - nxlen = MAXXLEN; - - /* get the extend (partial) page's disk block address and - * number of blocks. - */ - xaddr = addressXAD(xp); - xlen = lengthXAD(xp); - xoff = offsetXAD(xp); - - /* if the extend page is abnr and if the request is for - * the extent to be allocated and recorded, - * make the page allocated and recorded. - */ - if ((xp->flag & XAD_NOTRECORDED) && !abnr) { - xp->flag = 0; - if ((rc = xtUpdate(0, ip, xp))) - goto exit; - } - - /* try to allocated the request number of blocks for the - * extent. dbRealloc() first tries to satisfy the request - * by extending the allocation in place. otherwise, it will - * try to allocate a new set of blocks large enough for the - * request. in satisfying a request, dbReAlloc() may allocate - * less than what was request but will always allocate enough - * space as to satisfy the extend page. - */ - if ((rc = extBrealloc(ip, xaddr, xlen, &nxlen, &nxaddr))) - goto exit; - - /* Allocat blocks to quota. */ - rc = dquot_alloc_block(ip, nxlen); - if (rc) { - dbFree(ip, nxaddr, (s64) nxlen); - mutex_unlock(&JFS_IP(ip)->commit_mutex); - return rc; - } - - delta = nxlen - xlen; - - /* check if the extend page is not abnr but the request is abnr - * and the allocated disk space is for more than one page. if this - * is the case, there is a miss match of abnr between the extend page - * and the one or more pages following the extend page. as a result, - * two extents will have to be manipulated. the first will be that - * of the extent of the extend page and will be manipulated thru - * an xtExtend() or an xtTailgate(), depending upon whether the - * disk allocation occurred as an inplace extension. the second - * extent will be manipulated (created) through an xtInsert() and - * will be for the pages following the extend page. - */ - if (abnr && (!(xp->flag & XAD_NOTRECORDED)) && (nxlen > nbperpage)) { - ntail = nbperpage; - nextend = ntail - xlen; - ninsert = nxlen - nbperpage; - - xflag = XAD_NOTRECORDED; - } else { - ntail = nxlen; - nextend = delta; - ninsert = 0; - - xflag = xp->flag; - } - - /* if we were able to extend the disk allocation in place, - * extend the extent. otherwise, move the extent to a - * new disk location. - */ - if (xaddr == nxaddr) { - /* extend the extent */ - if ((rc = xtExtend(0, ip, xoff + xlen, (int) nextend, 0))) { - dbFree(ip, xaddr + xlen, delta); - dquot_free_block(ip, nxlen); - goto exit; - } - } else { - /* - * move the extent to a new location: - * - * xtTailgate() accounts for relocated tail extent; - */ - if ((rc = xtTailgate(0, ip, xoff, (int) ntail, nxaddr, 0))) { - dbFree(ip, nxaddr, nxlen); - dquot_free_block(ip, nxlen); - goto exit; - } - } - - - /* check if we need to also insert a new extent */ - if (ninsert) { - /* perform the insert. if it fails, free the blocks - * to be inserted and make it appear that we only did - * the xtExtend() or xtTailgate() above. - */ - xaddr = nxaddr + ntail; - if (xtInsert (0, ip, xflag, xoff + ntail, (int) ninsert, - &xaddr, 0)) { - dbFree(ip, xaddr, (s64) ninsert); - delta = nextend; - nxlen = ntail; - xflag = 0; - } - } - - /* set the return results */ - XADaddress(xp, nxaddr); - XADlength(xp, nxlen); - XADoffset(xp, xoff); - xp->flag = xflag; - - mark_inode_dirty(ip); -exit: - mutex_unlock(&JFS_IP(ip)->commit_mutex); - return (rc); -} -#endif /* _NOTYET */ - - /* * NAME: extHint() * @@ -423,44 +264,6 @@ int extRecord(struct inode *ip, xad_t * xp) return rc; } - -#ifdef _NOTYET -/* - * NAME: extFill() - * - * FUNCTION: allocate disk space for a file page that represents - * a file hole. - * - * PARAMETERS: - * ip - the inode of the file. - * cp - cbuf of the file page represent the hole. - * - * RETURN VALUES: - * 0 - success - * -EIO - i/o error. - * -ENOSPC - insufficient disk resources. - */ -int extFill(struct inode *ip, xad_t * xp) -{ - int rc, nbperpage = JFS_SBI(ip->i_sb)->nbperpage; - s64 blkno = offsetXAD(xp) >> ip->i_blkbits; - -// assert(ISSPARSE(ip)); - - /* initialize the extent allocation hint */ - XADaddress(xp, 0); - - /* allocate an extent to fill the hole */ - if ((rc = extAlloc(ip, nbperpage, blkno, xp, false))) - return (rc); - - assert(lengthPXD(xp) == nbperpage); - - return (0); -} -#endif /* _NOTYET */ - - /* * NAME: extBalloc() * @@ -550,64 +353,6 @@ extBalloc(struct inode *ip, s64 hint, s64 * nblocks, s64 * blkno) return (0); } - -#ifdef _NOTYET -/* - * NAME: extBrealloc() - * - * FUNCTION: attempt to extend an extent's allocation. - * - * Initially, we will try to extend the extent's allocation - * in place. If this fails, we'll try to move the extent - * to a new set of blocks. If moving the extent, we initially - * will try to allocate disk blocks for the requested size - * (newnblks). if this fails (new contiguous free blocks not - * available), we'll try to allocate a smaller number of - * blocks (producing a smaller extent), with this smaller - * number of blocks consisting of the requested number of - * blocks rounded down to the next smaller power of 2 - * number (i.e. 16 -> 8). We'll continue to round down and - * retry the allocation until the number of blocks to allocate - * is smaller than the number of blocks per page. - * - * PARAMETERS: - * ip - the inode of the file. - * blkno - starting block number of the extents current allocation. - * nblks - number of blocks within the extents current allocation. - * newnblks - pointer to a s64 value. on entry, this value is the - * new desired extent size (number of blocks). on - * successful exit, this value is set to the extent's actual - * new size (new number of blocks). - * newblkno - the starting block number of the extents new allocation. - * - * RETURN VALUES: - * 0 - success - * -EIO - i/o error. - * -ENOSPC - insufficient disk resources. - */ -static int -extBrealloc(struct inode *ip, - s64 blkno, s64 nblks, s64 * newnblks, s64 * newblkno) -{ - int rc; - - /* try to extend in place */ - if ((rc = dbExtend(ip, blkno, nblks, *newnblks - nblks)) == 0) { - *newblkno = blkno; - return (0); - } else { - if (rc != -ENOSPC) - return (rc); - } - - /* in place extension not possible. - * try to move the extent to a new set of blocks. - */ - return (extBalloc(ip, blkno, newnblks, newblkno)); -} -#endif /* _NOTYET */ - - /* * NAME: extRoundDown() * diff --git a/fs/jfs/jfs_logmgr.c b/fs/jfs/jfs_logmgr.c index 997c81fcea3492788eec8f5ccd44ad6d18d82496..695415cbfe985b995b38e984c628df13fe5dbab6 100644 --- a/fs/jfs/jfs_logmgr.c +++ b/fs/jfs/jfs_logmgr.c @@ -388,14 +388,6 @@ lmWriteRecord(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd, p = (caddr_t) &JFS_IP(tlck->ip)->i_xtroot; linelock = (struct linelock *) & tlck->lock; } -#ifdef _JFS_WIP - else if (tlck->flag & tlckINLINELOCK) { - - inlinelock = (struct inlinelock *) & tlck; - p = (caddr_t) & inlinelock->pxd; - linelock = (struct linelock *) & tlck; - } -#endif /* _JFS_WIP */ else { jfs_err("lmWriteRecord: UFO tlck:0x%p", tlck); return 0; /* Probably should trap */ diff --git a/fs/jfs/jfs_mount.c b/fs/jfs/jfs_mount.c index aa4ff7bcaff23dd8931de14fbd629467819772e0..48d1f70f786cf4265e06d4270f55668d9ba8691f 100644 --- a/fs/jfs/jfs_mount.c +++ b/fs/jfs/jfs_mount.c @@ -307,13 +307,11 @@ static int chkSuper(struct super_block *sb) } bsize = le32_to_cpu(j_sb->s_bsize); -#ifdef _JFS_4K if (bsize != PSIZE) { - jfs_err("Currently only 4K block size supported!"); + jfs_err("Only 4K block size supported!"); rc = -EINVAL; goto out; } -#endif /* _JFS_4K */ jfs_info("superblock: flag:0x%08x state:0x%08x size:0x%Lx", le32_to_cpu(j_sb->s_flag), le32_to_cpu(j_sb->s_state), diff --git a/fs/jfs/jfs_txnmgr.c b/fs/jfs/jfs_txnmgr.c index 042bbe6d8ac2e864e32a86313ed8c9e38d011875..ffd4feece0785a181085d060291ffbc82399d024 100644 --- a/fs/jfs/jfs_txnmgr.c +++ b/fs/jfs/jfs_txnmgr.c @@ -1490,40 +1490,6 @@ static void diLog(struct jfs_log *log, struct tblock *tblk, struct lrd *lrd, tlck->flag |= tlckWRITEPAGE; } else jfs_err("diLog: UFO type tlck:0x%p", tlck); -#ifdef _JFS_WIP - /* - * alloc/free external EA extent - * - * a maplock for txUpdateMap() to update bPWMAP for alloc/free - * of the extent has been formatted at txLock() time; - */ - else { - assert(tlck->type & tlckEA); - - /* log LOG_UPDATEMAP for logredo() to update bmap for - * alloc of new (and free of old) external EA extent; - */ - lrd->type = cpu_to_le16(LOG_UPDATEMAP); - pxdlock = (struct pxd_lock *) & tlck->lock; - nlock = pxdlock->index; - for (i = 0; i < nlock; i++, pxdlock++) { - if (pxdlock->flag & mlckALLOCPXD) - lrd->log.updatemap.type = - cpu_to_le16(LOG_ALLOCPXD); - else - lrd->log.updatemap.type = - cpu_to_le16(LOG_FREEPXD); - lrd->log.updatemap.nxd = cpu_to_le16(1); - lrd->log.updatemap.pxd = pxdlock->pxd; - lrd->backchain = - cpu_to_le32(lmLog(log, tblk, lrd, NULL)); - } - - /* update bmap */ - tlck->flag |= tlckUPDATEMAP; - } -#endif /* _JFS_WIP */ - return; } diff --git a/fs/jfs/jfs_xtree.c b/fs/jfs/jfs_xtree.c index 3148e9b35f3bcbe71ca070ded6f25bd97197ffd3..2d304cee884c6ff2cad43a06433abe425876f97f 100644 --- a/fs/jfs/jfs_xtree.c +++ b/fs/jfs/jfs_xtree.c @@ -114,17 +114,6 @@ static int xtSplitPage(tid_t tid, struct inode *ip, struct xtsplit * split, static int xtSplitRoot(tid_t tid, struct inode *ip, struct xtsplit * split, struct metapage ** rmpp); -#ifdef _STILL_TO_PORT -static int xtDeleteUp(tid_t tid, struct inode *ip, struct metapage * fmp, - xtpage_t * fp, struct btstack * btstack); - -static int xtSearchNode(struct inode *ip, - xad_t * xad, - int *cmpp, struct btstack * btstack, int flag); - -static int xtRelink(tid_t tid, struct inode *ip, xtpage_t * fp); -#endif /* _STILL_TO_PORT */ - /* * xtLookup() * @@ -1493,189 +1482,6 @@ int xtExtend(tid_t tid, /* transaction id */ return rc; } -#ifdef _NOTYET -/* - * xtTailgate() - * - * function: split existing 'tail' extent - * (split offset >= start offset of tail extent), and - * relocate and extend the split tail half; - * - * note: existing extent may or may not have been committed. - * caller is responsible for pager buffer cache update, and - * working block allocation map update; - * update pmap: free old split tail extent, alloc new extent; - */ -int xtTailgate(tid_t tid, /* transaction id */ - struct inode *ip, s64 xoff, /* split/new extent offset */ - s32 xlen, /* new extent length */ - s64 xaddr, /* new extent address */ - int flag) -{ - int rc = 0; - int cmp; - struct metapage *mp; /* meta-page buffer */ - xtpage_t *p; /* base B+-tree index page */ - s64 bn; - int index, nextindex, llen, rlen; - struct btstack btstack; /* traverse stack */ - struct xtsplit split; /* split information */ - xad_t *xad; - struct tlock *tlck; - struct xtlock *xtlck = 0; - struct tlock *mtlck; - struct maplock *pxdlock; - -/* -printf("xtTailgate: nxoff:0x%lx nxlen:0x%x nxaddr:0x%lx\n", - (ulong)xoff, xlen, (ulong)xaddr); -*/ - - /* there must exist extent to be tailgated */ - if ((rc = xtSearch(ip, xoff, NULL, &cmp, &btstack, XT_INSERT))) - return rc; - - /* retrieve search result */ - XT_GETSEARCH(ip, btstack.top, bn, mp, p, index); - - if (cmp != 0) { - XT_PUTPAGE(mp); - jfs_error(ip->i_sb, "couldn't find extent\n"); - return -EIO; - } - - /* entry found must be last entry */ - nextindex = le16_to_cpu(p->header.nextindex); - if (index != nextindex - 1) { - XT_PUTPAGE(mp); - jfs_error(ip->i_sb, "the entry found is not the last entry\n"); - return -EIO; - } - - BT_MARK_DIRTY(mp, ip); - /* - * acquire tlock of the leaf page containing original entry - */ - if (!test_cflag(COMMIT_Nolink, ip)) { - tlck = txLock(tid, ip, mp, tlckXTREE | tlckGROW); - xtlck = (struct xtlock *) & tlck->lock; - } - - /* completely replace extent ? */ - xad = &p->xad[index]; -/* -printf("xtTailgate: xoff:0x%lx xlen:0x%x xaddr:0x%lx\n", - (ulong)offsetXAD(xad), lengthXAD(xad), (ulong)addressXAD(xad)); -*/ - if ((llen = xoff - offsetXAD(xad)) == 0) - goto updateOld; - - /* - * partially replace extent: insert entry for new extent - */ -//insertNew: - /* - * if the leaf page is full, insert the new entry and - * propagate up the router entry for the new page from split - * - * The xtSplitUp() will insert the entry and unpin the leaf page. - */ - if (nextindex == le16_to_cpu(p->header.maxentry)) { - /* xtSpliUp() unpins leaf pages */ - split.mp = mp; - split.index = index + 1; - split.flag = XAD_NEW; - split.off = xoff; /* split offset */ - split.len = xlen; - split.addr = xaddr; - split.pxdlist = NULL; - if ((rc = xtSplitUp(tid, ip, &split, &btstack))) - return rc; - - /* get back old page */ - XT_GETPAGE(ip, bn, mp, PSIZE, p, rc); - if (rc) - return rc; - /* - * if leaf root has been split, original root has been - * copied to new child page, i.e., original entry now - * resides on the new child page; - */ - if (p->header.flag & BT_INTERNAL) { - ASSERT(p->header.nextindex == - cpu_to_le16(XTENTRYSTART + 1)); - xad = &p->xad[XTENTRYSTART]; - bn = addressXAD(xad); - XT_PUTPAGE(mp); - - /* get new child page */ - XT_GETPAGE(ip, bn, mp, PSIZE, p, rc); - if (rc) - return rc; - - BT_MARK_DIRTY(mp, ip); - if (!test_cflag(COMMIT_Nolink, ip)) { - tlck = txLock(tid, ip, mp, tlckXTREE|tlckGROW); - xtlck = (struct xtlock *) & tlck->lock; - } - } - } - /* - * insert the new entry into the leaf page - */ - else { - /* insert the new entry: mark the entry NEW */ - xad = &p->xad[index + 1]; - XT_PUTENTRY(xad, XAD_NEW, xoff, xlen, xaddr); - - /* advance next available entry index */ - le16_add_cpu(&p->header.nextindex, 1); - } - - /* get back old XAD */ - xad = &p->xad[index]; - - /* - * truncate/relocate old extent at split offset - */ - updateOld: - /* update dmap for old/committed/truncated extent */ - rlen = lengthXAD(xad) - llen; - if (!(xad->flag & XAD_NEW)) { - /* free from PWMAP at commit */ - if (!test_cflag(COMMIT_Nolink, ip)) { - mtlck = txMaplock(tid, ip, tlckMAP); - pxdlock = (struct maplock *) & mtlck->lock; - pxdlock->flag = mlckFREEPXD; - PXDaddress(&pxdlock->pxd, addressXAD(xad) + llen); - PXDlength(&pxdlock->pxd, rlen); - pxdlock->index = 1; - } - } else - /* free from WMAP */ - dbFree(ip, addressXAD(xad) + llen, (s64) rlen); - - if (llen) - /* truncate */ - XADlength(xad, llen); - else - /* replace */ - XT_PUTENTRY(xad, XAD_NEW, xoff, xlen, xaddr); - - if (!test_cflag(COMMIT_Nolink, ip)) { - xtlck->lwm.offset = (xtlck->lwm.offset) ? - min(index, (int)xtlck->lwm.offset) : index; - xtlck->lwm.length = le16_to_cpu(p->header.nextindex) - - xtlck->lwm.offset; - } - - /* unpin the leaf page */ - XT_PUTPAGE(mp); - - return rc; -} -#endif /* _NOTYET */ - /* * xtUpdate() * @@ -1753,32 +1559,12 @@ int xtUpdate(tid_t tid, struct inode *ip, xad_t * nxad) newindex = index + 1; nextindex = le16_to_cpu(p->header.nextindex); -#ifdef _JFS_WIP_NOCOALESCE - if (xoff < nxoff) - goto updateRight; - - /* - * replace XAD with nXAD - */ - replace: /* (nxoff == xoff) */ - if (nxlen == xlen) { - /* replace XAD with nXAD:recorded */ - *xad = *nxad; - xad->flag = xflag & ~XAD_NOTRECORDED; - - goto out; - } else /* (nxlen < xlen) */ - goto updateLeft; -#endif /* _JFS_WIP_NOCOALESCE */ - -/* #ifdef _JFS_WIP_COALESCE */ if (xoff < nxoff) goto coalesceRight; /* * coalesce with left XAD */ -//coalesceLeft: /* (xoff == nxoff) */ /* is XAD first entry of page ? */ if (index == XTENTRYSTART) goto replace; @@ -1897,7 +1683,6 @@ int xtUpdate(tid_t tid, struct inode *ip, xad_t * nxad) jfs_error(ip->i_sb, "xoff >= nxoff\n"); return -EIO; } -/* #endif _JFS_WIP_COALESCE */ /* * split XAD into (lXAD, nXAD): @@ -2305,752 +2090,6 @@ int xtAppend(tid_t tid, /* transaction id */ return rc; } -#ifdef _STILL_TO_PORT - -/* - TBD for defragmentaion/reorganization - - * - * xtDelete() - * - * function: - * delete the entry with the specified key. - * - * N.B.: whole extent of the entry is assumed to be deleted. - * - * parameter: - * - * return: - * ENOENT: if the entry is not found. - * - * exception: - */ -int xtDelete(tid_t tid, struct inode *ip, s64 xoff, s32 xlen, int flag) -{ - int rc = 0; - struct btstack btstack; - int cmp; - s64 bn; - struct metapage *mp; - xtpage_t *p; - int index, nextindex; - struct tlock *tlck; - struct xtlock *xtlck; - - /* - * find the matching entry; xtSearch() pins the page - */ - if ((rc = xtSearch(ip, xoff, NULL, &cmp, &btstack, 0))) - return rc; - - XT_GETSEARCH(ip, btstack.top, bn, mp, p, index); - if (cmp) { - /* unpin the leaf page */ - XT_PUTPAGE(mp); - return -ENOENT; - } - - /* - * delete the entry from the leaf page - */ - nextindex = le16_to_cpu(p->header.nextindex); - le16_add_cpu(&p->header.nextindex, -1); - - /* - * if the leaf page bocome empty, free the page - */ - if (p->header.nextindex == cpu_to_le16(XTENTRYSTART)) - return (xtDeleteUp(tid, ip, mp, p, &btstack)); - - BT_MARK_DIRTY(mp, ip); - /* - * acquire a transaction lock on the leaf page; - * - * action:xad deletion; - */ - tlck = txLock(tid, ip, mp, tlckXTREE); - xtlck = (struct xtlock *) & tlck->lock; - xtlck->lwm.offset = - (xtlck->lwm.offset) ? min(index, xtlck->lwm.offset) : index; - - /* if delete from middle, shift left/compact the remaining entries */ - if (index < nextindex - 1) - memmove(&p->xad[index], &p->xad[index + 1], - (nextindex - index - 1) * sizeof(xad_t)); - - XT_PUTPAGE(mp); - - return 0; -} - - -/* - TBD for defragmentaion/reorganization - - * - * xtDeleteUp() - * - * function: - * free empty pages as propagating deletion up the tree - * - * parameter: - * - * return: - */ -static int -xtDeleteUp(tid_t tid, struct inode *ip, - struct metapage * fmp, xtpage_t * fp, struct btstack * btstack) -{ - int rc = 0; - struct metapage *mp; - xtpage_t *p; - int index, nextindex; - s64 xaddr; - int xlen; - struct btframe *parent; - struct tlock *tlck; - struct xtlock *xtlck; - - /* - * keep root leaf page which has become empty - */ - if (fp->header.flag & BT_ROOT) { - /* keep the root page */ - fp->header.flag &= ~BT_INTERNAL; - fp->header.flag |= BT_LEAF; - fp->header.nextindex = cpu_to_le16(XTENTRYSTART); - - /* XT_PUTPAGE(fmp); */ - - return 0; - } - - /* - * free non-root leaf page - */ - if ((rc = xtRelink(tid, ip, fp))) { - XT_PUTPAGE(fmp); - return rc; - } - - xaddr = addressPXD(&fp->header.self); - xlen = lengthPXD(&fp->header.self); - /* free the page extent */ - dbFree(ip, xaddr, (s64) xlen); - - /* free the buffer page */ - discard_metapage(fmp); - - /* - * propagate page deletion up the index tree - * - * If the delete from the parent page makes it empty, - * continue all the way up the tree. - * stop if the root page is reached (which is never deleted) or - * if the entry deletion does not empty the page. - */ - while ((parent = BT_POP(btstack)) != NULL) { - /* get/pin the parent page */ - XT_GETPAGE(ip, parent->bn, mp, PSIZE, p, rc); - if (rc) - return rc; - - index = parent->index; - - /* delete the entry for the freed child page from parent. - */ - nextindex = le16_to_cpu(p->header.nextindex); - - /* - * the parent has the single entry being deleted: - * free the parent page which has become empty. - */ - if (nextindex == 1) { - if (p->header.flag & BT_ROOT) { - /* keep the root page */ - p->header.flag &= ~BT_INTERNAL; - p->header.flag |= BT_LEAF; - p->header.nextindex = - cpu_to_le16(XTENTRYSTART); - - /* XT_PUTPAGE(mp); */ - - break; - } else { - /* free the parent page */ - if ((rc = xtRelink(tid, ip, p))) - return rc; - - xaddr = addressPXD(&p->header.self); - /* free the page extent */ - dbFree(ip, xaddr, - (s64) JFS_SBI(ip->i_sb)->nbperpage); - - /* unpin/free the buffer page */ - discard_metapage(mp); - - /* propagate up */ - continue; - } - } - /* - * the parent has other entries remaining: - * delete the router entry from the parent page. - */ - else { - BT_MARK_DIRTY(mp, ip); - /* - * acquire a transaction lock on the leaf page; - * - * action:xad deletion; - */ - tlck = txLock(tid, ip, mp, tlckXTREE); - xtlck = (struct xtlock *) & tlck->lock; - xtlck->lwm.offset = - (xtlck->lwm.offset) ? min(index, - xtlck->lwm. - offset) : index; - - /* if delete from middle, - * shift left/compact the remaining entries in the page - */ - if (index < nextindex - 1) - memmove(&p->xad[index], &p->xad[index + 1], - (nextindex - index - - 1) << L2XTSLOTSIZE); - - le16_add_cpu(&p->header.nextindex, -1); - jfs_info("xtDeleteUp(entry): 0x%lx[%d]", - (ulong) parent->bn, index); - } - - /* unpin the parent page */ - XT_PUTPAGE(mp); - - /* exit propagation up */ - break; - } - - return 0; -} - - -/* - * NAME: xtRelocate() - * - * FUNCTION: relocate xtpage or data extent of regular file; - * This function is mainly used by defragfs utility. - * - * NOTE: This routine does not have the logic to handle - * uncommitted allocated extent. The caller should call - * txCommit() to commit all the allocation before call - * this routine. - */ -int -xtRelocate(tid_t tid, struct inode * ip, xad_t * oxad, /* old XAD */ - s64 nxaddr, /* new xaddr */ - int xtype) -{ /* extent type: XTPAGE or DATAEXT */ - int rc = 0; - struct tblock *tblk; - struct tlock *tlck; - struct xtlock *xtlck; - struct metapage *mp, *pmp, *lmp, *rmp; /* meta-page buffer */ - xtpage_t *p, *pp, *rp, *lp; /* base B+-tree index page */ - xad_t *xad; - pxd_t *pxd; - s64 xoff, xsize; - int xlen; - s64 oxaddr, sxaddr, dxaddr, nextbn, prevbn; - cbuf_t *cp; - s64 offset, nbytes, nbrd, pno; - int nb, npages, nblks; - s64 bn; - int cmp; - int index; - struct pxd_lock *pxdlock; - struct btstack btstack; /* traverse stack */ - - xtype = xtype & EXTENT_TYPE; - - xoff = offsetXAD(oxad); - oxaddr = addressXAD(oxad); - xlen = lengthXAD(oxad); - - /* validate extent offset */ - offset = xoff << JFS_SBI(ip->i_sb)->l2bsize; - if (offset >= ip->i_size) - return -ESTALE; /* stale extent */ - - jfs_info("xtRelocate: xtype:%d xoff:0x%lx xlen:0x%x xaddr:0x%lx:0x%lx", - xtype, (ulong) xoff, xlen, (ulong) oxaddr, (ulong) nxaddr); - - /* - * 1. get and validate the parent xtpage/xad entry - * covering the source extent to be relocated; - */ - if (xtype == DATAEXT) { - /* search in leaf entry */ - rc = xtSearch(ip, xoff, NULL, &cmp, &btstack, 0); - if (rc) - return rc; - - /* retrieve search result */ - XT_GETSEARCH(ip, btstack.top, bn, pmp, pp, index); - - if (cmp) { - XT_PUTPAGE(pmp); - return -ESTALE; - } - - /* validate for exact match with a single entry */ - xad = &pp->xad[index]; - if (addressXAD(xad) != oxaddr || lengthXAD(xad) != xlen) { - XT_PUTPAGE(pmp); - return -ESTALE; - } - } else { /* (xtype == XTPAGE) */ - - /* search in internal entry */ - rc = xtSearchNode(ip, oxad, &cmp, &btstack, 0); - if (rc) - return rc; - - /* retrieve search result */ - XT_GETSEARCH(ip, btstack.top, bn, pmp, pp, index); - - if (cmp) { - XT_PUTPAGE(pmp); - return -ESTALE; - } - - /* xtSearchNode() validated for exact match with a single entry - */ - xad = &pp->xad[index]; - } - jfs_info("xtRelocate: parent xad entry validated."); - - /* - * 2. relocate the extent - */ - if (xtype == DATAEXT) { - /* if the extent is allocated-but-not-recorded - * there is no real data to be moved in this extent, - */ - if (xad->flag & XAD_NOTRECORDED) - goto out; - else - /* release xtpage for cmRead()/xtLookup() */ - XT_PUTPAGE(pmp); - - /* - * cmRelocate() - * - * copy target data pages to be relocated; - * - * data extent must start at page boundary and - * multiple of page size (except the last data extent); - * read in each page of the source data extent into cbuf, - * update the cbuf extent descriptor of the page to be - * homeward bound to new dst data extent - * copy the data from the old extent to new extent. - * copy is essential for compressed files to avoid problems - * that can arise if there was a change in compression - * algorithms. - * it is a good strategy because it may disrupt cache - * policy to keep the pages in memory afterwards. - */ - offset = xoff << JFS_SBI(ip->i_sb)->l2bsize; - assert((offset & CM_OFFSET) == 0); - nbytes = xlen << JFS_SBI(ip->i_sb)->l2bsize; - pno = offset >> CM_L2BSIZE; - npages = (nbytes + (CM_BSIZE - 1)) >> CM_L2BSIZE; -/* - npages = ((offset + nbytes - 1) >> CM_L2BSIZE) - - (offset >> CM_L2BSIZE) + 1; -*/ - sxaddr = oxaddr; - dxaddr = nxaddr; - - /* process the request one cache buffer at a time */ - for (nbrd = 0; nbrd < nbytes; nbrd += nb, - offset += nb, pno++, npages--) { - /* compute page size */ - nb = min(nbytes - nbrd, CM_BSIZE); - - /* get the cache buffer of the page */ - if (rc = cmRead(ip, offset, npages, &cp)) - break; - - assert(addressPXD(&cp->cm_pxd) == sxaddr); - assert(!cp->cm_modified); - - /* bind buffer with the new extent address */ - nblks = nb >> JFS_IP(ip->i_sb)->l2bsize; - cmSetXD(ip, cp, pno, dxaddr, nblks); - - /* release the cbuf, mark it as modified */ - cmPut(cp, true); - - dxaddr += nblks; - sxaddr += nblks; - } - - /* get back parent page */ - if ((rc = xtSearch(ip, xoff, NULL, &cmp, &btstack, 0))) - return rc; - - XT_GETSEARCH(ip, btstack.top, bn, pmp, pp, index); - jfs_info("xtRelocate: target data extent relocated."); - } else { /* (xtype == XTPAGE) */ - - /* - * read in the target xtpage from the source extent; - */ - XT_GETPAGE(ip, oxaddr, mp, PSIZE, p, rc); - if (rc) { - XT_PUTPAGE(pmp); - return rc; - } - - /* - * read in sibling pages if any to update sibling pointers; - */ - rmp = NULL; - if (p->header.next) { - nextbn = le64_to_cpu(p->header.next); - XT_GETPAGE(ip, nextbn, rmp, PSIZE, rp, rc); - if (rc) { - XT_PUTPAGE(pmp); - XT_PUTPAGE(mp); - return (rc); - } - } - - lmp = NULL; - if (p->header.prev) { - prevbn = le64_to_cpu(p->header.prev); - XT_GETPAGE(ip, prevbn, lmp, PSIZE, lp, rc); - if (rc) { - XT_PUTPAGE(pmp); - XT_PUTPAGE(mp); - if (rmp) - XT_PUTPAGE(rmp); - return (rc); - } - } - - /* at this point, all xtpages to be updated are in memory */ - - /* - * update sibling pointers of sibling xtpages if any; - */ - if (lmp) { - BT_MARK_DIRTY(lmp, ip); - tlck = txLock(tid, ip, lmp, tlckXTREE | tlckRELINK); - lp->header.next = cpu_to_le64(nxaddr); - XT_PUTPAGE(lmp); - } - - if (rmp) { - BT_MARK_DIRTY(rmp, ip); - tlck = txLock(tid, ip, rmp, tlckXTREE | tlckRELINK); - rp->header.prev = cpu_to_le64(nxaddr); - XT_PUTPAGE(rmp); - } - - /* - * update the target xtpage to be relocated - * - * update the self address of the target page - * and write to destination extent; - * redo image covers the whole xtpage since it is new page - * to the destination extent; - * update of bmap for the free of source extent - * of the target xtpage itself: - * update of bmap for the allocation of destination extent - * of the target xtpage itself: - * update of bmap for the extents covered by xad entries in - * the target xtpage is not necessary since they are not - * updated; - * if not committed before this relocation, - * target page may contain XAD_NEW entries which must - * be scanned for bmap update (logredo() always - * scan xtpage REDOPAGE image for bmap update); - * if committed before this relocation (tlckRELOCATE), - * scan may be skipped by commit() and logredo(); - */ - BT_MARK_DIRTY(mp, ip); - /* tlckNEW init xtlck->lwm.offset = XTENTRYSTART; */ - tlck = txLock(tid, ip, mp, tlckXTREE | tlckNEW); - xtlck = (struct xtlock *) & tlck->lock; - - /* update the self address in the xtpage header */ - pxd = &p->header.self; - PXDaddress(pxd, nxaddr); - - /* linelock for the after image of the whole page */ - xtlck->lwm.length = - le16_to_cpu(p->header.nextindex) - xtlck->lwm.offset; - - /* update the buffer extent descriptor of target xtpage */ - xsize = xlen << JFS_SBI(ip->i_sb)->l2bsize; - bmSetXD(mp, nxaddr, xsize); - - /* unpin the target page to new homeward bound */ - XT_PUTPAGE(mp); - jfs_info("xtRelocate: target xtpage relocated."); - } - - /* - * 3. acquire maplock for the source extent to be freed; - * - * acquire a maplock saving the src relocated extent address; - * to free of the extent at commit time; - */ - out: - /* if DATAEXT relocation, write a LOG_UPDATEMAP record for - * free PXD of the source data extent (logredo() will update - * bmap for free of source data extent), and update bmap for - * free of the source data extent; - */ - if (xtype == DATAEXT) - tlck = txMaplock(tid, ip, tlckMAP); - /* if XTPAGE relocation, write a LOG_NOREDOPAGE record - * for the source xtpage (logredo() will init NoRedoPage - * filter and will also update bmap for free of the source - * xtpage), and update bmap for free of the source xtpage; - * N.B. We use tlckMAP instead of tlkcXTREE because there - * is no buffer associated with this lock since the buffer - * has been redirected to the target location. - */ - else /* (xtype == XTPAGE) */ - tlck = txMaplock(tid, ip, tlckMAP | tlckRELOCATE); - - pxdlock = (struct pxd_lock *) & tlck->lock; - pxdlock->flag = mlckFREEPXD; - PXDaddress(&pxdlock->pxd, oxaddr); - PXDlength(&pxdlock->pxd, xlen); - pxdlock->index = 1; - - /* - * 4. update the parent xad entry for relocation; - * - * acquire tlck for the parent entry with XAD_NEW as entry - * update which will write LOG_REDOPAGE and update bmap for - * allocation of XAD_NEW destination extent; - */ - jfs_info("xtRelocate: update parent xad entry."); - BT_MARK_DIRTY(pmp, ip); - tlck = txLock(tid, ip, pmp, tlckXTREE | tlckGROW); - xtlck = (struct xtlock *) & tlck->lock; - - /* update the XAD with the new destination extent; */ - xad = &pp->xad[index]; - xad->flag |= XAD_NEW; - XADaddress(xad, nxaddr); - - xtlck->lwm.offset = min(index, xtlck->lwm.offset); - xtlck->lwm.length = le16_to_cpu(pp->header.nextindex) - - xtlck->lwm.offset; - - /* unpin the parent xtpage */ - XT_PUTPAGE(pmp); - - return rc; -} - - -/* - * xtSearchNode() - * - * function: search for the internal xad entry covering specified extent. - * This function is mainly used by defragfs utility. - * - * parameters: - * ip - file object; - * xad - extent to find; - * cmpp - comparison result: - * btstack - traverse stack; - * flag - search process flag; - * - * returns: - * btstack contains (bn, index) of search path traversed to the entry. - * *cmpp is set to result of comparison with the entry returned. - * the page containing the entry is pinned at exit. - */ -static int xtSearchNode(struct inode *ip, xad_t * xad, /* required XAD entry */ - int *cmpp, struct btstack * btstack, int flag) -{ - int rc = 0; - s64 xoff, xaddr; - int xlen; - int cmp = 1; /* init for empty page */ - s64 bn; /* block number */ - struct metapage *mp; /* meta-page buffer */ - xtpage_t *p; /* page */ - int base, index, lim; - struct btframe *btsp; - s64 t64; - - BT_CLR(btstack); - - xoff = offsetXAD(xad); - xlen = lengthXAD(xad); - xaddr = addressXAD(xad); - - /* - * search down tree from root: - * - * between two consecutive entries of and of - * internal page, child page Pi contains entry with k, Ki <= K < Kj. - * - * if entry with search key K is not found - * internal page search find the entry with largest key Ki - * less than K which point to the child page to search; - * leaf page search find the entry with smallest key Kj - * greater than K so that the returned index is the position of - * the entry to be shifted right for insertion of new entry. - * for empty tree, search key is greater than any key of the tree. - * - * by convention, root bn = 0. - */ - for (bn = 0;;) { - /* get/pin the page to search */ - XT_GETPAGE(ip, bn, mp, PSIZE, p, rc); - if (rc) - return rc; - if (p->header.flag & BT_LEAF) { - XT_PUTPAGE(mp); - return -ESTALE; - } - - lim = le16_to_cpu(p->header.nextindex) - XTENTRYSTART; - - /* - * binary search with search key K on the current page - */ - for (base = XTENTRYSTART; lim; lim >>= 1) { - index = base + (lim >> 1); - - XT_CMP(cmp, xoff, &p->xad[index], t64); - if (cmp == 0) { - /* - * search hit - * - * verify for exact match; - */ - if (xaddr == addressXAD(&p->xad[index]) && - xoff == offsetXAD(&p->xad[index])) { - *cmpp = cmp; - - /* save search result */ - btsp = btstack->top; - btsp->bn = bn; - btsp->index = index; - btsp->mp = mp; - - return 0; - } - - /* descend/search its child page */ - goto next; - } - - if (cmp > 0) { - base = index + 1; - --lim; - } - } - - /* - * search miss - non-leaf page: - * - * base is the smallest index with key (Kj) greater than - * search key (K) and may be zero or maxentry index. - * if base is non-zero, decrement base by one to get the parent - * entry of the child page to search. - */ - index = base ? base - 1 : base; - - /* - * go down to child page - */ - next: - /* get the child page block number */ - bn = addressXAD(&p->xad[index]); - - /* unpin the parent page */ - XT_PUTPAGE(mp); - } -} - - -/* - * xtRelink() - * - * function: - * link around a freed page. - * - * Parameter: - * int tid, - * struct inode *ip, - * xtpage_t *p) - * - * returns: - */ -static int xtRelink(tid_t tid, struct inode *ip, xtpage_t * p) -{ - int rc = 0; - struct metapage *mp; - s64 nextbn, prevbn; - struct tlock *tlck; - - nextbn = le64_to_cpu(p->header.next); - prevbn = le64_to_cpu(p->header.prev); - - /* update prev pointer of the next page */ - if (nextbn != 0) { - XT_GETPAGE(ip, nextbn, mp, PSIZE, p, rc); - if (rc) - return rc; - - /* - * acquire a transaction lock on the page; - * - * action: update prev pointer; - */ - BT_MARK_DIRTY(mp, ip); - tlck = txLock(tid, ip, mp, tlckXTREE | tlckRELINK); - - /* the page may already have been tlock'd */ - - p->header.prev = cpu_to_le64(prevbn); - - XT_PUTPAGE(mp); - } - - /* update next pointer of the previous page */ - if (prevbn != 0) { - XT_GETPAGE(ip, prevbn, mp, PSIZE, p, rc); - if (rc) - return rc; - - /* - * acquire a transaction lock on the page; - * - * action: update next pointer; - */ - BT_MARK_DIRTY(mp, ip); - tlck = txLock(tid, ip, mp, tlckXTREE | tlckRELINK); - - /* the page may already have been tlock'd */ - - p->header.next = le64_to_cpu(nextbn); - - XT_PUTPAGE(mp); - } - - return 0; -} -#endif /* _STILL_TO_PORT */ - /* * xtInitRoot() diff --git a/fs/jfs/jfs_xtree.h b/fs/jfs/jfs_xtree.h index 5f51be8596b34c1c34b791c5c29dc54956ebe4c9..142caafc73b1546ba9c155325c2b01446320e485 100644 --- a/fs/jfs/jfs_xtree.h +++ b/fs/jfs/jfs_xtree.h @@ -95,10 +95,6 @@ extern int xtInsert(tid_t tid, struct inode *ip, int xflag, s64 xoff, int xlen, s64 * xaddrp, int flag); extern int xtExtend(tid_t tid, struct inode *ip, s64 xoff, int xlen, int flag); -#ifdef _NOTYET -extern int xtTailgate(tid_t tid, struct inode *ip, - s64 xoff, int xlen, s64 xaddr, int flag); -#endif extern int xtUpdate(tid_t tid, struct inode *ip, struct xad *nxad); extern int xtDelete(tid_t tid, struct inode *ip, s64 xoff, int xlen, int flag); diff --git a/fs/namei.c b/fs/namei.c index 3dc0db2df561835e78e6e3ab6b301d26d3f637fc..776ecf6799650c28702780749cf5102ebe7a0f4c 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -2769,7 +2769,8 @@ struct dentry *lookup_one(struct user_namespace *mnt_userns, const char *name, EXPORT_SYMBOL(lookup_one); /** - * lookup_one_len_unlocked - filesystem helper to lookup single pathname component + * lookup_one_unlocked - filesystem helper to lookup single pathname component + * @mnt_userns: idmapping of the mount the lookup is performed from * @name: pathname component to lookup * @base: base directory to lookup from * @len: maximum length @len should be interpreted to @@ -2780,14 +2781,15 @@ EXPORT_SYMBOL(lookup_one); * Unlike lookup_one_len, it should be called without the parent * i_mutex held, and will take the i_mutex itself if necessary. */ -struct dentry *lookup_one_len_unlocked(const char *name, - struct dentry *base, int len) +struct dentry *lookup_one_unlocked(struct user_namespace *mnt_userns, + const char *name, struct dentry *base, + int len) { struct qstr this; int err; struct dentry *ret; - err = lookup_one_common(&init_user_ns, name, base, len, &this); + err = lookup_one_common(mnt_userns, name, base, len, &this); if (err) return ERR_PTR(err); @@ -2796,6 +2798,59 @@ struct dentry *lookup_one_len_unlocked(const char *name, ret = lookup_slow(&this, base, 0); return ret; } +EXPORT_SYMBOL(lookup_one_unlocked); + +/** + * lookup_one_positive_unlocked - filesystem helper to lookup single + * pathname component + * @mnt_userns: idmapping of the mount the lookup is performed from + * @name: pathname component to lookup + * @base: base directory to lookup from + * @len: maximum length @len should be interpreted to + * + * This helper will yield ERR_PTR(-ENOENT) on negatives. The helper returns + * known positive or ERR_PTR(). This is what most of the users want. + * + * Note that pinned negative with unlocked parent _can_ become positive at any + * time, so callers of lookup_one_unlocked() need to be very careful; pinned + * positives have >d_inode stable, so this one avoids such problems. + * + * Note that this routine is purely a helper for filesystem usage and should + * not be called by generic code. + * + * The helper should be called without i_mutex held. + */ +struct dentry *lookup_one_positive_unlocked(struct user_namespace *mnt_userns, + const char *name, + struct dentry *base, int len) +{ + struct dentry *ret = lookup_one_unlocked(mnt_userns, name, base, len); + + if (!IS_ERR(ret) && d_flags_negative(smp_load_acquire(&ret->d_flags))) { + dput(ret); + ret = ERR_PTR(-ENOENT); + } + return ret; +} +EXPORT_SYMBOL(lookup_one_positive_unlocked); + +/** + * lookup_one_len_unlocked - filesystem helper to lookup single pathname component + * @name: pathname component to lookup + * @base: base directory to lookup from + * @len: maximum length @len should be interpreted to + * + * Note that this routine is purely a helper for filesystem usage and should + * not be called by generic code. + * + * Unlike lookup_one_len, it should be called without the parent + * i_mutex held, and will take the i_mutex itself if necessary. + */ +struct dentry *lookup_one_len_unlocked(const char *name, + struct dentry *base, int len) +{ + return lookup_one_unlocked(&init_user_ns, name, base, len); +} EXPORT_SYMBOL(lookup_one_len_unlocked); /* @@ -2809,12 +2864,7 @@ EXPORT_SYMBOL(lookup_one_len_unlocked); struct dentry *lookup_positive_unlocked(const char *name, struct dentry *base, int len) { - struct dentry *ret = lookup_one_len_unlocked(name, base, len); - if (!IS_ERR(ret) && d_flags_negative(smp_load_acquire(&ret->d_flags))) { - dput(ret); - ret = ERR_PTR(-ENOENT); - } - return ret; + return lookup_one_positive_unlocked(&init_user_ns, name, base, len); } EXPORT_SYMBOL(lookup_positive_unlocked); diff --git a/fs/open.c b/fs/open.c index 11e233e23a8edc1c169b06553c0334aca4fdbf22..3a5b4588186399d264aa136dd87d389967c01396 100644 --- a/fs/open.c +++ b/fs/open.c @@ -225,6 +225,21 @@ SYSCALL_DEFINE2(ftruncate64, unsigned int, fd, loff_t, length) } #endif /* BITS_PER_LONG == 32 */ +#if defined(CONFIG_COMPAT) && defined(__ARCH_WANT_COMPAT_TRUNCATE64) +COMPAT_SYSCALL_DEFINE3(truncate64, const char __user *, pathname, + compat_arg_u64_dual(length)) +{ + return ksys_truncate(pathname, compat_arg_u64_glue(length)); +} +#endif + +#if defined(CONFIG_COMPAT) && defined(__ARCH_WANT_COMPAT_FTRUNCATE64) +COMPAT_SYSCALL_DEFINE3(ftruncate64, unsigned int, fd, + compat_arg_u64_dual(length)) +{ + return ksys_ftruncate(fd, compat_arg_u64_glue(length)); +} +#endif int vfs_fallocate(struct file *file, int mode, loff_t offset, loff_t len) { @@ -340,6 +355,15 @@ SYSCALL_DEFINE4(fallocate, int, fd, int, mode, loff_t, offset, loff_t, len) return ksys_fallocate(fd, mode, offset, len); } +#if defined(CONFIG_COMPAT) && defined(__ARCH_WANT_COMPAT_FALLOCATE) +COMPAT_SYSCALL_DEFINE6(fallocate, int, fd, int, mode, compat_arg_u64_dual(offset), + compat_arg_u64_dual(len)) +{ + return ksys_fallocate(fd, mode, compat_arg_u64_glue(offset), + compat_arg_u64_glue(len)); +} +#endif + /* * access() needs to use the real uid/gid, not the effective uid/gid. * We do this by temporarily clearing all FS-related capabilities and diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c index e040970408d4ff2b57c3e64518961eacbf66113a..714ec569d25b31129831418d5f58a1d525580e0f 100644 --- a/fs/overlayfs/copy_up.c +++ b/fs/overlayfs/copy_up.c @@ -44,9 +44,9 @@ static bool ovl_must_copy_xattr(const char *name) !strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN); } -int ovl_copy_xattr(struct super_block *sb, struct dentry *old, - struct dentry *new) +int ovl_copy_xattr(struct super_block *sb, struct path *oldpath, struct dentry *new) { + struct dentry *old = oldpath->dentry; ssize_t list_size, size, value_size = 0; char *buf, *name, *value = NULL; int error = 0; @@ -94,9 +94,9 @@ int ovl_copy_xattr(struct super_block *sb, struct dentry *old, continue; /* Discard */ } retry: - size = vfs_getxattr(&init_user_ns, old, name, value, value_size); + size = ovl_do_getxattr(oldpath, name, value, value_size); if (size == -ERANGE) - size = vfs_getxattr(&init_user_ns, old, name, NULL, 0); + size = ovl_do_getxattr(oldpath, name, NULL, 0); if (size < 0) { error = size; @@ -117,7 +117,7 @@ retry: goto retry; } - error = vfs_setxattr(&init_user_ns, new, name, value, size, 0); + error = ovl_do_setxattr(OVL_FS(sb), new, name, value, size, 0); if (error) { if (error != -EOPNOTSUPP || ovl_must_copy_xattr(name)) break; @@ -292,17 +292,19 @@ out_fput: return error; } -static int ovl_set_size(struct dentry *upperdentry, struct kstat *stat) +static int ovl_set_size(struct ovl_fs *ofs, + struct dentry *upperdentry, struct kstat *stat) { struct iattr attr = { .ia_valid = ATTR_SIZE, .ia_size = stat->size, }; - return notify_change(&init_user_ns, upperdentry, &attr, NULL); + return ovl_do_notify_change(ofs, upperdentry, &attr); } -static int ovl_set_timestamps(struct dentry *upperdentry, struct kstat *stat) +static int ovl_set_timestamps(struct ovl_fs *ofs, struct dentry *upperdentry, + struct kstat *stat) { struct iattr attr = { .ia_valid = @@ -311,10 +313,11 @@ static int ovl_set_timestamps(struct dentry *upperdentry, struct kstat *stat) .ia_mtime = stat->mtime, }; - return notify_change(&init_user_ns, upperdentry, &attr, NULL); + return ovl_do_notify_change(ofs, upperdentry, &attr); } -int ovl_set_attr(struct dentry *upperdentry, struct kstat *stat) +int ovl_set_attr(struct ovl_fs *ofs, struct dentry *upperdentry, + struct kstat *stat) { int err = 0; @@ -323,7 +326,7 @@ int ovl_set_attr(struct dentry *upperdentry, struct kstat *stat) .ia_valid = ATTR_MODE, .ia_mode = stat->mode, }; - err = notify_change(&init_user_ns, upperdentry, &attr, NULL); + err = ovl_do_notify_change(ofs, upperdentry, &attr); } if (!err) { struct iattr attr = { @@ -331,10 +334,10 @@ int ovl_set_attr(struct dentry *upperdentry, struct kstat *stat) .ia_uid = stat->uid, .ia_gid = stat->gid, }; - err = notify_change(&init_user_ns, upperdentry, &attr, NULL); + err = ovl_do_notify_change(ofs, upperdentry, &attr); } if (!err) - ovl_set_timestamps(upperdentry, stat); + ovl_set_timestamps(ofs, upperdentry, stat); return err; } @@ -433,7 +436,7 @@ static int ovl_set_upper_fh(struct ovl_fs *ofs, struct dentry *upper, if (IS_ERR(fh)) return PTR_ERR(fh); - err = ovl_do_setxattr(ofs, index, OVL_XATTR_UPPER, fh->buf, fh->fb.len); + err = ovl_setxattr(ofs, index, OVL_XATTR_UPPER, fh->buf, fh->fb.len); kfree(fh); return err; @@ -474,7 +477,7 @@ static int ovl_create_index(struct dentry *dentry, struct dentry *origin, if (err) return err; - temp = ovl_create_temp(indexdir, OVL_CATTR(S_IFDIR | 0)); + temp = ovl_create_temp(ofs, indexdir, OVL_CATTR(S_IFDIR | 0)); err = PTR_ERR(temp); if (IS_ERR(temp)) goto free_name; @@ -483,16 +486,16 @@ static int ovl_create_index(struct dentry *dentry, struct dentry *origin, if (err) goto out; - index = lookup_one_len(name.name, indexdir, name.len); + index = ovl_lookup_upper(ofs, name.name, indexdir, name.len); if (IS_ERR(index)) { err = PTR_ERR(index); } else { - err = ovl_do_rename(dir, temp, dir, index, 0); + err = ovl_do_rename(ofs, dir, temp, dir, index, 0); dput(index); } out: if (err) - ovl_cleanup(dir, temp); + ovl_cleanup(ofs, dir, temp); dput(temp); free_name: kfree(name.name); @@ -519,6 +522,7 @@ static int ovl_link_up(struct ovl_copy_up_ctx *c) int err; struct dentry *upper; struct dentry *upperdir = ovl_dentry_upper(c->parent); + struct ovl_fs *ofs = OVL_FS(c->dentry->d_sb); struct inode *udir = d_inode(upperdir); /* Mark parent "impure" because it may now contain non-pure upper */ @@ -531,16 +535,16 @@ static int ovl_link_up(struct ovl_copy_up_ctx *c) return err; inode_lock_nested(udir, I_MUTEX_PARENT); - upper = lookup_one_len(c->dentry->d_name.name, upperdir, - c->dentry->d_name.len); + upper = ovl_lookup_upper(ofs, c->dentry->d_name.name, upperdir, + c->dentry->d_name.len); err = PTR_ERR(upper); if (!IS_ERR(upper)) { - err = ovl_do_link(ovl_dentry_upper(c->dentry), udir, upper); + err = ovl_do_link(ofs, ovl_dentry_upper(c->dentry), udir, upper); dput(upper); if (!err) { /* Restore timestamps on parent (best effort) */ - ovl_set_timestamps(upperdir, &c->pstat); + ovl_set_timestamps(ofs, upperdir, &c->pstat); ovl_dentry_set_upper_alias(c->dentry); } } @@ -578,7 +582,7 @@ static int ovl_copy_up_inode(struct ovl_copy_up_ctx *c, struct dentry *temp) return err; } - err = ovl_copy_xattr(c->dentry->d_sb, c->lowerpath.dentry, temp); + err = ovl_copy_xattr(c->dentry->d_sb, &c->lowerpath, temp); if (err) return err; @@ -614,9 +618,9 @@ static int ovl_copy_up_inode(struct ovl_copy_up_ctx *c, struct dentry *temp) inode_lock(temp->d_inode); if (S_ISREG(c->stat.mode)) - err = ovl_set_size(temp, &c->stat); + err = ovl_set_size(ofs, temp, &c->stat); if (!err) - err = ovl_set_attr(temp, &c->stat); + err = ovl_set_attr(ofs, temp, &c->stat); inode_unlock(temp->d_inode); return err; @@ -656,6 +660,7 @@ static void ovl_revert_cu_creds(struct ovl_cu_creds *cc) */ static int ovl_copy_up_workdir(struct ovl_copy_up_ctx *c) { + struct ovl_fs *ofs = OVL_FS(c->dentry->d_sb); struct inode *inode; struct inode *udir = d_inode(c->destdir), *wdir = d_inode(c->workdir); struct dentry *temp, *upper; @@ -677,7 +682,7 @@ static int ovl_copy_up_workdir(struct ovl_copy_up_ctx *c) if (err) goto unlock; - temp = ovl_create_temp(c->workdir, &cattr); + temp = ovl_create_temp(ofs, c->workdir, &cattr); ovl_revert_cu_creds(&cc); err = PTR_ERR(temp); @@ -694,12 +699,13 @@ static int ovl_copy_up_workdir(struct ovl_copy_up_ctx *c) goto cleanup; } - upper = lookup_one_len(c->destname.name, c->destdir, c->destname.len); + upper = ovl_lookup_upper(ofs, c->destname.name, c->destdir, + c->destname.len); err = PTR_ERR(upper); if (IS_ERR(upper)) goto cleanup; - err = ovl_do_rename(wdir, temp, udir, upper, 0); + err = ovl_do_rename(ofs, wdir, temp, udir, upper, 0); dput(upper); if (err) goto cleanup; @@ -716,7 +722,7 @@ unlock: return err; cleanup: - ovl_cleanup(wdir, temp); + ovl_cleanup(ofs, wdir, temp); dput(temp); goto unlock; } @@ -724,6 +730,7 @@ cleanup: /* Copyup using O_TMPFILE which does not require cross dir locking */ static int ovl_copy_up_tmpfile(struct ovl_copy_up_ctx *c) { + struct ovl_fs *ofs = OVL_FS(c->dentry->d_sb); struct inode *udir = d_inode(c->destdir); struct dentry *temp, *upper; struct ovl_cu_creds cc; @@ -733,7 +740,7 @@ static int ovl_copy_up_tmpfile(struct ovl_copy_up_ctx *c) if (err) return err; - temp = ovl_do_tmpfile(c->workdir, c->stat.mode); + temp = ovl_do_tmpfile(ofs, c->workdir, c->stat.mode); ovl_revert_cu_creds(&cc); if (IS_ERR(temp)) @@ -745,10 +752,11 @@ static int ovl_copy_up_tmpfile(struct ovl_copy_up_ctx *c) inode_lock_nested(udir, I_MUTEX_PARENT); - upper = lookup_one_len(c->destname.name, c->destdir, c->destname.len); + upper = ovl_lookup_upper(ofs, c->destname.name, c->destdir, + c->destname.len); err = PTR_ERR(upper); if (!IS_ERR(upper)) { - err = ovl_do_link(temp, udir, upper); + err = ovl_do_link(ofs, temp, udir, upper); dput(upper); } inode_unlock(udir); @@ -836,7 +844,7 @@ static int ovl_do_copy_up(struct ovl_copy_up_ctx *c) /* Restore timestamps on parent (best effort) */ inode_lock(udir); - ovl_set_timestamps(c->destdir, &c->pstat); + ovl_set_timestamps(ofs, c->destdir, &c->pstat); inode_unlock(udir); ovl_dentry_set_upper_alias(c->dentry); @@ -865,12 +873,12 @@ static bool ovl_need_meta_copy_up(struct dentry *dentry, umode_t mode, return true; } -static ssize_t ovl_getxattr(struct dentry *dentry, char *name, char **value) +static ssize_t ovl_getxattr_value(struct path *path, char *name, char **value) { ssize_t res; char *buf; - res = vfs_getxattr(&init_user_ns, dentry, name, NULL, 0); + res = ovl_do_getxattr(path, name, NULL, 0); if (res == -ENODATA || res == -EOPNOTSUPP) res = 0; @@ -879,7 +887,7 @@ static ssize_t ovl_getxattr(struct dentry *dentry, char *name, char **value) if (!buf) return -ENOMEM; - res = vfs_getxattr(&init_user_ns, dentry, name, buf, res); + res = ovl_do_getxattr(path, name, buf, res); if (res < 0) kfree(buf); else @@ -906,8 +914,8 @@ static int ovl_copy_up_meta_inode_data(struct ovl_copy_up_ctx *c) return -EIO; if (c->stat.size) { - err = cap_size = ovl_getxattr(upperpath.dentry, XATTR_NAME_CAPS, - &capability); + err = cap_size = ovl_getxattr_value(&upperpath, XATTR_NAME_CAPS, + &capability); if (cap_size < 0) goto out; } @@ -921,14 +929,14 @@ static int ovl_copy_up_meta_inode_data(struct ovl_copy_up_ctx *c) * don't want that to happen for normal copy-up operation. */ if (capability) { - err = vfs_setxattr(&init_user_ns, upperpath.dentry, - XATTR_NAME_CAPS, capability, cap_size, 0); + err = ovl_do_setxattr(ofs, upperpath.dentry, XATTR_NAME_CAPS, + capability, cap_size, 0); if (err) goto out_free; } - err = ovl_do_removexattr(ofs, upperpath.dentry, OVL_XATTR_METACOPY); + err = ovl_removexattr(ofs, upperpath.dentry, OVL_XATTR_METACOPY); if (err) goto out_free; diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c index f18490813170af41375c24360ba6e136a841b30a..6b03457f72bb10b3ca0cb4532e6e12eb4ff7cb64 100644 --- a/fs/overlayfs/dir.c +++ b/fs/overlayfs/dir.c @@ -23,15 +23,15 @@ MODULE_PARM_DESC(redirect_max, static int ovl_set_redirect(struct dentry *dentry, bool samedir); -int ovl_cleanup(struct inode *wdir, struct dentry *wdentry) +int ovl_cleanup(struct ovl_fs *ofs, struct inode *wdir, struct dentry *wdentry) { int err; dget(wdentry); if (d_is_dir(wdentry)) - err = ovl_do_rmdir(wdir, wdentry); + err = ovl_do_rmdir(ofs, wdir, wdentry); else - err = ovl_do_unlink(wdir, wdentry); + err = ovl_do_unlink(ofs, wdir, wdentry); dput(wdentry); if (err) { @@ -42,7 +42,7 @@ int ovl_cleanup(struct inode *wdir, struct dentry *wdentry) return err; } -struct dentry *ovl_lookup_temp(struct dentry *workdir) +struct dentry *ovl_lookup_temp(struct ovl_fs *ofs, struct dentry *workdir) { struct dentry *temp; char name[20]; @@ -51,7 +51,7 @@ struct dentry *ovl_lookup_temp(struct dentry *workdir) /* counter is allowed to wrap, since temp dentries are ephemeral */ snprintf(name, sizeof(name), "#%x", atomic_inc_return(&temp_id)); - temp = lookup_one_len(name, workdir, strlen(name)); + temp = ovl_lookup_upper(ofs, name, workdir, strlen(name)); if (!IS_ERR(temp) && temp->d_inode) { pr_err("workdir/%s already exists\n", name); dput(temp); @@ -70,11 +70,11 @@ static struct dentry *ovl_whiteout(struct ovl_fs *ofs) struct inode *wdir = workdir->d_inode; if (!ofs->whiteout) { - whiteout = ovl_lookup_temp(workdir); + whiteout = ovl_lookup_temp(ofs, workdir); if (IS_ERR(whiteout)) goto out; - err = ovl_do_whiteout(wdir, whiteout); + err = ovl_do_whiteout(ofs, wdir, whiteout); if (err) { dput(whiteout); whiteout = ERR_PTR(err); @@ -84,11 +84,11 @@ static struct dentry *ovl_whiteout(struct ovl_fs *ofs) } if (ofs->share_whiteout) { - whiteout = ovl_lookup_temp(workdir); + whiteout = ovl_lookup_temp(ofs, workdir); if (IS_ERR(whiteout)) goto out; - err = ovl_do_link(ofs->whiteout, wdir, whiteout); + err = ovl_do_link(ofs, ofs->whiteout, wdir, whiteout); if (!err) goto out; @@ -122,27 +122,28 @@ int ovl_cleanup_and_whiteout(struct ovl_fs *ofs, struct inode *dir, if (d_is_dir(dentry)) flags = RENAME_EXCHANGE; - err = ovl_do_rename(wdir, whiteout, dir, dentry, flags); + err = ovl_do_rename(ofs, wdir, whiteout, dir, dentry, flags); if (err) goto kill_whiteout; if (flags) - ovl_cleanup(wdir, dentry); + ovl_cleanup(ofs, wdir, dentry); out: dput(whiteout); return err; kill_whiteout: - ovl_cleanup(wdir, whiteout); + ovl_cleanup(ofs, wdir, whiteout); goto out; } -int ovl_mkdir_real(struct inode *dir, struct dentry **newdentry, umode_t mode) +int ovl_mkdir_real(struct ovl_fs *ofs, struct inode *dir, + struct dentry **newdentry, umode_t mode) { int err; struct dentry *d, *dentry = *newdentry; - err = ovl_do_mkdir(dir, dentry, mode); + err = ovl_do_mkdir(ofs, dir, dentry, mode); if (err) return err; @@ -154,8 +155,8 @@ int ovl_mkdir_real(struct inode *dir, struct dentry **newdentry, umode_t mode) * to it unhashed and negative. If that happens, try to * lookup a new hashed and positive dentry. */ - d = lookup_one_len(dentry->d_name.name, dentry->d_parent, - dentry->d_name.len); + d = ovl_lookup_upper(ofs, dentry->d_name.name, dentry->d_parent, + dentry->d_name.len); if (IS_ERR(d)) { pr_warn("failed lookup after mkdir (%pd2, err=%i).\n", dentry, err); @@ -167,8 +168,8 @@ int ovl_mkdir_real(struct inode *dir, struct dentry **newdentry, umode_t mode) return 0; } -struct dentry *ovl_create_real(struct inode *dir, struct dentry *newdentry, - struct ovl_cattr *attr) +struct dentry *ovl_create_real(struct ovl_fs *ofs, struct inode *dir, + struct dentry *newdentry, struct ovl_cattr *attr) { int err; @@ -180,28 +181,28 @@ struct dentry *ovl_create_real(struct inode *dir, struct dentry *newdentry, goto out; if (attr->hardlink) { - err = ovl_do_link(attr->hardlink, dir, newdentry); + err = ovl_do_link(ofs, attr->hardlink, dir, newdentry); } else { switch (attr->mode & S_IFMT) { case S_IFREG: - err = ovl_do_create(dir, newdentry, attr->mode); + err = ovl_do_create(ofs, dir, newdentry, attr->mode); break; case S_IFDIR: /* mkdir is special... */ - err = ovl_mkdir_real(dir, &newdentry, attr->mode); + err = ovl_mkdir_real(ofs, dir, &newdentry, attr->mode); break; case S_IFCHR: case S_IFBLK: case S_IFIFO: case S_IFSOCK: - err = ovl_do_mknod(dir, newdentry, attr->mode, + err = ovl_do_mknod(ofs, dir, newdentry, attr->mode, attr->rdev); break; case S_IFLNK: - err = ovl_do_symlink(dir, newdentry, attr->link); + err = ovl_do_symlink(ofs, dir, newdentry, attr->link); break; default: @@ -223,10 +224,11 @@ out: return newdentry; } -struct dentry *ovl_create_temp(struct dentry *workdir, struct ovl_cattr *attr) +struct dentry *ovl_create_temp(struct ovl_fs *ofs, struct dentry *workdir, + struct ovl_cattr *attr) { - return ovl_create_real(d_inode(workdir), ovl_lookup_temp(workdir), - attr); + return ovl_create_real(ofs, d_inode(workdir), + ovl_lookup_temp(ofs, workdir), attr); } static int ovl_set_opaque_xerr(struct dentry *dentry, struct dentry *upper, @@ -330,10 +332,9 @@ static int ovl_create_upper(struct dentry *dentry, struct inode *inode, attr->mode &= ~current_umask(); inode_lock_nested(udir, I_MUTEX_PARENT); - newdentry = ovl_create_real(udir, - lookup_one_len(dentry->d_name.name, - upperdir, - dentry->d_name.len), + newdentry = ovl_create_real(ofs, udir, + ovl_lookup_upper(ofs, dentry->d_name.name, + upperdir, dentry->d_name.len), attr); err = PTR_ERR(newdentry); if (IS_ERR(newdentry)) @@ -353,7 +354,7 @@ out_unlock: return err; out_cleanup: - ovl_cleanup(udir, newdentry); + ovl_cleanup(ofs, udir, newdentry); dput(newdentry); goto out_unlock; } @@ -361,6 +362,7 @@ out_cleanup: static struct dentry *ovl_clear_empty(struct dentry *dentry, struct list_head *list) { + struct ovl_fs *ofs = OVL_FS(dentry->d_sb); struct dentry *workdir = ovl_workdir(dentry); struct inode *wdir = workdir->d_inode; struct dentry *upperdir = ovl_dentry_upper(dentry->d_parent); @@ -391,12 +393,12 @@ static struct dentry *ovl_clear_empty(struct dentry *dentry, if (upper->d_parent->d_inode != udir) goto out_unlock; - opaquedir = ovl_create_temp(workdir, OVL_CATTR(stat.mode)); + opaquedir = ovl_create_temp(ofs, workdir, OVL_CATTR(stat.mode)); err = PTR_ERR(opaquedir); if (IS_ERR(opaquedir)) goto out_unlock; - err = ovl_copy_xattr(dentry->d_sb, upper, opaquedir); + err = ovl_copy_xattr(dentry->d_sb, &upperpath, opaquedir); if (err) goto out_cleanup; @@ -405,17 +407,17 @@ static struct dentry *ovl_clear_empty(struct dentry *dentry, goto out_cleanup; inode_lock(opaquedir->d_inode); - err = ovl_set_attr(opaquedir, &stat); + err = ovl_set_attr(ofs, opaquedir, &stat); inode_unlock(opaquedir->d_inode); if (err) goto out_cleanup; - err = ovl_do_rename(wdir, opaquedir, udir, upper, RENAME_EXCHANGE); + err = ovl_do_rename(ofs, wdir, opaquedir, udir, upper, RENAME_EXCHANGE); if (err) goto out_cleanup; - ovl_cleanup_whiteouts(upper, list); - ovl_cleanup(wdir, upper); + ovl_cleanup_whiteouts(ofs, upper, list); + ovl_cleanup(ofs, wdir, upper); unlock_rename(workdir, upperdir); /* dentry's upper doesn't match now, get rid of it */ @@ -424,7 +426,7 @@ static struct dentry *ovl_clear_empty(struct dentry *dentry, return opaquedir; out_cleanup: - ovl_cleanup(wdir, opaquedir); + ovl_cleanup(ofs, wdir, opaquedir); dput(opaquedir); out_unlock: unlock_rename(workdir, upperdir); @@ -432,8 +434,8 @@ out: return ERR_PTR(err); } -static int ovl_set_upper_acl(struct dentry *upperdentry, const char *name, - const struct posix_acl *acl) +static int ovl_set_upper_acl(struct ovl_fs *ofs, struct dentry *upperdentry, + const char *name, const struct posix_acl *acl) { void *buffer; size_t size; @@ -451,7 +453,7 @@ static int ovl_set_upper_acl(struct dentry *upperdentry, const char *name, if (err < 0) goto out_free; - err = vfs_setxattr(&init_user_ns, upperdentry, name, buffer, size, XATTR_CREATE); + err = ovl_do_setxattr(ofs, upperdentry, name, buffer, size, XATTR_CREATE); out_free: kfree(buffer); return err; @@ -460,6 +462,7 @@ out_free: static int ovl_create_over_whiteout(struct dentry *dentry, struct inode *inode, struct ovl_cattr *cattr) { + struct ovl_fs *ofs = OVL_FS(dentry->d_sb); struct dentry *workdir = ovl_workdir(dentry); struct inode *wdir = workdir->d_inode; struct dentry *upperdir = ovl_dentry_upper(dentry->d_parent); @@ -484,8 +487,8 @@ static int ovl_create_over_whiteout(struct dentry *dentry, struct inode *inode, if (err) goto out; - upper = lookup_one_len(dentry->d_name.name, upperdir, - dentry->d_name.len); + upper = ovl_lookup_upper(ofs, dentry->d_name.name, upperdir, + dentry->d_name.len); err = PTR_ERR(upper); if (IS_ERR(upper)) goto out_unlock; @@ -494,7 +497,7 @@ static int ovl_create_over_whiteout(struct dentry *dentry, struct inode *inode, if (d_is_negative(upper) || !IS_WHITEOUT(d_inode(upper))) goto out_dput; - newdentry = ovl_create_temp(workdir, cattr); + newdentry = ovl_create_temp(ofs, workdir, cattr); err = PTR_ERR(newdentry); if (IS_ERR(newdentry)) goto out_dput; @@ -510,19 +513,19 @@ static int ovl_create_over_whiteout(struct dentry *dentry, struct inode *inode, .ia_mode = cattr->mode, }; inode_lock(newdentry->d_inode); - err = notify_change(&init_user_ns, newdentry, &attr, NULL); + err = ovl_do_notify_change(ofs, newdentry, &attr); inode_unlock(newdentry->d_inode); if (err) goto out_cleanup; } if (!hardlink) { - err = ovl_set_upper_acl(newdentry, XATTR_NAME_POSIX_ACL_ACCESS, - acl); + err = ovl_set_upper_acl(ofs, newdentry, + XATTR_NAME_POSIX_ACL_ACCESS, acl); if (err) goto out_cleanup; - err = ovl_set_upper_acl(newdentry, XATTR_NAME_POSIX_ACL_DEFAULT, - default_acl); + err = ovl_set_upper_acl(ofs, newdentry, + XATTR_NAME_POSIX_ACL_DEFAULT, default_acl); if (err) goto out_cleanup; } @@ -532,20 +535,20 @@ static int ovl_create_over_whiteout(struct dentry *dentry, struct inode *inode, if (err) goto out_cleanup; - err = ovl_do_rename(wdir, newdentry, udir, upper, + err = ovl_do_rename(ofs, wdir, newdentry, udir, upper, RENAME_EXCHANGE); if (err) goto out_cleanup; - ovl_cleanup(wdir, upper); + ovl_cleanup(ofs, wdir, upper); } else { - err = ovl_do_rename(wdir, newdentry, udir, upper, 0); + err = ovl_do_rename(ofs, wdir, newdentry, udir, upper, 0); if (err) goto out_cleanup; } err = ovl_instantiate(dentry, inode, newdentry, hardlink); if (err) { - ovl_cleanup(udir, newdentry); + ovl_cleanup(ofs, udir, newdentry); dput(newdentry); } out_dput: @@ -560,7 +563,7 @@ out: return err; out_cleanup: - ovl_cleanup(wdir, newdentry); + ovl_cleanup(ofs, wdir, newdentry); dput(newdentry); goto out_dput; } @@ -767,8 +770,8 @@ static int ovl_remove_and_whiteout(struct dentry *dentry, if (err) goto out_dput; - upper = lookup_one_len(dentry->d_name.name, upperdir, - dentry->d_name.len); + upper = ovl_lookup_upper(ofs, dentry->d_name.name, upperdir, + dentry->d_name.len); err = PTR_ERR(upper); if (IS_ERR(upper)) goto out_unlock; @@ -800,6 +803,7 @@ out: static int ovl_remove_upper(struct dentry *dentry, bool is_dir, struct list_head *list) { + struct ovl_fs *ofs = OVL_FS(dentry->d_sb); struct dentry *upperdir = ovl_dentry_upper(dentry->d_parent); struct inode *dir = upperdir->d_inode; struct dentry *upper; @@ -814,8 +818,8 @@ static int ovl_remove_upper(struct dentry *dentry, bool is_dir, } inode_lock_nested(dir, I_MUTEX_PARENT); - upper = lookup_one_len(dentry->d_name.name, upperdir, - dentry->d_name.len); + upper = ovl_lookup_upper(ofs, dentry->d_name.name, upperdir, + dentry->d_name.len); err = PTR_ERR(upper); if (IS_ERR(upper)) goto out_unlock; @@ -826,9 +830,9 @@ static int ovl_remove_upper(struct dentry *dentry, bool is_dir, goto out_dput_upper; if (is_dir) - err = vfs_rmdir(&init_user_ns, dir, upper); + err = ovl_do_rmdir(ofs, dir, upper); else - err = vfs_unlink(&init_user_ns, dir, upper, NULL); + err = ovl_do_unlink(ofs, dir, upper); ovl_dir_modified(dentry->d_parent, ovl_type_origin(dentry)); /* @@ -880,7 +884,6 @@ static int ovl_do_remove(struct dentry *dentry, bool is_dir) { int err; const struct cred *old_cred; - struct dentry *upperdentry; bool lower_positive = ovl_lower_positive(dentry); LIST_HEAD(list); @@ -923,9 +926,8 @@ static int ovl_do_remove(struct dentry *dentry, bool is_dir) * Note: we fail to update ctime if there was no copy-up, only a * whiteout */ - upperdentry = ovl_dentry_upper(dentry); - if (upperdentry) - ovl_copyattr(d_inode(upperdentry), d_inode(dentry)); + if (ovl_dentry_upper(dentry)) + ovl_copyattr(d_inode(dentry)); out_drop_write: ovl_drop_write(dentry); @@ -1095,6 +1097,7 @@ static int ovl_rename(struct user_namespace *mnt_userns, struct inode *olddir, bool samedir = olddir == newdir; struct dentry *opaquedir = NULL; const struct cred *old_cred = NULL; + struct ovl_fs *ofs = OVL_FS(old->d_sb); LIST_HEAD(list); err = -EINVAL; @@ -1189,8 +1192,8 @@ static int ovl_rename(struct user_namespace *mnt_userns, struct inode *olddir, trap = lock_rename(new_upperdir, old_upperdir); - olddentry = lookup_one_len(old->d_name.name, old_upperdir, - old->d_name.len); + olddentry = ovl_lookup_upper(ofs, old->d_name.name, old_upperdir, + old->d_name.len); err = PTR_ERR(olddentry); if (IS_ERR(olddentry)) goto out_unlock; @@ -1199,8 +1202,8 @@ static int ovl_rename(struct user_namespace *mnt_userns, struct inode *olddir, if (!ovl_matches_upper(old, olddentry)) goto out_dput_old; - newdentry = lookup_one_len(new->d_name.name, new_upperdir, - new->d_name.len); + newdentry = ovl_lookup_upper(ofs, new->d_name.name, new_upperdir, + new->d_name.len); err = PTR_ERR(newdentry); if (IS_ERR(newdentry)) goto out_dput_old; @@ -1251,13 +1254,13 @@ static int ovl_rename(struct user_namespace *mnt_userns, struct inode *olddir, if (err) goto out_dput; - err = ovl_do_rename(old_upperdir->d_inode, olddentry, + err = ovl_do_rename(ofs, old_upperdir->d_inode, olddentry, new_upperdir->d_inode, newdentry, flags); if (err) goto out_dput; if (cleanup_whiteout) - ovl_cleanup(old_upperdir->d_inode, newdentry); + ovl_cleanup(ofs, old_upperdir->d_inode, newdentry); if (overwrite && d_inode(new)) { if (new_is_dir) @@ -1272,9 +1275,9 @@ static int ovl_rename(struct user_namespace *mnt_userns, struct inode *olddir, (d_inode(new) && ovl_type_origin(new))); /* copy ctime: */ - ovl_copyattr(d_inode(olddentry), d_inode(old)); + ovl_copyattr(d_inode(old)); if (d_inode(new) && ovl_dentry_upper(new)) - ovl_copyattr(d_inode(newdentry), d_inode(new)); + ovl_copyattr(d_inode(new)); out_dput: dput(newdentry); diff --git a/fs/overlayfs/export.c b/fs/overlayfs/export.c index ebde05c9cf62e8e5a69fc87fb62c6431c434b8dc..2eada97bbd23fbd845bc384f6853cf31e51448a3 100644 --- a/fs/overlayfs/export.c +++ b/fs/overlayfs/export.c @@ -391,6 +391,11 @@ static struct dentry *ovl_lookup_real_one(struct dentry *connected, * pointer because we hold no lock on the real dentry. */ take_dentry_name_snapshot(&name, real); + /* + * No mnt_userns handling here: it's an internal lookup. Could skip + * permission checking altogether, but for now just use non-mnt_userns + * transformed ids. + */ this = lookup_one_len(name.name.name, connected, name.name.len); release_dentry_name_snapshot(&name); err = PTR_ERR(this); diff --git a/fs/overlayfs/file.c b/fs/overlayfs/file.c index 5e7ce55360f41eb3c3f1ad293bbea227c110a786..c9df015770522c6c7a83880e17cf1de571908691 100644 --- a/fs/overlayfs/file.c +++ b/fs/overlayfs/file.c @@ -40,9 +40,11 @@ static char ovl_whatisit(struct inode *inode, struct inode *realinode) #define OVL_OPEN_FLAGS (O_NOATIME | FMODE_NONOTIFY) static struct file *ovl_open_realfile(const struct file *file, - struct inode *realinode) + struct path *realpath) { + struct inode *realinode = d_inode(realpath->dentry); struct inode *inode = file_inode(file); + struct user_namespace *real_mnt_userns; struct file *realfile; const struct cred *old_cred; int flags = file->f_flags | OVL_OPEN_FLAGS; @@ -53,11 +55,12 @@ static struct file *ovl_open_realfile(const struct file *file, acc_mode |= MAY_APPEND; old_cred = ovl_override_creds(inode->i_sb); - err = inode_permission(&init_user_ns, realinode, MAY_OPEN | acc_mode); + real_mnt_userns = mnt_user_ns(realpath->mnt); + err = inode_permission(real_mnt_userns, realinode, MAY_OPEN | acc_mode); if (err) { realfile = ERR_PTR(err); } else { - if (!inode_owner_or_capable(&init_user_ns, realinode)) + if (!inode_owner_or_capable(real_mnt_userns, realinode)) flags &= ~O_NOATIME; realfile = open_with_fake_path(&file->f_path, flags, realinode, @@ -103,21 +106,21 @@ static int ovl_change_flags(struct file *file, unsigned int flags) static int ovl_real_fdget_meta(const struct file *file, struct fd *real, bool allow_meta) { - struct inode *inode = file_inode(file); - struct inode *realinode; + struct dentry *dentry = file_dentry(file); + struct path realpath; real->flags = 0; real->file = file->private_data; if (allow_meta) - realinode = ovl_inode_real(inode); + ovl_path_real(dentry, &realpath); else - realinode = ovl_inode_realdata(inode); + ovl_path_realdata(dentry, &realpath); /* Has it been copied up since we'd opened it? */ - if (unlikely(file_inode(real->file) != realinode)) { + if (unlikely(file_inode(real->file) != d_inode(realpath.dentry))) { real->flags = FDPUT_FPUT; - real->file = ovl_open_realfile(file, realinode); + real->file = ovl_open_realfile(file, &realpath); return PTR_ERR_OR_ZERO(real->file); } @@ -143,17 +146,20 @@ static int ovl_real_fdget(const struct file *file, struct fd *real) static int ovl_open(struct inode *inode, struct file *file) { + struct dentry *dentry = file_dentry(file); struct file *realfile; + struct path realpath; int err; - err = ovl_maybe_copy_up(file_dentry(file), file->f_flags); + err = ovl_maybe_copy_up(dentry, file->f_flags); if (err) return err; /* No longer need these flags, so don't pass them on to underlying fs */ file->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC); - realfile = ovl_open_realfile(file, ovl_inode_realdata(inode)); + ovl_path_realdata(dentry, &realpath); + realfile = ovl_open_realfile(file, &realpath); if (IS_ERR(realfile)) return PTR_ERR(realfile); @@ -256,7 +262,7 @@ static void ovl_aio_cleanup_handler(struct ovl_aio_req *aio_req) __sb_writers_acquired(file_inode(iocb->ki_filp)->i_sb, SB_FREEZE_WRITE); file_end_write(iocb->ki_filp); - ovl_copyattr(ovl_inode_real(inode), inode); + ovl_copyattr(inode); } orig_iocb->ki_pos = iocb->ki_pos; @@ -339,7 +345,7 @@ static ssize_t ovl_write_iter(struct kiocb *iocb, struct iov_iter *iter) inode_lock(inode); /* Update mode */ - ovl_copyattr(ovl_inode_real(inode), inode); + ovl_copyattr(inode); ret = file_remove_privs(file); if (ret) goto out_unlock; @@ -363,7 +369,7 @@ static ssize_t ovl_write_iter(struct kiocb *iocb, struct iov_iter *iter) iocb_to_rw_flags(ifl, OVL_IOCB_MASK)); file_end_write(real.file); /* Update size */ - ovl_copyattr(ovl_inode_real(inode), inode); + ovl_copyattr(inode); } else { struct ovl_aio_req *aio_req; @@ -413,12 +419,11 @@ static ssize_t ovl_splice_write(struct pipe_inode_info *pipe, struct file *out, struct fd real; const struct cred *old_cred; struct inode *inode = file_inode(out); - struct inode *realinode = ovl_inode_real(inode); ssize_t ret; inode_lock(inode); /* Update mode */ - ovl_copyattr(realinode, inode); + ovl_copyattr(inode); ret = file_remove_privs(out); if (ret) goto out_unlock; @@ -434,7 +439,7 @@ static ssize_t ovl_splice_write(struct pipe_inode_info *pipe, struct file *out, file_end_write(real.file); /* Update size */ - ovl_copyattr(realinode, inode); + ovl_copyattr(inode); revert_creds(old_cred); fdput(real); @@ -508,7 +513,7 @@ static long ovl_fallocate(struct file *file, int mode, loff_t offset, loff_t len revert_creds(old_cred); /* Update size */ - ovl_copyattr(ovl_inode_real(inode), inode); + ovl_copyattr(inode); fdput(real); @@ -580,7 +585,7 @@ static loff_t ovl_copyfile(struct file *file_in, loff_t pos_in, revert_creds(old_cred); /* Update size */ - ovl_copyattr(ovl_inode_real(inode_out), inode_out); + ovl_copyattr(inode_out); fdput(real_in); fdput(real_out); diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c index 1f36158c7dbe2f8782a2dcb6f15a4f0c4bbef28c..492eddeb481f3b8aa8b6e1b2feefb287ccfda481 100644 --- a/fs/overlayfs/inode.c +++ b/fs/overlayfs/inode.c @@ -21,6 +21,7 @@ int ovl_setattr(struct user_namespace *mnt_userns, struct dentry *dentry, struct iattr *attr) { int err; + struct ovl_fs *ofs = OVL_FS(dentry->d_sb); bool full_copy_up = false; struct dentry *upperdentry; const struct cred *old_cred; @@ -77,10 +78,10 @@ int ovl_setattr(struct user_namespace *mnt_userns, struct dentry *dentry, inode_lock(upperdentry->d_inode); old_cred = ovl_override_creds(dentry->d_sb); - err = notify_change(&init_user_ns, upperdentry, attr, NULL); + err = ovl_do_notify_change(ofs, upperdentry, attr); revert_creds(old_cred); if (!err) - ovl_copyattr(upperdentry->d_inode, dentry->d_inode); + ovl_copyattr(dentry->d_inode); inode_unlock(upperdentry->d_inode); if (winode) @@ -279,12 +280,14 @@ int ovl_permission(struct user_namespace *mnt_userns, struct inode *inode, int mask) { struct inode *upperinode = ovl_inode_upper(inode); - struct inode *realinode = upperinode ?: ovl_inode_lower(inode); + struct inode *realinode; + struct path realpath; const struct cred *old_cred; int err; /* Careful in RCU walk mode */ - if (!realinode) { + ovl_i_path_real(inode, &realpath); + if (!realpath.dentry) { WARN_ON(!(mask & MAY_NOT_BLOCK)); return -ECHILD; } @@ -297,6 +300,7 @@ int ovl_permission(struct user_namespace *mnt_userns, if (err) return err; + realinode = d_inode(realpath.dentry); old_cred = ovl_override_creds(inode->i_sb); if (!upperinode && !special_file(realinode->i_mode) && mask & MAY_WRITE) { @@ -304,7 +308,7 @@ int ovl_permission(struct user_namespace *mnt_userns, /* Make sure mounter can read file for copy up later */ mask |= MAY_READ; } - err = inode_permission(&init_user_ns, realinode, mask); + err = inode_permission(mnt_user_ns(realpath.mnt), realinode, mask); revert_creds(old_cred); return err; @@ -342,8 +346,10 @@ int ovl_xattr_set(struct dentry *dentry, struct inode *inode, const char *name, const void *value, size_t size, int flags) { int err; + struct ovl_fs *ofs = OVL_FS(dentry->d_sb); struct dentry *upperdentry = ovl_i_dentry_upper(inode); struct dentry *realdentry = upperdentry ?: ovl_dentry_lower(dentry); + struct path realpath; const struct cred *old_cred; err = ovl_want_write(dentry); @@ -351,8 +357,9 @@ int ovl_xattr_set(struct dentry *dentry, struct inode *inode, const char *name, goto out; if (!value && !upperdentry) { + ovl_path_lower(dentry, &realpath); old_cred = ovl_override_creds(dentry->d_sb); - err = vfs_getxattr(&init_user_ns, realdentry, name, NULL, 0); + err = vfs_getxattr(mnt_user_ns(realpath.mnt), realdentry, name, NULL, 0); revert_creds(old_cred); if (err < 0) goto out_drop_write; @@ -367,17 +374,17 @@ int ovl_xattr_set(struct dentry *dentry, struct inode *inode, const char *name, } old_cred = ovl_override_creds(dentry->d_sb); - if (value) - err = vfs_setxattr(&init_user_ns, realdentry, name, value, size, - flags); - else { + if (value) { + err = ovl_do_setxattr(ofs, realdentry, name, value, size, + flags); + } else { WARN_ON(flags != XATTR_REPLACE); - err = vfs_removexattr(&init_user_ns, realdentry, name); + err = ovl_do_removexattr(ofs, realdentry, name); } revert_creds(old_cred); /* copy c/mtime */ - ovl_copyattr(d_inode(realdentry), inode); + ovl_copyattr(inode); out_drop_write: ovl_drop_write(dentry); @@ -390,11 +397,11 @@ int ovl_xattr_get(struct dentry *dentry, struct inode *inode, const char *name, { ssize_t res; const struct cred *old_cred; - struct dentry *realdentry = - ovl_i_dentry_upper(inode) ?: ovl_dentry_lower(dentry); + struct path realpath; + ovl_i_path_real(inode, &realpath); old_cred = ovl_override_creds(dentry->d_sb); - res = vfs_getxattr(&init_user_ns, realdentry, name, value, size); + res = vfs_getxattr(mnt_user_ns(realpath.mnt), realpath.dentry, name, value, size); revert_creds(old_cred); return res; } @@ -535,7 +542,7 @@ int ovl_real_fileattr_set(struct path *realpath, struct fileattr *fa) if (err) return err; - return vfs_fileattr_set(&init_user_ns, realpath->dentry, fa); + return vfs_fileattr_set(mnt_user_ns(realpath->mnt), realpath->dentry, fa); } int ovl_fileattr_set(struct user_namespace *mnt_userns, @@ -579,7 +586,7 @@ int ovl_fileattr_set(struct user_namespace *mnt_userns, inode_set_flags(inode, flags, OVL_COPY_I_FLAGS_MASK); /* Update ctime */ - ovl_copyattr(ovl_inode_real(inode), inode); + ovl_copyattr(inode); } ovl_drop_write(dentry); out: @@ -777,16 +784,19 @@ void ovl_inode_init(struct inode *inode, struct ovl_inode_params *oip, unsigned long ino, int fsid) { struct inode *realinode; + struct ovl_inode *oi = OVL_I(inode); if (oip->upperdentry) - OVL_I(inode)->__upperdentry = oip->upperdentry; - if (oip->lowerpath && oip->lowerpath->dentry) - OVL_I(inode)->lower = igrab(d_inode(oip->lowerpath->dentry)); + oi->__upperdentry = oip->upperdentry; + if (oip->lowerpath && oip->lowerpath->dentry) { + oi->lowerpath.dentry = dget(oip->lowerpath->dentry); + oi->lowerpath.layer = oip->lowerpath->layer; + } if (oip->lowerdata) - OVL_I(inode)->lowerdata = igrab(d_inode(oip->lowerdata)); + oi->lowerdata = igrab(d_inode(oip->lowerdata)); realinode = ovl_inode_real(inode); - ovl_copyattr(realinode, inode); + ovl_copyattr(inode); ovl_copyflags(realinode, inode); ovl_map_ino(inode, ino, fsid); } @@ -871,8 +881,8 @@ static int ovl_set_nlink_common(struct dentry *dentry, if (WARN_ON(len >= sizeof(buf))) return -EIO; - return ovl_do_setxattr(OVL_FS(inode->i_sb), ovl_dentry_upper(dentry), - OVL_XATTR_NLINK, buf, len); + return ovl_setxattr(OVL_FS(inode->i_sb), ovl_dentry_upper(dentry), + OVL_XATTR_NLINK, buf, len); } int ovl_set_nlink_upper(struct dentry *dentry) @@ -897,8 +907,8 @@ unsigned int ovl_get_nlink(struct ovl_fs *ofs, struct dentry *lowerdentry, if (!lowerdentry || !upperdentry || d_inode(lowerdentry)->i_nlink == 1) return fallback; - err = ovl_do_getxattr(ofs, upperdentry, OVL_XATTR_NLINK, - &buf, sizeof(buf) - 1); + err = ovl_getxattr_upper(ofs, upperdentry, OVL_XATTR_NLINK, + &buf, sizeof(buf) - 1); if (err < 0) goto fail; @@ -1102,6 +1112,10 @@ struct inode *ovl_get_inode(struct super_block *sb, struct inode *realinode = upperdentry ? d_inode(upperdentry) : NULL; struct inode *inode; struct dentry *lowerdentry = lowerpath ? lowerpath->dentry : NULL; + struct path realpath = { + .dentry = upperdentry ?: lowerdentry, + .mnt = upperdentry ? ovl_upper_mnt(ofs) : lowerpath->layer->mnt, + }; bool bylower = ovl_hash_bylower(sb, upperdentry, lowerdentry, oip->index); int fsid = bylower ? lowerpath->layer->fsid : 0; @@ -1175,7 +1189,7 @@ struct inode *ovl_get_inode(struct super_block *sb, /* Check for non-merge dir that may have whiteouts */ if (is_dir) { if (((upperdentry && lowerdentry) || oip->numlower > 1) || - ovl_check_origin_xattr(ofs, upperdentry ?: lowerdentry)) { + ovl_path_check_origin_xattr(ofs, &realpath)) { ovl_set_flag(OVL_WHITEOUTS, inode); } } diff --git a/fs/overlayfs/namei.c b/fs/overlayfs/namei.c index 1a9b515fc45d468bcd435931a99444aed9eca634..65c4346a5b4312602eb98e19947690bf780003d6 100644 --- a/fs/overlayfs/namei.c +++ b/fs/overlayfs/namei.c @@ -16,6 +16,7 @@ struct ovl_lookup_data { struct super_block *sb; + struct vfsmount *mnt; struct qstr name; bool is_dir; bool opaque; @@ -25,14 +26,14 @@ struct ovl_lookup_data { bool metacopy; }; -static int ovl_check_redirect(struct dentry *dentry, struct ovl_lookup_data *d, +static int ovl_check_redirect(struct path *path, struct ovl_lookup_data *d, size_t prelen, const char *post) { int res; char *buf; struct ovl_fs *ofs = OVL_FS(d->sb); - buf = ovl_get_redirect_xattr(ofs, dentry, prelen + strlen(post)); + buf = ovl_get_redirect_xattr(ofs, path, prelen + strlen(post)); if (IS_ERR_OR_NULL(buf)) return PTR_ERR(buf); @@ -105,13 +106,13 @@ int ovl_check_fb_len(struct ovl_fb *fb, int fb_len) return 0; } -static struct ovl_fh *ovl_get_fh(struct ovl_fs *ofs, struct dentry *dentry, +static struct ovl_fh *ovl_get_fh(struct ovl_fs *ofs, struct dentry *upperdentry, enum ovl_xattr ox) { int res, err; struct ovl_fh *fh = NULL; - res = ovl_do_getxattr(ofs, dentry, ox, NULL, 0); + res = ovl_getxattr_upper(ofs, upperdentry, ox, NULL, 0); if (res < 0) { if (res == -ENODATA || res == -EOPNOTSUPP) return NULL; @@ -125,7 +126,7 @@ static struct ovl_fh *ovl_get_fh(struct ovl_fs *ofs, struct dentry *dentry, if (!fh) return ERR_PTR(-ENOMEM); - res = ovl_do_getxattr(ofs, dentry, ox, fh->buf, res); + res = ovl_getxattr_upper(ofs, upperdentry, ox, fh->buf, res); if (res < 0) goto fail; @@ -193,16 +194,17 @@ struct dentry *ovl_decode_real_fh(struct ovl_fs *ofs, struct ovl_fh *fh, return real; } -static bool ovl_is_opaquedir(struct super_block *sb, struct dentry *dentry) +static bool ovl_is_opaquedir(struct ovl_fs *ofs, struct path *path) { - return ovl_check_dir_xattr(sb, dentry, OVL_XATTR_OPAQUE); + return ovl_path_check_dir_xattr(ofs, path, OVL_XATTR_OPAQUE); } -static struct dentry *ovl_lookup_positive_unlocked(const char *name, +static struct dentry *ovl_lookup_positive_unlocked(struct ovl_lookup_data *d, + const char *name, struct dentry *base, int len, bool drop_negative) { - struct dentry *ret = lookup_one_len_unlocked(name, base, len); + struct dentry *ret = lookup_one_unlocked(mnt_user_ns(d->mnt), name, base, len); if (!IS_ERR(ret) && d_flags_negative(smp_load_acquire(&ret->d_flags))) { if (drop_negative && ret->d_lockref.count == 1) { @@ -224,10 +226,11 @@ static int ovl_lookup_single(struct dentry *base, struct ovl_lookup_data *d, struct dentry **ret, bool drop_negative) { struct dentry *this; + struct path path; int err; bool last_element = !post[0]; - this = ovl_lookup_positive_unlocked(name, base, namelen, drop_negative); + this = ovl_lookup_positive_unlocked(d, name, base, namelen, drop_negative); if (IS_ERR(this)) { err = PTR_ERR(this); this = NULL; @@ -253,12 +256,15 @@ static int ovl_lookup_single(struct dentry *base, struct ovl_lookup_data *d, d->stop = true; goto put_and_out; } + + path.dentry = this; + path.mnt = d->mnt; if (!d_can_lookup(this)) { if (d->is_dir || !last_element) { d->stop = true; goto put_and_out; } - err = ovl_check_metacopy_xattr(OVL_FS(d->sb), this); + err = ovl_check_metacopy_xattr(OVL_FS(d->sb), &path); if (err < 0) goto out_err; @@ -278,14 +284,14 @@ static int ovl_lookup_single(struct dentry *base, struct ovl_lookup_data *d, if (d->last) goto out; - if (ovl_is_opaquedir(d->sb, this)) { + if (ovl_is_opaquedir(OVL_FS(d->sb), &path)) { d->stop = true; if (last_element) d->opaque = true; goto out; } } - err = ovl_check_redirect(this, d, prelen, post); + err = ovl_check_redirect(&path, d, prelen, post); if (err) goto out_err; out: @@ -464,7 +470,7 @@ int ovl_verify_set_fh(struct ovl_fs *ofs, struct dentry *dentry, err = ovl_verify_fh(ofs, dentry, ox, fh); if (set && err == -ENODATA) - err = ovl_do_setxattr(ofs, dentry, ox, fh->buf, fh->fb.len); + err = ovl_setxattr(ofs, dentry, ox, fh->buf, fh->fb.len); if (err) goto fail; @@ -704,7 +710,8 @@ struct dentry *ovl_lookup_index(struct ovl_fs *ofs, struct dentry *upper, if (err) return ERR_PTR(err); - index = lookup_positive_unlocked(name.name, ofs->indexdir, name.len); + index = lookup_one_positive_unlocked(ovl_upper_mnt_userns(ofs), name.name, + ofs->indexdir, name.len); if (IS_ERR(index)) { err = PTR_ERR(index); if (err == -ENOENT) { @@ -856,6 +863,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry, old_cred = ovl_override_creds(dentry->d_sb); upperdir = ovl_dentry_upper(dentry->d_parent); if (upperdir) { + d.mnt = ovl_upper_mnt(ofs); err = ovl_lookup_layer(upperdir, &d, &upperdentry, true); if (err) goto out; @@ -911,6 +919,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry, else d.last = lower.layer->idx == roe->numlower; + d.mnt = lower.layer->mnt; err = ovl_lookup_layer(lower.dentry, &d, &this, false); if (err) goto out_put; @@ -1071,14 +1080,18 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry, if (upperdentry) ovl_dentry_set_upper_alias(dentry); else if (index) { - upperdentry = dget(index); - upperredirect = ovl_get_redirect_xattr(ofs, upperdentry, 0); + struct path upperpath = { + .dentry = upperdentry = dget(index), + .mnt = ovl_upper_mnt(ofs), + }; + + upperredirect = ovl_get_redirect_xattr(ofs, &upperpath, 0); if (IS_ERR(upperredirect)) { err = PTR_ERR(upperredirect); upperredirect = NULL; goto out_free_oe; } - err = ovl_check_metacopy_xattr(ofs, upperdentry); + err = ovl_check_metacopy_xattr(ofs, &upperpath); if (err < 0) goto out_free_oe; uppermetacopy = err; @@ -1163,8 +1176,8 @@ bool ovl_lower_positive(struct dentry *dentry) struct dentry *this; struct dentry *lowerdir = poe->lowerstack[i].dentry; - this = lookup_positive_unlocked(name->name, lowerdir, - name->len); + this = lookup_one_positive_unlocked(mnt_user_ns(poe->lowerstack[i].layer->mnt), + name->name, lowerdir, name->len); if (IS_ERR(this)) { switch (PTR_ERR(this)) { case -ENOENT: diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h index 2cd5741c873b60592a139273017b669075bac72f..4f34b7e02eeeb5659345c7929afa147646a4f594 100644 --- a/fs/overlayfs/overlayfs.h +++ b/fs/overlayfs/overlayfs.h @@ -7,6 +7,7 @@ #include #include #include +#include #include "ovl_entry.h" #undef pr_fmt @@ -122,109 +123,180 @@ static inline const char *ovl_xattr(struct ovl_fs *ofs, enum ovl_xattr ox) return ovl_xattr_table[ox][ofs->config.userxattr]; } -static inline int ovl_do_rmdir(struct inode *dir, struct dentry *dentry) +/* + * When changing ownership of an upper object map the intended ownership + * according to the upper layer's idmapping. When an upper mount idmaps files + * that are stored on-disk as owned by id 1001 to id 1000 this means stat on + * this object will report it as being owned by id 1000 when calling stat via + * the upper mount. + * In order to change ownership of an object so stat reports id 1000 when + * called on an idmapped upper mount the value written to disk - i.e., the + * value stored in ia_*id - must 1001. The mount mapping helper will thus take + * care to map 1000 to 1001. + * The mnt idmapping helpers are nops if the upper layer isn't idmapped. + */ +static inline int ovl_do_notify_change(struct ovl_fs *ofs, + struct dentry *upperdentry, + struct iattr *attr) +{ + struct user_namespace *upper_mnt_userns = ovl_upper_mnt_userns(ofs); + struct user_namespace *fs_userns = i_user_ns(d_inode(upperdentry)); + + if (attr->ia_valid & ATTR_UID) + attr->ia_uid = mapped_kuid_user(upper_mnt_userns, + fs_userns, attr->ia_uid); + if (attr->ia_valid & ATTR_GID) + attr->ia_gid = mapped_kgid_user(upper_mnt_userns, + fs_userns, attr->ia_gid); + + return notify_change(upper_mnt_userns, upperdentry, attr, NULL); +} + +static inline int ovl_do_rmdir(struct ovl_fs *ofs, + struct inode *dir, struct dentry *dentry) { - int err = vfs_rmdir(&init_user_ns, dir, dentry); + int err = vfs_rmdir(ovl_upper_mnt_userns(ofs), dir, dentry); pr_debug("rmdir(%pd2) = %i\n", dentry, err); return err; } -static inline int ovl_do_unlink(struct inode *dir, struct dentry *dentry) +static inline int ovl_do_unlink(struct ovl_fs *ofs, struct inode *dir, + struct dentry *dentry) { - int err = vfs_unlink(&init_user_ns, dir, dentry, NULL); + int err = vfs_unlink(ovl_upper_mnt_userns(ofs), dir, dentry, NULL); pr_debug("unlink(%pd2) = %i\n", dentry, err); return err; } -static inline int ovl_do_link(struct dentry *old_dentry, struct inode *dir, - struct dentry *new_dentry) +static inline int ovl_do_link(struct ovl_fs *ofs, struct dentry *old_dentry, + struct inode *dir, struct dentry *new_dentry) { - int err = vfs_link(old_dentry, &init_user_ns, dir, new_dentry, NULL); + int err = vfs_link(old_dentry, ovl_upper_mnt_userns(ofs), dir, new_dentry, NULL); pr_debug("link(%pd2, %pd2) = %i\n", old_dentry, new_dentry, err); return err; } -static inline int ovl_do_create(struct inode *dir, struct dentry *dentry, +static inline int ovl_do_create(struct ovl_fs *ofs, + struct inode *dir, struct dentry *dentry, umode_t mode) { - int err = vfs_create(&init_user_ns, dir, dentry, mode, true); + int err = vfs_create(ovl_upper_mnt_userns(ofs), dir, dentry, mode, true); pr_debug("create(%pd2, 0%o) = %i\n", dentry, mode, err); return err; } -static inline int ovl_do_mkdir(struct inode *dir, struct dentry *dentry, +static inline int ovl_do_mkdir(struct ovl_fs *ofs, + struct inode *dir, struct dentry *dentry, umode_t mode) { - int err = vfs_mkdir(&init_user_ns, dir, dentry, mode); + int err = vfs_mkdir(ovl_upper_mnt_userns(ofs), dir, dentry, mode); pr_debug("mkdir(%pd2, 0%o) = %i\n", dentry, mode, err); return err; } -static inline int ovl_do_mknod(struct inode *dir, struct dentry *dentry, +static inline int ovl_do_mknod(struct ovl_fs *ofs, + struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev) { - int err = vfs_mknod(&init_user_ns, dir, dentry, mode, dev); + int err = vfs_mknod(ovl_upper_mnt_userns(ofs), dir, dentry, mode, dev); pr_debug("mknod(%pd2, 0%o, 0%o) = %i\n", dentry, mode, dev, err); return err; } -static inline int ovl_do_symlink(struct inode *dir, struct dentry *dentry, +static inline int ovl_do_symlink(struct ovl_fs *ofs, + struct inode *dir, struct dentry *dentry, const char *oldname) { - int err = vfs_symlink(&init_user_ns, dir, dentry, oldname); + int err = vfs_symlink(ovl_upper_mnt_userns(ofs), dir, dentry, oldname); pr_debug("symlink(\"%s\", %pd2) = %i\n", oldname, dentry, err); return err; } -static inline ssize_t ovl_do_getxattr(struct ovl_fs *ofs, struct dentry *dentry, - enum ovl_xattr ox, void *value, - size_t size) +static inline ssize_t ovl_do_getxattr(struct path *path, const char *name, + void *value, size_t size) { - const char *name = ovl_xattr(ofs, ox); - int err = vfs_getxattr(&init_user_ns, dentry, name, value, size); - int len = (value && err > 0) ? err : 0; + int err, len; + + WARN_ON(path->dentry->d_sb != path->mnt->mnt_sb); + + err = vfs_getxattr(mnt_user_ns(path->mnt), path->dentry, + name, value, size); + len = (value && err > 0) ? err : 0; pr_debug("getxattr(%pd2, \"%s\", \"%*pE\", %zu, 0) = %i\n", - dentry, name, min(len, 48), value, size, err); + path->dentry, name, min(len, 48), value, size, err); return err; } +static inline ssize_t ovl_getxattr_upper(struct ovl_fs *ofs, + struct dentry *upperdentry, + enum ovl_xattr ox, void *value, + size_t size) +{ + struct path upperpath = { + .dentry = upperdentry, + .mnt = ovl_upper_mnt(ofs), + }; + + return ovl_do_getxattr(&upperpath, ovl_xattr(ofs, ox), value, size); +} + +static inline ssize_t ovl_path_getxattr(struct ovl_fs *ofs, + struct path *path, + enum ovl_xattr ox, void *value, + size_t size) +{ + return ovl_do_getxattr(path, ovl_xattr(ofs, ox), value, size); +} + static inline int ovl_do_setxattr(struct ovl_fs *ofs, struct dentry *dentry, - enum ovl_xattr ox, const void *value, - size_t size) + const char *name, const void *value, + size_t size, int flags) { - const char *name = ovl_xattr(ofs, ox); - int err = vfs_setxattr(&init_user_ns, dentry, name, value, size, 0); - pr_debug("setxattr(%pd2, \"%s\", \"%*pE\", %zu, 0) = %i\n", - dentry, name, min((int)size, 48), value, size, err); + int err = vfs_setxattr(ovl_upper_mnt_userns(ofs), dentry, name, value, size, flags); + + pr_debug("setxattr(%pd2, \"%s\", \"%*pE\", %zu, %d) = %i\n", + dentry, name, min((int)size, 48), value, size, flags, err); return err; } +static inline int ovl_setxattr(struct ovl_fs *ofs, struct dentry *dentry, + enum ovl_xattr ox, const void *value, + size_t size) +{ + return ovl_do_setxattr(ofs, dentry, ovl_xattr(ofs, ox), value, size, 0); +} + static inline int ovl_do_removexattr(struct ovl_fs *ofs, struct dentry *dentry, - enum ovl_xattr ox) + const char *name) { - const char *name = ovl_xattr(ofs, ox); - int err = vfs_removexattr(&init_user_ns, dentry, name); + int err = vfs_removexattr(ovl_upper_mnt_userns(ofs), dentry, name); pr_debug("removexattr(%pd2, \"%s\") = %i\n", dentry, name, err); return err; } -static inline int ovl_do_rename(struct inode *olddir, struct dentry *olddentry, - struct inode *newdir, struct dentry *newdentry, - unsigned int flags) +static inline int ovl_removexattr(struct ovl_fs *ofs, struct dentry *dentry, + enum ovl_xattr ox) +{ + return ovl_do_removexattr(ofs, dentry, ovl_xattr(ofs, ox)); +} + +static inline int ovl_do_rename(struct ovl_fs *ofs, struct inode *olddir, + struct dentry *olddentry, struct inode *newdir, + struct dentry *newdentry, unsigned int flags) { int err; struct renamedata rd = { - .old_mnt_userns = &init_user_ns, + .old_mnt_userns = ovl_upper_mnt_userns(ofs), .old_dir = olddir, .old_dentry = olddentry, - .new_mnt_userns = &init_user_ns, + .new_mnt_userns = ovl_upper_mnt_userns(ofs), .new_dir = newdir, .new_dentry = newdentry, .flags = flags, @@ -239,22 +311,31 @@ static inline int ovl_do_rename(struct inode *olddir, struct dentry *olddentry, return err; } -static inline int ovl_do_whiteout(struct inode *dir, struct dentry *dentry) +static inline int ovl_do_whiteout(struct ovl_fs *ofs, + struct inode *dir, struct dentry *dentry) { - int err = vfs_whiteout(&init_user_ns, dir, dentry); + int err = vfs_whiteout(ovl_upper_mnt_userns(ofs), dir, dentry); pr_debug("whiteout(%pd2) = %i\n", dentry, err); return err; } -static inline struct dentry *ovl_do_tmpfile(struct dentry *dentry, umode_t mode) +static inline struct dentry *ovl_do_tmpfile(struct ovl_fs *ofs, + struct dentry *dentry, umode_t mode) { - struct dentry *ret = vfs_tmpfile(&init_user_ns, dentry, mode, 0); + struct dentry *ret = vfs_tmpfile(ovl_upper_mnt_userns(ofs), dentry, mode, 0); int err = PTR_ERR_OR_ZERO(ret); pr_debug("tmpfile(%pd2, 0%o) = %i\n", dentry, mode, err); return ret; } +static inline struct dentry *ovl_lookup_upper(struct ovl_fs *ofs, + const char *name, + struct dentry *base, int len) +{ + return lookup_one(ovl_upper_mnt_userns(ofs), name, base, len); +} + static inline bool ovl_open_flags_need_copy_up(int flags) { if (!flags) @@ -293,10 +374,13 @@ enum ovl_path_type ovl_path_type(struct dentry *dentry); void ovl_path_upper(struct dentry *dentry, struct path *path); void ovl_path_lower(struct dentry *dentry, struct path *path); void ovl_path_lowerdata(struct dentry *dentry, struct path *path); +void ovl_i_path_real(struct inode *inode, struct path *path); enum ovl_path_type ovl_path_real(struct dentry *dentry, struct path *path); +enum ovl_path_type ovl_path_realdata(struct dentry *dentry, struct path *path); struct dentry *ovl_dentry_upper(struct dentry *dentry); struct dentry *ovl_dentry_lower(struct dentry *dentry); struct dentry *ovl_dentry_lowerdata(struct dentry *dentry); +const struct ovl_layer *ovl_i_layer_lower(struct inode *inode); const struct ovl_layer *ovl_layer_lower(struct dentry *dentry); struct dentry *ovl_dentry_real(struct dentry *dentry); struct dentry *ovl_i_dentry_upper(struct inode *inode); @@ -330,9 +414,20 @@ struct file *ovl_path_open(struct path *path, int flags); int ovl_copy_up_start(struct dentry *dentry, int flags); void ovl_copy_up_end(struct dentry *dentry); bool ovl_already_copied_up(struct dentry *dentry, int flags); -bool ovl_check_origin_xattr(struct ovl_fs *ofs, struct dentry *dentry); -bool ovl_check_dir_xattr(struct super_block *sb, struct dentry *dentry, - enum ovl_xattr ox); +bool ovl_path_check_dir_xattr(struct ovl_fs *ofs, struct path *path, + enum ovl_xattr ox); +bool ovl_path_check_origin_xattr(struct ovl_fs *ofs, struct path *path); + +static inline bool ovl_check_origin_xattr(struct ovl_fs *ofs, + struct dentry *upperdentry) +{ + struct path upperpath = { + .dentry = upperdentry, + .mnt = ovl_upper_mnt(ofs), + }; + return ovl_path_check_origin_xattr(ofs, &upperpath); +} + int ovl_check_setxattr(struct ovl_fs *ofs, struct dentry *upperdentry, enum ovl_xattr ox, const void *value, size_t size, int xerr); @@ -344,10 +439,9 @@ bool ovl_need_index(struct dentry *dentry); int ovl_nlink_start(struct dentry *dentry); void ovl_nlink_end(struct dentry *dentry); int ovl_lock_rename_workdir(struct dentry *workdir, struct dentry *upperdir); -int ovl_check_metacopy_xattr(struct ovl_fs *ofs, struct dentry *dentry); +int ovl_check_metacopy_xattr(struct ovl_fs *ofs, struct path *path); bool ovl_is_metacopy_dentry(struct dentry *dentry); -char *ovl_get_redirect_xattr(struct ovl_fs *ofs, struct dentry *dentry, - int padding); +char *ovl_get_redirect_xattr(struct ovl_fs *ofs, struct path *path, int padding); int ovl_sync_status(struct ovl_fs *ofs); static inline void ovl_set_flag(unsigned long flag, struct inode *inode) @@ -366,9 +460,15 @@ static inline bool ovl_test_flag(unsigned long flag, struct inode *inode) } static inline bool ovl_is_impuredir(struct super_block *sb, - struct dentry *dentry) + struct dentry *upperdentry) { - return ovl_check_dir_xattr(sb, dentry, OVL_XATTR_IMPURE); + struct ovl_fs *ofs = OVL_FS(sb); + struct path upperpath = { + .dentry = upperdentry, + .mnt = ovl_upper_mnt(ofs), + }; + + return ovl_path_check_dir_xattr(ofs, &upperpath, OVL_XATTR_IMPURE); } /* @@ -461,12 +561,13 @@ static inline int ovl_verify_upper(struct ovl_fs *ofs, struct dentry *index, extern const struct file_operations ovl_dir_operations; struct file *ovl_dir_real_file(const struct file *file, bool want_upper); int ovl_check_empty_dir(struct dentry *dentry, struct list_head *list); -void ovl_cleanup_whiteouts(struct dentry *upper, struct list_head *list); +void ovl_cleanup_whiteouts(struct ovl_fs *ofs, struct dentry *upper, + struct list_head *list); void ovl_cache_free(struct list_head *list); void ovl_dir_cache_free(struct inode *inode); int ovl_check_d_type_supported(struct path *realpath); -int ovl_workdir_cleanup(struct inode *dir, struct vfsmount *mnt, - struct dentry *dentry, int level); +int ovl_workdir_cleanup(struct ovl_fs *ofs, struct inode *dir, + struct vfsmount *mnt, struct dentry *dentry, int level); int ovl_indexdir_cleanup(struct ovl_fs *ofs); /* @@ -520,16 +621,7 @@ bool ovl_lookup_trap_inode(struct super_block *sb, struct dentry *dir); struct inode *ovl_get_trap_inode(struct super_block *sb, struct dentry *dir); struct inode *ovl_get_inode(struct super_block *sb, struct ovl_inode_params *oip); -static inline void ovl_copyattr(struct inode *from, struct inode *to) -{ - to->i_uid = from->i_uid; - to->i_gid = from->i_gid; - to->i_mode = from->i_mode; - to->i_atime = from->i_atime; - to->i_mtime = from->i_mtime; - to->i_ctime = from->i_ctime; - i_size_write(to, i_size_read(from)); -} +void ovl_copyattr(struct inode *to); /* vfs inode flags copied from real to ovl inode */ #define OVL_COPY_I_FLAGS_MASK (S_SYNC | S_NOATIME | S_APPEND | S_IMMUTABLE) @@ -570,12 +662,15 @@ struct ovl_cattr { #define OVL_CATTR(m) (&(struct ovl_cattr) { .mode = (m) }) -int ovl_mkdir_real(struct inode *dir, struct dentry **newdentry, umode_t mode); -struct dentry *ovl_create_real(struct inode *dir, struct dentry *newdentry, +int ovl_mkdir_real(struct ovl_fs *ofs, struct inode *dir, + struct dentry **newdentry, umode_t mode); +struct dentry *ovl_create_real(struct ovl_fs *ofs, + struct inode *dir, struct dentry *newdentry, + struct ovl_cattr *attr); +int ovl_cleanup(struct ovl_fs *ofs, struct inode *dir, struct dentry *dentry); +struct dentry *ovl_lookup_temp(struct ovl_fs *ofs, struct dentry *workdir); +struct dentry *ovl_create_temp(struct ovl_fs *ofs, struct dentry *workdir, struct ovl_cattr *attr); -int ovl_cleanup(struct inode *dir, struct dentry *dentry); -struct dentry *ovl_lookup_temp(struct dentry *workdir); -struct dentry *ovl_create_temp(struct dentry *workdir, struct ovl_cattr *attr); /* file.c */ extern const struct file_operations ovl_file_operations; @@ -591,9 +686,8 @@ int ovl_fileattr_set(struct user_namespace *mnt_userns, int ovl_copy_up(struct dentry *dentry); int ovl_copy_up_with_data(struct dentry *dentry); int ovl_maybe_copy_up(struct dentry *dentry, int flags); -int ovl_copy_xattr(struct super_block *sb, struct dentry *old, - struct dentry *new); -int ovl_set_attr(struct dentry *upper, struct kstat *stat); +int ovl_copy_xattr(struct super_block *sb, struct path *path, struct dentry *new); +int ovl_set_attr(struct ovl_fs *ofs, struct dentry *upper, struct kstat *stat); struct ovl_fh *ovl_encode_real_fh(struct ovl_fs *ofs, struct dentry *real, bool is_upper); int ovl_set_origin(struct ovl_fs *ofs, struct dentry *lower, diff --git a/fs/overlayfs/ovl_entry.h b/fs/overlayfs/ovl_entry.h index 63efee554f69a7c1e862650d8f7b388576fda2cd..e1af8f66069843c04ab3b4e1c1be384d965a7ecb 100644 --- a/fs/overlayfs/ovl_entry.h +++ b/fs/overlayfs/ovl_entry.h @@ -90,6 +90,11 @@ static inline struct vfsmount *ovl_upper_mnt(struct ovl_fs *ofs) return ofs->layers[0].mnt; } +static inline struct user_namespace *ovl_upper_mnt_userns(struct ovl_fs *ofs) +{ + return mnt_user_ns(ovl_upper_mnt(ofs)); +} + static inline struct ovl_fs *OVL_FS(struct super_block *sb) { return (struct ovl_fs *)sb->s_fs_info; @@ -129,7 +134,7 @@ struct ovl_inode { unsigned long flags; struct inode vfs_inode; struct dentry *__upperdentry; - struct inode *lower; + struct ovl_path lowerpath; /* synchronize copy up and more */ struct mutex lock; diff --git a/fs/overlayfs/readdir.c b/fs/overlayfs/readdir.c index 150fdf3bc68d4c812fe45a886c724e58c56f84aa..78f62cc1797becb9caac4d1842a5278f81cf2f71 100644 --- a/fs/overlayfs/readdir.c +++ b/fs/overlayfs/readdir.c @@ -264,11 +264,11 @@ static int ovl_fill_merge(struct dir_context *ctx, const char *name, return ovl_fill_lowest(rdd, name, namelen, offset, ino, d_type); } -static int ovl_check_whiteouts(struct dentry *dir, struct ovl_readdir_data *rdd) +static int ovl_check_whiteouts(struct path *path, struct ovl_readdir_data *rdd) { int err; struct ovl_cache_entry *p; - struct dentry *dentry; + struct dentry *dentry, *dir = path->dentry; const struct cred *old_cred; old_cred = ovl_override_creds(rdd->dentry->d_sb); @@ -278,7 +278,7 @@ static int ovl_check_whiteouts(struct dentry *dir, struct ovl_readdir_data *rdd) while (rdd->first_maybe_whiteout) { p = rdd->first_maybe_whiteout; rdd->first_maybe_whiteout = p->next_maybe_whiteout; - dentry = lookup_one_len(p->name, dir, p->len); + dentry = lookup_one(mnt_user_ns(path->mnt), p->name, dir, p->len); if (!IS_ERR(dentry)) { p->is_whiteout = ovl_is_whiteout(dentry); dput(dentry); @@ -312,7 +312,7 @@ static inline int ovl_dir_read(struct path *realpath, } while (!err && rdd->count); if (!err && rdd->first_maybe_whiteout && rdd->dentry) - err = ovl_check_whiteouts(realpath->dentry, rdd); + err = ovl_check_whiteouts(realpath, rdd); fput(realfile); @@ -479,7 +479,7 @@ static int ovl_cache_update_ino(struct path *path, struct ovl_cache_entry *p) goto get; } } - this = lookup_one_len(p->name, dir, p->len); + this = lookup_one(mnt_user_ns(path->mnt), p->name, dir, p->len); if (IS_ERR_OR_NULL(this) || !this->d_inode) { /* Mark a stale entry */ p->is_whiteout = true; @@ -623,8 +623,8 @@ static struct ovl_dir_cache *ovl_cache_get_impure(struct path *path) * Removing the "impure" xattr is best effort. */ if (!ovl_want_write(dentry)) { - ovl_do_removexattr(ofs, ovl_dentry_upper(dentry), - OVL_XATTR_IMPURE); + ovl_removexattr(ofs, ovl_dentry_upper(dentry), + OVL_XATTR_IMPURE); ovl_drop_write(dentry); } ovl_clear_flag(OVL_IMPURE, d_inode(dentry)); @@ -1001,7 +1001,8 @@ del_entry: return err; } -void ovl_cleanup_whiteouts(struct dentry *upper, struct list_head *list) +void ovl_cleanup_whiteouts(struct ovl_fs *ofs, struct dentry *upper, + struct list_head *list) { struct ovl_cache_entry *p; @@ -1012,7 +1013,7 @@ void ovl_cleanup_whiteouts(struct dentry *upper, struct list_head *list) if (WARN_ON(!p->is_whiteout || !p->is_upper)) continue; - dentry = lookup_one_len(p->name, upper, p->len); + dentry = ovl_lookup_upper(ofs, p->name, upper, p->len); if (IS_ERR(dentry)) { pr_err("lookup '%s/%.*s' failed (%i)\n", upper->d_name.name, p->len, p->name, @@ -1020,7 +1021,7 @@ void ovl_cleanup_whiteouts(struct dentry *upper, struct list_head *list) continue; } if (dentry->d_inode) - ovl_cleanup(upper->d_inode, dentry); + ovl_cleanup(ofs, upper->d_inode, dentry); dput(dentry); } inode_unlock(upper->d_inode); @@ -1064,7 +1065,8 @@ int ovl_check_d_type_supported(struct path *realpath) #define OVL_INCOMPATDIR_NAME "incompat" -static int ovl_workdir_cleanup_recurse(struct path *path, int level) +static int ovl_workdir_cleanup_recurse(struct ovl_fs *ofs, struct path *path, + int level) { int err; struct inode *dir = path->dentry->d_inode; @@ -1111,11 +1113,11 @@ static int ovl_workdir_cleanup_recurse(struct path *path, int level) err = -EINVAL; break; } - dentry = lookup_one_len(p->name, path->dentry, p->len); + dentry = ovl_lookup_upper(ofs, p->name, path->dentry, p->len); if (IS_ERR(dentry)) continue; if (dentry->d_inode) - err = ovl_workdir_cleanup(dir, path->mnt, dentry, level); + err = ovl_workdir_cleanup(ofs, dir, path->mnt, dentry, level); dput(dentry); if (err) break; @@ -1126,24 +1128,24 @@ out: return err; } -int ovl_workdir_cleanup(struct inode *dir, struct vfsmount *mnt, - struct dentry *dentry, int level) +int ovl_workdir_cleanup(struct ovl_fs *ofs, struct inode *dir, + struct vfsmount *mnt, struct dentry *dentry, int level) { int err; if (!d_is_dir(dentry) || level > 1) { - return ovl_cleanup(dir, dentry); + return ovl_cleanup(ofs, dir, dentry); } - err = ovl_do_rmdir(dir, dentry); + err = ovl_do_rmdir(ofs, dir, dentry); if (err) { struct path path = { .mnt = mnt, .dentry = dentry }; inode_unlock(dir); - err = ovl_workdir_cleanup_recurse(&path, level + 1); + err = ovl_workdir_cleanup_recurse(ofs, &path, level + 1); inode_lock_nested(dir, I_MUTEX_PARENT); if (!err) - err = ovl_cleanup(dir, dentry); + err = ovl_cleanup(ofs, dir, dentry); } return err; @@ -1179,7 +1181,7 @@ int ovl_indexdir_cleanup(struct ovl_fs *ofs) if (p->len == 2 && p->name[1] == '.') continue; } - index = lookup_one_len(p->name, indexdir, p->len); + index = ovl_lookup_upper(ofs, p->name, indexdir, p->len); if (IS_ERR(index)) { err = PTR_ERR(index); index = NULL; @@ -1187,7 +1189,7 @@ int ovl_indexdir_cleanup(struct ovl_fs *ofs) } /* Cleanup leftover from index create/cleanup attempt */ if (index->d_name.name[0] == '#') { - err = ovl_workdir_cleanup(dir, path.mnt, index, 1); + err = ovl_workdir_cleanup(ofs, dir, path.mnt, index, 1); if (err) break; goto next; @@ -1197,7 +1199,7 @@ int ovl_indexdir_cleanup(struct ovl_fs *ofs) goto next; } else if (err == -ESTALE) { /* Cleanup stale index entries */ - err = ovl_cleanup(dir, index); + err = ovl_cleanup(ofs, dir, index); } else if (err != -ENOENT) { /* * Abort mount to avoid corrupting the index if @@ -1213,7 +1215,7 @@ int ovl_indexdir_cleanup(struct ovl_fs *ofs) err = ovl_cleanup_and_whiteout(ofs, dir, index); } else { /* Cleanup orphan index entries */ - err = ovl_cleanup(dir, index); + err = ovl_cleanup(ofs, dir, index); } if (err) diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c index 001cdbb8f015212b3bf2ade964adaf82294954b1..e0a2e0468ee7f1e4bb668df4a9d13cea9d34082b 100644 --- a/fs/overlayfs/super.c +++ b/fs/overlayfs/super.c @@ -184,7 +184,8 @@ static struct inode *ovl_alloc_inode(struct super_block *sb) oi->version = 0; oi->flags = 0; oi->__upperdentry = NULL; - oi->lower = NULL; + oi->lowerpath.dentry = NULL; + oi->lowerpath.layer = NULL; oi->lowerdata = NULL; mutex_init(&oi->lock); @@ -205,7 +206,7 @@ static void ovl_destroy_inode(struct inode *inode) struct ovl_inode *oi = OVL_I(inode); dput(oi->__upperdentry); - iput(oi->lower); + dput(oi->lowerpath.dentry); if (S_ISDIR(inode->i_mode)) ovl_dir_cache_free(inode); else @@ -761,7 +762,7 @@ static struct dentry *ovl_workdir_create(struct ovl_fs *ofs, inode_lock_nested(dir, I_MUTEX_PARENT); retry: - work = lookup_one_len(name, ofs->workbasedir, strlen(name)); + work = ovl_lookup_upper(ofs, name, ofs->workbasedir, strlen(name)); if (!IS_ERR(work)) { struct iattr attr = { @@ -778,7 +779,7 @@ retry: goto out_unlock; retried = true; - err = ovl_workdir_cleanup(dir, mnt, work, 0); + err = ovl_workdir_cleanup(ofs, dir, mnt, work, 0); dput(work); if (err == -EINVAL) { work = ERR_PTR(err); @@ -787,7 +788,7 @@ retry: goto retry; } - err = ovl_mkdir_real(dir, &work, attr.ia_mode); + err = ovl_mkdir_real(ofs, dir, &work, attr.ia_mode); if (err) goto out_dput; @@ -809,19 +810,19 @@ retry: * allowed as upper are limited to "normal" ones, where checking * for the above two errors is sufficient. */ - err = vfs_removexattr(&init_user_ns, work, - XATTR_NAME_POSIX_ACL_DEFAULT); + err = ovl_do_removexattr(ofs, work, + XATTR_NAME_POSIX_ACL_DEFAULT); if (err && err != -ENODATA && err != -EOPNOTSUPP) goto out_dput; - err = vfs_removexattr(&init_user_ns, work, - XATTR_NAME_POSIX_ACL_ACCESS); + err = ovl_do_removexattr(ofs, work, + XATTR_NAME_POSIX_ACL_ACCESS); if (err && err != -ENODATA && err != -EOPNOTSUPP) goto out_dput; /* Clear any inherited mode bits */ inode_lock(work->d_inode); - err = notify_change(&init_user_ns, work, &attr, NULL); + err = ovl_do_notify_change(ofs, work, &attr); inode_unlock(work->d_inode); if (err) goto out_dput; @@ -873,10 +874,6 @@ static int ovl_mount_dir_noesc(const char *name, struct path *path) pr_err("filesystem on '%s' not supported\n", name); goto out_put; } - if (is_idmapped_mnt(path->mnt)) { - pr_err("idmapped layers are currently not supported\n"); - goto out_put; - } if (!d_is_dir(path->dentry)) { pr_err("'%s' not a directory\n", name); goto out_put; @@ -1256,8 +1253,9 @@ out: * Returns 1 if RENAME_WHITEOUT is supported, 0 if not supported and * negative values if error is encountered. */ -static int ovl_check_rename_whiteout(struct dentry *workdir) +static int ovl_check_rename_whiteout(struct ovl_fs *ofs) { + struct dentry *workdir = ofs->workdir; struct inode *dir = d_inode(workdir); struct dentry *temp; struct dentry *dest; @@ -1267,12 +1265,12 @@ static int ovl_check_rename_whiteout(struct dentry *workdir) inode_lock_nested(dir, I_MUTEX_PARENT); - temp = ovl_create_temp(workdir, OVL_CATTR(S_IFREG | 0)); + temp = ovl_create_temp(ofs, workdir, OVL_CATTR(S_IFREG | 0)); err = PTR_ERR(temp); if (IS_ERR(temp)) goto out_unlock; - dest = ovl_lookup_temp(workdir); + dest = ovl_lookup_temp(ofs, workdir); err = PTR_ERR(dest); if (IS_ERR(dest)) { dput(temp); @@ -1281,14 +1279,14 @@ static int ovl_check_rename_whiteout(struct dentry *workdir) /* Name is inline and stable - using snapshot as a copy helper */ take_dentry_name_snapshot(&name, temp); - err = ovl_do_rename(dir, temp, dir, dest, RENAME_WHITEOUT); + err = ovl_do_rename(ofs, dir, temp, dir, dest, RENAME_WHITEOUT); if (err) { if (err == -EINVAL) err = 0; goto cleanup_temp; } - whiteout = lookup_one_len(name.name.name, workdir, name.name.len); + whiteout = ovl_lookup_upper(ofs, name.name.name, workdir, name.name.len); err = PTR_ERR(whiteout); if (IS_ERR(whiteout)) goto cleanup_temp; @@ -1297,11 +1295,11 @@ static int ovl_check_rename_whiteout(struct dentry *workdir) /* Best effort cleanup of whiteout and temp file */ if (err) - ovl_cleanup(dir, whiteout); + ovl_cleanup(ofs, dir, whiteout); dput(whiteout); cleanup_temp: - ovl_cleanup(dir, temp); + ovl_cleanup(ofs, dir, temp); release_dentry_name_snapshot(&name); dput(temp); dput(dest); @@ -1312,16 +1310,17 @@ out_unlock: return err; } -static struct dentry *ovl_lookup_or_create(struct dentry *parent, +static struct dentry *ovl_lookup_or_create(struct ovl_fs *ofs, + struct dentry *parent, const char *name, umode_t mode) { size_t len = strlen(name); struct dentry *child; inode_lock_nested(parent->d_inode, I_MUTEX_PARENT); - child = lookup_one_len(name, parent, len); + child = ovl_lookup_upper(ofs, name, parent, len); if (!IS_ERR(child) && !child->d_inode) - child = ovl_create_real(parent->d_inode, child, + child = ovl_create_real(ofs, parent->d_inode, child, OVL_CATTR(mode)); inode_unlock(parent->d_inode); dput(parent); @@ -1343,7 +1342,7 @@ static int ovl_create_volatile_dirty(struct ovl_fs *ofs) const char *const *name = volatile_path; for (ctr = ARRAY_SIZE(volatile_path); ctr; ctr--, name++) { - d = ovl_lookup_or_create(d, *name, ctr > 1 ? S_IFDIR : S_IFREG); + d = ovl_lookup_or_create(ofs, d, *name, ctr > 1 ? S_IFDIR : S_IFREG); if (IS_ERR(d)) return PTR_ERR(d); } @@ -1391,7 +1390,7 @@ static int ovl_make_workdir(struct super_block *sb, struct ovl_fs *ofs, pr_warn("upper fs needs to support d_type.\n"); /* Check if upper/work fs supports O_TMPFILE */ - temp = ovl_do_tmpfile(ofs->workdir, S_IFREG | 0); + temp = ovl_do_tmpfile(ofs, ofs->workdir, S_IFREG | 0); ofs->tmpfile = !IS_ERR(temp); if (ofs->tmpfile) dput(temp); @@ -1400,7 +1399,7 @@ static int ovl_make_workdir(struct super_block *sb, struct ovl_fs *ofs, /* Check if upper/work fs supports RENAME_WHITEOUT */ - err = ovl_check_rename_whiteout(ofs->workdir); + err = ovl_check_rename_whiteout(ofs); if (err < 0) goto out; @@ -1411,7 +1410,7 @@ static int ovl_make_workdir(struct super_block *sb, struct ovl_fs *ofs, /* * Check if upper/work fs supports (trusted|user).overlay.* xattr */ - err = ovl_do_setxattr(ofs, ofs->workdir, OVL_XATTR_OPAQUE, "0", 1); + err = ovl_setxattr(ofs, ofs->workdir, OVL_XATTR_OPAQUE, "0", 1); if (err) { ofs->noxattr = true; if (ofs->config.index || ofs->config.metacopy) { @@ -1429,7 +1428,7 @@ static int ovl_make_workdir(struct super_block *sb, struct ovl_fs *ofs, } err = 0; } else { - ovl_do_removexattr(ofs, ofs->workdir, OVL_XATTR_OPAQUE); + ovl_removexattr(ofs, ofs->workdir, OVL_XATTR_OPAQUE); } /* diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c index f48284a2a89600d32ef96ec600cdbc47b04781d4..87f811c089e4ff395ad8722ad7a0222504bf5b6b 100644 --- a/fs/overlayfs/util.c +++ b/fs/overlayfs/util.c @@ -194,6 +194,20 @@ enum ovl_path_type ovl_path_real(struct dentry *dentry, struct path *path) return type; } +enum ovl_path_type ovl_path_realdata(struct dentry *dentry, struct path *path) +{ + enum ovl_path_type type = ovl_path_type(dentry); + + WARN_ON_ONCE(d_is_dir(dentry)); + + if (!OVL_TYPE_UPPER(type) || OVL_TYPE_MERGE(type)) + ovl_path_lowerdata(dentry, path); + else + ovl_path_upper(dentry, path); + + return type; +} + struct dentry *ovl_dentry_upper(struct dentry *dentry) { return ovl_upperdentry_dereference(OVL_I(d_inode(dentry))); @@ -236,6 +250,17 @@ struct dentry *ovl_i_dentry_upper(struct inode *inode) return ovl_upperdentry_dereference(OVL_I(inode)); } +void ovl_i_path_real(struct inode *inode, struct path *path) +{ + path->dentry = ovl_i_dentry_upper(inode); + if (!path->dentry) { + path->dentry = OVL_I(inode)->lowerpath.dentry; + path->mnt = OVL_I(inode)->lowerpath.layer->mnt; + } else { + path->mnt = ovl_upper_mnt(OVL_FS(inode->i_sb)); + } +} + struct inode *ovl_inode_upper(struct inode *inode) { struct dentry *upperdentry = ovl_i_dentry_upper(inode); @@ -245,7 +270,9 @@ struct inode *ovl_inode_upper(struct inode *inode) struct inode *ovl_inode_lower(struct inode *inode) { - return OVL_I(inode)->lower; + struct dentry *lowerdentry = OVL_I(inode)->lowerpath.dentry; + + return lowerdentry ? d_inode(lowerdentry) : NULL; } struct inode *ovl_inode_real(struct inode *inode) @@ -443,7 +470,7 @@ static void ovl_dir_version_inc(struct dentry *dentry, bool impurity) void ovl_dir_modified(struct dentry *dentry, bool impurity) { /* Copy mtime/ctime */ - ovl_copyattr(d_inode(ovl_dentry_upper(dentry)), d_inode(dentry)); + ovl_copyattr(d_inode(dentry)); ovl_dir_version_inc(dentry, impurity); } @@ -466,6 +493,7 @@ bool ovl_is_whiteout(struct dentry *dentry) struct file *ovl_path_open(struct path *path, int flags) { struct inode *inode = d_inode(path->dentry); + struct user_namespace *real_mnt_userns = mnt_user_ns(path->mnt); int err, acc_mode; if (flags & ~(O_ACCMODE | O_LARGEFILE)) @@ -482,12 +510,12 @@ struct file *ovl_path_open(struct path *path, int flags) BUG(); } - err = inode_permission(&init_user_ns, inode, acc_mode | MAY_OPEN); + err = inode_permission(real_mnt_userns, inode, acc_mode | MAY_OPEN); if (err) return ERR_PTR(err); /* O_NOATIME is an optimization, don't fail if not permitted */ - if (inode_owner_or_capable(&init_user_ns, inode)) + if (inode_owner_or_capable(real_mnt_userns, inode)) flags |= O_NOATIME; return dentry_open(path, flags, current_cred()); @@ -550,11 +578,11 @@ void ovl_copy_up_end(struct dentry *dentry) ovl_inode_unlock(d_inode(dentry)); } -bool ovl_check_origin_xattr(struct ovl_fs *ofs, struct dentry *dentry) +bool ovl_path_check_origin_xattr(struct ovl_fs *ofs, struct path *path) { int res; - res = ovl_do_getxattr(ofs, dentry, OVL_XATTR_ORIGIN, NULL, 0); + res = ovl_path_getxattr(ofs, path, OVL_XATTR_ORIGIN, NULL, 0); /* Zero size value means "copied up but origin unknown" */ if (res >= 0) @@ -563,16 +591,16 @@ bool ovl_check_origin_xattr(struct ovl_fs *ofs, struct dentry *dentry) return false; } -bool ovl_check_dir_xattr(struct super_block *sb, struct dentry *dentry, - enum ovl_xattr ox) +bool ovl_path_check_dir_xattr(struct ovl_fs *ofs, struct path *path, + enum ovl_xattr ox) { int res; char val; - if (!d_is_dir(dentry)) + if (!d_is_dir(path->dentry)) return false; - res = ovl_do_getxattr(OVL_FS(sb), dentry, ox, &val, 1); + res = ovl_path_getxattr(ofs, path, ox, &val, 1); if (res == 1 && val == 'y') return true; @@ -612,7 +640,7 @@ int ovl_check_setxattr(struct ovl_fs *ofs, struct dentry *upperdentry, if (ofs->noxattr) return xerr; - err = ovl_do_setxattr(ofs, upperdentry, ox, value, size); + err = ovl_setxattr(ofs, upperdentry, ox, value, size); if (err == -EOPNOTSUPP) { pr_warn("cannot set %s xattr on upper\n", ovl_xattr(ofs, ox)); @@ -652,8 +680,8 @@ void ovl_check_protattr(struct inode *inode, struct dentry *upper) char buf[OVL_PROTATTR_MAX+1]; int res, n; - res = ovl_do_getxattr(ofs, upper, OVL_XATTR_PROTATTR, buf, - OVL_PROTATTR_MAX); + res = ovl_getxattr_upper(ofs, upper, OVL_XATTR_PROTATTR, buf, + OVL_PROTATTR_MAX); if (res < 0) return; @@ -708,7 +736,7 @@ int ovl_set_protattr(struct inode *inode, struct dentry *upper, err = ovl_check_setxattr(ofs, upper, OVL_XATTR_PROTATTR, buf, len, -EPERM); } else if (inode->i_flags & OVL_PROT_I_FLAGS_MASK) { - err = ovl_do_removexattr(ofs, upper, OVL_XATTR_PROTATTR); + err = ovl_removexattr(ofs, upper, OVL_XATTR_PROTATTR); if (err == -EOPNOTSUPP || err == -ENODATA) err = 0; } @@ -824,7 +852,7 @@ static void ovl_cleanup_index(struct dentry *dentry) } inode_lock_nested(dir, I_MUTEX_PARENT); - index = lookup_one_len(name.name, indexdir, name.len); + index = ovl_lookup_upper(ofs, name.name, indexdir, name.len); err = PTR_ERR(index); if (IS_ERR(index)) { index = NULL; @@ -834,7 +862,7 @@ static void ovl_cleanup_index(struct dentry *dentry) dir, index); } else { /* Cleanup orphan index entries */ - err = ovl_cleanup(dir, index); + err = ovl_cleanup(ofs, dir, index); } inode_unlock(dir); @@ -943,15 +971,15 @@ err: } /* err < 0, 0 if no metacopy xattr, 1 if metacopy xattr found */ -int ovl_check_metacopy_xattr(struct ovl_fs *ofs, struct dentry *dentry) +int ovl_check_metacopy_xattr(struct ovl_fs *ofs, struct path *path) { int res; /* Only regular files can have metacopy xattr */ - if (!S_ISREG(d_inode(dentry)->i_mode)) + if (!S_ISREG(d_inode(path->dentry)->i_mode)) return 0; - res = ovl_do_getxattr(ofs, dentry, OVL_XATTR_METACOPY, NULL, 0); + res = ovl_path_getxattr(ofs, path, OVL_XATTR_METACOPY, NULL, 0); if (res < 0) { if (res == -ENODATA || res == -EOPNOTSUPP) return 0; @@ -987,13 +1015,12 @@ bool ovl_is_metacopy_dentry(struct dentry *dentry) return (oe->numlower > 1); } -char *ovl_get_redirect_xattr(struct ovl_fs *ofs, struct dentry *dentry, - int padding) +char *ovl_get_redirect_xattr(struct ovl_fs *ofs, struct path *path, int padding) { int res; char *s, *next, *buf = NULL; - res = ovl_do_getxattr(ofs, dentry, OVL_XATTR_REDIRECT, NULL, 0); + res = ovl_path_getxattr(ofs, path, OVL_XATTR_REDIRECT, NULL, 0); if (res == -ENODATA || res == -EOPNOTSUPP) return NULL; if (res < 0) @@ -1005,7 +1032,7 @@ char *ovl_get_redirect_xattr(struct ovl_fs *ofs, struct dentry *dentry, if (!buf) return ERR_PTR(-ENOMEM); - res = ovl_do_getxattr(ofs, dentry, OVL_XATTR_REDIRECT, buf, res); + res = ovl_path_getxattr(ofs, path, OVL_XATTR_REDIRECT, buf, res); if (res < 0) goto fail; if (res == 0) @@ -1060,3 +1087,33 @@ int ovl_sync_status(struct ovl_fs *ofs) return errseq_check(&mnt->mnt_sb->s_wb_err, ofs->errseq); } + +/* + * ovl_copyattr() - copy inode attributes from layer to ovl inode + * + * When overlay copies inode information from an upper or lower layer to the + * relevant overlay inode it will apply the idmapping of the upper or lower + * layer when doing so ensuring that the ovl inode ownership will correctly + * reflect the ownership of the idmapped upper or lower layer. For example, an + * idmapped upper or lower layer mapping id 1001 to id 1000 will take care to + * map any lower or upper inode owned by id 1001 to id 1000. These mapping + * helpers are nops when the relevant layer isn't idmapped. + */ +void ovl_copyattr(struct inode *inode) +{ + struct path realpath; + struct inode *realinode; + struct user_namespace *real_mnt_userns; + + ovl_i_path_real(inode, &realpath); + realinode = d_inode(realpath.dentry); + real_mnt_userns = mnt_user_ns(realpath.mnt); + + inode->i_uid = i_uid_into_mnt(real_mnt_userns, realinode); + inode->i_gid = i_gid_into_mnt(real_mnt_userns, realinode); + inode->i_mode = realinode->i_mode; + inode->i_atime = realinode->i_atime; + inode->i_mtime = realinode->i_mtime; + inode->i_ctime = realinode->i_ctime; + i_size_write(inode, i_size_read(realinode)); +} diff --git a/fs/read_write.c b/fs/read_write.c index e643aec2b0efe929bce63d6b4d1ddcf81b0b0399..b1b1cdfee9d39a85c777166688119bdc71026a09 100644 --- a/fs/read_write.c +++ b/fs/read_write.c @@ -682,6 +682,14 @@ SYSCALL_DEFINE4(pread64, unsigned int, fd, char __user *, buf, return ksys_pread64(fd, buf, count, pos); } +#if defined(CONFIG_COMPAT) && defined(__ARCH_WANT_COMPAT_PREAD64) +COMPAT_SYSCALL_DEFINE5(pread64, unsigned int, fd, char __user *, buf, + size_t, count, compat_arg_u64_dual(pos)) +{ + return ksys_pread64(fd, buf, count, compat_arg_u64_glue(pos)); +} +#endif + ssize_t ksys_pwrite64(unsigned int fd, const char __user *buf, size_t count, loff_t pos) { @@ -708,6 +716,14 @@ SYSCALL_DEFINE4(pwrite64, unsigned int, fd, const char __user *, buf, return ksys_pwrite64(fd, buf, count, pos); } +#if defined(CONFIG_COMPAT) && defined(__ARCH_WANT_COMPAT_PWRITE64) +COMPAT_SYSCALL_DEFINE5(pwrite64, unsigned int, fd, const char __user *, buf, + size_t, count, compat_arg_u64_dual(pos)) +{ + return ksys_pwrite64(fd, buf, count, compat_arg_u64_glue(pos)); +} +#endif + static ssize_t do_iter_readv_writev(struct file *filp, struct iov_iter *iter, loff_t *ppos, int type, rwf_t flags) { diff --git a/fs/smbfs_common/smb2pdu.h b/fs/smbfs_common/smb2pdu.h index 0507aecfc6694fe10aa827fc85578562988d90a8..2cab413fffeea4adc732ad5e0ab336694001ecf5 100644 --- a/fs/smbfs_common/smb2pdu.h +++ b/fs/smbfs_common/smb2pdu.h @@ -1244,6 +1244,106 @@ struct file_zero_data_information { __le64 BeyondFinalZero; } __packed; +/* See MS-FSCC 2.3.7 */ +struct duplicate_extents_to_file { + __u64 PersistentFileHandle; /* source file handle, opaque endianness */ + __u64 VolatileFileHandle; + __le64 SourceFileOffset; + __le64 TargetFileOffset; + __le64 ByteCount; /* Bytes to be copied */ +} __packed; + +/* See MS-FSCC 2.3.8 */ +#define DUPLICATE_EXTENTS_DATA_EX_SOURCE_ATOMIC 0x00000001 +struct duplicate_extents_to_file_ex { + __u64 PersistentFileHandle; /* source file handle, opaque endianness */ + __u64 VolatileFileHandle; + __le64 SourceFileOffset; + __le64 TargetFileOffset; + __le64 ByteCount; /* Bytes to be copied */ + __le32 Flags; + __le32 Reserved; +} __packed; + + +/* See MS-FSCC 2.3.20 */ +struct fsctl_get_integrity_information_rsp { + __le16 ChecksumAlgorithm; + __le16 Reserved; + __le32 Flags; + __le32 ChecksumChunkSizeInBytes; + __le32 ClusterSizeInBytes; +} __packed; + +/* See MS-FSCC 2.3.55 */ +struct fsctl_query_file_regions_req { + __le64 FileOffset; + __le64 Length; + __le32 DesiredUsage; + __le32 Reserved; +} __packed; + +/* DesiredUsage flags see MS-FSCC 2.3.56.1 */ +#define FILE_USAGE_INVALID_RANGE 0x00000000 +#define FILE_USAGE_VALID_CACHED_DATA 0x00000001 +#define FILE_USAGE_NONCACHED_DATA 0x00000002 + +struct file_region_info { + __le64 FileOffset; + __le64 Length; + __le32 DesiredUsage; + __le32 Reserved; +} __packed; + +/* See MS-FSCC 2.3.56 */ +struct fsctl_query_file_region_rsp { + __le32 Flags; + __le32 TotalRegionEntryCount; + __le32 RegionEntryCount; + __u32 Reserved; + struct file_region_info Regions[]; +} __packed; + +/* See MS-FSCC 2.3.58 */ +struct fsctl_query_on_disk_vol_info_rsp { + __le64 DirectoryCount; + __le64 FileCount; + __le16 FsFormatMajVersion; + __le16 FsFormatMinVersion; + __u8 FsFormatName[24]; + __le64 FormatTime; + __le64 LastUpdateTime; + __u8 CopyrightInfo[68]; + __u8 AbstractInfo[68]; + __u8 FormatImplInfo[68]; + __u8 LastModifyImplInfo[68]; +} __packed; + +/* See MS-FSCC 2.3.73 */ +struct fsctl_set_integrity_information_req { + __le16 ChecksumAlgorithm; + __le16 Reserved; + __le32 Flags; +} __packed; + +/* See MS-FSCC 2.3.75 */ +struct fsctl_set_integrity_info_ex_req { + __u8 EnableIntegrity; + __u8 KeepState; + __u16 Reserved; + __le32 Flags; + __u8 Version; + __u8 Reserved2[7]; +} __packed; + +/* Integrity ChecksumAlgorithm choices for above */ +#define CHECKSUM_TYPE_NONE 0x0000 +#define CHECKSUM_TYPE_CRC64 0x0002 +#define CHECKSUM_TYPE_UNCHANGED 0xFFFF /* set only */ + +/* Integrity flags for above */ +#define FSCTL_INTEGRITY_FLAG_CHECKSUM_ENFORCEMENT_OFF 0x00000001 + /* Reparse structures - see MS-FSCC 2.1.2 */ /* struct fsctl_reparse_info_req is empty, only response structs (see below) */ @@ -1304,13 +1404,6 @@ struct validate_negotiate_info_rsp { __le16 Dialect; /* Dialect in use for the connection */ } __packed; -struct duplicate_extents_to_file { - __u64 PersistentFileHandle; /* source file handle, opaque endianness */ - __u64 VolatileFileHandle; - __le64 SourceFileOffset; - __le64 TargetFileOffset; - __le64 ByteCount; /* Bytes to be copied */ -} __packed; /* Possible InfoType values */ #define SMB2_O_INFO_FILE 0x01 @@ -1419,6 +1512,7 @@ struct smb2_query_info_rsp { * PDU query infolevel structure definitions */ +/* See MS-FSCC 2.3.52 */ struct file_allocated_range_buffer { __le64 file_offset; __le64 length; diff --git a/fs/smbfs_common/smbfsctl.h b/fs/smbfs_common/smbfsctl.h index d51939c43ad7f5e70a60bbb47e1570bad14b283d..edd7fc2a7921b884d5407efe772048d8378b6106 100644 --- a/fs/smbfs_common/smbfsctl.h +++ b/fs/smbfs_common/smbfsctl.h @@ -88,21 +88,27 @@ #define FSCTL_READ_RAW_ENCRYPTED 0x000900E3 /* BB add struct */ #define FSCTL_READ_FILE_USN_DATA 0x000900EB /* BB add struct */ #define FSCTL_WRITE_USN_CLOSE_RECORD 0x000900EF /* BB add struct */ +#define FSCTL_MARK_HANDLE 0x000900FC /* BB add struct */ #define FSCTL_SIS_COPYFILE 0x00090100 /* BB add struct */ #define FSCTL_RECALL_FILE 0x00090117 /* BB add struct */ #define FSCTL_QUERY_SPARING_INFO 0x00090138 /* BB add struct */ +#define FSCTL_QUERY_ON_DISK_VOLUME_INFO 0x0009013C #define FSCTL_SET_ZERO_ON_DEALLOC 0x00090194 /* BB add struct */ #define FSCTL_SET_SHORT_NAME_BEHAVIOR 0x000901B4 /* BB add struct */ #define FSCTL_GET_INTEGRITY_INFORMATION 0x0009027C +#define FSCTL_QUERY_FILE_REGIONS 0x00090284 #define FSCTL_GET_REFS_VOLUME_DATA 0x000902D8 /* See MS-FSCC 2.3.24 */ #define FSCTL_SET_INTEGRITY_INFORMATION_EXT 0x00090380 #define FSCTL_GET_RETRIEVAL_POINTERS_AND_REFCOUNT 0x000903d3 #define FSCTL_GET_RETRIEVAL_POINTER_COUNT 0x0009042b #define FSCTL_REFS_STREAM_SNAPSHOT_MANAGEMENT 0x00090440 #define FSCTL_QUERY_ALLOCATED_RANGES 0x000940CF +#define FSCTL_OFFLOAD_READ 0x00094264 /* BB add struct */ +#define FSCTL_OFFLOAD_WRITE 0x00098268 /* BB add struct */ #define FSCTL_SET_DEFECT_MANAGEMENT 0x00098134 /* BB add struct */ #define FSCTL_FILE_LEVEL_TRIM 0x00098208 /* BB add struct */ #define FSCTL_DUPLICATE_EXTENTS_TO_FILE 0x00098344 +#define FSCTL_DUPLICATE_EXTENTS_TO_FILE_EX 0x000983E8 #define FSCTL_SIS_LINK_FILES 0x0009C104 #define FSCTL_SET_INTEGRITY_INFORMATION 0x0009C280 #define FSCTL_PIPE_PEEK 0x0011400C /* BB add struct */ diff --git a/fs/stat.c b/fs/stat.c index 5c2c94464e8b0242430dc050f96678c35511509d..9ced8860e0f35d305fabe984254d9f746808117a 100644 --- a/fs/stat.c +++ b/fs/stat.c @@ -659,7 +659,7 @@ SYSCALL_DEFINE5(statx, return ret; } -#ifdef CONFIG_COMPAT +#if defined(CONFIG_COMPAT) && defined(__ARCH_WANT_COMPAT_STAT) static int cp_compat_stat(struct kstat *stat, struct compat_stat __user *ubuf) { struct compat_stat tmp; diff --git a/fs/sync.c b/fs/sync.c index 2e771396bc15e9fd7472493b9261930a9099850f..df955436a6250bdaeef2cfcb1223aa06595ac561 100644 --- a/fs/sync.c +++ b/fs/sync.c @@ -374,6 +374,15 @@ SYSCALL_DEFINE4(sync_file_range, int, fd, loff_t, offset, loff_t, nbytes, return ksys_sync_file_range(fd, offset, nbytes, flags); } +#if defined(CONFIG_COMPAT) && defined(__ARCH_WANT_COMPAT_SYNC_FILE_RANGE) +COMPAT_SYSCALL_DEFINE6(sync_file_range, int, fd, compat_arg_u64_dual(offset), + compat_arg_u64_dual(nbytes), unsigned int, flags) +{ + return ksys_sync_file_range(fd, compat_arg_u64_glue(offset), + compat_arg_u64_glue(nbytes), flags); +} +#endif + /* It would be nice if people remember that not all the world's an i386 when they introduce new system calls */ SYSCALL_DEFINE4(sync_file_range2, int, fd, unsigned int, flags, diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 772590e2eddb8eaca3789a741b59a0847eb724da..0dc1ea0b52f51de5009caddb343debf4bc02c308 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -585,14 +585,22 @@ int unregister_acpi_bus_type(struct acpi_bus_type *); int acpi_bind_one(struct device *dev, struct acpi_device *adev); int acpi_unbind_one(struct device *dev); +enum acpi_bridge_type { + ACPI_BRIDGE_TYPE_PCIE = 1, + ACPI_BRIDGE_TYPE_CXL, +}; + struct acpi_pci_root { struct acpi_device * device; struct pci_bus *bus; u16 segment; + int bridge_type; struct resource secondary; /* downstream bus range */ - u32 osc_support_set; /* _OSC state of support bits */ - u32 osc_control_set; /* _OSC state of control bits */ + u32 osc_support_set; /* _OSC state of support bits */ + u32 osc_control_set; /* _OSC state of control bits */ + u32 osc_ext_support_set; /* _OSC state of extended support bits */ + u32 osc_ext_control_set; /* _OSC state of extended control bits */ phys_addr_t mcfg_addr; }; diff --git a/include/asm-generic/compat.h b/include/asm-generic/compat.h index d46c0201cc34c1ebc5fb66f4c7d031dde1c86c0a..d06308a2a7a8d9292dd5d474ea15669455951c37 100644 --- a/include/asm-generic/compat.h +++ b/include/asm-generic/compat.h @@ -2,6 +2,25 @@ #ifndef __ASM_GENERIC_COMPAT_H #define __ASM_GENERIC_COMPAT_H +#ifndef COMPAT_USER_HZ +#define COMPAT_USER_HZ 100 +#endif + +#ifndef COMPAT_RLIM_INFINITY +#define COMPAT_RLIM_INFINITY 0xffffffff +#endif + +#ifndef COMPAT_OFF_T_MAX +#define COMPAT_OFF_T_MAX 0x7fffffff +#endif + +#if !defined(compat_arg_u64) && !defined(CONFIG_CPU_BIG_ENDIAN) +#define compat_arg_u64(name) u32 name##_lo, u32 name##_hi +#define compat_arg_u64_dual(name) u32, name##_lo, u32, name##_hi +#define compat_arg_u64_glue(name) (((u64)name##_lo & 0xffffffffUL) | \ + ((u64)name##_hi << 32)) +#endif + /* These types are common across all compat ABIs */ typedef u32 compat_size_t; typedef s32 compat_ssize_t; @@ -24,6 +43,11 @@ typedef u32 compat_caddr_t; typedef u32 compat_aio_context_t; typedef u32 compat_old_sigset_t; +#ifndef __compat_uid_t +typedef u32 __compat_uid_t; +typedef u32 __compat_gid_t; +#endif + #ifndef __compat_uid32_t typedef u32 __compat_uid32_t; typedef u32 __compat_gid32_t; @@ -47,4 +71,93 @@ typedef u32 compat_sigset_word; #define _COMPAT_NSIG_BPW 32 #endif +#ifndef compat_dev_t +typedef u32 compat_dev_t; +#endif + +#ifndef compat_ipc_pid_t +typedef s32 compat_ipc_pid_t; +#endif + +#ifndef compat_fsid_t +typedef __kernel_fsid_t compat_fsid_t; +#endif + +#ifndef compat_statfs +struct compat_statfs { + compat_int_t f_type; + compat_int_t f_bsize; + compat_int_t f_blocks; + compat_int_t f_bfree; + compat_int_t f_bavail; + compat_int_t f_files; + compat_int_t f_ffree; + compat_fsid_t f_fsid; + compat_int_t f_namelen; + compat_int_t f_frsize; + compat_int_t f_flags; + compat_int_t f_spare[4]; +}; +#endif + +#ifndef compat_ipc64_perm +struct compat_ipc64_perm { + compat_key_t key; + __compat_uid32_t uid; + __compat_gid32_t gid; + __compat_uid32_t cuid; + __compat_gid32_t cgid; + compat_mode_t mode; + unsigned char __pad1[4 - sizeof(compat_mode_t)]; + compat_ushort_t seq; + compat_ushort_t __pad2; + compat_ulong_t unused1; + compat_ulong_t unused2; +}; + +struct compat_semid64_ds { + struct compat_ipc64_perm sem_perm; + compat_ulong_t sem_otime; + compat_ulong_t sem_otime_high; + compat_ulong_t sem_ctime; + compat_ulong_t sem_ctime_high; + compat_ulong_t sem_nsems; + compat_ulong_t __unused3; + compat_ulong_t __unused4; +}; + +struct compat_msqid64_ds { + struct compat_ipc64_perm msg_perm; + compat_ulong_t msg_stime; + compat_ulong_t msg_stime_high; + compat_ulong_t msg_rtime; + compat_ulong_t msg_rtime_high; + compat_ulong_t msg_ctime; + compat_ulong_t msg_ctime_high; + compat_ulong_t msg_cbytes; + compat_ulong_t msg_qnum; + compat_ulong_t msg_qbytes; + compat_pid_t msg_lspid; + compat_pid_t msg_lrpid; + compat_ulong_t __unused4; + compat_ulong_t __unused5; +}; + +struct compat_shmid64_ds { + struct compat_ipc64_perm shm_perm; + compat_size_t shm_segsz; + compat_ulong_t shm_atime; + compat_ulong_t shm_atime_high; + compat_ulong_t shm_dtime; + compat_ulong_t shm_dtime_high; + compat_ulong_t shm_ctime; + compat_ulong_t shm_ctime_high; + compat_pid_t shm_cpid; + compat_pid_t shm_lpid; + compat_ulong_t shm_nattch; + compat_ulong_t __unused4; + compat_ulong_t __unused5; +}; +#endif + #endif diff --git a/include/crypto/sm4.h b/include/crypto/sm4.h index 709f286e7b25355e60e1aa007ad84ee5f67ac9b5..9656a9a403264cf26a7efe598b4b15ded9540fc7 100644 --- a/include/crypto/sm4.h +++ b/include/crypto/sm4.h @@ -21,6 +21,10 @@ struct sm4_ctx { u32 rkey_dec[SM4_RKEY_WORDS]; }; +extern const u32 crypto_sm4_fk[]; +extern const u32 crypto_sm4_ck[]; +extern const u8 crypto_sm4_sbox[]; + /** * sm4_expandkey - Expands the SM4 key as described in GB/T 32907-2016 * @ctx: The location where the computed key will be stored. diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h index c3204a58fb09542631d006bf66bd875807d8b044..b2756753370b77c1f522ccbe729f96cd4ef35535 100644 --- a/include/drm/drm_edid.h +++ b/include/drm/drm_edid.h @@ -121,7 +121,7 @@ struct detailed_data_monitor_range { u8 supported_scalings; u8 preferred_refresh; } __attribute__((packed)) cvt; - } formula; + } __attribute__((packed)) formula; } __attribute__((packed)); struct detailed_data_wpindex { @@ -154,7 +154,7 @@ struct detailed_non_pixel { struct detailed_data_wpindex color; struct std_timing timings[6]; struct cvt_timing cvt[4]; - } data; + } __attribute__((packed)) data; } __attribute__((packed)); #define EDID_DETAIL_EST_TIMINGS 0xf7 @@ -172,7 +172,7 @@ struct detailed_timing { union { struct detailed_pixel_timing pixel_data; struct detailed_non_pixel other_data; - } data; + } __attribute__((packed)) data; } __attribute__((packed)); #define DRM_EDID_INPUT_SERRATION_VSYNC (1 << 0) diff --git a/include/dt-bindings/clock/en7523-clk.h b/include/dt-bindings/clock/en7523-clk.h new file mode 100644 index 0000000000000000000000000000000000000000..717d23a5e5aef08b15062db85ae41ed539ee350b --- /dev/null +++ b/include/dt-bindings/clock/en7523-clk.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ + +#ifndef _DT_BINDINGS_CLOCK_AIROHA_EN7523_H_ +#define _DT_BINDINGS_CLOCK_AIROHA_EN7523_H_ + +#define EN7523_CLK_GSW 0 +#define EN7523_CLK_EMI 1 +#define EN7523_CLK_BUS 2 +#define EN7523_CLK_SLIC 3 +#define EN7523_CLK_SPI 4 +#define EN7523_CLK_NPU 5 +#define EN7523_CLK_CRYPTO 6 +#define EN7523_CLK_PCIE 7 + +#define EN7523_NUM_CLOCKS 8 + +#endif /* _DT_BINDINGS_CLOCK_AIROHA_EN7523_H_ */ diff --git a/include/dt-bindings/clock/imx8mn-clock.h b/include/dt-bindings/clock/imx8mn-clock.h index 01e8bab1d767a1a8e8f3099eb09917408cbcd1ea..07b8a282c26828e173f636af6def2c2650134eff 100644 --- a/include/dt-bindings/clock/imx8mn-clock.h +++ b/include/dt-bindings/clock/imx8mn-clock.h @@ -243,6 +243,20 @@ #define IMX8MN_CLK_M7_CORE 221 -#define IMX8MN_CLK_END 222 +#define IMX8MN_CLK_GPT_3M 222 +#define IMX8MN_CLK_GPT1 223 +#define IMX8MN_CLK_GPT1_ROOT 224 +#define IMX8MN_CLK_GPT2 225 +#define IMX8MN_CLK_GPT2_ROOT 226 +#define IMX8MN_CLK_GPT3 227 +#define IMX8MN_CLK_GPT3_ROOT 228 +#define IMX8MN_CLK_GPT4 229 +#define IMX8MN_CLK_GPT4_ROOT 230 +#define IMX8MN_CLK_GPT5 231 +#define IMX8MN_CLK_GPT5_ROOT 232 +#define IMX8MN_CLK_GPT6 233 +#define IMX8MN_CLK_GPT6_ROOT 234 + +#define IMX8MN_CLK_END 235 #endif diff --git a/include/dt-bindings/clock/imx8mp-clock.h b/include/dt-bindings/clock/imx8mp-clock.h index 235c7a00d379cc751723eac5ea18e32909575bd3..9d5cc2ddde896530d6c01162ec2ad0e2df4c6999 100644 --- a/include/dt-bindings/clock/imx8mp-clock.h +++ b/include/dt-bindings/clock/imx8mp-clock.h @@ -317,8 +317,15 @@ #define IMX8MP_CLK_AUDIO_AXI 310 #define IMX8MP_CLK_HSIO_AXI 311 #define IMX8MP_CLK_MEDIA_ISP 312 +#define IMX8MP_CLK_MEDIA_DISP2_PIX 313 +#define IMX8MP_CLK_CLKOUT1_SEL 314 +#define IMX8MP_CLK_CLKOUT1_DIV 315 +#define IMX8MP_CLK_CLKOUT1 316 +#define IMX8MP_CLK_CLKOUT2_SEL 317 +#define IMX8MP_CLK_CLKOUT2_DIV 318 +#define IMX8MP_CLK_CLKOUT2 319 -#define IMX8MP_CLK_END 313 +#define IMX8MP_CLK_END 320 #define IMX8MP_CLK_AUDIOMIX_SAI1_IPG 0 #define IMX8MP_CLK_AUDIOMIX_SAI1_MCLK1 1 diff --git a/include/dt-bindings/clock/mt8186-clk.h b/include/dt-bindings/clock/mt8186-clk.h new file mode 100644 index 0000000000000000000000000000000000000000..a70bf67af47de7b3ddbf27561318a9118f625f10 --- /dev/null +++ b/include/dt-bindings/clock/mt8186-clk.h @@ -0,0 +1,445 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */ +/* + * Copyright (c) 2022 MediaTek Inc. + * Author: Chun-Jie Chen + */ + +#ifndef _DT_BINDINGS_CLK_MT8186_H +#define _DT_BINDINGS_CLK_MT8186_H + +/* MCUSYS */ + +#define CLK_MCU_ARMPLL_LL_SEL 0 +#define CLK_MCU_ARMPLL_BL_SEL 1 +#define CLK_MCU_ARMPLL_BUS_SEL 2 +#define CLK_MCU_NR_CLK 3 + +/* TOPCKGEN */ + +#define CLK_TOP_AXI 0 +#define CLK_TOP_SCP 1 +#define CLK_TOP_MFG 2 +#define CLK_TOP_CAMTG 3 +#define CLK_TOP_CAMTG1 4 +#define CLK_TOP_CAMTG2 5 +#define CLK_TOP_CAMTG3 6 +#define CLK_TOP_CAMTG4 7 +#define CLK_TOP_CAMTG5 8 +#define CLK_TOP_CAMTG6 9 +#define CLK_TOP_UART 10 +#define CLK_TOP_SPI 11 +#define CLK_TOP_MSDC50_0_HCLK 12 +#define CLK_TOP_MSDC50_0 13 +#define CLK_TOP_MSDC30_1 14 +#define CLK_TOP_AUDIO 15 +#define CLK_TOP_AUD_INTBUS 16 +#define CLK_TOP_AUD_1 17 +#define CLK_TOP_AUD_2 18 +#define CLK_TOP_AUD_ENGEN1 19 +#define CLK_TOP_AUD_ENGEN2 20 +#define CLK_TOP_DISP_PWM 21 +#define CLK_TOP_SSPM 22 +#define CLK_TOP_DXCC 23 +#define CLK_TOP_USB_TOP 24 +#define CLK_TOP_SRCK 25 +#define CLK_TOP_SPM 26 +#define CLK_TOP_I2C 27 +#define CLK_TOP_PWM 28 +#define CLK_TOP_SENINF 29 +#define CLK_TOP_SENINF1 30 +#define CLK_TOP_SENINF2 31 +#define CLK_TOP_SENINF3 32 +#define CLK_TOP_AES_MSDCFDE 33 +#define CLK_TOP_PWRAP_ULPOSC 34 +#define CLK_TOP_CAMTM 35 +#define CLK_TOP_VENC 36 +#define CLK_TOP_CAM 37 +#define CLK_TOP_IMG1 38 +#define CLK_TOP_IPE 39 +#define CLK_TOP_DPMAIF 40 +#define CLK_TOP_VDEC 41 +#define CLK_TOP_DISP 42 +#define CLK_TOP_MDP 43 +#define CLK_TOP_AUDIO_H 44 +#define CLK_TOP_UFS 45 +#define CLK_TOP_AES_FDE 46 +#define CLK_TOP_AUDIODSP 47 +#define CLK_TOP_DVFSRC 48 +#define CLK_TOP_DSI_OCC 49 +#define CLK_TOP_SPMI_MST 50 +#define CLK_TOP_SPINOR 51 +#define CLK_TOP_NNA 52 +#define CLK_TOP_NNA1 53 +#define CLK_TOP_NNA2 54 +#define CLK_TOP_SSUSB_XHCI 55 +#define CLK_TOP_SSUSB_TOP_1P 56 +#define CLK_TOP_SSUSB_XHCI_1P 57 +#define CLK_TOP_WPE 58 +#define CLK_TOP_DPI 59 +#define CLK_TOP_U3_OCC_250M 60 +#define CLK_TOP_U3_OCC_500M 61 +#define CLK_TOP_ADSP_BUS 62 +#define CLK_TOP_APLL_I2S0_MCK_SEL 63 +#define CLK_TOP_APLL_I2S1_MCK_SEL 64 +#define CLK_TOP_APLL_I2S2_MCK_SEL 65 +#define CLK_TOP_APLL_I2S4_MCK_SEL 66 +#define CLK_TOP_APLL_TDMOUT_MCK_SEL 67 +#define CLK_TOP_MAINPLL_D2 68 +#define CLK_TOP_MAINPLL_D2_D2 69 +#define CLK_TOP_MAINPLL_D2_D4 70 +#define CLK_TOP_MAINPLL_D2_D16 71 +#define CLK_TOP_MAINPLL_D3 72 +#define CLK_TOP_MAINPLL_D3_D2 73 +#define CLK_TOP_MAINPLL_D3_D4 74 +#define CLK_TOP_MAINPLL_D5 75 +#define CLK_TOP_MAINPLL_D5_D2 76 +#define CLK_TOP_MAINPLL_D5_D4 77 +#define CLK_TOP_MAINPLL_D7 78 +#define CLK_TOP_MAINPLL_D7_D2 79 +#define CLK_TOP_MAINPLL_D7_D4 80 +#define CLK_TOP_UNIVPLL 81 +#define CLK_TOP_UNIVPLL_D2 82 +#define CLK_TOP_UNIVPLL_D2_D2 83 +#define CLK_TOP_UNIVPLL_D2_D4 84 +#define CLK_TOP_UNIVPLL_D3 85 +#define CLK_TOP_UNIVPLL_D3_D2 86 +#define CLK_TOP_UNIVPLL_D3_D4 87 +#define CLK_TOP_UNIVPLL_D3_D8 88 +#define CLK_TOP_UNIVPLL_D3_D32 89 +#define CLK_TOP_UNIVPLL_D5 90 +#define CLK_TOP_UNIVPLL_D5_D2 91 +#define CLK_TOP_UNIVPLL_D5_D4 92 +#define CLK_TOP_UNIVPLL_D7 93 +#define CLK_TOP_UNIVPLL_192M 94 +#define CLK_TOP_UNIVPLL_192M_D4 95 +#define CLK_TOP_UNIVPLL_192M_D8 96 +#define CLK_TOP_UNIVPLL_192M_D16 97 +#define CLK_TOP_UNIVPLL_192M_D32 98 +#define CLK_TOP_APLL1_D2 99 +#define CLK_TOP_APLL1_D4 100 +#define CLK_TOP_APLL1_D8 101 +#define CLK_TOP_APLL2_D2 102 +#define CLK_TOP_APLL2_D4 103 +#define CLK_TOP_APLL2_D8 104 +#define CLK_TOP_MMPLL_D2 105 +#define CLK_TOP_TVDPLL_D2 106 +#define CLK_TOP_TVDPLL_D4 107 +#define CLK_TOP_TVDPLL_D8 108 +#define CLK_TOP_TVDPLL_D16 109 +#define CLK_TOP_TVDPLL_D32 110 +#define CLK_TOP_MSDCPLL_D2 111 +#define CLK_TOP_ULPOSC1 112 +#define CLK_TOP_ULPOSC1_D2 113 +#define CLK_TOP_ULPOSC1_D4 114 +#define CLK_TOP_ULPOSC1_D8 115 +#define CLK_TOP_ULPOSC1_D10 116 +#define CLK_TOP_ULPOSC1_D16 117 +#define CLK_TOP_ULPOSC1_D32 118 +#define CLK_TOP_ADSPPLL_D2 119 +#define CLK_TOP_ADSPPLL_D4 120 +#define CLK_TOP_ADSPPLL_D8 121 +#define CLK_TOP_NNAPLL_D2 122 +#define CLK_TOP_NNAPLL_D4 123 +#define CLK_TOP_NNAPLL_D8 124 +#define CLK_TOP_NNA2PLL_D2 125 +#define CLK_TOP_NNA2PLL_D4 126 +#define CLK_TOP_NNA2PLL_D8 127 +#define CLK_TOP_F_BIST2FPC 128 +#define CLK_TOP_466M_FMEM 129 +#define CLK_TOP_MPLL 130 +#define CLK_TOP_APLL12_CK_DIV0 131 +#define CLK_TOP_APLL12_CK_DIV1 132 +#define CLK_TOP_APLL12_CK_DIV2 133 +#define CLK_TOP_APLL12_CK_DIV4 134 +#define CLK_TOP_APLL12_CK_DIV_TDMOUT_M 135 +#define CLK_TOP_NR_CLK 136 + +/* INFRACFG_AO */ + +#define CLK_INFRA_AO_PMIC_TMR 0 +#define CLK_INFRA_AO_PMIC_AP 1 +#define CLK_INFRA_AO_PMIC_MD 2 +#define CLK_INFRA_AO_PMIC_CONN 3 +#define CLK_INFRA_AO_SCP_CORE 4 +#define CLK_INFRA_AO_SEJ 5 +#define CLK_INFRA_AO_APXGPT 6 +#define CLK_INFRA_AO_ICUSB 7 +#define CLK_INFRA_AO_GCE 8 +#define CLK_INFRA_AO_THERM 9 +#define CLK_INFRA_AO_I2C_AP 10 +#define CLK_INFRA_AO_I2C_CCU 11 +#define CLK_INFRA_AO_I2C_SSPM 12 +#define CLK_INFRA_AO_I2C_RSV 13 +#define CLK_INFRA_AO_PWM_HCLK 14 +#define CLK_INFRA_AO_PWM1 15 +#define CLK_INFRA_AO_PWM2 16 +#define CLK_INFRA_AO_PWM3 17 +#define CLK_INFRA_AO_PWM4 18 +#define CLK_INFRA_AO_PWM5 19 +#define CLK_INFRA_AO_PWM 20 +#define CLK_INFRA_AO_UART0 21 +#define CLK_INFRA_AO_UART1 22 +#define CLK_INFRA_AO_UART2 23 +#define CLK_INFRA_AO_GCE_26M 24 +#define CLK_INFRA_AO_CQ_DMA_FPC 25 +#define CLK_INFRA_AO_BTIF 26 +#define CLK_INFRA_AO_SPI0 27 +#define CLK_INFRA_AO_MSDC0 28 +#define CLK_INFRA_AO_MSDCFDE 29 +#define CLK_INFRA_AO_MSDC1 30 +#define CLK_INFRA_AO_DVFSRC 31 +#define CLK_INFRA_AO_GCPU 32 +#define CLK_INFRA_AO_TRNG 33 +#define CLK_INFRA_AO_AUXADC 34 +#define CLK_INFRA_AO_CPUM 35 +#define CLK_INFRA_AO_CCIF1_AP 36 +#define CLK_INFRA_AO_CCIF1_MD 37 +#define CLK_INFRA_AO_AUXADC_MD 38 +#define CLK_INFRA_AO_AP_DMA 39 +#define CLK_INFRA_AO_XIU 40 +#define CLK_INFRA_AO_DEVICE_APC 41 +#define CLK_INFRA_AO_CCIF_AP 42 +#define CLK_INFRA_AO_DEBUGTOP 43 +#define CLK_INFRA_AO_AUDIO 44 +#define CLK_INFRA_AO_CCIF_MD 45 +#define CLK_INFRA_AO_DXCC_SEC_CORE 46 +#define CLK_INFRA_AO_DXCC_AO 47 +#define CLK_INFRA_AO_IMP_IIC 48 +#define CLK_INFRA_AO_DRAMC_F26M 49 +#define CLK_INFRA_AO_RG_PWM_FBCLK6 50 +#define CLK_INFRA_AO_SSUSB_TOP_HCLK 51 +#define CLK_INFRA_AO_DISP_PWM 52 +#define CLK_INFRA_AO_CLDMA_BCLK 53 +#define CLK_INFRA_AO_AUDIO_26M_BCLK 54 +#define CLK_INFRA_AO_SSUSB_TOP_P1_HCLK 55 +#define CLK_INFRA_AO_SPI1 56 +#define CLK_INFRA_AO_I2C4 57 +#define CLK_INFRA_AO_MODEM_TEMP_SHARE 58 +#define CLK_INFRA_AO_SPI2 59 +#define CLK_INFRA_AO_SPI3 60 +#define CLK_INFRA_AO_SSUSB_TOP_REF 61 +#define CLK_INFRA_AO_SSUSB_TOP_XHCI 62 +#define CLK_INFRA_AO_SSUSB_TOP_P1_REF 63 +#define CLK_INFRA_AO_SSUSB_TOP_P1_XHCI 64 +#define CLK_INFRA_AO_SSPM 65 +#define CLK_INFRA_AO_SSUSB_TOP_P1_SYS 66 +#define CLK_INFRA_AO_I2C5 67 +#define CLK_INFRA_AO_I2C5_ARBITER 68 +#define CLK_INFRA_AO_I2C5_IMM 69 +#define CLK_INFRA_AO_I2C1_ARBITER 70 +#define CLK_INFRA_AO_I2C1_IMM 71 +#define CLK_INFRA_AO_I2C2_ARBITER 72 +#define CLK_INFRA_AO_I2C2_IMM 73 +#define CLK_INFRA_AO_SPI4 74 +#define CLK_INFRA_AO_SPI5 75 +#define CLK_INFRA_AO_CQ_DMA 76 +#define CLK_INFRA_AO_BIST2FPC 77 +#define CLK_INFRA_AO_MSDC0_SELF 78 +#define CLK_INFRA_AO_SPINOR 79 +#define CLK_INFRA_AO_SSPM_26M_SELF 80 +#define CLK_INFRA_AO_SSPM_32K_SELF 81 +#define CLK_INFRA_AO_I2C6 82 +#define CLK_INFRA_AO_AP_MSDC0 83 +#define CLK_INFRA_AO_MD_MSDC0 84 +#define CLK_INFRA_AO_MSDC0_SRC 85 +#define CLK_INFRA_AO_MSDC1_SRC 86 +#define CLK_INFRA_AO_SEJ_F13M 87 +#define CLK_INFRA_AO_AES_TOP0_BCLK 88 +#define CLK_INFRA_AO_MCU_PM_BCLK 89 +#define CLK_INFRA_AO_CCIF2_AP 90 +#define CLK_INFRA_AO_CCIF2_MD 91 +#define CLK_INFRA_AO_CCIF3_AP 92 +#define CLK_INFRA_AO_CCIF3_MD 93 +#define CLK_INFRA_AO_FADSP_26M 94 +#define CLK_INFRA_AO_FADSP_32K 95 +#define CLK_INFRA_AO_CCIF4_AP 96 +#define CLK_INFRA_AO_CCIF4_MD 97 +#define CLK_INFRA_AO_FADSP 98 +#define CLK_INFRA_AO_FLASHIF_133M 99 +#define CLK_INFRA_AO_FLASHIF_66M 100 +#define CLK_INFRA_AO_NR_CLK 101 + +/* APMIXEDSYS */ + +#define CLK_APMIXED_ARMPLL_LL 0 +#define CLK_APMIXED_ARMPLL_BL 1 +#define CLK_APMIXED_CCIPLL 2 +#define CLK_APMIXED_MAINPLL 3 +#define CLK_APMIXED_UNIV2PLL 4 +#define CLK_APMIXED_MSDCPLL 5 +#define CLK_APMIXED_MMPLL 6 +#define CLK_APMIXED_NNAPLL 7 +#define CLK_APMIXED_NNA2PLL 8 +#define CLK_APMIXED_ADSPPLL 9 +#define CLK_APMIXED_MFGPLL 10 +#define CLK_APMIXED_TVDPLL 11 +#define CLK_APMIXED_APLL1 12 +#define CLK_APMIXED_APLL2 13 +#define CLK_APMIXED_NR_CLK 14 + +/* IMP_IIC_WRAP */ + +#define CLK_IMP_IIC_WRAP_AP_CLOCK_I2C0 0 +#define CLK_IMP_IIC_WRAP_AP_CLOCK_I2C1 1 +#define CLK_IMP_IIC_WRAP_AP_CLOCK_I2C2 2 +#define CLK_IMP_IIC_WRAP_AP_CLOCK_I2C3 3 +#define CLK_IMP_IIC_WRAP_AP_CLOCK_I2C4 4 +#define CLK_IMP_IIC_WRAP_AP_CLOCK_I2C5 5 +#define CLK_IMP_IIC_WRAP_AP_CLOCK_I2C6 6 +#define CLK_IMP_IIC_WRAP_AP_CLOCK_I2C7 7 +#define CLK_IMP_IIC_WRAP_AP_CLOCK_I2C8 8 +#define CLK_IMP_IIC_WRAP_AP_CLOCK_I2C9 9 +#define CLK_IMP_IIC_WRAP_NR_CLK 10 + +/* MFGCFG */ + +#define CLK_MFG_BG3D 0 +#define CLK_MFG_NR_CLK 1 + +/* MMSYS */ + +#define CLK_MM_DISP_MUTEX0 0 +#define CLK_MM_APB_MM_BUS 1 +#define CLK_MM_DISP_OVL0 2 +#define CLK_MM_DISP_RDMA0 3 +#define CLK_MM_DISP_OVL0_2L 4 +#define CLK_MM_DISP_WDMA0 5 +#define CLK_MM_DISP_RSZ0 6 +#define CLK_MM_DISP_AAL0 7 +#define CLK_MM_DISP_CCORR0 8 +#define CLK_MM_DISP_COLOR0 9 +#define CLK_MM_SMI_INFRA 10 +#define CLK_MM_DISP_DSC_WRAP0 11 +#define CLK_MM_DISP_GAMMA0 12 +#define CLK_MM_DISP_POSTMASK0 13 +#define CLK_MM_DISP_DITHER0 14 +#define CLK_MM_SMI_COMMON 15 +#define CLK_MM_DSI0 16 +#define CLK_MM_DISP_FAKE_ENG0 17 +#define CLK_MM_DISP_FAKE_ENG1 18 +#define CLK_MM_SMI_GALS 19 +#define CLK_MM_SMI_IOMMU 20 +#define CLK_MM_DISP_RDMA1 21 +#define CLK_MM_DISP_DPI 22 +#define CLK_MM_DSI0_DSI_CK_DOMAIN 23 +#define CLK_MM_DISP_26M 24 +#define CLK_MM_NR_CLK 25 + +/* WPESYS */ + +#define CLK_WPE_CK_EN 0 +#define CLK_WPE_SMI_LARB8_CK_EN 1 +#define CLK_WPE_SYS_EVENT_TX_CK_EN 2 +#define CLK_WPE_SMI_LARB8_PCLK_EN 3 +#define CLK_WPE_NR_CLK 4 + +/* IMGSYS1 */ + +#define CLK_IMG1_LARB9_IMG1 0 +#define CLK_IMG1_LARB10_IMG1 1 +#define CLK_IMG1_DIP 2 +#define CLK_IMG1_GALS_IMG1 3 +#define CLK_IMG1_NR_CLK 4 + +/* IMGSYS2 */ + +#define CLK_IMG2_LARB9_IMG2 0 +#define CLK_IMG2_LARB10_IMG2 1 +#define CLK_IMG2_MFB 2 +#define CLK_IMG2_WPE 3 +#define CLK_IMG2_MSS 4 +#define CLK_IMG2_GALS_IMG2 5 +#define CLK_IMG2_NR_CLK 6 + +/* VDECSYS */ + +#define CLK_VDEC_LARB1_CKEN 0 +#define CLK_VDEC_LAT_CKEN 1 +#define CLK_VDEC_LAT_ACTIVE 2 +#define CLK_VDEC_LAT_CKEN_ENG 3 +#define CLK_VDEC_MINI_MDP_CKEN_CFG_RG 4 +#define CLK_VDEC_CKEN 5 +#define CLK_VDEC_ACTIVE 6 +#define CLK_VDEC_CKEN_ENG 7 +#define CLK_VDEC_NR_CLK 8 + +/* VENCSYS */ + +#define CLK_VENC_CKE0_LARB 0 +#define CLK_VENC_CKE1_VENC 1 +#define CLK_VENC_CKE2_JPGENC 2 +#define CLK_VENC_CKE5_GALS 3 +#define CLK_VENC_NR_CLK 4 + +/* CAMSYS */ + +#define CLK_CAM_LARB13 0 +#define CLK_CAM_DFP_VAD 1 +#define CLK_CAM_LARB14 2 +#define CLK_CAM 3 +#define CLK_CAMTG 4 +#define CLK_CAM_SENINF 5 +#define CLK_CAMSV1 6 +#define CLK_CAMSV2 7 +#define CLK_CAMSV3 8 +#define CLK_CAM_CCU0 9 +#define CLK_CAM_CCU1 10 +#define CLK_CAM_MRAW0 11 +#define CLK_CAM_FAKE_ENG 12 +#define CLK_CAM_CCU_GALS 13 +#define CLK_CAM2MM_GALS 14 +#define CLK_CAM_NR_CLK 15 + +/* CAMSYS_RAWA */ + +#define CLK_CAM_RAWA_LARBX_RAWA 0 +#define CLK_CAM_RAWA 1 +#define CLK_CAM_RAWA_CAMTG_RAWA 2 +#define CLK_CAM_RAWA_NR_CLK 3 + +/* CAMSYS_RAWB */ + +#define CLK_CAM_RAWB_LARBX_RAWB 0 +#define CLK_CAM_RAWB 1 +#define CLK_CAM_RAWB_CAMTG_RAWB 2 +#define CLK_CAM_RAWB_NR_CLK 3 + +/* MDPSYS */ + +#define CLK_MDP_RDMA0 0 +#define CLK_MDP_TDSHP0 1 +#define CLK_MDP_IMG_DL_ASYNC0 2 +#define CLK_MDP_IMG_DL_ASYNC1 3 +#define CLK_MDP_DISP_RDMA 4 +#define CLK_MDP_HMS 5 +#define CLK_MDP_SMI0 6 +#define CLK_MDP_APB_BUS 7 +#define CLK_MDP_WROT0 8 +#define CLK_MDP_RSZ0 9 +#define CLK_MDP_HDR0 10 +#define CLK_MDP_MUTEX0 11 +#define CLK_MDP_WROT1 12 +#define CLK_MDP_RSZ1 13 +#define CLK_MDP_FAKE_ENG0 14 +#define CLK_MDP_AAL0 15 +#define CLK_MDP_DISP_WDMA 16 +#define CLK_MDP_COLOR 17 +#define CLK_MDP_IMG_DL_ASYNC2 18 +#define CLK_MDP_IMG_DL_RELAY0_ASYNC0 19 +#define CLK_MDP_IMG_DL_RELAY1_ASYNC1 20 +#define CLK_MDP_IMG_DL_RELAY2_ASYNC2 21 +#define CLK_MDP_NR_CLK 22 + +/* IPESYS */ + +#define CLK_IPE_LARB19 0 +#define CLK_IPE_LARB20 1 +#define CLK_IPE_SMI_SUBCOM 2 +#define CLK_IPE_FD 3 +#define CLK_IPE_FE 4 +#define CLK_IPE_RSC 5 +#define CLK_IPE_DPE 6 +#define CLK_IPE_GALS_IPE 7 +#define CLK_IPE_NR_CLK 8 + +#endif /* _DT_BINDINGS_CLK_MT8186_H */ diff --git a/include/dt-bindings/clock/qcom,gcc-msm8976.h b/include/dt-bindings/clock/qcom,gcc-msm8976.h index 51955fd4942621fbc4648368acd6956a600b316c..5351f48b20687c4538f36d6fe4e9af69c4c6173e 100644 --- a/include/dt-bindings/clock/qcom,gcc-msm8976.h +++ b/include/dt-bindings/clock/qcom,gcc-msm8976.h @@ -224,6 +224,7 @@ #define RST_CAMSS_CSI_VFE1_BCR 7 #define RST_CAMSS_VFE1_BCR 8 #define RST_CAMSS_CPP_BCR 9 +#define RST_MSS_BCR 10 /* GDSCs */ #define VENUS_GDSC 0 diff --git a/include/dt-bindings/clock/qcom,gcc-sc8280xp.h b/include/dt-bindings/clock/qcom,gcc-sc8280xp.h new file mode 100644 index 0000000000000000000000000000000000000000..cb2fb638825ca847ed7fcbc76403e3d4a5b1c0f9 --- /dev/null +++ b/include/dt-bindings/clock/qcom,gcc-sc8280xp.h @@ -0,0 +1,496 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* + * Copyright (c) 2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2022, Linaro Ltd. + */ + +#ifndef _DT_BINDINGS_CLK_QCOM_GCC_DIREWOLF_H +#define _DT_BINDINGS_CLK_QCOM_GCC_DIREWOLF_H + +/* GCC clocks */ +#define GCC_GPLL0 0 +#define GCC_GPLL0_OUT_EVEN 1 +#define GCC_GPLL2 2 +#define GCC_GPLL4 3 +#define GCC_GPLL7 4 +#define GCC_GPLL8 5 +#define GCC_GPLL9 6 +#define GCC_AGGRE_NOC_PCIE0_TUNNEL_AXI_CLK 7 +#define GCC_AGGRE_NOC_PCIE1_TUNNEL_AXI_CLK 8 +#define GCC_AGGRE_NOC_PCIE_4_AXI_CLK 9 +#define GCC_AGGRE_NOC_PCIE_SOUTH_SF_AXI_CLK 10 +#define GCC_AGGRE_UFS_CARD_AXI_CLK 11 +#define GCC_AGGRE_UFS_PHY_AXI_CLK 12 +#define GCC_AGGRE_USB3_MP_AXI_CLK 13 +#define GCC_AGGRE_USB3_PRIM_AXI_CLK 14 +#define GCC_AGGRE_USB3_SEC_AXI_CLK 15 +#define GCC_AGGRE_USB4_1_AXI_CLK 16 +#define GCC_AGGRE_USB4_AXI_CLK 17 +#define GCC_AGGRE_USB_NOC_AXI_CLK 18 +#define GCC_AGGRE_USB_NOC_NORTH_AXI_CLK 19 +#define GCC_AGGRE_USB_NOC_SOUTH_AXI_CLK 20 +#define GCC_AHB2PHY0_CLK 21 +#define GCC_AHB2PHY2_CLK 22 +#define GCC_BOOT_ROM_AHB_CLK 23 +#define GCC_CAMERA_AHB_CLK 24 +#define GCC_CAMERA_HF_AXI_CLK 25 +#define GCC_CAMERA_SF_AXI_CLK 26 +#define GCC_CAMERA_THROTTLE_NRT_AXI_CLK 27 +#define GCC_CAMERA_THROTTLE_RT_AXI_CLK 28 +#define GCC_CAMERA_THROTTLE_XO_CLK 29 +#define GCC_CAMERA_XO_CLK 30 +#define GCC_CFG_NOC_USB3_MP_AXI_CLK 31 +#define GCC_CFG_NOC_USB3_PRIM_AXI_CLK 32 +#define GCC_CFG_NOC_USB3_SEC_AXI_CLK 33 +#define GCC_CNOC_PCIE0_TUNNEL_CLK 34 +#define GCC_CNOC_PCIE1_TUNNEL_CLK 35 +#define GCC_CNOC_PCIE4_QX_CLK 36 +#define GCC_DDRSS_GPU_AXI_CLK 37 +#define GCC_DDRSS_PCIE_SF_TBU_CLK 38 +#define GCC_DISP1_AHB_CLK 39 +#define GCC_DISP1_HF_AXI_CLK 40 +#define GCC_DISP1_SF_AXI_CLK 41 +#define GCC_DISP1_THROTTLE_NRT_AXI_CLK 42 +#define GCC_DISP1_THROTTLE_RT_AXI_CLK 43 +#define GCC_DISP1_XO_CLK 44 +#define GCC_DISP_AHB_CLK 45 +#define GCC_DISP_HF_AXI_CLK 46 +#define GCC_DISP_SF_AXI_CLK 47 +#define GCC_DISP_THROTTLE_NRT_AXI_CLK 48 +#define GCC_DISP_THROTTLE_RT_AXI_CLK 49 +#define GCC_DISP_XO_CLK 50 +#define GCC_EMAC0_AXI_CLK 51 +#define GCC_EMAC0_PTP_CLK 52 +#define GCC_EMAC0_PTP_CLK_SRC 53 +#define GCC_EMAC0_RGMII_CLK 54 +#define GCC_EMAC0_RGMII_CLK_SRC 55 +#define GCC_EMAC0_SLV_AHB_CLK 56 +#define GCC_EMAC1_AXI_CLK 57 +#define GCC_EMAC1_PTP_CLK 58 +#define GCC_EMAC1_PTP_CLK_SRC 59 +#define GCC_EMAC1_RGMII_CLK 60 +#define GCC_EMAC1_RGMII_CLK_SRC 61 +#define GCC_EMAC1_SLV_AHB_CLK 62 +#define GCC_GP1_CLK 63 +#define GCC_GP1_CLK_SRC 64 +#define GCC_GP2_CLK 65 +#define GCC_GP2_CLK_SRC 66 +#define GCC_GP3_CLK 67 +#define GCC_GP3_CLK_SRC 68 +#define GCC_GP4_CLK 69 +#define GCC_GP4_CLK_SRC 70 +#define GCC_GP5_CLK 71 +#define GCC_GP5_CLK_SRC 72 +#define GCC_GPU_CFG_AHB_CLK 73 +#define GCC_GPU_GPLL0_CLK_SRC 74 +#define GCC_GPU_GPLL0_DIV_CLK_SRC 75 +#define GCC_GPU_IREF_EN 76 +#define GCC_GPU_MEMNOC_GFX_CLK 77 +#define GCC_GPU_SNOC_DVM_GFX_CLK 78 +#define GCC_GPU_TCU_THROTTLE_AHB_CLK 79 +#define GCC_GPU_TCU_THROTTLE_CLK 80 +#define GCC_PCIE0_PHY_RCHNG_CLK 81 +#define GCC_PCIE1_PHY_RCHNG_CLK 82 +#define GCC_PCIE2A_PHY_RCHNG_CLK 83 +#define GCC_PCIE2B_PHY_RCHNG_CLK 84 +#define GCC_PCIE3A_PHY_RCHNG_CLK 85 +#define GCC_PCIE3B_PHY_RCHNG_CLK 86 +#define GCC_PCIE4_PHY_RCHNG_CLK 87 +#define GCC_PCIE_0_AUX_CLK 88 +#define GCC_PCIE_0_AUX_CLK_SRC 89 +#define GCC_PCIE_0_CFG_AHB_CLK 90 +#define GCC_PCIE_0_MSTR_AXI_CLK 91 +#define GCC_PCIE_0_PHY_RCHNG_CLK_SRC 92 +#define GCC_PCIE_0_PIPE_CLK 93 +#define GCC_PCIE_0_SLV_AXI_CLK 94 +#define GCC_PCIE_0_SLV_Q2A_AXI_CLK 95 +#define GCC_PCIE_1_AUX_CLK 96 +#define GCC_PCIE_1_AUX_CLK_SRC 97 +#define GCC_PCIE_1_CFG_AHB_CLK 98 +#define GCC_PCIE_1_MSTR_AXI_CLK 99 +#define GCC_PCIE_1_PHY_RCHNG_CLK_SRC 100 +#define GCC_PCIE_1_PIPE_CLK 101 +#define GCC_PCIE_1_SLV_AXI_CLK 102 +#define GCC_PCIE_1_SLV_Q2A_AXI_CLK 103 +#define GCC_PCIE_2A2B_CLKREF_CLK 104 +#define GCC_PCIE_2A_AUX_CLK 105 +#define GCC_PCIE_2A_AUX_CLK_SRC 106 +#define GCC_PCIE_2A_CFG_AHB_CLK 107 +#define GCC_PCIE_2A_MSTR_AXI_CLK 108 +#define GCC_PCIE_2A_PHY_RCHNG_CLK_SRC 109 +#define GCC_PCIE_2A_PIPE_CLK 110 +#define GCC_PCIE_2A_PIPE_CLK_SRC 111 +#define GCC_PCIE_2A_PIPE_DIV_CLK_SRC 112 +#define GCC_PCIE_2A_PIPEDIV2_CLK 113 +#define GCC_PCIE_2A_SLV_AXI_CLK 114 +#define GCC_PCIE_2A_SLV_Q2A_AXI_CLK 115 +#define GCC_PCIE_2B_AUX_CLK 116 +#define GCC_PCIE_2B_AUX_CLK_SRC 117 +#define GCC_PCIE_2B_CFG_AHB_CLK 118 +#define GCC_PCIE_2B_MSTR_AXI_CLK 119 +#define GCC_PCIE_2B_PHY_RCHNG_CLK_SRC 120 +#define GCC_PCIE_2B_PIPE_CLK 121 +#define GCC_PCIE_2B_PIPE_CLK_SRC 122 +#define GCC_PCIE_2B_PIPE_DIV_CLK_SRC 123 +#define GCC_PCIE_2B_PIPEDIV2_CLK 124 +#define GCC_PCIE_2B_SLV_AXI_CLK 125 +#define GCC_PCIE_2B_SLV_Q2A_AXI_CLK 126 +#define GCC_PCIE_3A3B_CLKREF_CLK 127 +#define GCC_PCIE_3A_AUX_CLK 128 +#define GCC_PCIE_3A_AUX_CLK_SRC 129 +#define GCC_PCIE_3A_CFG_AHB_CLK 130 +#define GCC_PCIE_3A_MSTR_AXI_CLK 131 +#define GCC_PCIE_3A_PHY_RCHNG_CLK_SRC 132 +#define GCC_PCIE_3A_PIPE_CLK 133 +#define GCC_PCIE_3A_PIPE_CLK_SRC 134 +#define GCC_PCIE_3A_PIPE_DIV_CLK_SRC 135 +#define GCC_PCIE_3A_PIPEDIV2_CLK 136 +#define GCC_PCIE_3A_SLV_AXI_CLK 137 +#define GCC_PCIE_3A_SLV_Q2A_AXI_CLK 138 +#define GCC_PCIE_3B_AUX_CLK 139 +#define GCC_PCIE_3B_AUX_CLK_SRC 140 +#define GCC_PCIE_3B_CFG_AHB_CLK 141 +#define GCC_PCIE_3B_MSTR_AXI_CLK 142 +#define GCC_PCIE_3B_PHY_RCHNG_CLK_SRC 143 +#define GCC_PCIE_3B_PIPE_CLK 144 +#define GCC_PCIE_3B_PIPE_CLK_SRC 145 +#define GCC_PCIE_3B_PIPE_DIV_CLK_SRC 146 +#define GCC_PCIE_3B_PIPEDIV2_CLK 147 +#define GCC_PCIE_3B_SLV_AXI_CLK 148 +#define GCC_PCIE_3B_SLV_Q2A_AXI_CLK 149 +#define GCC_PCIE_4_AUX_CLK 150 +#define GCC_PCIE_4_AUX_CLK_SRC 151 +#define GCC_PCIE_4_CFG_AHB_CLK 152 +#define GCC_PCIE_4_CLKREF_CLK 153 +#define GCC_PCIE_4_MSTR_AXI_CLK 154 +#define GCC_PCIE_4_PHY_RCHNG_CLK_SRC 155 +#define GCC_PCIE_4_PIPE_CLK 156 +#define GCC_PCIE_4_PIPE_CLK_SRC 157 +#define GCC_PCIE_4_PIPE_DIV_CLK_SRC 158 +#define GCC_PCIE_4_PIPEDIV2_CLK 159 +#define GCC_PCIE_4_SLV_AXI_CLK 160 +#define GCC_PCIE_4_SLV_Q2A_AXI_CLK 161 +#define GCC_PCIE_RSCC_AHB_CLK 162 +#define GCC_PCIE_RSCC_XO_CLK 163 +#define GCC_PCIE_RSCC_XO_CLK_SRC 164 +#define GCC_PCIE_THROTTLE_CFG_CLK 165 +#define GCC_PDM2_CLK 166 +#define GCC_PDM2_CLK_SRC 167 +#define GCC_PDM_AHB_CLK 168 +#define GCC_PDM_XO4_CLK 169 +#define GCC_QMIP_CAMERA_NRT_AHB_CLK 170 +#define GCC_QMIP_CAMERA_RT_AHB_CLK 171 +#define GCC_QMIP_DISP1_AHB_CLK 172 +#define GCC_QMIP_DISP1_ROT_AHB_CLK 173 +#define GCC_QMIP_DISP_AHB_CLK 174 +#define GCC_QMIP_DISP_ROT_AHB_CLK 175 +#define GCC_QMIP_VIDEO_CVP_AHB_CLK 176 +#define GCC_QMIP_VIDEO_VCODEC_AHB_CLK 177 +#define GCC_QUPV3_WRAP0_CORE_2X_CLK 178 +#define GCC_QUPV3_WRAP0_CORE_CLK 179 +#define GCC_QUPV3_WRAP0_QSPI0_CLK 180 +#define GCC_QUPV3_WRAP0_S0_CLK 181 +#define GCC_QUPV3_WRAP0_S0_CLK_SRC 182 +#define GCC_QUPV3_WRAP0_S1_CLK 183 +#define GCC_QUPV3_WRAP0_S1_CLK_SRC 184 +#define GCC_QUPV3_WRAP0_S2_CLK 185 +#define GCC_QUPV3_WRAP0_S2_CLK_SRC 186 +#define GCC_QUPV3_WRAP0_S3_CLK 187 +#define GCC_QUPV3_WRAP0_S3_CLK_SRC 188 +#define GCC_QUPV3_WRAP0_S4_CLK 189 +#define GCC_QUPV3_WRAP0_S4_CLK_SRC 190 +#define GCC_QUPV3_WRAP0_S4_DIV_CLK_SRC 191 +#define GCC_QUPV3_WRAP0_S5_CLK 192 +#define GCC_QUPV3_WRAP0_S5_CLK_SRC 193 +#define GCC_QUPV3_WRAP0_S6_CLK 194 +#define GCC_QUPV3_WRAP0_S6_CLK_SRC 195 +#define GCC_QUPV3_WRAP0_S7_CLK 196 +#define GCC_QUPV3_WRAP0_S7_CLK_SRC 197 +#define GCC_QUPV3_WRAP1_CORE_2X_CLK 198 +#define GCC_QUPV3_WRAP1_CORE_CLK 199 +#define GCC_QUPV3_WRAP1_QSPI0_CLK 200 +#define GCC_QUPV3_WRAP1_S0_CLK 201 +#define GCC_QUPV3_WRAP1_S0_CLK_SRC 202 +#define GCC_QUPV3_WRAP1_S1_CLK 203 +#define GCC_QUPV3_WRAP1_S1_CLK_SRC 204 +#define GCC_QUPV3_WRAP1_S2_CLK 205 +#define GCC_QUPV3_WRAP1_S2_CLK_SRC 206 +#define GCC_QUPV3_WRAP1_S3_CLK 207 +#define GCC_QUPV3_WRAP1_S3_CLK_SRC 208 +#define GCC_QUPV3_WRAP1_S4_CLK 209 +#define GCC_QUPV3_WRAP1_S4_CLK_SRC 210 +#define GCC_QUPV3_WRAP1_S4_DIV_CLK_SRC 211 +#define GCC_QUPV3_WRAP1_S5_CLK 212 +#define GCC_QUPV3_WRAP1_S5_CLK_SRC 213 +#define GCC_QUPV3_WRAP1_S6_CLK 214 +#define GCC_QUPV3_WRAP1_S6_CLK_SRC 215 +#define GCC_QUPV3_WRAP1_S7_CLK 216 +#define GCC_QUPV3_WRAP1_S7_CLK_SRC 217 +#define GCC_QUPV3_WRAP2_CORE_2X_CLK 218 +#define GCC_QUPV3_WRAP2_CORE_CLK 219 +#define GCC_QUPV3_WRAP2_QSPI0_CLK 220 +#define GCC_QUPV3_WRAP2_S0_CLK 221 +#define GCC_QUPV3_WRAP2_S0_CLK_SRC 222 +#define GCC_QUPV3_WRAP2_S1_CLK 223 +#define GCC_QUPV3_WRAP2_S1_CLK_SRC 224 +#define GCC_QUPV3_WRAP2_S2_CLK 225 +#define GCC_QUPV3_WRAP2_S2_CLK_SRC 226 +#define GCC_QUPV3_WRAP2_S3_CLK 227 +#define GCC_QUPV3_WRAP2_S3_CLK_SRC 228 +#define GCC_QUPV3_WRAP2_S4_CLK 229 +#define GCC_QUPV3_WRAP2_S4_CLK_SRC 230 +#define GCC_QUPV3_WRAP2_S4_DIV_CLK_SRC 231 +#define GCC_QUPV3_WRAP2_S5_CLK 232 +#define GCC_QUPV3_WRAP2_S5_CLK_SRC 233 +#define GCC_QUPV3_WRAP2_S6_CLK 234 +#define GCC_QUPV3_WRAP2_S6_CLK_SRC 235 +#define GCC_QUPV3_WRAP2_S7_CLK 236 +#define GCC_QUPV3_WRAP2_S7_CLK_SRC 237 +#define GCC_QUPV3_WRAP_0_M_AHB_CLK 238 +#define GCC_QUPV3_WRAP_0_S_AHB_CLK 239 +#define GCC_QUPV3_WRAP_1_M_AHB_CLK 240 +#define GCC_QUPV3_WRAP_1_S_AHB_CLK 241 +#define GCC_QUPV3_WRAP_2_M_AHB_CLK 242 +#define GCC_QUPV3_WRAP_2_S_AHB_CLK 243 +#define GCC_SDCC2_AHB_CLK 244 +#define GCC_SDCC2_APPS_CLK 245 +#define GCC_SDCC2_APPS_CLK_SRC 246 +#define GCC_SDCC4_AHB_CLK 247 +#define GCC_SDCC4_APPS_CLK 248 +#define GCC_SDCC4_APPS_CLK_SRC 249 +#define GCC_SYS_NOC_USB_AXI_CLK 250 +#define GCC_UFS_1_CARD_CLKREF_CLK 251 +#define GCC_UFS_CARD_AHB_CLK 252 +#define GCC_UFS_CARD_AXI_CLK 253 +#define GCC_UFS_CARD_AXI_CLK_SRC 254 +#define GCC_UFS_CARD_CLKREF_CLK 255 +#define GCC_UFS_CARD_ICE_CORE_CLK 256 +#define GCC_UFS_CARD_ICE_CORE_CLK_SRC 257 +#define GCC_UFS_CARD_PHY_AUX_CLK 258 +#define GCC_UFS_CARD_PHY_AUX_CLK_SRC 259 +#define GCC_UFS_CARD_RX_SYMBOL_0_CLK 260 +#define GCC_UFS_CARD_RX_SYMBOL_0_CLK_SRC 261 +#define GCC_UFS_CARD_RX_SYMBOL_1_CLK 262 +#define GCC_UFS_CARD_RX_SYMBOL_1_CLK_SRC 263 +#define GCC_UFS_CARD_TX_SYMBOL_0_CLK 264 +#define GCC_UFS_CARD_TX_SYMBOL_0_CLK_SRC 265 +#define GCC_UFS_CARD_UNIPRO_CORE_CLK 266 +#define GCC_UFS_CARD_UNIPRO_CORE_CLK_SRC 267 +#define GCC_UFS_PHY_AHB_CLK 268 +#define GCC_UFS_PHY_AXI_CLK 269 +#define GCC_UFS_PHY_AXI_CLK_SRC 270 +#define GCC_UFS_PHY_ICE_CORE_CLK 271 +#define GCC_UFS_PHY_ICE_CORE_CLK_SRC 272 +#define GCC_UFS_PHY_PHY_AUX_CLK 273 +#define GCC_UFS_PHY_PHY_AUX_CLK_SRC 274 +#define GCC_UFS_PHY_RX_SYMBOL_0_CLK 275 +#define GCC_UFS_PHY_RX_SYMBOL_0_CLK_SRC 276 +#define GCC_UFS_PHY_RX_SYMBOL_1_CLK 277 +#define GCC_UFS_PHY_RX_SYMBOL_1_CLK_SRC 278 +#define GCC_UFS_PHY_TX_SYMBOL_0_CLK 279 +#define GCC_UFS_PHY_TX_SYMBOL_0_CLK_SRC 280 +#define GCC_UFS_PHY_UNIPRO_CORE_CLK 281 +#define GCC_UFS_PHY_UNIPRO_CORE_CLK_SRC 282 +#define GCC_UFS_REF_CLKREF_CLK 283 +#define GCC_USB2_HS0_CLKREF_CLK 284 +#define GCC_USB2_HS1_CLKREF_CLK 285 +#define GCC_USB2_HS2_CLKREF_CLK 286 +#define GCC_USB2_HS3_CLKREF_CLK 287 +#define GCC_USB30_MP_MASTER_CLK 288 +#define GCC_USB30_MP_MASTER_CLK_SRC 289 +#define GCC_USB30_MP_MOCK_UTMI_CLK 290 +#define GCC_USB30_MP_MOCK_UTMI_CLK_SRC 291 +#define GCC_USB30_MP_MOCK_UTMI_POSTDIV_CLK_SRC 292 +#define GCC_USB30_MP_SLEEP_CLK 293 +#define GCC_USB30_PRIM_MASTER_CLK 294 +#define GCC_USB30_PRIM_MASTER_CLK_SRC 295 +#define GCC_USB30_PRIM_MOCK_UTMI_CLK 296 +#define GCC_USB30_PRIM_MOCK_UTMI_CLK_SRC 297 +#define GCC_USB30_PRIM_MOCK_UTMI_POSTDIV_CLK_SRC 298 +#define GCC_USB30_PRIM_SLEEP_CLK 299 +#define GCC_USB30_SEC_MASTER_CLK 300 +#define GCC_USB30_SEC_MASTER_CLK_SRC 301 +#define GCC_USB30_SEC_MOCK_UTMI_CLK 302 +#define GCC_USB30_SEC_MOCK_UTMI_CLK_SRC 303 +#define GCC_USB30_SEC_MOCK_UTMI_POSTDIV_CLK_SRC 304 +#define GCC_USB30_SEC_SLEEP_CLK 305 +#define GCC_USB34_PRIM_PHY_PIPE_CLK_SRC 306 +#define GCC_USB34_SEC_PHY_PIPE_CLK_SRC 307 +#define GCC_USB3_MP0_CLKREF_CLK 308 +#define GCC_USB3_MP1_CLKREF_CLK 309 +#define GCC_USB3_MP_PHY_AUX_CLK 310 +#define GCC_USB3_MP_PHY_AUX_CLK_SRC 311 +#define GCC_USB3_MP_PHY_COM_AUX_CLK 312 +#define GCC_USB3_MP_PHY_PIPE_0_CLK 313 +#define GCC_USB3_MP_PHY_PIPE_0_CLK_SRC 314 +#define GCC_USB3_MP_PHY_PIPE_1_CLK 315 +#define GCC_USB3_MP_PHY_PIPE_1_CLK_SRC 316 +#define GCC_USB3_PRIM_PHY_AUX_CLK 317 +#define GCC_USB3_PRIM_PHY_AUX_CLK_SRC 318 +#define GCC_USB3_PRIM_PHY_COM_AUX_CLK 319 +#define GCC_USB3_PRIM_PHY_PIPE_CLK 320 +#define GCC_USB3_PRIM_PHY_PIPE_CLK_SRC 321 +#define GCC_USB3_SEC_PHY_AUX_CLK 322 +#define GCC_USB3_SEC_PHY_AUX_CLK_SRC 323 +#define GCC_USB3_SEC_PHY_COM_AUX_CLK 324 +#define GCC_USB3_SEC_PHY_PIPE_CLK 325 +#define GCC_USB3_SEC_PHY_PIPE_CLK_SRC 326 +#define GCC_USB4_1_CFG_AHB_CLK 327 +#define GCC_USB4_1_DP_CLK 328 +#define GCC_USB4_1_MASTER_CLK 329 +#define GCC_USB4_1_MASTER_CLK_SRC 330 +#define GCC_USB4_1_PHY_DP_CLK_SRC 331 +#define GCC_USB4_1_PHY_P2RR2P_PIPE_CLK 332 +#define GCC_USB4_1_PHY_P2RR2P_PIPE_CLK_SRC 333 +#define GCC_USB4_1_PHY_PCIE_PIPE_CLK 334 +#define GCC_USB4_1_PHY_PCIE_PIPE_CLK_SRC 335 +#define GCC_USB4_1_PHY_PCIE_PIPE_MUX_CLK_SRC 336 +#define GCC_USB4_1_PHY_PCIE_PIPEGMUX_CLK_SRC 337 +#define GCC_USB4_1_PHY_RX0_CLK 338 +#define GCC_USB4_1_PHY_RX0_CLK_SRC 339 +#define GCC_USB4_1_PHY_RX1_CLK 340 +#define GCC_USB4_1_PHY_RX1_CLK_SRC 341 +#define GCC_USB4_1_PHY_SYS_CLK_SRC 342 +#define GCC_USB4_1_PHY_USB_PIPE_CLK 343 +#define GCC_USB4_1_SB_IF_CLK 344 +#define GCC_USB4_1_SB_IF_CLK_SRC 345 +#define GCC_USB4_1_SYS_CLK 346 +#define GCC_USB4_1_TMU_CLK 347 +#define GCC_USB4_1_TMU_CLK_SRC 348 +#define GCC_USB4_CFG_AHB_CLK 349 +#define GCC_USB4_CLKREF_CLK 350 +#define GCC_USB4_DP_CLK 351 +#define GCC_USB4_EUD_CLKREF_CLK 352 +#define GCC_USB4_MASTER_CLK 353 +#define GCC_USB4_MASTER_CLK_SRC 354 +#define GCC_USB4_PHY_DP_CLK_SRC 355 +#define GCC_USB4_PHY_P2RR2P_PIPE_CLK 356 +#define GCC_USB4_PHY_P2RR2P_PIPE_CLK_SRC 357 +#define GCC_USB4_PHY_PCIE_PIPE_CLK 358 +#define GCC_USB4_PHY_PCIE_PIPE_CLK_SRC 359 +#define GCC_USB4_PHY_PCIE_PIPE_MUX_CLK_SRC 360 +#define GCC_USB4_PHY_PCIE_PIPEGMUX_CLK_SRC 361 +#define GCC_USB4_PHY_RX0_CLK 362 +#define GCC_USB4_PHY_RX0_CLK_SRC 363 +#define GCC_USB4_PHY_RX1_CLK 364 +#define GCC_USB4_PHY_RX1_CLK_SRC 365 +#define GCC_USB4_PHY_SYS_CLK_SRC 366 +#define GCC_USB4_PHY_USB_PIPE_CLK 367 +#define GCC_USB4_SB_IF_CLK 368 +#define GCC_USB4_SB_IF_CLK_SRC 369 +#define GCC_USB4_SYS_CLK 370 +#define GCC_USB4_TMU_CLK 371 +#define GCC_USB4_TMU_CLK_SRC 372 +#define GCC_VIDEO_AHB_CLK 373 +#define GCC_VIDEO_AXI0_CLK 374 +#define GCC_VIDEO_AXI1_CLK 375 +#define GCC_VIDEO_CVP_THROTTLE_CLK 376 +#define GCC_VIDEO_VCODEC_THROTTLE_CLK 377 +#define GCC_VIDEO_XO_CLK 378 +#define GCC_AGGRE_UFS_CARD_AXI_HW_CTL_CLK 379 +#define GCC_AGGRE_UFS_PHY_AXI_HW_CTL_CLK 380 +#define GCC_UFS_CARD_AXI_HW_CTL_CLK 381 +#define GCC_UFS_CARD_ICE_CORE_HW_CTL_CLK 382 +#define GCC_UFS_CARD_PHY_AUX_HW_CTL_CLK 383 +#define GCC_UFS_CARD_UNIPRO_CORE_HW_CTL_CLK 384 +#define GCC_UFS_PHY_AXI_HW_CTL_CLK 385 +#define GCC_UFS_PHY_ICE_CORE_HW_CTL_CLK 386 +#define GCC_UFS_PHY_PHY_AUX_HW_CTL_CLK 387 +#define GCC_UFS_PHY_UNIPRO_CORE_HW_CTL_CLK 388 + +/* GCC resets */ +#define GCC_EMAC0_BCR 0 +#define GCC_EMAC1_BCR 1 +#define GCC_PCIE_0_LINK_DOWN_BCR 2 +#define GCC_PCIE_0_NOCSR_COM_PHY_BCR 3 +#define GCC_PCIE_0_PHY_BCR 4 +#define GCC_PCIE_0_PHY_NOCSR_COM_PHY_BCR 5 +#define GCC_PCIE_0_TUNNEL_BCR 6 +#define GCC_PCIE_1_LINK_DOWN_BCR 7 +#define GCC_PCIE_1_NOCSR_COM_PHY_BCR 8 +#define GCC_PCIE_1_PHY_BCR 9 +#define GCC_PCIE_1_PHY_NOCSR_COM_PHY_BCR 10 +#define GCC_PCIE_1_TUNNEL_BCR 11 +#define GCC_PCIE_2A_BCR 12 +#define GCC_PCIE_2A_LINK_DOWN_BCR 13 +#define GCC_PCIE_2A_NOCSR_COM_PHY_BCR 14 +#define GCC_PCIE_2A_PHY_BCR 15 +#define GCC_PCIE_2A_PHY_NOCSR_COM_PHY_BCR 16 +#define GCC_PCIE_2B_BCR 17 +#define GCC_PCIE_2B_LINK_DOWN_BCR 18 +#define GCC_PCIE_2B_NOCSR_COM_PHY_BCR 19 +#define GCC_PCIE_2B_PHY_BCR 20 +#define GCC_PCIE_2B_PHY_NOCSR_COM_PHY_BCR 21 +#define GCC_PCIE_3A_BCR 22 +#define GCC_PCIE_3A_LINK_DOWN_BCR 23 +#define GCC_PCIE_3A_NOCSR_COM_PHY_BCR 24 +#define GCC_PCIE_3A_PHY_BCR 25 +#define GCC_PCIE_3A_PHY_NOCSR_COM_PHY_BCR 26 +#define GCC_PCIE_3B_BCR 27 +#define GCC_PCIE_3B_LINK_DOWN_BCR 28 +#define GCC_PCIE_3B_NOCSR_COM_PHY_BCR 29 +#define GCC_PCIE_3B_PHY_BCR 30 +#define GCC_PCIE_3B_PHY_NOCSR_COM_PHY_BCR 31 +#define GCC_PCIE_4_BCR 32 +#define GCC_PCIE_4_LINK_DOWN_BCR 33 +#define GCC_PCIE_4_NOCSR_COM_PHY_BCR 34 +#define GCC_PCIE_4_PHY_BCR 35 +#define GCC_PCIE_4_PHY_NOCSR_COM_PHY_BCR 36 +#define GCC_PCIE_PHY_CFG_AHB_BCR 37 +#define GCC_PCIE_PHY_COM_BCR 38 +#define GCC_PCIE_RSCC_BCR 39 +#define GCC_QUSB2PHY_HS0_MP_BCR 40 +#define GCC_QUSB2PHY_HS1_MP_BCR 41 +#define GCC_QUSB2PHY_HS2_MP_BCR 42 +#define GCC_QUSB2PHY_HS3_MP_BCR 43 +#define GCC_QUSB2PHY_PRIM_BCR 44 +#define GCC_QUSB2PHY_SEC_BCR 45 +#define GCC_SDCC2_BCR 46 +#define GCC_SDCC4_BCR 47 +#define GCC_UFS_CARD_BCR 48 +#define GCC_UFS_PHY_BCR 49 +#define GCC_USB2_PHY_PRIM_BCR 50 +#define GCC_USB2_PHY_SEC_BCR 51 +#define GCC_USB30_MP_BCR 52 +#define GCC_USB30_PRIM_BCR 53 +#define GCC_USB30_SEC_BCR 54 +#define GCC_USB3_DP_PHY_PRIM_BCR 55 +#define GCC_USB3_DP_PHY_SEC_BCR 56 +#define GCC_USB3_PHY_PRIM_BCR 57 +#define GCC_USB3_PHY_SEC_BCR 58 +#define GCC_USB3_UNIPHY_MP0_BCR 59 +#define GCC_USB3_UNIPHY_MP1_BCR 60 +#define GCC_USB3PHY_PHY_PRIM_BCR 61 +#define GCC_USB3PHY_PHY_SEC_BCR 62 +#define GCC_USB3UNIPHY_PHY_MP0_BCR 63 +#define GCC_USB3UNIPHY_PHY_MP1_BCR 64 +#define GCC_USB4_1_BCR 65 +#define GCC_USB4_1_DP_PHY_PRIM_BCR 66 +#define GCC_USB4_1_DPPHY_AUX_BCR 67 +#define GCC_USB4_1_PHY_PRIM_BCR 68 +#define GCC_USB4_BCR 69 +#define GCC_USB4_DP_PHY_PRIM_BCR 70 +#define GCC_USB4_DPPHY_AUX_BCR 71 +#define GCC_USB4_PHY_PRIM_BCR 72 +#define GCC_USB4PHY_1_PHY_PRIM_BCR 73 +#define GCC_USB4PHY_PHY_PRIM_BCR 74 +#define GCC_USB_PHY_CFG_AHB2PHY_BCR 75 +#define GCC_VIDEO_BCR 76 +#define GCC_VIDEO_AXI0_CLK_ARES 77 +#define GCC_VIDEO_AXI1_CLK_ARES 78 + +/* GCC GDSCs */ +#define PCIE_0_TUNNEL_GDSC 0 +#define PCIE_1_TUNNEL_GDSC 1 +#define PCIE_2A_GDSC 2 +#define PCIE_2B_GDSC 3 +#define PCIE_3A_GDSC 4 +#define PCIE_3B_GDSC 5 +#define PCIE_4_GDSC 6 +#define UFS_CARD_GDSC 7 +#define UFS_PHY_GDSC 8 +#define USB30_MP_GDSC 9 +#define USB30_PRIM_GDSC 10 +#define USB30_SEC_GDSC 11 + +#endif diff --git a/include/dt-bindings/clock/samsung,exynosautov9.h b/include/dt-bindings/clock/samsung,exynosautov9.h index 71ec0a9553648887e1bbdaa5ac6334865b0b1a77..ea9f91b4eb1a3586580f22ec074fd1fab045a1a4 100644 --- a/include/dt-bindings/clock/samsung,exynosautov9.h +++ b/include/dt-bindings/clock/samsung,exynosautov9.h @@ -166,7 +166,7 @@ #define GOUT_CLKCMU_PERIC1_IP 248 #define GOUT_CLKCMU_PERIS_BUS 249 -#define TOP_NR_CLK 249 +#define TOP_NR_CLK 250 /* CMU_BUSMC */ #define CLK_MOUT_BUSMC_BUS_USER 1 @@ -174,7 +174,7 @@ #define CLK_GOUT_BUSMC_PDMA0_PCLK 3 #define CLK_GOUT_BUSMC_SPDMA_PCLK 4 -#define BUSMC_NR_CLK 4 +#define BUSMC_NR_CLK 5 /* CMU_CORE */ #define CLK_MOUT_CORE_BUS_USER 1 @@ -183,7 +183,7 @@ #define CLK_GOUT_CORE_CCI_PCLK 4 #define CLK_GOUT_CORE_CMU_CORE_PCLK 5 -#define CORE_NR_CLK 5 +#define CORE_NR_CLK 6 /* CMU_FSYS2 */ #define CLK_MOUT_FSYS2_BUS_USER 1 @@ -194,7 +194,7 @@ #define CLK_GOUT_FSYS2_UFS_EMBD1_ACLK 6 #define CLK_GOUT_FSYS2_UFS_EMBD1_UNIPRO 7 -#define FSYS2_NR_CLK 7 +#define FSYS2_NR_CLK 8 /* CMU_PERIC0 */ #define CLK_MOUT_PERIC0_BUS_USER 1 @@ -240,7 +240,7 @@ #define CLK_GOUT_PERIC0_PCLK_10 41 #define CLK_GOUT_PERIC0_PCLK_11 42 -#define PERIC0_NR_CLK 42 +#define PERIC0_NR_CLK 43 /* CMU_PERIC1 */ #define CLK_MOUT_PERIC1_BUS_USER 1 @@ -286,7 +286,7 @@ #define CLK_GOUT_PERIC1_PCLK_10 41 #define CLK_GOUT_PERIC1_PCLK_11 42 -#define PERIC1_NR_CLK 42 +#define PERIC1_NR_CLK 43 /* CMU_PERIS */ #define CLK_MOUT_PERIS_BUS_USER 1 @@ -294,6 +294,6 @@ #define CLK_GOUT_WDT_CLUSTER0 3 #define CLK_GOUT_WDT_CLUSTER1 4 -#define PERIS_NR_CLK 4 +#define PERIS_NR_CLK 5 #endif /* _DT_BINDINGS_CLOCK_EXYNOSAUTOV9_H */ diff --git a/include/dt-bindings/clock/ste-db8500-clkout.h b/include/dt-bindings/clock/ste-db8500-clkout.h new file mode 100644 index 0000000000000000000000000000000000000000..ca07cb2bd1bcae8a01854eb014c153e0f9b70172 --- /dev/null +++ b/include/dt-bindings/clock/ste-db8500-clkout.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __STE_CLK_DB8500_CLKOUT_H__ +#define __STE_CLK_DB8500_CLKOUT_H__ + +#define DB8500_CLKOUT_1 0 +#define DB8500_CLKOUT_2 1 + +#define DB8500_CLKOUT_SRC_CLK38M 0 +#define DB8500_CLKOUT_SRC_ACLK 1 +#define DB8500_CLKOUT_SRC_SYSCLK 2 +#define DB8500_CLKOUT_SRC_LCDCLK 3 +#define DB8500_CLKOUT_SRC_SDMMCCLK 4 +#define DB8500_CLKOUT_SRC_TVCLK 5 +#define DB8500_CLKOUT_SRC_TIMCLK 6 +#define DB8500_CLKOUT_SRC_CLK009 7 + +#endif diff --git a/include/dt-bindings/clock/stm32mp13-clks.h b/include/dt-bindings/clock/stm32mp13-clks.h new file mode 100644 index 0000000000000000000000000000000000000000..02befd25edcef0ff3f54650cc38436cddf75c74b --- /dev/null +++ b/include/dt-bindings/clock/stm32mp13-clks.h @@ -0,0 +1,229 @@ +/* SPDX-License-Identifier: GPL-2.0+ or BSD-3-Clause */ +/* + * Copyright (C) STMicroelectronics 2020 - All Rights Reserved + * Author: Gabriel Fernandez for STMicroelectronics. + */ + +#ifndef _DT_BINDINGS_STM32MP13_CLKS_H_ +#define _DT_BINDINGS_STM32MP13_CLKS_H_ + +/* OSCILLATOR clocks */ +#define CK_HSE 0 +#define CK_CSI 1 +#define CK_LSI 2 +#define CK_LSE 3 +#define CK_HSI 4 +#define CK_HSE_DIV2 5 + +/* PLL */ +#define PLL1 6 +#define PLL2 7 +#define PLL3 8 +#define PLL4 9 + +/* ODF */ +#define PLL1_P 10 +#define PLL1_Q 11 +#define PLL1_R 12 +#define PLL2_P 13 +#define PLL2_Q 14 +#define PLL2_R 15 +#define PLL3_P 16 +#define PLL3_Q 17 +#define PLL3_R 18 +#define PLL4_P 19 +#define PLL4_Q 20 +#define PLL4_R 21 + +#define PCLK1 22 +#define PCLK2 23 +#define PCLK3 24 +#define PCLK4 25 +#define PCLK5 26 +#define PCLK6 27 + +/* SYSTEM CLOCK */ +#define CK_PER 28 +#define CK_MPU 29 +#define CK_AXI 30 +#define CK_MLAHB 31 + +/* BASE TIMER */ +#define CK_TIMG1 32 +#define CK_TIMG2 33 +#define CK_TIMG3 34 + +/* AUX */ +#define RTC 35 + +/* TRACE & DEBUG clocks */ +#define CK_DBG 36 +#define CK_TRACE 37 + +/* MCO clocks */ +#define CK_MCO1 38 +#define CK_MCO2 39 + +/* IP clocks */ +#define SYSCFG 40 +#define VREF 41 +#define DTS 42 +#define PMBCTRL 43 +#define HDP 44 +#define IWDG2 45 +#define STGENRO 46 +#define USART1 47 +#define RTCAPB 48 +#define TZC 49 +#define TZPC 50 +#define IWDG1 51 +#define BSEC 52 +#define DMA1 53 +#define DMA2 54 +#define DMAMUX1 55 +#define DMAMUX2 56 +#define GPIOA 57 +#define GPIOB 58 +#define GPIOC 59 +#define GPIOD 60 +#define GPIOE 61 +#define GPIOF 62 +#define GPIOG 63 +#define GPIOH 64 +#define GPIOI 65 +#define CRYP1 66 +#define HASH1 67 +#define BKPSRAM 68 +#define MDMA 69 +#define CRC1 70 +#define USBH 71 +#define DMA3 72 +#define TSC 73 +#define PKA 74 +#define AXIMC 75 +#define MCE 76 +#define ETH1TX 77 +#define ETH2TX 78 +#define ETH1RX 79 +#define ETH2RX 80 +#define ETH1MAC 81 +#define ETH2MAC 82 +#define ETH1STP 83 +#define ETH2STP 84 + +/* IP clocks with parents */ +#define SDMMC1_K 85 +#define SDMMC2_K 86 +#define ADC1_K 87 +#define ADC2_K 88 +#define FMC_K 89 +#define QSPI_K 90 +#define RNG1_K 91 +#define USBPHY_K 92 +#define STGEN_K 93 +#define SPDIF_K 94 +#define SPI1_K 95 +#define SPI2_K 96 +#define SPI3_K 97 +#define SPI4_K 98 +#define SPI5_K 99 +#define I2C1_K 100 +#define I2C2_K 101 +#define I2C3_K 102 +#define I2C4_K 103 +#define I2C5_K 104 +#define TIM2_K 105 +#define TIM3_K 106 +#define TIM4_K 107 +#define TIM5_K 108 +#define TIM6_K 109 +#define TIM7_K 110 +#define TIM12_K 111 +#define TIM13_K 112 +#define TIM14_K 113 +#define TIM1_K 114 +#define TIM8_K 115 +#define TIM15_K 116 +#define TIM16_K 117 +#define TIM17_K 118 +#define LPTIM1_K 119 +#define LPTIM2_K 120 +#define LPTIM3_K 121 +#define LPTIM4_K 122 +#define LPTIM5_K 123 +#define USART1_K 124 +#define USART2_K 125 +#define USART3_K 126 +#define UART4_K 127 +#define UART5_K 128 +#define USART6_K 129 +#define UART7_K 130 +#define UART8_K 131 +#define DFSDM_K 132 +#define FDCAN_K 133 +#define SAI1_K 134 +#define SAI2_K 135 +#define ADFSDM_K 136 +#define USBO_K 137 +#define LTDC_PX 138 +#define ETH1CK_K 139 +#define ETH1PTP_K 140 +#define ETH2CK_K 141 +#define ETH2PTP_K 142 +#define DCMIPP_K 143 +#define SAES_K 144 +#define DTS_K 145 + +/* DDR */ +#define DDRC1 146 +#define DDRC1LP 147 +#define DDRC2 148 +#define DDRC2LP 149 +#define DDRPHYC 150 +#define DDRPHYCLP 151 +#define DDRCAPB 152 +#define DDRCAPBLP 153 +#define AXIDCG 154 +#define DDRPHYCAPB 155 +#define DDRPHYCAPBLP 156 +#define DDRPERFM 157 + +#define ADC1 158 +#define ADC2 159 +#define SAI1 160 +#define SAI2 161 + +#define STM32MP1_LAST_CLK 162 + +/* SCMI clock identifiers */ +#define CK_SCMI_HSE 0 +#define CK_SCMI_HSI 1 +#define CK_SCMI_CSI 2 +#define CK_SCMI_LSE 3 +#define CK_SCMI_LSI 4 +#define CK_SCMI_HSE_DIV2 5 +#define CK_SCMI_PLL2_Q 6 +#define CK_SCMI_PLL2_R 7 +#define CK_SCMI_PLL3_P 8 +#define CK_SCMI_PLL3_Q 9 +#define CK_SCMI_PLL3_R 10 +#define CK_SCMI_PLL4_P 11 +#define CK_SCMI_PLL4_Q 12 +#define CK_SCMI_PLL4_R 13 +#define CK_SCMI_MPU 14 +#define CK_SCMI_AXI 15 +#define CK_SCMI_MLAHB 16 +#define CK_SCMI_CKPER 17 +#define CK_SCMI_PCLK1 18 +#define CK_SCMI_PCLK2 19 +#define CK_SCMI_PCLK3 20 +#define CK_SCMI_PCLK4 21 +#define CK_SCMI_PCLK5 22 +#define CK_SCMI_PCLK6 23 +#define CK_SCMI_CKTIMG1 24 +#define CK_SCMI_CKTIMG2 25 +#define CK_SCMI_CKTIMG3 26 +#define CK_SCMI_RTC 27 +#define CK_SCMI_RTCAPB 28 + +#endif /* _DT_BINDINGS_STM32MP13_CLKS_H_ */ diff --git a/include/dt-bindings/clock/sun50i-h6-r-ccu.h b/include/dt-bindings/clock/sun50i-h6-r-ccu.h index 890368d252c455316bef24baf921ccd01d33594e..a96087abc86fbec9b13bd01962b67151b227dec0 100644 --- a/include/dt-bindings/clock/sun50i-h6-r-ccu.h +++ b/include/dt-bindings/clock/sun50i-h6-r-ccu.h @@ -22,5 +22,6 @@ #define CLK_W1 12 #define CLK_R_APB2_RSB 13 +#define CLK_R_APB1_RTC 14 #endif /* _DT_BINDINGS_CLK_SUN50I_H6_R_CCU_H_ */ diff --git a/include/dt-bindings/clock/sun50i-h616-ccu.h b/include/dt-bindings/clock/sun50i-h616-ccu.h index 4fc08b0df2f3c4f3ca2240168a0c28fd53677312..1191aca53ac64ae0fc7a0f24bf6857d072469a95 100644 --- a/include/dt-bindings/clock/sun50i-h616-ccu.h +++ b/include/dt-bindings/clock/sun50i-h616-ccu.h @@ -111,5 +111,6 @@ #define CLK_BUS_TVE0 125 #define CLK_HDCP 126 #define CLK_BUS_HDCP 127 +#define CLK_PLL_SYSTEM_32K 128 #endif /* _DT_BINDINGS_CLK_SUN50I_H616_H_ */ diff --git a/include/dt-bindings/memory/mt8186-memory-port.h b/include/dt-bindings/memory/mt8186-memory-port.h new file mode 100644 index 0000000000000000000000000000000000000000..2bc6e443304882daaa40d199a6db934c7b934443 --- /dev/null +++ b/include/dt-bindings/memory/mt8186-memory-port.h @@ -0,0 +1,217 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2022 MediaTek Inc. + * + * Author: Anan Sun + * Author: Yong Wu + */ +#ifndef _DT_BINDINGS_MEMORY_MT8186_LARB_PORT_H_ +#define _DT_BINDINGS_MEMORY_MT8186_LARB_PORT_H_ + +#include + +/* + * MM IOMMU supports 16GB dma address. We separate it to four ranges: + * 0 ~ 4G; 4G ~ 8G; 8G ~ 12G; 12G ~ 16G, we could adjust these masters + * locate in anyone region. BUT: + * a) Make sure all the ports inside a larb are in one range. + * b) The iova of any master can NOT cross the 4G/8G/12G boundary. + * + * This is the suggested mapping in this SoC: + * + * modules dma-address-region larbs-ports + * disp 0 ~ 4G larb0/1/2 + * vcodec 4G ~ 8G larb4/7 + * cam/mdp 8G ~ 12G the other larbs. + * N/A 12G ~ 16G + * CCU0 0x24000_0000 ~ 0x243ff_ffff larb13: port 9/10 + * CCU1 0x24400_0000 ~ 0x247ff_ffff larb14: port 4/5 + */ + +/* MM IOMMU ports */ +/* LARB 0 -- MMSYS */ +#define IOMMU_PORT_L0_DISP_POSTMASK0 MTK_M4U_ID(0, 0) +#define IOMMU_PORT_L0_REVERSED MTK_M4U_ID(0, 1) +#define IOMMU_PORT_L0_OVL_RDMA0 MTK_M4U_ID(0, 2) +#define IOMMU_PORT_L0_DISP_FAKE0 MTK_M4U_ID(0, 3) + +/* LARB 1 -- MMSYS */ +#define IOMMU_PORT_L1_DISP_RDMA1 MTK_M4U_ID(1, 0) +#define IOMMU_PORT_L1_OVL_2L_RDMA0 MTK_M4U_ID(1, 1) +#define IOMMU_PORT_L1_DISP_RDMA0 MTK_M4U_ID(1, 2) +#define IOMMU_PORT_L1_DISP_WDMA0 MTK_M4U_ID(1, 3) +#define IOMMU_PORT_L1_DISP_FAKE1 MTK_M4U_ID(1, 4) + +/* LARB 2 -- MMSYS */ +#define IOMMU_PORT_L2_MDP_RDMA0 MTK_M4U_ID(2, 0) +#define IOMMU_PORT_L2_MDP_RDMA1 MTK_M4U_ID(2, 1) +#define IOMMU_PORT_L2_MDP_WROT0 MTK_M4U_ID(2, 2) +#define IOMMU_PORT_L2_MDP_WROT1 MTK_M4U_ID(2, 3) +#define IOMMU_PORT_L2_DISP_FAKE0 MTK_M4U_ID(2, 4) + +/* LARB 4 -- VDEC */ +#define IOMMU_PORT_L4_HW_VDEC_MC_EXT MTK_M4U_ID(4, 0) +#define IOMMU_PORT_L4_HW_VDEC_UFO_EXT MTK_M4U_ID(4, 1) +#define IOMMU_PORT_L4_HW_VDEC_PP_EXT MTK_M4U_ID(4, 2) +#define IOMMU_PORT_L4_HW_VDEC_PRED_RD_EXT MTK_M4U_ID(4, 3) +#define IOMMU_PORT_L4_HW_VDEC_PRED_WR_EXT MTK_M4U_ID(4, 4) +#define IOMMU_PORT_L4_HW_VDEC_PPWRAP_EXT MTK_M4U_ID(4, 5) +#define IOMMU_PORT_L4_HW_VDEC_TILE_EXT MTK_M4U_ID(4, 6) +#define IOMMU_PORT_L4_HW_VDEC_VLD_EXT MTK_M4U_ID(4, 7) +#define IOMMU_PORT_L4_HW_VDEC_VLD2_EXT MTK_M4U_ID(4, 8) +#define IOMMU_PORT_L4_HW_VDEC_AVC_MV_EXT MTK_M4U_ID(4, 9) +#define IOMMU_PORT_L4_HW_VDEC_UFO_ENC_EXT MTK_M4U_ID(4, 10) +#define IOMMU_PORT_L4_HW_VDEC_RG_CTRL_DMA_EXT MTK_M4U_ID(4, 11) +#define IOMMU_PORT_L4_HW_MINI_MDP_R0_EXT MTK_M4U_ID(4, 12) +#define IOMMU_PORT_L4_HW_MINI_MDP_W0_EXT MTK_M4U_ID(4, 13) + +/* LARB 7 -- VENC */ +#define IOMMU_PORT_L7_VENC_RCPU MTK_M4U_ID(7, 0) +#define IOMMU_PORT_L7_VENC_REC MTK_M4U_ID(7, 1) +#define IOMMU_PORT_L7_VENC_BSDMA MTK_M4U_ID(7, 2) +#define IOMMU_PORT_L7_VENC_SV_COMV MTK_M4U_ID(7, 3) +#define IOMMU_PORT_L7_VENC_RD_COMV MTK_M4U_ID(7, 4) +#define IOMMU_PORT_L7_VENC_CUR_LUMA MTK_M4U_ID(7, 5) +#define IOMMU_PORT_L7_VENC_CUR_CHROMA MTK_M4U_ID(7, 6) +#define IOMMU_PORT_L7_VENC_REF_LUMA MTK_M4U_ID(7, 7) +#define IOMMU_PORT_L7_VENC_REF_CHROMA MTK_M4U_ID(7, 8) +#define IOMMU_PORT_L7_JPGENC_Y_RDMA MTK_M4U_ID(7, 9) +#define IOMMU_PORT_L7_JPGENC_C_RDMA MTK_M4U_ID(7, 10) +#define IOMMU_PORT_L7_JPGENC_Q_TABLE MTK_M4U_ID(7, 11) +#define IOMMU_PORT_L7_JPGENC_BSDMA MTK_M4U_ID(7, 12) + +/* LARB 8 -- WPE */ +#define IOMMU_PORT_L8_WPE_RDMA_0 MTK_M4U_ID(8, 0) +#define IOMMU_PORT_L8_WPE_RDMA_1 MTK_M4U_ID(8, 1) +#define IOMMU_PORT_L8_WPE_WDMA_0 MTK_M4U_ID(8, 2) + +/* LARB 9 -- IMG-1 */ +#define IOMMU_PORT_L9_IMG_IMGI_D1 MTK_M4U_ID(9, 0) +#define IOMMU_PORT_L9_IMG_IMGBI_D1 MTK_M4U_ID(9, 1) +#define IOMMU_PORT_L9_IMG_DMGI_D1 MTK_M4U_ID(9, 2) +#define IOMMU_PORT_L9_IMG_DEPI_D1 MTK_M4U_ID(9, 3) +#define IOMMU_PORT_L9_IMG_LCE_D1 MTK_M4U_ID(9, 4) +#define IOMMU_PORT_L9_IMG_SMTI_D1 MTK_M4U_ID(9, 5) +#define IOMMU_PORT_L9_IMG_SMTO_D2 MTK_M4U_ID(9, 6) +#define IOMMU_PORT_L9_IMG_SMTO_D1 MTK_M4U_ID(9, 7) +#define IOMMU_PORT_L9_IMG_CRZO_D1 MTK_M4U_ID(9, 8) +#define IOMMU_PORT_L9_IMG_IMG3O_D1 MTK_M4U_ID(9, 9) +#define IOMMU_PORT_L9_IMG_VIPI_D1 MTK_M4U_ID(9, 10) +#define IOMMU_PORT_L9_IMG_SMTI_D5 MTK_M4U_ID(9, 11) +#define IOMMU_PORT_L9_IMG_TIMGO_D1 MTK_M4U_ID(9, 12) +#define IOMMU_PORT_L9_IMG_UFBC_W0 MTK_M4U_ID(9, 13) +#define IOMMU_PORT_L9_IMG_UFBC_R0 MTK_M4U_ID(9, 14) +#define IOMMU_PORT_L9_IMG_WPE_RDMA1 MTK_M4U_ID(9, 15) +#define IOMMU_PORT_L9_IMG_WPE_RDMA0 MTK_M4U_ID(9, 16) +#define IOMMU_PORT_L9_IMG_WPE_WDMA MTK_M4U_ID(9, 17) +#define IOMMU_PORT_L9_IMG_MFB_RDMA0 MTK_M4U_ID(9, 18) +#define IOMMU_PORT_L9_IMG_MFB_RDMA1 MTK_M4U_ID(9, 19) +#define IOMMU_PORT_L9_IMG_MFB_RDMA2 MTK_M4U_ID(9, 20) +#define IOMMU_PORT_L9_IMG_MFB_RDMA3 MTK_M4U_ID(9, 21) +#define IOMMU_PORT_L9_IMG_MFB_RDMA4 MTK_M4U_ID(9, 22) +#define IOMMU_PORT_L9_IMG_MFB_RDMA5 MTK_M4U_ID(9, 23) +#define IOMMU_PORT_L9_IMG_MFB_WDMA0 MTK_M4U_ID(9, 24) +#define IOMMU_PORT_L9_IMG_MFB_WDMA1 MTK_M4U_ID(9, 25) +#define IOMMU_PORT_L9_IMG_RESERVE6 MTK_M4U_ID(9, 26) +#define IOMMU_PORT_L9_IMG_RESERVE7 MTK_M4U_ID(9, 27) +#define IOMMU_PORT_L9_IMG_RESERVE8 MTK_M4U_ID(9, 28) + +/* LARB 11 -- IMG-2 */ +#define IOMMU_PORT_L11_IMG_IMGI_D1 MTK_M4U_ID(11, 0) +#define IOMMU_PORT_L11_IMG_IMGBI_D1 MTK_M4U_ID(11, 1) +#define IOMMU_PORT_L11_IMG_DMGI_D1 MTK_M4U_ID(11, 2) +#define IOMMU_PORT_L11_IMG_DEPI_D1 MTK_M4U_ID(11, 3) +#define IOMMU_PORT_L11_IMG_LCE_D1 MTK_M4U_ID(11, 4) +#define IOMMU_PORT_L11_IMG_SMTI_D1 MTK_M4U_ID(11, 5) +#define IOMMU_PORT_L11_IMG_SMTO_D2 MTK_M4U_ID(11, 6) +#define IOMMU_PORT_L11_IMG_SMTO_D1 MTK_M4U_ID(11, 7) +#define IOMMU_PORT_L11_IMG_CRZO_D1 MTK_M4U_ID(11, 8) +#define IOMMU_PORT_L11_IMG_IMG3O_D1 MTK_M4U_ID(11, 9) +#define IOMMU_PORT_L11_IMG_VIPI_D1 MTK_M4U_ID(11, 10) +#define IOMMU_PORT_L11_IMG_SMTI_D5 MTK_M4U_ID(11, 11) +#define IOMMU_PORT_L11_IMG_TIMGO_D1 MTK_M4U_ID(11, 12) +#define IOMMU_PORT_L11_IMG_UFBC_W0 MTK_M4U_ID(11, 13) +#define IOMMU_PORT_L11_IMG_UFBC_R0 MTK_M4U_ID(11, 14) +#define IOMMU_PORT_L11_IMG_WPE_RDMA1 MTK_M4U_ID(11, 15) +#define IOMMU_PORT_L11_IMG_WPE_RDMA0 MTK_M4U_ID(11, 16) +#define IOMMU_PORT_L11_IMG_WPE_WDMA MTK_M4U_ID(11, 17) +#define IOMMU_PORT_L11_IMG_MFB_RDMA0 MTK_M4U_ID(11, 18) +#define IOMMU_PORT_L11_IMG_MFB_RDMA1 MTK_M4U_ID(11, 19) +#define IOMMU_PORT_L11_IMG_MFB_RDMA2 MTK_M4U_ID(11, 20) +#define IOMMU_PORT_L11_IMG_MFB_RDMA3 MTK_M4U_ID(11, 21) +#define IOMMU_PORT_L11_IMG_MFB_RDMA4 MTK_M4U_ID(11, 22) +#define IOMMU_PORT_L11_IMG_MFB_RDMA5 MTK_M4U_ID(11, 23) +#define IOMMU_PORT_L11_IMG_MFB_WDMA0 MTK_M4U_ID(11, 24) +#define IOMMU_PORT_L11_IMG_MFB_WDMA1 MTK_M4U_ID(11, 25) +#define IOMMU_PORT_L11_IMG_RESERVE6 MTK_M4U_ID(11, 26) +#define IOMMU_PORT_L11_IMG_RESERVE7 MTK_M4U_ID(11, 27) +#define IOMMU_PORT_L11_IMG_RESERVE8 MTK_M4U_ID(11, 28) + +/* LARB 13 -- CAM */ +#define IOMMU_PORT_L13_CAM_MRAWI MTK_M4U_ID(13, 0) +#define IOMMU_PORT_L13_CAM_MRAWO_0 MTK_M4U_ID(13, 1) +#define IOMMU_PORT_L13_CAM_MRAWO_1 MTK_M4U_ID(13, 2) +#define IOMMU_PORT_L13_CAM_CAMSV_4 MTK_M4U_ID(13, 6) +#define IOMMU_PORT_L13_CAM_CAMSV_5 MTK_M4U_ID(13, 7) +#define IOMMU_PORT_L13_CAM_CAMSV_6 MTK_M4U_ID(13, 8) +#define IOMMU_PORT_L13_CAM_CCUI MTK_M4U_ID(13, 9) +#define IOMMU_PORT_L13_CAM_CCUO MTK_M4U_ID(13, 10) +#define IOMMU_PORT_L13_CAM_FAKE MTK_M4U_ID(13, 11) + +/* LARB 14 -- CAM */ +#define IOMMU_PORT_L14_CAM_CCUI MTK_M4U_ID(14, 4) +#define IOMMU_PORT_L14_CAM_CCUO MTK_M4U_ID(14, 5) + +/* LARB 16 -- RAW-A */ +#define IOMMU_PORT_L16_CAM_IMGO_R1_A MTK_M4U_ID(16, 0) +#define IOMMU_PORT_L16_CAM_RRZO_R1_A MTK_M4U_ID(16, 1) +#define IOMMU_PORT_L16_CAM_CQI_R1_A MTK_M4U_ID(16, 2) +#define IOMMU_PORT_L16_CAM_BPCI_R1_A MTK_M4U_ID(16, 3) +#define IOMMU_PORT_L16_CAM_YUVO_R1_A MTK_M4U_ID(16, 4) +#define IOMMU_PORT_L16_CAM_UFDI_R2_A MTK_M4U_ID(16, 5) +#define IOMMU_PORT_L16_CAM_RAWI_R2_A MTK_M4U_ID(16, 6) +#define IOMMU_PORT_L16_CAM_RAWI_R3_A MTK_M4U_ID(16, 7) +#define IOMMU_PORT_L16_CAM_AAO_R1_A MTK_M4U_ID(16, 8) +#define IOMMU_PORT_L16_CAM_AFO_R1_A MTK_M4U_ID(16, 9) +#define IOMMU_PORT_L16_CAM_FLKO_R1_A MTK_M4U_ID(16, 10) +#define IOMMU_PORT_L16_CAM_LCESO_R1_A MTK_M4U_ID(16, 11) +#define IOMMU_PORT_L16_CAM_CRZO_R1_A MTK_M4U_ID(16, 12) +#define IOMMU_PORT_L16_CAM_LTMSO_R1_A MTK_M4U_ID(16, 13) +#define IOMMU_PORT_L16_CAM_RSSO_R1_A MTK_M4U_ID(16, 14) +#define IOMMU_PORT_L16_CAM_AAHO_R1_A MTK_M4U_ID(16, 15) +#define IOMMU_PORT_L16_CAM_LSCI_R1_A MTK_M4U_ID(16, 16) + +/* LARB 17 -- RAW-B */ +#define IOMMU_PORT_L17_CAM_IMGO_R1_B MTK_M4U_ID(17, 0) +#define IOMMU_PORT_L17_CAM_RRZO_R1_B MTK_M4U_ID(17, 1) +#define IOMMU_PORT_L17_CAM_CQI_R1_B MTK_M4U_ID(17, 2) +#define IOMMU_PORT_L17_CAM_BPCI_R1_B MTK_M4U_ID(17, 3) +#define IOMMU_PORT_L17_CAM_YUVO_R1_B MTK_M4U_ID(17, 4) +#define IOMMU_PORT_L17_CAM_UFDI_R2_B MTK_M4U_ID(17, 5) +#define IOMMU_PORT_L17_CAM_RAWI_R2_B MTK_M4U_ID(17, 6) +#define IOMMU_PORT_L17_CAM_RAWI_R3_B MTK_M4U_ID(17, 7) +#define IOMMU_PORT_L17_CAM_AAO_R1_B MTK_M4U_ID(17, 8) +#define IOMMU_PORT_L17_CAM_AFO_R1_B MTK_M4U_ID(17, 9) +#define IOMMU_PORT_L17_CAM_FLKO_R1_B MTK_M4U_ID(17, 10) +#define IOMMU_PORT_L17_CAM_LCESO_R1_B MTK_M4U_ID(17, 11) +#define IOMMU_PORT_L17_CAM_CRZO_R1_B MTK_M4U_ID(17, 12) +#define IOMMU_PORT_L17_CAM_LTMSO_R1_B MTK_M4U_ID(17, 13) +#define IOMMU_PORT_L17_CAM_RSSO_R1_B MTK_M4U_ID(17, 14) +#define IOMMU_PORT_L17_CAM_AAHO_R1_B MTK_M4U_ID(17, 15) +#define IOMMU_PORT_L17_CAM_LSCI_R1_B MTK_M4U_ID(17, 16) + +/* LARB 19 -- IPE */ +#define IOMMU_PORT_L19_IPE_DVS_RDMA MTK_M4U_ID(19, 0) +#define IOMMU_PORT_L19_IPE_DVS_WDMA MTK_M4U_ID(19, 1) +#define IOMMU_PORT_L19_IPE_DVP_RDMA MTK_M4U_ID(19, 2) +#define IOMMU_PORT_L19_IPE_DVP_WDMA MTK_M4U_ID(19, 3) + +/* LARB 20 -- IPE */ +#define IOMMU_PORT_L20_IPE_FDVT_RDA MTK_M4U_ID(20, 0) +#define IOMMU_PORT_L20_IPE_FDVT_RDB MTK_M4U_ID(20, 1) +#define IOMMU_PORT_L20_IPE_FDVT_WRA MTK_M4U_ID(20, 2) +#define IOMMU_PORT_L20_IPE_FDVT_WRB MTK_M4U_ID(20, 3) +#define IOMMU_PORT_L20_IPE_RSC_RDMA0 MTK_M4U_ID(20, 4) +#define IOMMU_PORT_L20_IPE_RSC_WDMA MTK_M4U_ID(20, 5) + +#endif diff --git a/include/dt-bindings/memory/mt8195-memory-port.h b/include/dt-bindings/memory/mt8195-memory-port.h new file mode 100644 index 0000000000000000000000000000000000000000..70ba9f498eeb2f2d981d09f9b3006ac72ab51b20 --- /dev/null +++ b/include/dt-bindings/memory/mt8195-memory-port.h @@ -0,0 +1,408 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2022 MediaTek Inc. + * Author: Yong Wu + */ +#ifndef _DT_BINDINGS_MEMORY_MT8195_LARB_PORT_H_ +#define _DT_BINDINGS_MEMORY_MT8195_LARB_PORT_H_ + +#include + +/* + * MM IOMMU supports 16GB dma address. We separate it to four ranges: + * 0 ~ 4G; 4G ~ 8G; 8G ~ 12G; 12G ~ 16G, we could adjust these masters + * locate in anyone region. BUT: + * a) Make sure all the ports inside a larb are in one range. + * b) The iova of any master can NOT cross the 4G/8G/12G boundary. + * + * This is the suggested mapping in this SoC: + * + * modules dma-address-region larbs-ports + * disp 0 ~ 4G larb0/1/2/3 + * vcodec 4G ~ 8G larb19/20/21/22/23/24 + * cam/mdp 8G ~ 12G the other larbs. + * N/A 12G ~ 16G + * CCU0 0x24000_0000 ~ 0x243ff_ffff larb18: port 0/1 + * CCU1 0x24400_0000 ~ 0x247ff_ffff larb18: port 2/3 + * + * This SoC have two IOMMU HWs, this is the detailed connected information: + * iommu-vdo: larb0/2/5/7/9/10/11/13/17/19/21/24/25/28 + * iommu-vpp: larb1/3/4/6/8/12/14/16/18/20/22/23/26/27 + */ + +/* MM IOMMU ports */ +/* larb0 */ +#define M4U_PORT_L0_DISP_RDMA0 MTK_M4U_ID(0, 0) +#define M4U_PORT_L0_DISP_WDMA0 MTK_M4U_ID(0, 1) +#define M4U_PORT_L0_DISP_OVL0_RDMA0 MTK_M4U_ID(0, 2) +#define M4U_PORT_L0_DISP_OVL0_RDMA1 MTK_M4U_ID(0, 3) +#define M4U_PORT_L0_DISP_OVL0_HDR MTK_M4U_ID(0, 4) +#define M4U_PORT_L0_DISP_FAKE0 MTK_M4U_ID(0, 5) + +/* larb1 */ +#define M4U_PORT_L1_DISP_RDMA0 MTK_M4U_ID(1, 0) +#define M4U_PORT_L1_DISP_WDMA0 MTK_M4U_ID(1, 1) +#define M4U_PORT_L1_DISP_OVL0_RDMA0 MTK_M4U_ID(1, 2) +#define M4U_PORT_L1_DISP_OVL0_RDMA1 MTK_M4U_ID(1, 3) +#define M4U_PORT_L1_DISP_OVL0_HDR MTK_M4U_ID(1, 4) +#define M4U_PORT_L1_DISP_FAKE0 MTK_M4U_ID(1, 5) + +/* larb2 */ +#define M4U_PORT_L2_MDP_RDMA0 MTK_M4U_ID(2, 0) +#define M4U_PORT_L2_MDP_RDMA2 MTK_M4U_ID(2, 1) +#define M4U_PORT_L2_MDP_RDMA4 MTK_M4U_ID(2, 2) +#define M4U_PORT_L2_MDP_RDMA6 MTK_M4U_ID(2, 3) +#define M4U_PORT_L2_DISP_FAKE1 MTK_M4U_ID(2, 4) + +/* larb3 */ +#define M4U_PORT_L3_MDP_RDMA1 MTK_M4U_ID(3, 0) +#define M4U_PORT_L3_MDP_RDMA3 MTK_M4U_ID(3, 1) +#define M4U_PORT_L3_MDP_RDMA5 MTK_M4U_ID(3, 2) +#define M4U_PORT_L3_MDP_RDMA7 MTK_M4U_ID(3, 3) +#define M4U_PORT_L3_HDR_DS MTK_M4U_ID(3, 4) +#define M4U_PORT_L3_HDR_ADL MTK_M4U_ID(3, 5) +#define M4U_PORT_L3_DISP_FAKE1 MTK_M4U_ID(3, 6) + +/* larb4 */ +#define M4U_PORT_L4_MDP_RDMA MTK_M4U_ID(4, 0) +#define M4U_PORT_L4_MDP_FG MTK_M4U_ID(4, 1) +#define M4U_PORT_L4_MDP_OVL MTK_M4U_ID(4, 2) +#define M4U_PORT_L4_MDP_WROT MTK_M4U_ID(4, 3) +#define M4U_PORT_L4_FAKE MTK_M4U_ID(4, 4) + +/* larb5 */ +#define M4U_PORT_L5_SVPP1_MDP_RDMA MTK_M4U_ID(5, 0) +#define M4U_PORT_L5_SVPP1_MDP_FG MTK_M4U_ID(5, 1) +#define M4U_PORT_L5_SVPP1_MDP_OVL MTK_M4U_ID(5, 2) +#define M4U_PORT_L5_SVPP1_MDP_WROT MTK_M4U_ID(5, 3) +#define M4U_PORT_L5_SVPP2_MDP_RDMA MTK_M4U_ID(5, 4) +#define M4U_PORT_L5_SVPP2_MDP_FG MTK_M4U_ID(5, 5) +#define M4U_PORT_L5_SVPP2_MDP_WROT MTK_M4U_ID(5, 6) +#define M4U_PORT_L5_FAKE MTK_M4U_ID(5, 7) + +/* larb6 */ +#define M4U_PORT_L6_SVPP3_MDP_RDMA MTK_M4U_ID(6, 0) +#define M4U_PORT_L6_SVPP3_MDP_FG MTK_M4U_ID(6, 1) +#define M4U_PORT_L6_SVPP3_MDP_WROT MTK_M4U_ID(6, 2) +#define M4U_PORT_L6_FAKE MTK_M4U_ID(6, 3) + +/* larb7 */ +#define M4U_PORT_L7_IMG_WPE_RDMA0 MTK_M4U_ID(7, 0) +#define M4U_PORT_L7_IMG_WPE_RDMA1 MTK_M4U_ID(7, 1) +#define M4U_PORT_L7_IMG_WPE_WDMA0 MTK_M4U_ID(7, 2) + +/* larb8 */ +#define M4U_PORT_L8_IMG_WPE_RDMA0 MTK_M4U_ID(8, 0) +#define M4U_PORT_L8_IMG_WPE_RDMA1 MTK_M4U_ID(8, 1) +#define M4U_PORT_L8_IMG_WPE_WDMA0 MTK_M4U_ID(8, 2) + +/* larb9 */ +#define M4U_PORT_L9_IMG_IMGI_T1_A MTK_M4U_ID(9, 0) +#define M4U_PORT_L9_IMG_IMGBI_T1_A MTK_M4U_ID(9, 1) +#define M4U_PORT_L9_IMG_IMGCI_T1_A MTK_M4U_ID(9, 2) +#define M4U_PORT_L9_IMG_SMTI_T1_A MTK_M4U_ID(9, 3) +#define M4U_PORT_L9_IMG_TNCSTI_T1_A MTK_M4U_ID(9, 4) +#define M4U_PORT_L9_IMG_TNCSTI_T4_A MTK_M4U_ID(9, 5) +#define M4U_PORT_L9_IMG_YUVO_T1_A MTK_M4U_ID(9, 6) +#define M4U_PORT_L9_IMG_TIMGO_T1_A MTK_M4U_ID(9, 7) +#define M4U_PORT_L9_IMG_YUVO_T2_A MTK_M4U_ID(9, 8) +#define M4U_PORT_L9_IMG_IMGI_T1_B MTK_M4U_ID(9, 9) +#define M4U_PORT_L9_IMG_IMGBI_T1_B MTK_M4U_ID(9, 10) +#define M4U_PORT_L9_IMG_IMGCI_T1_B MTK_M4U_ID(9, 11) +#define M4U_PORT_L9_IMG_YUVO_T5_A MTK_M4U_ID(9, 12) +#define M4U_PORT_L9_IMG_SMTI_T1_B MTK_M4U_ID(9, 13) +#define M4U_PORT_L9_IMG_TNCSO_T1_A MTK_M4U_ID(9, 14) +#define M4U_PORT_L9_IMG_SMTO_T1_A MTK_M4U_ID(9, 15) +#define M4U_PORT_L9_IMG_TNCSTO_T1_A MTK_M4U_ID(9, 16) +#define M4U_PORT_L9_IMG_YUVO_T2_B MTK_M4U_ID(9, 17) +#define M4U_PORT_L9_IMG_YUVO_T5_B MTK_M4U_ID(9, 18) +#define M4U_PORT_L9_IMG_SMTO_T1_B MTK_M4U_ID(9, 19) + +/* larb10 */ +#define M4U_PORT_L10_IMG_IMGI_D1_A MTK_M4U_ID(10, 0) +#define M4U_PORT_L10_IMG_IMGCI_D1_A MTK_M4U_ID(10, 1) +#define M4U_PORT_L10_IMG_DEPI_D1_A MTK_M4U_ID(10, 2) +#define M4U_PORT_L10_IMG_DMGI_D1_A MTK_M4U_ID(10, 3) +#define M4U_PORT_L10_IMG_VIPI_D1_A MTK_M4U_ID(10, 4) +#define M4U_PORT_L10_IMG_TNRWI_D1_A MTK_M4U_ID(10, 5) +#define M4U_PORT_L10_IMG_RECI_D1_A MTK_M4U_ID(10, 6) +#define M4U_PORT_L10_IMG_SMTI_D1_A MTK_M4U_ID(10, 7) +#define M4U_PORT_L10_IMG_SMTI_D6_A MTK_M4U_ID(10, 8) +#define M4U_PORT_L10_IMG_PIMGI_P1_A MTK_M4U_ID(10, 9) +#define M4U_PORT_L10_IMG_PIMGBI_P1_A MTK_M4U_ID(10, 10) +#define M4U_PORT_L10_IMG_PIMGCI_P1_A MTK_M4U_ID(10, 11) +#define M4U_PORT_L10_IMG_PIMGI_P1_B MTK_M4U_ID(10, 12) +#define M4U_PORT_L10_IMG_PIMGBI_P1_B MTK_M4U_ID(10, 13) +#define M4U_PORT_L10_IMG_PIMGCI_P1_B MTK_M4U_ID(10, 14) +#define M4U_PORT_L10_IMG_IMG3O_D1_A MTK_M4U_ID(10, 15) +#define M4U_PORT_L10_IMG_IMG4O_D1_A MTK_M4U_ID(10, 16) +#define M4U_PORT_L10_IMG_IMG3CO_D1_A MTK_M4U_ID(10, 17) +#define M4U_PORT_L10_IMG_FEO_D1_A MTK_M4U_ID(10, 18) +#define M4U_PORT_L10_IMG_IMG2O_D1_A MTK_M4U_ID(10, 19) +#define M4U_PORT_L10_IMG_TNRWO_D1_A MTK_M4U_ID(10, 20) +#define M4U_PORT_L10_IMG_SMTO_D1_A MTK_M4U_ID(10, 21) +#define M4U_PORT_L10_IMG_WROT_P1_A MTK_M4U_ID(10, 22) +#define M4U_PORT_L10_IMG_WROT_P1_B MTK_M4U_ID(10, 23) + +/* larb11 */ +#define M4U_PORT_L11_IMG_WPE_EIS_RDMA0_A MTK_M4U_ID(11, 0) +#define M4U_PORT_L11_IMG_WPE_EIS_RDMA1_A MTK_M4U_ID(11, 1) +#define M4U_PORT_L11_IMG_WPE_EIS_WDMA0_A MTK_M4U_ID(11, 2) +#define M4U_PORT_L11_IMG_WPE_TNR_RDMA0_A MTK_M4U_ID(11, 3) +#define M4U_PORT_L11_IMG_WPE_TNR_RDMA1_A MTK_M4U_ID(11, 4) +#define M4U_PORT_L11_IMG_WPE_TNR_WDMA0_A MTK_M4U_ID(11, 5) +#define M4U_PORT_L11_IMG_WPE_EIS_CQ0_A MTK_M4U_ID(11, 6) +#define M4U_PORT_L11_IMG_WPE_EIS_CQ1_A MTK_M4U_ID(11, 7) +#define M4U_PORT_L11_IMG_WPE_TNR_CQ0_A MTK_M4U_ID(11, 8) +#define M4U_PORT_L11_IMG_WPE_TNR_CQ1_A MTK_M4U_ID(11, 9) + +/* larb12 */ +#define M4U_PORT_L12_IMG_FDVT_RDA MTK_M4U_ID(12, 0) +#define M4U_PORT_L12_IMG_FDVT_RDB MTK_M4U_ID(12, 1) +#define M4U_PORT_L12_IMG_FDVT_WRA MTK_M4U_ID(12, 2) +#define M4U_PORT_L12_IMG_FDVT_WRB MTK_M4U_ID(12, 3) +#define M4U_PORT_L12_IMG_ME_RDMA MTK_M4U_ID(12, 4) +#define M4U_PORT_L12_IMG_ME_WDMA MTK_M4U_ID(12, 5) +#define M4U_PORT_L12_IMG_DVS_RDMA MTK_M4U_ID(12, 6) +#define M4U_PORT_L12_IMG_DVS_WDMA MTK_M4U_ID(12, 7) +#define M4U_PORT_L12_IMG_DVP_RDMA MTK_M4U_ID(12, 8) +#define M4U_PORT_L12_IMG_DVP_WDMA MTK_M4U_ID(12, 9) + +/* larb13 */ +#define M4U_PORT_L13_CAM_CAMSV_CQI_E1 MTK_M4U_ID(13, 0) +#define M4U_PORT_L13_CAM_CAMSV_CQI_E2 MTK_M4U_ID(13, 1) +#define M4U_PORT_L13_CAM_GCAMSV_A_IMGO_0 MTK_M4U_ID(13, 2) +#define M4U_PORT_L13_CAM_SCAMSV_A_IMGO_0 MTK_M4U_ID(13, 3) +#define M4U_PORT_L13_CAM_GCAMSV_B_IMGO_0 MTK_M4U_ID(13, 4) +#define M4U_PORT_L13_CAM_GCAMSV_B_IMGO_1 MTK_M4U_ID(13, 5) +#define M4U_PORT_L13_CAM_GCAMSV_A_UFEO_0 MTK_M4U_ID(13, 6) +#define M4U_PORT_L13_CAM_GCAMSV_B_UFEO_0 MTK_M4U_ID(13, 7) +#define M4U_PORT_L13_CAM_PDAI_0 MTK_M4U_ID(13, 8) +#define M4U_PORT_L13_CAM_FAKE MTK_M4U_ID(13, 9) + +/* larb14 */ +#define M4U_PORT_L14_CAM_GCAMSV_A_IMGO_1 MTK_M4U_ID(14, 0) +#define M4U_PORT_L14_CAM_SCAMSV_A_IMGO_1 MTK_M4U_ID(14, 1) +#define M4U_PORT_L14_CAM_GCAMSV_B_IMGO_0 MTK_M4U_ID(14, 2) +#define M4U_PORT_L14_CAM_GCAMSV_B_IMGO_1 MTK_M4U_ID(14, 3) +#define M4U_PORT_L14_CAM_SCAMSV_B_IMGO_0 MTK_M4U_ID(14, 4) +#define M4U_PORT_L14_CAM_SCAMSV_B_IMGO_1 MTK_M4U_ID(14, 5) +#define M4U_PORT_L14_CAM_IPUI MTK_M4U_ID(14, 6) +#define M4U_PORT_L14_CAM_IPU2I MTK_M4U_ID(14, 7) +#define M4U_PORT_L14_CAM_IPUO MTK_M4U_ID(14, 8) +#define M4U_PORT_L14_CAM_IPU2O MTK_M4U_ID(14, 9) +#define M4U_PORT_L14_CAM_IPU3O MTK_M4U_ID(14, 10) +#define M4U_PORT_L14_CAM_GCAMSV_A_UFEO_1 MTK_M4U_ID(14, 11) +#define M4U_PORT_L14_CAM_GCAMSV_B_UFEO_1 MTK_M4U_ID(14, 12) +#define M4U_PORT_L14_CAM_PDAI_1 MTK_M4U_ID(14, 13) +#define M4U_PORT_L14_CAM_PDAO MTK_M4U_ID(14, 14) + +/* larb15: null */ + +/* larb16 */ +#define M4U_PORT_L16_CAM_IMGO_R1 MTK_M4U_ID(16, 0) +#define M4U_PORT_L16_CAM_CQI_R1 MTK_M4U_ID(16, 1) +#define M4U_PORT_L16_CAM_CQI_R2 MTK_M4U_ID(16, 2) +#define M4U_PORT_L16_CAM_BPCI_R1 MTK_M4U_ID(16, 3) +#define M4U_PORT_L16_CAM_LSCI_R1 MTK_M4U_ID(16, 4) +#define M4U_PORT_L16_CAM_RAWI_R2 MTK_M4U_ID(16, 5) +#define M4U_PORT_L16_CAM_RAWI_R3 MTK_M4U_ID(16, 6) +#define M4U_PORT_L16_CAM_UFDI_R2 MTK_M4U_ID(16, 7) +#define M4U_PORT_L16_CAM_UFDI_R3 MTK_M4U_ID(16, 8) +#define M4U_PORT_L16_CAM_RAWI_R4 MTK_M4U_ID(16, 9) +#define M4U_PORT_L16_CAM_RAWI_R5 MTK_M4U_ID(16, 10) +#define M4U_PORT_L16_CAM_AAI_R1 MTK_M4U_ID(16, 11) +#define M4U_PORT_L16_CAM_FHO_R1 MTK_M4U_ID(16, 12) +#define M4U_PORT_L16_CAM_AAO_R1 MTK_M4U_ID(16, 13) +#define M4U_PORT_L16_CAM_TSFSO_R1 MTK_M4U_ID(16, 14) +#define M4U_PORT_L16_CAM_FLKO_R1 MTK_M4U_ID(16, 15) + +/* larb17 */ +#define M4U_PORT_L17_CAM_YUVO_R1 MTK_M4U_ID(17, 0) +#define M4U_PORT_L17_CAM_YUVO_R3 MTK_M4U_ID(17, 1) +#define M4U_PORT_L17_CAM_YUVCO_R1 MTK_M4U_ID(17, 2) +#define M4U_PORT_L17_CAM_YUVO_R2 MTK_M4U_ID(17, 3) +#define M4U_PORT_L17_CAM_RZH1N2TO_R1 MTK_M4U_ID(17, 4) +#define M4U_PORT_L17_CAM_DRZS4NO_R1 MTK_M4U_ID(17, 5) +#define M4U_PORT_L17_CAM_TNCSO_R1 MTK_M4U_ID(17, 6) + +/* larb18 */ +#define M4U_PORT_L18_CAM_CCUI MTK_M4U_ID(18, 0) +#define M4U_PORT_L18_CAM_CCUO MTK_M4U_ID(18, 1) +#define M4U_PORT_L18_CAM_CCUI2 MTK_M4U_ID(18, 2) +#define M4U_PORT_L18_CAM_CCUO2 MTK_M4U_ID(18, 3) + +/* larb19 */ +#define M4U_PORT_L19_VENC_RCPU MTK_M4U_ID(19, 0) +#define M4U_PORT_L19_VENC_REC MTK_M4U_ID(19, 1) +#define M4U_PORT_L19_VENC_BSDMA MTK_M4U_ID(19, 2) +#define M4U_PORT_L19_VENC_SV_COMV MTK_M4U_ID(19, 3) +#define M4U_PORT_L19_VENC_RD_COMV MTK_M4U_ID(19, 4) +#define M4U_PORT_L19_VENC_NBM_RDMA MTK_M4U_ID(19, 5) +#define M4U_PORT_L19_VENC_NBM_RDMA_LITE MTK_M4U_ID(19, 6) +#define M4U_PORT_L19_JPGENC_Y_RDMA MTK_M4U_ID(19, 7) +#define M4U_PORT_L19_JPGENC_C_RDMA MTK_M4U_ID(19, 8) +#define M4U_PORT_L19_JPGENC_Q_TABLE MTK_M4U_ID(19, 9) +#define M4U_PORT_L19_VENC_SUB_W_LUMA MTK_M4U_ID(19, 10) +#define M4U_PORT_L19_VENC_FCS_NBM_RDMA MTK_M4U_ID(19, 11) +#define M4U_PORT_L19_JPGENC_BSDMA MTK_M4U_ID(19, 12) +#define M4U_PORT_L19_JPGDEC_WDMA0 MTK_M4U_ID(19, 13) +#define M4U_PORT_L19_JPGDEC_BSDMA0 MTK_M4U_ID(19, 14) +#define M4U_PORT_L19_VENC_NBM_WDMA MTK_M4U_ID(19, 15) +#define M4U_PORT_L19_VENC_NBM_WDMA_LITE MTK_M4U_ID(19, 16) +#define M4U_PORT_L19_VENC_FCS_NBM_WDMA MTK_M4U_ID(19, 17) +#define M4U_PORT_L19_JPGDEC_WDMA1 MTK_M4U_ID(19, 18) +#define M4U_PORT_L19_JPGDEC_BSDMA1 MTK_M4U_ID(19, 19) +#define M4U_PORT_L19_JPGDEC_BUFF_OFFSET1 MTK_M4U_ID(19, 20) +#define M4U_PORT_L19_JPGDEC_BUFF_OFFSET0 MTK_M4U_ID(19, 21) +#define M4U_PORT_L19_VENC_CUR_LUMA MTK_M4U_ID(19, 22) +#define M4U_PORT_L19_VENC_CUR_CHROMA MTK_M4U_ID(19, 23) +#define M4U_PORT_L19_VENC_REF_LUMA MTK_M4U_ID(19, 24) +#define M4U_PORT_L19_VENC_REF_CHROMA MTK_M4U_ID(19, 25) +#define M4U_PORT_L19_VENC_SUB_R_CHROMA MTK_M4U_ID(19, 26) + +/* larb20 */ +#define M4U_PORT_L20_VENC_RCPU MTK_M4U_ID(20, 0) +#define M4U_PORT_L20_VENC_REC MTK_M4U_ID(20, 1) +#define M4U_PORT_L20_VENC_BSDMA MTK_M4U_ID(20, 2) +#define M4U_PORT_L20_VENC_SV_COMV MTK_M4U_ID(20, 3) +#define M4U_PORT_L20_VENC_RD_COMV MTK_M4U_ID(20, 4) +#define M4U_PORT_L20_VENC_NBM_RDMA MTK_M4U_ID(20, 5) +#define M4U_PORT_L20_VENC_NBM_RDMA_LITE MTK_M4U_ID(20, 6) +#define M4U_PORT_L20_JPGENC_Y_RDMA MTK_M4U_ID(20, 7) +#define M4U_PORT_L20_JPGENC_C_RDMA MTK_M4U_ID(20, 8) +#define M4U_PORT_L20_JPGENC_Q_TABLE MTK_M4U_ID(20, 9) +#define M4U_PORT_L20_VENC_SUB_W_LUMA MTK_M4U_ID(20, 10) +#define M4U_PORT_L20_VENC_FCS_NBM_RDMA MTK_M4U_ID(20, 11) +#define M4U_PORT_L20_JPGENC_BSDMA MTK_M4U_ID(20, 12) +#define M4U_PORT_L20_JPGDEC_WDMA0 MTK_M4U_ID(20, 13) +#define M4U_PORT_L20_JPGDEC_BSDMA0 MTK_M4U_ID(20, 14) +#define M4U_PORT_L20_VENC_NBM_WDMA MTK_M4U_ID(20, 15) +#define M4U_PORT_L20_VENC_NBM_WDMA_LITE MTK_M4U_ID(20, 16) +#define M4U_PORT_L20_VENC_FCS_NBM_WDMA MTK_M4U_ID(20, 17) +#define M4U_PORT_L20_JPGDEC_WDMA1 MTK_M4U_ID(20, 18) +#define M4U_PORT_L20_JPGDEC_BSDMA1 MTK_M4U_ID(20, 19) +#define M4U_PORT_L20_JPGDEC_BUFF_OFFSET1 MTK_M4U_ID(20, 20) +#define M4U_PORT_L20_JPGDEC_BUFF_OFFSET0 MTK_M4U_ID(20, 21) +#define M4U_PORT_L20_VENC_CUR_LUMA MTK_M4U_ID(20, 22) +#define M4U_PORT_L20_VENC_CUR_CHROMA MTK_M4U_ID(20, 23) +#define M4U_PORT_L20_VENC_REF_LUMA MTK_M4U_ID(20, 24) +#define M4U_PORT_L20_VENC_REF_CHROMA MTK_M4U_ID(20, 25) +#define M4U_PORT_L20_VENC_SUB_R_CHROMA MTK_M4U_ID(20, 26) + +/* larb21 */ +#define M4U_PORT_L21_VDEC_MC_EXT MTK_M4U_ID(21, 0) +#define M4U_PORT_L21_VDEC_UFO_EXT MTK_M4U_ID(21, 1) +#define M4U_PORT_L21_VDEC_PP_EXT MTK_M4U_ID(21, 2) +#define M4U_PORT_L21_VDEC_PRED_RD_EXT MTK_M4U_ID(21, 3) +#define M4U_PORT_L21_VDEC_PRED_WR_EXT MTK_M4U_ID(21, 4) +#define M4U_PORT_L21_VDEC_PPWRAP_EXT MTK_M4U_ID(21, 5) +#define M4U_PORT_L21_VDEC_TILE_EXT MTK_M4U_ID(21, 6) +#define M4U_PORT_L21_VDEC_VLD_EXT MTK_M4U_ID(21, 7) +#define M4U_PORT_L21_VDEC_VLD2_EXT MTK_M4U_ID(21, 8) +#define M4U_PORT_L21_VDEC_AVC_MV_EXT MTK_M4U_ID(21, 9) + +/* larb22 */ +#define M4U_PORT_L22_VDEC_MC_EXT MTK_M4U_ID(22, 0) +#define M4U_PORT_L22_VDEC_UFO_EXT MTK_M4U_ID(22, 1) +#define M4U_PORT_L22_VDEC_PP_EXT MTK_M4U_ID(22, 2) +#define M4U_PORT_L22_VDEC_PRED_RD_EXT MTK_M4U_ID(22, 3) +#define M4U_PORT_L22_VDEC_PRED_WR_EXT MTK_M4U_ID(22, 4) +#define M4U_PORT_L22_VDEC_PPWRAP_EXT MTK_M4U_ID(22, 5) +#define M4U_PORT_L22_VDEC_TILE_EXT MTK_M4U_ID(22, 6) +#define M4U_PORT_L22_VDEC_VLD_EXT MTK_M4U_ID(22, 7) +#define M4U_PORT_L22_VDEC_VLD2_EXT MTK_M4U_ID(22, 8) +#define M4U_PORT_L22_VDEC_AVC_MV_EXT MTK_M4U_ID(22, 9) + +/* larb23 */ +#define M4U_PORT_L23_VDEC_UFO_ENC_EXT MTK_M4U_ID(23, 0) +#define M4U_PORT_L23_VDEC_RDMA_EXT MTK_M4U_ID(23, 1) + +/* larb24 */ +#define M4U_PORT_L24_VDEC_LAT0_VLD_EXT MTK_M4U_ID(24, 0) +#define M4U_PORT_L24_VDEC_LAT0_VLD2_EXT MTK_M4U_ID(24, 1) +#define M4U_PORT_L24_VDEC_LAT0_AVC_MC_EXT MTK_M4U_ID(24, 2) +#define M4U_PORT_L24_VDEC_LAT0_PRED_RD_EXT MTK_M4U_ID(24, 3) +#define M4U_PORT_L24_VDEC_LAT0_TILE_EXT MTK_M4U_ID(24, 4) +#define M4U_PORT_L24_VDEC_LAT0_WDMA_EXT MTK_M4U_ID(24, 5) +#define M4U_PORT_L24_VDEC_LAT1_VLD_EXT MTK_M4U_ID(24, 6) +#define M4U_PORT_L24_VDEC_LAT1_VLD2_EXT MTK_M4U_ID(24, 7) +#define M4U_PORT_L24_VDEC_LAT1_AVC_MC_EXT MTK_M4U_ID(24, 8) +#define M4U_PORT_L24_VDEC_LAT1_PRED_RD_EXT MTK_M4U_ID(24, 9) +#define M4U_PORT_L24_VDEC_LAT1_TILE_EXT MTK_M4U_ID(24, 10) +#define M4U_PORT_L24_VDEC_LAT1_WDMA_EXT MTK_M4U_ID(24, 11) + +/* larb25 */ +#define M4U_PORT_L25_CAM_MRAW0_LSCI_M1 MTK_M4U_ID(25, 0) +#define M4U_PORT_L25_CAM_MRAW0_CQI_M1 MTK_M4U_ID(25, 1) +#define M4U_PORT_L25_CAM_MRAW0_CQI_M2 MTK_M4U_ID(25, 2) +#define M4U_PORT_L25_CAM_MRAW0_IMGO_M1 MTK_M4U_ID(25, 3) +#define M4U_PORT_L25_CAM_MRAW0_IMGBO_M1 MTK_M4U_ID(25, 4) +#define M4U_PORT_L25_CAM_MRAW2_LSCI_M1 MTK_M4U_ID(25, 5) +#define M4U_PORT_L25_CAM_MRAW2_CQI_M1 MTK_M4U_ID(25, 6) +#define M4U_PORT_L25_CAM_MRAW2_CQI_M2 MTK_M4U_ID(25, 7) +#define M4U_PORT_L25_CAM_MRAW2_IMGO_M1 MTK_M4U_ID(25, 8) +#define M4U_PORT_L25_CAM_MRAW2_IMGBO_M1 MTK_M4U_ID(25, 9) +#define M4U_PORT_L25_CAM_MRAW0_AFO_M1 MTK_M4U_ID(25, 10) +#define M4U_PORT_L25_CAM_MRAW2_AFO_M1 MTK_M4U_ID(25, 11) + +/* larb26 */ +#define M4U_PORT_L26_CAM_MRAW1_LSCI_M1 MTK_M4U_ID(26, 0) +#define M4U_PORT_L26_CAM_MRAW1_CQI_M1 MTK_M4U_ID(26, 1) +#define M4U_PORT_L26_CAM_MRAW1_CQI_M2 MTK_M4U_ID(26, 2) +#define M4U_PORT_L26_CAM_MRAW1_IMGO_M1 MTK_M4U_ID(26, 3) +#define M4U_PORT_L26_CAM_MRAW1_IMGBO_M1 MTK_M4U_ID(26, 4) +#define M4U_PORT_L26_CAM_MRAW3_LSCI_M1 MTK_M4U_ID(26, 5) +#define M4U_PORT_L26_CAM_MRAW3_CQI_M1 MTK_M4U_ID(26, 6) +#define M4U_PORT_L26_CAM_MRAW3_CQI_M2 MTK_M4U_ID(26, 7) +#define M4U_PORT_L26_CAM_MRAW3_IMGO_M1 MTK_M4U_ID(26, 8) +#define M4U_PORT_L26_CAM_MRAW3_IMGBO_M1 MTK_M4U_ID(26, 9) +#define M4U_PORT_L26_CAM_MRAW1_AFO_M1 MTK_M4U_ID(26, 10) +#define M4U_PORT_L26_CAM_MRAW3_AFO_M1 MTK_M4U_ID(26, 11) + +/* larb27 */ +#define M4U_PORT_L27_CAM_IMGO_R1 MTK_M4U_ID(27, 0) +#define M4U_PORT_L27_CAM_CQI_R1 MTK_M4U_ID(27, 1) +#define M4U_PORT_L27_CAM_CQI_R2 MTK_M4U_ID(27, 2) +#define M4U_PORT_L27_CAM_BPCI_R1 MTK_M4U_ID(27, 3) +#define M4U_PORT_L27_CAM_LSCI_R1 MTK_M4U_ID(27, 4) +#define M4U_PORT_L27_CAM_RAWI_R2 MTK_M4U_ID(27, 5) +#define M4U_PORT_L27_CAM_RAWI_R3 MTK_M4U_ID(27, 6) +#define M4U_PORT_L27_CAM_UFDI_R2 MTK_M4U_ID(27, 7) +#define M4U_PORT_L27_CAM_UFDI_R3 MTK_M4U_ID(27, 8) +#define M4U_PORT_L27_CAM_RAWI_R4 MTK_M4U_ID(27, 9) +#define M4U_PORT_L27_CAM_RAWI_R5 MTK_M4U_ID(27, 10) +#define M4U_PORT_L27_CAM_AAI_R1 MTK_M4U_ID(27, 11) +#define M4U_PORT_L27_CAM_FHO_R1 MTK_M4U_ID(27, 12) +#define M4U_PORT_L27_CAM_AAO_R1 MTK_M4U_ID(27, 13) +#define M4U_PORT_L27_CAM_TSFSO_R1 MTK_M4U_ID(27, 14) +#define M4U_PORT_L27_CAM_FLKO_R1 MTK_M4U_ID(27, 15) + +/* larb28 */ +#define M4U_PORT_L28_CAM_YUVO_R1 MTK_M4U_ID(28, 0) +#define M4U_PORT_L28_CAM_YUVO_R3 MTK_M4U_ID(28, 1) +#define M4U_PORT_L28_CAM_YUVCO_R1 MTK_M4U_ID(28, 2) +#define M4U_PORT_L28_CAM_YUVO_R2 MTK_M4U_ID(28, 3) +#define M4U_PORT_L28_CAM_RZH1N2TO_R1 MTK_M4U_ID(28, 4) +#define M4U_PORT_L28_CAM_DRZS4NO_R1 MTK_M4U_ID(28, 5) +#define M4U_PORT_L28_CAM_TNCSO_R1 MTK_M4U_ID(28, 6) + +/* Infra iommu ports */ +/* PCIe1: read: BIT16; write BIT17. */ +#define IOMMU_PORT_INFRA_PCIE1 MTK_IFAIOMMU_PERI_ID(16) +/* PCIe0: read: BIT18; write BIT19. */ +#define IOMMU_PORT_INFRA_PCIE0 MTK_IFAIOMMU_PERI_ID(18) +#define IOMMU_PORT_INFRA_SSUSB_P3_R MTK_IFAIOMMU_PERI_ID(20) +#define IOMMU_PORT_INFRA_SSUSB_P3_W MTK_IFAIOMMU_PERI_ID(21) +#define IOMMU_PORT_INFRA_SSUSB_P2_R MTK_IFAIOMMU_PERI_ID(22) +#define IOMMU_PORT_INFRA_SSUSB_P2_W MTK_IFAIOMMU_PERI_ID(23) +#define IOMMU_PORT_INFRA_SSUSB_P1_1_R MTK_IFAIOMMU_PERI_ID(24) +#define IOMMU_PORT_INFRA_SSUSB_P1_1_W MTK_IFAIOMMU_PERI_ID(25) +#define IOMMU_PORT_INFRA_SSUSB_P1_0_R MTK_IFAIOMMU_PERI_ID(26) +#define IOMMU_PORT_INFRA_SSUSB_P1_0_W MTK_IFAIOMMU_PERI_ID(27) +#define IOMMU_PORT_INFRA_SSUSB2_R MTK_IFAIOMMU_PERI_ID(28) +#define IOMMU_PORT_INFRA_SSUSB2_W MTK_IFAIOMMU_PERI_ID(29) +#define IOMMU_PORT_INFRA_SSUSB_R MTK_IFAIOMMU_PERI_ID(30) +#define IOMMU_PORT_INFRA_SSUSB_W MTK_IFAIOMMU_PERI_ID(31) + +#endif diff --git a/include/dt-bindings/memory/mtk-memory-port.h b/include/dt-bindings/memory/mtk-memory-port.h index 7d64103209afcdc75b689441fe49d9172ee77325..2f68a0511a2578e2e4354b50b64b1380357b657b 100644 --- a/include/dt-bindings/memory/mtk-memory-port.h +++ b/include/dt-bindings/memory/mtk-memory-port.h @@ -12,4 +12,6 @@ #define MTK_M4U_TO_LARB(id) (((id) >> 5) & 0x1f) #define MTK_M4U_TO_PORT(id) ((id) & 0x1f) +#define MTK_IFAIOMMU_PERI_ID(port) MTK_M4U_ID(0, port) + #endif diff --git a/include/dt-bindings/pinctrl/mt6795-pinfunc.h b/include/dt-bindings/pinctrl/mt6795-pinfunc.h new file mode 100644 index 0000000000000000000000000000000000000000..bd1c5a9fad069f19512eba718452ccdf2edb04ee --- /dev/null +++ b/include/dt-bindings/pinctrl/mt6795-pinfunc.h @@ -0,0 +1,908 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* + * Copyright (c) 2022 Collabora Ltd. + * Author: AngeloGioacchino Del Regno + */ + +#ifndef __DTS_MT8173_PINFUNC_H +#define __DTS_MT8173_PINFUNC_H + +#include + +#define PINMUX_GPIO0__FUNC_GPIO0 (MTK_PIN_NO(0) | 0) +#define PINMUX_GPIO0__FUNC_IRDA_PDN (MTK_PIN_NO(0) | 1) +#define PINMUX_GPIO0__FUNC_I2S1_WS (MTK_PIN_NO(0) | 2) +#define PINMUX_GPIO0__FUNC_TDD_TMS (MTK_PIN_NO(0) | 4) +#define PINMUX_GPIO0__FUNC_UTXD0 (MTK_PIN_NO(0) | 5) + +#define PINMUX_GPIO1__FUNC_GPIO1 (MTK_PIN_NO(1) | 0) +#define PINMUX_GPIO1__FUNC_IRDA_RXD (MTK_PIN_NO(1) | 1) +#define PINMUX_GPIO1__FUNC_I2S1_BCK (MTK_PIN_NO(1) | 2) +#define PINMUX_GPIO1__FUNC_SDA4 (MTK_PIN_NO(1) | 3) +#define PINMUX_GPIO1__FUNC_TDD_TCK (MTK_PIN_NO(1) | 4) +#define PINMUX_GPIO1__FUNC_URXD0 (MTK_PIN_NO(1) | 5) + +#define PINMUX_GPIO2__FUNC_GPIO2 (MTK_PIN_NO(2) | 0) +#define PINMUX_GPIO2__FUNC_IRDA_TXD (MTK_PIN_NO(2) | 1) +#define PINMUX_GPIO2__FUNC_I2S1_MCK (MTK_PIN_NO(2) | 2) +#define PINMUX_GPIO2__FUNC_SCL4 (MTK_PIN_NO(2) | 3) +#define PINMUX_GPIO2__FUNC_TDD_TDI (MTK_PIN_NO(2) | 4) +#define PINMUX_GPIO2__FUNC_UTXD3 (MTK_PIN_NO(2) | 5) + +#define PINMUX_GPIO3__FUNC_GPIO3 (MTK_PIN_NO(3) | 0) +#define PINMUX_GPIO3__FUNC_DSI1_TE (MTK_PIN_NO(3) | 1) +#define PINMUX_GPIO3__FUNC_I2S1_DO_1 (MTK_PIN_NO(3) | 2) +#define PINMUX_GPIO3__FUNC_SDA3 (MTK_PIN_NO(3) | 3) +#define PINMUX_GPIO3__FUNC_TDD_TDO (MTK_PIN_NO(3) | 4) +#define PINMUX_GPIO3__FUNC_URXD3 (MTK_PIN_NO(3) | 5) + +#define PINMUX_GPIO4__FUNC_GPIO4 (MTK_PIN_NO(4) | 0) +#define PINMUX_GPIO4__FUNC_DISP_PWM1 (MTK_PIN_NO(4) | 1) +#define PINMUX_GPIO4__FUNC_I2S1_DO_2 (MTK_PIN_NO(4) | 2) +#define PINMUX_GPIO4__FUNC_SCL3 (MTK_PIN_NO(4) | 3) +#define PINMUX_GPIO4__FUNC_TDD_TRSTN (MTK_PIN_NO(4) | 4) + +#define PINMUX_GPIO5__FUNC_GPIO5 (MTK_PIN_NO(5) | 0) +#define PINMUX_GPIO5__FUNC_PCM1_CLK (MTK_PIN_NO(5) | 1) +#define PINMUX_GPIO5__FUNC_I2S2_WS (MTK_PIN_NO(5) | 2) +#define PINMUX_GPIO5__FUNC_SPI_CK_3 (MTK_PIN_NO(5) | 3) +#define PINMUX_GPIO5__FUNC_LTE_MD32_JTAG_TMS (MTK_PIN_NO(5) | 4) +#define PINMUX_GPIO5__FUNC_AP_MD32_JTAG_TMS (MTK_PIN_NO(5) | 5) + +#define PINMUX_GPIO6__FUNC_GPIO6 (MTK_PIN_NO(6) | 0) +#define PINMUX_GPIO6__FUNC_PCM1_SYNC (MTK_PIN_NO(6) | 1) +#define PINMUX_GPIO6__FUNC_I2S2_BCK (MTK_PIN_NO(6) | 2) +#define PINMUX_GPIO6__FUNC_SPI_MI_3 (MTK_PIN_NO(6) | 3) +#define PINMUX_GPIO6__FUNC_LTE_MD32_JTAG_TCK (MTK_PIN_NO(6) | 4) +#define PINMUX_GPIO6__FUNC_AP_MD32_JTAG_TCK (MTK_PIN_NO(6) | 5) + +#define PINMUX_GPIO7__FUNC_GPIO7 (MTK_PIN_NO(7) | 0) +#define PINMUX_GPIO7__FUNC_PCM1_DI (MTK_PIN_NO(7) | 1) +#define PINMUX_GPIO7__FUNC_I2S2_DI_1 (MTK_PIN_NO(7) | 2) +#define PINMUX_GPIO7__FUNC_SPI_MO_3 (MTK_PIN_NO(7) | 3) +#define PINMUX_GPIO7__FUNC_LTE_MD32_JTAG_TDI (MTK_PIN_NO(7) | 4) +#define PINMUX_GPIO7__FUNC_AP_MD32_JTAG_TDI (MTK_PIN_NO(7) | 5) + +#define PINMUX_GPIO8__FUNC_GPIO8 (MTK_PIN_NO(8) | 0) +#define PINMUX_GPIO8__FUNC_PCM1_DO (MTK_PIN_NO(8) | 1) +#define PINMUX_GPIO8__FUNC_I2S2_DI_2 (MTK_PIN_NO(8) | 2) +#define PINMUX_GPIO8__FUNC_SPI_CS_3 (MTK_PIN_NO(8) | 3) +#define PINMUX_GPIO8__FUNC_LTE_MD32_JTAG_TDO (MTK_PIN_NO(8) | 4) +#define PINMUX_GPIO8__FUNC_AP_MD32_JTAG_TDO (MTK_PIN_NO(8) | 5) + +#define PINMUX_GPIO9__FUNC_GPIO9 (MTK_PIN_NO(9) | 0) +#define PINMUX_GPIO9__FUNC_USB_DRVVBUS (MTK_PIN_NO(9) | 1) +#define PINMUX_GPIO9__FUNC_I2S2_MCK (MTK_PIN_NO(9) | 2) +#define PINMUX_GPIO9__FUNC_LTE_MD32_JTAG_TRST (MTK_PIN_NO(9) | 4) +#define PINMUX_GPIO9__FUNC_AP_MD32_JTAG_TRST (MTK_PIN_NO(9) | 5) + +#define PINMUX_GPIO10__FUNC_GPIO10 (MTK_PIN_NO(10) | 0) +#define PINMUX_GPIO10__FUNC_I2S0_WS (MTK_PIN_NO(10) | 2) + +#define PINMUX_GPIO11__FUNC_GPIO11 (MTK_PIN_NO(11) | 0) +#define PINMUX_GPIO11__FUNC_I2S0_BCK (MTK_PIN_NO(11) | 2) + +#define PINMUX_GPIO12__FUNC_GPIO12 (MTK_PIN_NO(12) | 0) +#define PINMUX_GPIO12__FUNC_I2S0_MCK (MTK_PIN_NO(12) | 2) + +#define PINMUX_GPIO13__FUNC_GPIO13 (MTK_PIN_NO(13) | 0) +#define PINMUX_GPIO13__FUNC_I2S0_DO (MTK_PIN_NO(13) | 2) + +#define PINMUX_GPIO14__FUNC_GPIO14 (MTK_PIN_NO(14) | 0) +#define PINMUX_GPIO14__FUNC_I2S0_DI (MTK_PIN_NO(14) | 2) +#define PINMUX_GPIO14__FUNC_DISP_PWM1 (MTK_PIN_NO(14) | 3) +#define PINMUX_GPIO14__FUNC_PWM4 (MTK_PIN_NO(14) | 4) +#define PINMUX_GPIO14__FUNC_IRDA_RXD (MTK_PIN_NO(14) | 5) +#define PINMUX_GPIO14__FUNC_I2S1_BCK (MTK_PIN_NO(14) | 6) + +#define PINMUX_GPIO15__FUNC_GPIO15 (MTK_PIN_NO(15) | 0) +#define PINMUX_GPIO15__FUNC_DSI1_TE (MTK_PIN_NO(15) | 2) +#define PINMUX_GPIO15__FUNC_USB_DRVVBUS (MTK_PIN_NO(15) | 3) +#define PINMUX_GPIO15__FUNC_PWM5 (MTK_PIN_NO(15) | 4) +#define PINMUX_GPIO15__FUNC_IRDA_TXD (MTK_PIN_NO(15) | 5) +#define PINMUX_GPIO15__FUNC_I2S1_MCK (MTK_PIN_NO(15) | 6) + +#define PINMUX_GPIO16__FUNC_GPIO16 (MTK_PIN_NO(16) | 0) +#define PINMUX_GPIO16__FUNC_IDDIG (MTK_PIN_NO(16) | 1) +#define PINMUX_GPIO16__FUNC_FLASH (MTK_PIN_NO(16) | 2) +#define PINMUX_GPIO16__FUNC_EXT_FRAME_SYNC (MTK_PIN_NO(16) | 3) +#define PINMUX_GPIO16__FUNC_PWM5 (MTK_PIN_NO(16) | 4) + +#define PINMUX_GPIO17__FUNC_GPIO17 (MTK_PIN_NO(17) | 0) +#define PINMUX_GPIO17__FUNC_SIM1_SCLK (MTK_PIN_NO(17) | 1) +#define PINMUX_GPIO17__FUNC_SIM2_SCLK (MTK_PIN_NO(17) | 2) + +#define PINMUX_GPIO18__FUNC_GPIO18 (MTK_PIN_NO(18) | 0) +#define PINMUX_GPIO18__FUNC_SIM1_SRST (MTK_PIN_NO(18) | 1) +#define PINMUX_GPIO18__FUNC_SIM2_SRST (MTK_PIN_NO(18) | 2) + +#define PINMUX_GPIO19__FUNC_GPIO19 (MTK_PIN_NO(19) | 0) +#define PINMUX_GPIO19__FUNC_SIM1_SDAT (MTK_PIN_NO(19) | 1) +#define PINMUX_GPIO19__FUNC_SIM2_SDAT (MTK_PIN_NO(19) | 2) + +#define PINMUX_GPIO20__FUNC_GPIO20 (MTK_PIN_NO(20) | 0) +#define PINMUX_GPIO20__FUNC_SIM2_SCLK (MTK_PIN_NO(20) | 1) +#define PINMUX_GPIO20__FUNC_SIM1_SCLK (MTK_PIN_NO(20) | 2) + +#define PINMUX_GPIO21__FUNC_GPIO21 (MTK_PIN_NO(21) | 0) +#define PINMUX_GPIO21__FUNC_SIM2_SRST (MTK_PIN_NO(21) | 1) +#define PINMUX_GPIO21__FUNC_SIM1_SRST (MTK_PIN_NO(21) | 2) + +#define PINMUX_GPIO22__FUNC_GPIO22 (MTK_PIN_NO(22) | 0) +#define PINMUX_GPIO22__FUNC_SIM2_SDAT (MTK_PIN_NO(22) | 1) +#define PINMUX_GPIO22__FUNC_SIM1_SDAT (MTK_PIN_NO(22) | 2) + +#define PINMUX_GPIO23__FUNC_GPIO23 (MTK_PIN_NO(23) | 0) +#define PINMUX_GPIO23__FUNC_MSDC3_DAT0 (MTK_PIN_NO(23) | 1) + +#define PINMUX_GPIO24__FUNC_GPIO24 (MTK_PIN_NO(24) | 0) +#define PINMUX_GPIO24__FUNC_MSDC3_DAT1 (MTK_PIN_NO(24) | 1) + +#define PINMUX_GPIO25__FUNC_GPIO25 (MTK_PIN_NO(25) | 0) +#define PINMUX_GPIO25__FUNC_MSDC3_DAT2 (MTK_PIN_NO(25) | 1) + +#define PINMUX_GPIO26__FUNC_GPIO26 (MTK_PIN_NO(26) | 0) +#define PINMUX_GPIO26__FUNC_MSDC3_DAT3 (MTK_PIN_NO(26) | 1) + +#define PINMUX_GPIO27__FUNC_GPIO27 (MTK_PIN_NO(27) | 0) +#define PINMUX_GPIO27__FUNC_MSDC3_CLK (MTK_PIN_NO(27) | 1) + +#define PINMUX_GPIO28__FUNC_GPIO28 (MTK_PIN_NO(28) | 0) +#define PINMUX_GPIO28__FUNC_MSDC3_CMD (MTK_PIN_NO(28) | 1) + +#define PINMUX_GPIO29__FUNC_GPIO29 (MTK_PIN_NO(29) | 0) +#define PINMUX_GPIO29__FUNC_PTA_RXD (MTK_PIN_NO(29) | 1) +#define PINMUX_GPIO29__FUNC_UCTS2 (MTK_PIN_NO(29) | 2) + +#define PINMUX_GPIO30__FUNC_GPIO30 (MTK_PIN_NO(30) | 0) +#define PINMUX_GPIO30__FUNC_PTA_TXD (MTK_PIN_NO(30) | 1) +#define PINMUX_GPIO30__FUNC_URTS2 (MTK_PIN_NO(30) | 2) + +#define PINMUX_GPIO31__FUNC_GPIO31 (MTK_PIN_NO(31) | 0) +#define PINMUX_GPIO31__FUNC_URXD2 (MTK_PIN_NO(31) | 1) +#define PINMUX_GPIO31__FUNC_UTXD2 (MTK_PIN_NO(31) | 2) + +#define PINMUX_GPIO32__FUNC_GPIO32 (MTK_PIN_NO(32) | 0) +#define PINMUX_GPIO32__FUNC_UTXD2 (MTK_PIN_NO(32) | 1) +#define PINMUX_GPIO32__FUNC_URXD2 (MTK_PIN_NO(32) | 2) + +#define PINMUX_GPIO33__FUNC_GPIO33 (MTK_PIN_NO(33) | 0) +#define PINMUX_GPIO33__FUNC_MRG_CLK (MTK_PIN_NO(33) | 1) +#define PINMUX_GPIO33__FUNC_PCM0_CLK (MTK_PIN_NO(33) | 2) + +#define PINMUX_GPIO34__FUNC_GPIO34 (MTK_PIN_NO(34) | 0) +#define PINMUX_GPIO34__FUNC_MRG_DI (MTK_PIN_NO(34) | 1) +#define PINMUX_GPIO34__FUNC_PCM0_DI (MTK_PIN_NO(34) | 2) + +#define PINMUX_GPIO35__FUNC_GPIO35 (MTK_PIN_NO(35) | 0) +#define PINMUX_GPIO35__FUNC_MRG_DO (MTK_PIN_NO(35) | 1) +#define PINMUX_GPIO35__FUNC_PCM0_DO (MTK_PIN_NO(35) | 2) + +#define PINMUX_GPIO36__FUNC_GPIO36 (MTK_PIN_NO(36) | 0) +#define PINMUX_GPIO36__FUNC_MRG_SYNC (MTK_PIN_NO(36) | 1) +#define PINMUX_GPIO36__FUNC_PCM0_SYNC (MTK_PIN_NO(36) | 2) + +#define PINMUX_GPIO37__FUNC_GPIO37 (MTK_PIN_NO(37) | 0) +#define PINMUX_GPIO37__FUNC_GPS_SYNC (MTK_PIN_NO(37) | 1) + +#define PINMUX_GPIO38__FUNC_GPIO38 (MTK_PIN_NO(38) | 0) +#define PINMUX_GPIO38__FUNC_DAIRSTB (MTK_PIN_NO(38) | 1) + +#define PINMUX_GPIO39__FUNC_GPIO39 (MTK_PIN_NO(39) | 0) +#define PINMUX_GPIO39__FUNC_CM2MCLK (MTK_PIN_NO(39) | 1) + +#define PINMUX_GPIO40__FUNC_GPIO40 (MTK_PIN_NO(40) | 0) +#define PINMUX_GPIO40__FUNC_CM3MCLK (MTK_PIN_NO(40) | 1) +#define PINMUX_GPIO40__FUNC_IRDA_PDN (MTK_PIN_NO(40) | 2) +#define PINMUX_GPIO40__FUNC_PWM6 (MTK_PIN_NO(40) | 3) +#define PINMUX_GPIO40__FUNC_I2S1_WS (MTK_PIN_NO(40) | 4) + +#define PINMUX_GPIO41__FUNC_GPIO41 (MTK_PIN_NO(41) | 0) +#define PINMUX_GPIO41__FUNC_CMPCLK (MTK_PIN_NO(41) | 1) +#define PINMUX_GPIO41__FUNC_CMCSK (MTK_PIN_NO(41) | 2) +#define PINMUX_GPIO41__FUNC_FLASH (MTK_PIN_NO(41) | 3) + +#define PINMUX_GPIO42__FUNC_GPIO42 (MTK_PIN_NO(42) | 0) +#define PINMUX_GPIO42__FUNC_CMMCLK (MTK_PIN_NO(42) | 1) + +#define PINMUX_GPIO43__FUNC_GPIO43 (MTK_PIN_NO(43) | 0) +#define PINMUX_GPIO43__FUNC_SDA2 (MTK_PIN_NO(43) | 1) + +#define PINMUX_GPIO44__FUNC_GPIO44 (MTK_PIN_NO(44) | 0) +#define PINMUX_GPIO44__FUNC_SCL2 (MTK_PIN_NO(44) | 1) + +#define PINMUX_GPIO45__FUNC_GPIO45 (MTK_PIN_NO(45) | 0) +#define PINMUX_GPIO45__FUNC_SDA0 (MTK_PIN_NO(45) | 1) + +#define PINMUX_GPIO46__FUNC_GPIO46 (MTK_PIN_NO(46) | 0) +#define PINMUX_GPIO46__FUNC_SCL0 (MTK_PIN_NO(46) | 1) + +#define PINMUX_GPIO47__FUNC_GPIO47 (MTK_PIN_NO(47) | 0) +#define PINMUX_GPIO47__FUNC_BPI_BUS0 (MTK_PIN_NO(47) | 1) + +#define PINMUX_GPIO48__FUNC_GPIO48 (MTK_PIN_NO(48) | 0) +#define PINMUX_GPIO48__FUNC_BPI_BUS1 (MTK_PIN_NO(48) | 1) + +#define PINMUX_GPIO49__FUNC_GPIO49 (MTK_PIN_NO(49) | 0) +#define PINMUX_GPIO49__FUNC_BPI_BUS2 (MTK_PIN_NO(49) | 1) + +#define PINMUX_GPIO50__FUNC_GPIO50 (MTK_PIN_NO(50) | 0) +#define PINMUX_GPIO50__FUNC_BPI_BUS3 (MTK_PIN_NO(50) | 1) + +#define PINMUX_GPIO51__FUNC_GPIO51 (MTK_PIN_NO(51) | 0) +#define PINMUX_GPIO51__FUNC_BPI_BUS4 (MTK_PIN_NO(51) | 1) + +#define PINMUX_GPIO52__FUNC_GPIO52 (MTK_PIN_NO(52) | 0) +#define PINMUX_GPIO52__FUNC_BPI_BUS5 (MTK_PIN_NO(52) | 1) + +#define PINMUX_GPIO53__FUNC_GPIO53 (MTK_PIN_NO(53) | 0) +#define PINMUX_GPIO53__FUNC_BPI_BUS6 (MTK_PIN_NO(53) | 1) + +#define PINMUX_GPIO54__FUNC_GPIO54 (MTK_PIN_NO(54) | 0) +#define PINMUX_GPIO54__FUNC_BPI_BUS7 (MTK_PIN_NO(54) | 1) + +#define PINMUX_GPIO55__FUNC_GPIO55 (MTK_PIN_NO(55) | 0) +#define PINMUX_GPIO55__FUNC_BPI_BUS8 (MTK_PIN_NO(55) | 1) + +#define PINMUX_GPIO56__FUNC_GPIO56 (MTK_PIN_NO(56) | 0) +#define PINMUX_GPIO56__FUNC_BPI_BUS9 (MTK_PIN_NO(56) | 1) + +#define PINMUX_GPIO57__FUNC_GPIO57 (MTK_PIN_NO(57) | 0) +#define PINMUX_GPIO57__FUNC_BPI_BUS10 (MTK_PIN_NO(57) | 1) + +#define PINMUX_GPIO58__FUNC_GPIO58 (MTK_PIN_NO(58) | 0) +#define PINMUX_GPIO58__FUNC_BPI_BUS11 (MTK_PIN_NO(58) | 1) + +#define PINMUX_GPIO59__FUNC_GPIO59 (MTK_PIN_NO(59) | 0) +#define PINMUX_GPIO59__FUNC_BPI_BUS12 (MTK_PIN_NO(59) | 1) + +#define PINMUX_GPIO60__FUNC_GPIO60 (MTK_PIN_NO(60) | 0) +#define PINMUX_GPIO60__FUNC_BPI_BUS13 (MTK_PIN_NO(60) | 1) + +#define PINMUX_GPIO61__FUNC_GPIO61 (MTK_PIN_NO(61) | 0) +#define PINMUX_GPIO61__FUNC_BPI_BUS14 (MTK_PIN_NO(61) | 1) + +#define PINMUX_GPIO62__FUNC_GPIO62 (MTK_PIN_NO(62) | 0) +#define PINMUX_GPIO62__FUNC_RFIC1_BSI_CK (MTK_PIN_NO(62) | 1) + +#define PINMUX_GPIO63__FUNC_GPIO63 (MTK_PIN_NO(63) | 0) +#define PINMUX_GPIO63__FUNC_RFIC1_BSI_D0 (MTK_PIN_NO(63) | 1) + +#define PINMUX_GPIO64__FUNC_GPIO64 (MTK_PIN_NO(64) | 0) +#define PINMUX_GPIO64__FUNC_RFIC1_BSI_D1 (MTK_PIN_NO(64) | 1) + +#define PINMUX_GPIO65__FUNC_GPIO65 (MTK_PIN_NO(65) | 0) +#define PINMUX_GPIO65__FUNC_RFIC1_BSI_D2 (MTK_PIN_NO(65) | 1) + +#define PINMUX_GPIO66__FUNC_GPIO66 (MTK_PIN_NO(66) | 0) +#define PINMUX_GPIO66__FUNC_RFIC1_BSI_CS (MTK_PIN_NO(66) | 1) + +#define PINMUX_GPIO67__FUNC_GPIO67 (MTK_PIN_NO(67) | 0) +#define PINMUX_GPIO67__FUNC_TD_TXBPI (MTK_PIN_NO(67) | 1) + +#define PINMUX_GPIO68__FUNC_GPIO68 (MTK_PIN_NO(68) | 0) +#define PINMUX_GPIO68__FUNC_RFIC0_BSI_CK (MTK_PIN_NO(68) | 1) + +#define PINMUX_GPIO69__FUNC_GPIO69 (MTK_PIN_NO(69) | 0) +#define PINMUX_GPIO69__FUNC_RFIC0_BSI_D0 (MTK_PIN_NO(69) | 1) + +#define PINMUX_GPIO70__FUNC_GPIO70 (MTK_PIN_NO(70) | 0) +#define PINMUX_GPIO70__FUNC_RFIC0_BSI_D1 (MTK_PIN_NO(70) | 1) + +#define PINMUX_GPIO71__FUNC_GPIO71 (MTK_PIN_NO(71) | 0) +#define PINMUX_GPIO71__FUNC_RFIC0_BSI_D2 (MTK_PIN_NO(71) | 1) + +#define PINMUX_GPIO72__FUNC_GPIO72 (MTK_PIN_NO(72) | 0) +#define PINMUX_GPIO72__FUNC_RFIC0_BSI_CS (MTK_PIN_NO(72) | 1) + +#define PINMUX_GPIO73__FUNC_GPIO73 (MTK_PIN_NO(73) | 0) +#define PINMUX_GPIO73__FUNC_MISC_BSI_DO (MTK_PIN_NO(73) | 1) + +#define PINMUX_GPIO74__FUNC_GPIO74 (MTK_PIN_NO(74) | 0) +#define PINMUX_GPIO74__FUNC_MISC_BSI_CK (MTK_PIN_NO(74) | 1) + +#define PINMUX_GPIO75__FUNC_GPIO75 (MTK_PIN_NO(75) | 0) +#define PINMUX_GPIO75__FUNC_MISC_BSI_CS0B (MTK_PIN_NO(75) | 1) +#define PINMUX_GPIO75__FUNC_MIPI1_SCLK (MTK_PIN_NO(75) | 2) + +#define PINMUX_GPIO76__FUNC_GPIO76 (MTK_PIN_NO(76) | 0) +#define PINMUX_GPIO76__FUNC_MISC_BSI_CS1B (MTK_PIN_NO(76) | 1) + +#define PINMUX_GPIO77__FUNC_GPIO77 (MTK_PIN_NO(77) | 0) +#define PINMUX_GPIO77__FUNC_MISC_BSI_DI (MTK_PIN_NO(77) | 1) +#define PINMUX_GPIO77__FUNC_MIPI1_SDATA (MTK_PIN_NO(77) | 2) + +#define PINMUX_GPIO78__FUNC_GPIO78 (MTK_PIN_NO(78) | 0) +#define PINMUX_GPIO78__FUNC_LTE_TXBPI (MTK_PIN_NO(78) | 1) + +#define PINMUX_GPIO79__FUNC_GPIO79 (MTK_PIN_NO(79) | 0) +#define PINMUX_GPIO79__FUNC_BPI_BUS15 (MTK_PIN_NO(79) | 1) + +#define PINMUX_GPIO80__FUNC_GPIO80 (MTK_PIN_NO(80) | 0) +#define PINMUX_GPIO80__FUNC_BPI_BUS16 (MTK_PIN_NO(80) | 1) + +#define PINMUX_GPIO81__FUNC_GPIO81 (MTK_PIN_NO(81) | 0) +#define PINMUX_GPIO81__FUNC_BPI_BUS17 (MTK_PIN_NO(81) | 1) + +#define PINMUX_GPIO82__FUNC_GPIO82 (MTK_PIN_NO(82) | 0) +#define PINMUX_GPIO82__FUNC_BPI_BUS18 (MTK_PIN_NO(82) | 1) + +#define PINMUX_GPIO83__FUNC_GPIO83 (MTK_PIN_NO(83) | 0) +#define PINMUX_GPIO83__FUNC_BPI_BUS19 (MTK_PIN_NO(83) | 1) + +#define PINMUX_GPIO84__FUNC_GPIO84 (MTK_PIN_NO(84) | 0) +#define PINMUX_GPIO84__FUNC_BPI_BUS20 (MTK_PIN_NO(84) | 1) + +#define PINMUX_GPIO85__FUNC_GPIO85 (MTK_PIN_NO(85) | 0) +#define PINMUX_GPIO85__FUNC_BPI_BUS21 (MTK_PIN_NO(85) | 1) + +#define PINMUX_GPIO86__FUNC_GPIO86 (MTK_PIN_NO(86) | 0) +#define PINMUX_GPIO86__FUNC_BPI_BUS22 (MTK_PIN_NO(86) | 1) + +#define PINMUX_GPIO87__FUNC_GPIO87 (MTK_PIN_NO(87) | 0) +#define PINMUX_GPIO87__FUNC_BPI_BUS23 (MTK_PIN_NO(87) | 1) + +#define PINMUX_GPIO88__FUNC_GPIO88 (MTK_PIN_NO(88) | 0) +#define PINMUX_GPIO88__FUNC_BPI_BUS24 (MTK_PIN_NO(88) | 1) + +#define PINMUX_GPIO89__FUNC_GPIO89 (MTK_PIN_NO(89) | 0) +#define PINMUX_GPIO89__FUNC_BPI_BUS25 (MTK_PIN_NO(89) | 1) + +#define PINMUX_GPIO90__FUNC_GPIO90 (MTK_PIN_NO(90) | 0) +#define PINMUX_GPIO90__FUNC_BPI_BUS26 (MTK_PIN_NO(90) | 1) + +#define PINMUX_GPIO91__FUNC_GPIO91 (MTK_PIN_NO(91) | 0) +#define PINMUX_GPIO91__FUNC_BPI_BUS27 (MTK_PIN_NO(91) | 1) + +#define PINMUX_GPIO92__FUNC_GPIO92 (MTK_PIN_NO(92) | 0) +#define PINMUX_GPIO92__FUNC_PCM1_CLK (MTK_PIN_NO(92) | 1) +#define PINMUX_GPIO92__FUNC_I2S0_BCK (MTK_PIN_NO(92) | 2) +#define PINMUX_GPIO92__FUNC_NLD6 (MTK_PIN_NO(92) | 3) + +#define PINMUX_GPIO93__FUNC_GPIO93 (MTK_PIN_NO(93) | 0) +#define PINMUX_GPIO93__FUNC_PCM1_SYNC (MTK_PIN_NO(93) | 1) +#define PINMUX_GPIO93__FUNC_I2S0_WS (MTK_PIN_NO(93) | 2) +#define PINMUX_GPIO93__FUNC_NLD7 (MTK_PIN_NO(93) | 3) + +#define PINMUX_GPIO94__FUNC_GPIO94 (MTK_PIN_NO(94) | 0) +#define PINMUX_GPIO94__FUNC_PCM1_DI (MTK_PIN_NO(94) | 1) +#define PINMUX_GPIO94__FUNC_I2S0_DI (MTK_PIN_NO(94) | 2) +#define PINMUX_GPIO94__FUNC_NREB (MTK_PIN_NO(94) | 3) + +#define PINMUX_GPIO95__FUNC_GPIO95 (MTK_PIN_NO(95) | 0) +#define PINMUX_GPIO95__FUNC_PCM1_DO (MTK_PIN_NO(95) | 1) +#define PINMUX_GPIO95__FUNC_I2S0_DO (MTK_PIN_NO(95) | 2) +#define PINMUX_GPIO95__FUNC_NRNB0 (MTK_PIN_NO(95) | 3) + +#define PINMUX_GPIO96__FUNC_GPIO96 (MTK_PIN_NO(96) | 0) +#define PINMUX_GPIO96__FUNC_URXD1 (MTK_PIN_NO(96) | 1) +#define PINMUX_GPIO96__FUNC_UTXD1 (MTK_PIN_NO(96) | 2) +#define PINMUX_GPIO96__FUNC_NWEB (MTK_PIN_NO(96) | 3) + +#define PINMUX_GPIO97__FUNC_GPIO97 (MTK_PIN_NO(97) | 0) +#define PINMUX_GPIO97__FUNC_UTXD1 (MTK_PIN_NO(97) | 1) +#define PINMUX_GPIO97__FUNC_URXD1 (MTK_PIN_NO(97) | 2) +#define PINMUX_GPIO97__FUNC_NCEB0 (MTK_PIN_NO(97) | 3) + +#define PINMUX_GPIO98__FUNC_GPIO98 (MTK_PIN_NO(98) | 0) +#define PINMUX_GPIO98__FUNC_URTS1 (MTK_PIN_NO(98) | 1) +#define PINMUX_GPIO98__FUNC_UCTS1 (MTK_PIN_NO(98) | 2) +#define PINMUX_GPIO98__FUNC_NALE (MTK_PIN_NO(98) | 3) + +#define PINMUX_GPIO99__FUNC_GPIO99 (MTK_PIN_NO(99) | 0) +#define PINMUX_GPIO99__FUNC_UCTS1 (MTK_PIN_NO(99) | 1) +#define PINMUX_GPIO99__FUNC_URTS1 (MTK_PIN_NO(99) | 2) +#define PINMUX_GPIO99__FUNC_NCLE (MTK_PIN_NO(99) | 3) + +#define PINMUX_GPIO100__FUNC_GPIO100 (MTK_PIN_NO(100) | 0) +#define PINMUX_GPIO100__FUNC_MSDC2_DAT0 (MTK_PIN_NO(100) | 1) +#define PINMUX_GPIO100__FUNC_URXD1 (MTK_PIN_NO(100) | 2) +#define PINMUX_GPIO100__FUNC_USB_DRVVBUS (MTK_PIN_NO(100) | 3) +#define PINMUX_GPIO100__FUNC_SDA4 (MTK_PIN_NO(100) | 4) + +#define PINMUX_GPIO101__FUNC_GPIO101 (MTK_PIN_NO(101) | 0) +#define PINMUX_GPIO101__FUNC_MSDC2_DAT1 (MTK_PIN_NO(101) | 1) +#define PINMUX_GPIO101__FUNC_UTXD1 (MTK_PIN_NO(101) | 2) +#define PINMUX_GPIO101__FUNC_SCL4 (MTK_PIN_NO(101) | 4) + +#define PINMUX_GPIO102__FUNC_GPIO102 (MTK_PIN_NO(102) | 0) +#define PINMUX_GPIO102__FUNC_MSDC2_DAT2 (MTK_PIN_NO(102) | 1) +#define PINMUX_GPIO102__FUNC_URTS1 (MTK_PIN_NO(102) | 2) +#define PINMUX_GPIO102__FUNC_UTXD0 (MTK_PIN_NO(102) | 3) +#define PINMUX_GPIO102__FUNC_PWM0 (MTK_PIN_NO(102) | 5) +#define PINMUX_GPIO102__FUNC_SPI_CK_1 (MTK_PIN_NO(102) | 6) + +#define PINMUX_GPIO103__FUNC_GPIO103 (MTK_PIN_NO(103) | 0) +#define PINMUX_GPIO103__FUNC_MSDC2_DAT3 (MTK_PIN_NO(103) | 1) +#define PINMUX_GPIO103__FUNC_UCTS1 (MTK_PIN_NO(103) | 2) +#define PINMUX_GPIO103__FUNC_URXD0 (MTK_PIN_NO(103) | 3) +#define PINMUX_GPIO103__FUNC_PWM1 (MTK_PIN_NO(103) | 5) +#define PINMUX_GPIO103__FUNC_SPI_MI_1 (MTK_PIN_NO(103) | 6) + +#define PINMUX_GPIO104__FUNC_GPIO104 (MTK_PIN_NO(104) | 0) +#define PINMUX_GPIO104__FUNC_MSDC2_CLK (MTK_PIN_NO(104) | 1) +#define PINMUX_GPIO104__FUNC_NLD4 (MTK_PIN_NO(104) | 2) +#define PINMUX_GPIO104__FUNC_UTXD3 (MTK_PIN_NO(104) | 3) +#define PINMUX_GPIO104__FUNC_SDA3 (MTK_PIN_NO(104) | 4) +#define PINMUX_GPIO104__FUNC_PWM2 (MTK_PIN_NO(104) | 5) +#define PINMUX_GPIO104__FUNC_SPI_MO_1 (MTK_PIN_NO(104) | 6) + +#define PINMUX_GPIO105__FUNC_GPIO105 (MTK_PIN_NO(105) | 0) +#define PINMUX_GPIO105__FUNC_MSDC2_CMD (MTK_PIN_NO(105) | 1) +#define PINMUX_GPIO105__FUNC_NLD5 (MTK_PIN_NO(105) | 2) +#define PINMUX_GPIO105__FUNC_URXD3 (MTK_PIN_NO(105) | 3) +#define PINMUX_GPIO105__FUNC_SCL3 (MTK_PIN_NO(105) | 4) +#define PINMUX_GPIO105__FUNC_PWM3 (MTK_PIN_NO(105) | 5) +#define PINMUX_GPIO105__FUNC_SPI_CS_1 (MTK_PIN_NO(105) | 6) + +#define PINMUX_GPIO106__FUNC_GPIO106 (MTK_PIN_NO(106) | 0) +#define PINMUX_GPIO106__FUNC_LCM_RST (MTK_PIN_NO(106) | 1) + +#define PINMUX_GPIO107__FUNC_GPIO107 (MTK_PIN_NO(107) | 0) +#define PINMUX_GPIO107__FUNC_DSI_TE (MTK_PIN_NO(107) | 1) + +#define PINMUX_GPIO108__FUNC_GPIO108 (MTK_PIN_NO(108) | 0) +#define PINMUX_GPIO108__FUNC_JTMS (MTK_PIN_NO(108) | 1) +#define PINMUX_GPIO108__FUNC_MFG_JTAG_TMS (MTK_PIN_NO(108) | 2) +#define PINMUX_GPIO108__FUNC_TDD_TMS (MTK_PIN_NO(108) | 3) +#define PINMUX_GPIO108__FUNC_LTE_MD32_JTAG_TMS (MTK_PIN_NO(108) | 4) +#define PINMUX_GPIO108__FUNC_AP_MD32_JTAG_TMS (MTK_PIN_NO(108) | 5) +#define PINMUX_GPIO108__FUNC_DFD_TMS (MTK_PIN_NO(108) | 6) + +#define PINMUX_GPIO109__FUNC_GPIO109 (MTK_PIN_NO(109) | 0) +#define PINMUX_GPIO109__FUNC_JTCK (MTK_PIN_NO(109) | 1) +#define PINMUX_GPIO109__FUNC_MFG_JTAG_TCK (MTK_PIN_NO(109) | 2) +#define PINMUX_GPIO109__FUNC_TDD_TCK (MTK_PIN_NO(109) | 3) +#define PINMUX_GPIO109__FUNC_LTE_MD32_JTAG_TCK (MTK_PIN_NO(109) | 4) +#define PINMUX_GPIO109__FUNC_AP_MD32_JTAG_TCK (MTK_PIN_NO(109) | 5) +#define PINMUX_GPIO109__FUNC_DFD_TCK (MTK_PIN_NO(109) | 6) + +#define PINMUX_GPIO110__FUNC_GPIO110 (MTK_PIN_NO(110) | 0) +#define PINMUX_GPIO110__FUNC_JTDI (MTK_PIN_NO(110) | 1) +#define PINMUX_GPIO110__FUNC_MFG_JTAG_TDI (MTK_PIN_NO(110) | 2) +#define PINMUX_GPIO110__FUNC_TDD_TDI (MTK_PIN_NO(110) | 3) +#define PINMUX_GPIO110__FUNC_LTE_MD32_JTAG_TDI (MTK_PIN_NO(110) | 4) +#define PINMUX_GPIO110__FUNC_AP_MD32_JTAG_TDI (MTK_PIN_NO(110) | 5) +#define PINMUX_GPIO110__FUNC_DFD_TDI (MTK_PIN_NO(110) | 6) + +#define PINMUX_GPIO111__FUNC_GPIO111 (MTK_PIN_NO(111) | 0) +#define PINMUX_GPIO111__FUNC_JTDO (MTK_PIN_NO(111) | 1) +#define PINMUX_GPIO111__FUNC_MFG_JTAG_TDO (MTK_PIN_NO(111) | 2) +#define PINMUX_GPIO111__FUNC_TDD_TDO (MTK_PIN_NO(111) | 3) +#define PINMUX_GPIO111__FUNC_LTE_MD32_JTAG_TDO (MTK_PIN_NO(111) | 4) +#define PINMUX_GPIO111__FUNC_AP_MD32_JTAG_TDO (MTK_PIN_NO(111) | 5) +#define PINMUX_GPIO111__FUNC_DFD_TDO (MTK_PIN_NO(111) | 6) + +#define PINMUX_GPIO112__FUNC_GPIO112 (MTK_PIN_NO(112) | 0) +#define PINMUX_GPIO112__FUNC_JTRST_B (MTK_PIN_NO(112) | 1) +#define PINMUX_GPIO112__FUNC_MFG_JTAG_TRSTN (MTK_PIN_NO(112) | 2) +#define PINMUX_GPIO112__FUNC_TDD_TRSTN (MTK_PIN_NO(112) | 3) +#define PINMUX_GPIO112__FUNC_LTE_MD32_JTAG_TRST (MTK_PIN_NO(112) | 4) +#define PINMUX_GPIO112__FUNC_AP_MD32_JTAG_TRST (MTK_PIN_NO(112) | 5) +#define PINMUX_GPIO112__FUNC_DFD_NTRST (MTK_PIN_NO(112) | 6) + +#define PINMUX_GPIO113__FUNC_GPIO113 (MTK_PIN_NO(113) | 0) +#define PINMUX_GPIO113__FUNC_URXD0 (MTK_PIN_NO(113) | 1) +#define PINMUX_GPIO113__FUNC_UTXD0 (MTK_PIN_NO(113) | 2) +#define PINMUX_GPIO113__FUNC_MD_URXD (MTK_PIN_NO(113) | 3) +#define PINMUX_GPIO113__FUNC_LTE_URXD (MTK_PIN_NO(113) | 4) +#define PINMUX_GPIO113__FUNC_TDD_TXD (MTK_PIN_NO(113) | 5) +#define PINMUX_GPIO113__FUNC_I2S2_WS (MTK_PIN_NO(113) | 6) + +#define PINMUX_GPIO114__FUNC_GPIO114 (MTK_PIN_NO(114) | 0) +#define PINMUX_GPIO114__FUNC_UTXD0 (MTK_PIN_NO(114) | 1) +#define PINMUX_GPIO114__FUNC_URXD0 (MTK_PIN_NO(114) | 2) +#define PINMUX_GPIO114__FUNC_MD_UTXD (MTK_PIN_NO(114) | 3) +#define PINMUX_GPIO114__FUNC_LTE_UTXD (MTK_PIN_NO(114) | 4) +#define PINMUX_GPIO114__FUNC_TDD_TXD (MTK_PIN_NO(114) | 5) +#define PINMUX_GPIO114__FUNC_I2S2_BCK (MTK_PIN_NO(114) | 6) + +#define PINMUX_GPIO115__FUNC_GPIO115 (MTK_PIN_NO(115) | 0) +#define PINMUX_GPIO115__FUNC_URTS0 (MTK_PIN_NO(115) | 1) +#define PINMUX_GPIO115__FUNC_UCTS0 (MTK_PIN_NO(115) | 2) +#define PINMUX_GPIO115__FUNC_MD_URXD (MTK_PIN_NO(115) | 3) +#define PINMUX_GPIO115__FUNC_LTE_URXD (MTK_PIN_NO(115) | 4) +#define PINMUX_GPIO115__FUNC_TDD_TXD (MTK_PIN_NO(115) | 5) +#define PINMUX_GPIO115__FUNC_I2S2_MCK (MTK_PIN_NO(115) | 6) + +#define PINMUX_GPIO116__FUNC_GPIO116 (MTK_PIN_NO(116) | 0) +#define PINMUX_GPIO116__FUNC_UCTS0 (MTK_PIN_NO(116) | 1) +#define PINMUX_GPIO116__FUNC_URTS0 (MTK_PIN_NO(116) | 2) +#define PINMUX_GPIO116__FUNC_MD_UTXD (MTK_PIN_NO(116) | 3) +#define PINMUX_GPIO116__FUNC_LTE_UTXD (MTK_PIN_NO(116) | 4) +#define PINMUX_GPIO116__FUNC_TDD_TXD (MTK_PIN_NO(116) | 5) +#define PINMUX_GPIO116__FUNC_I2S2_DI_1 (MTK_PIN_NO(116) | 6) + +#define PINMUX_GPIO117__FUNC_GPIO117 (MTK_PIN_NO(117) | 0) +#define PINMUX_GPIO117__FUNC_URXD3 (MTK_PIN_NO(117) | 1) +#define PINMUX_GPIO117__FUNC_UTXD3 (MTK_PIN_NO(117) | 2) +#define PINMUX_GPIO117__FUNC_MD_URXD (MTK_PIN_NO(117) | 3) +#define PINMUX_GPIO117__FUNC_LTE_URXD (MTK_PIN_NO(117) | 4) +#define PINMUX_GPIO117__FUNC_TDD_TXD (MTK_PIN_NO(117) | 5) + +#define PINMUX_GPIO118__FUNC_GPIO118 (MTK_PIN_NO(118) | 0) +#define PINMUX_GPIO118__FUNC_UTXD3 (MTK_PIN_NO(118) | 1) +#define PINMUX_GPIO118__FUNC_URXD3 (MTK_PIN_NO(118) | 2) +#define PINMUX_GPIO118__FUNC_MD_UTXD (MTK_PIN_NO(118) | 3) +#define PINMUX_GPIO118__FUNC_LTE_UTXD (MTK_PIN_NO(118) | 4) +#define PINMUX_GPIO118__FUNC_TDD_TXD (MTK_PIN_NO(118) | 5) + +#define PINMUX_GPIO119__FUNC_GPIO119 (MTK_PIN_NO(119) | 0) +#define PINMUX_GPIO119__FUNC_KROW0 (MTK_PIN_NO(119) | 1) + +#define PINMUX_GPIO120__FUNC_GPIO120 (MTK_PIN_NO(120) | 0) +#define PINMUX_GPIO120__FUNC_KROW1 (MTK_PIN_NO(120) | 1) +#define PINMUX_GPIO120__FUNC_PWM6 (MTK_PIN_NO(120) | 3) + +#define PINMUX_GPIO121__FUNC_GPIO121 (MTK_PIN_NO(121) | 0) +#define PINMUX_GPIO121__FUNC_KROW2 (MTK_PIN_NO(121) | 1) +#define PINMUX_GPIO121__FUNC_IRDA_PDN (MTK_PIN_NO(121) | 2) +#define PINMUX_GPIO121__FUNC_I2S1_DO_1 (MTK_PIN_NO(121) | 3) +#define PINMUX_GPIO121__FUNC_USB_DRVVBUS (MTK_PIN_NO(121) | 4) +#define PINMUX_GPIO121__FUNC_SPI_CK_2 (MTK_PIN_NO(121) | 5) +#define PINMUX_GPIO121__FUNC_PWM4 (MTK_PIN_NO(121) | 6) + +#define PINMUX_GPIO122__FUNC_GPIO122 (MTK_PIN_NO(122) | 0) +#define PINMUX_GPIO122__FUNC_KCOL0 (MTK_PIN_NO(122) | 1) + +#define PINMUX_GPIO123__FUNC_GPIO123 (MTK_PIN_NO(123) | 0) +#define PINMUX_GPIO123__FUNC_KCOL1 (MTK_PIN_NO(123) | 1) +#define PINMUX_GPIO123__FUNC_IRDA_RXD (MTK_PIN_NO(123) | 2) +#define PINMUX_GPIO123__FUNC_I2S2_DI_2 (MTK_PIN_NO(123) | 3) +#define PINMUX_GPIO123__FUNC_PWM5 (MTK_PIN_NO(123) | 4) + +#define PINMUX_GPIO124__FUNC_GPIO124 (MTK_PIN_NO(124) | 0) +#define PINMUX_GPIO124__FUNC_KCOL2 (MTK_PIN_NO(124) | 1) +#define PINMUX_GPIO124__FUNC_IRDA_TXD (MTK_PIN_NO(124) | 2) +#define PINMUX_GPIO124__FUNC_I2S1_DO_2 (MTK_PIN_NO(124) | 3) +#define PINMUX_GPIO124__FUNC_USB_DRVVBUS (MTK_PIN_NO(124) | 4) +#define PINMUX_GPIO124__FUNC_SPI_MI_2 (MTK_PIN_NO(124) | 5) +#define PINMUX_GPIO124__FUNC_PWM3 (MTK_PIN_NO(124) | 6) + +#define PINMUX_GPIO125__FUNC_GPIO125 (MTK_PIN_NO(125) | 0) +#define PINMUX_GPIO125__FUNC_SDA1 (MTK_PIN_NO(125) | 1) + +#define PINMUX_GPIO126__FUNC_GPIO126 (MTK_PIN_NO(126) | 0) +#define PINMUX_GPIO126__FUNC_SCL1 (MTK_PIN_NO(126) | 1) + +#define PINMUX_GPIO127__FUNC_GPIO127 (MTK_PIN_NO(127) | 0) +#define PINMUX_GPIO127__FUNC_MD_EINT1 (MTK_PIN_NO(127) | 1) +#define PINMUX_GPIO127__FUNC_DISP_PWM1 (MTK_PIN_NO(127) | 2) +#define PINMUX_GPIO127__FUNC_SPI_MO_2 (MTK_PIN_NO(127) | 3) + +#define PINMUX_GPIO128__FUNC_GPIO128 (MTK_PIN_NO(128) | 0) +#define PINMUX_GPIO128__FUNC_MD_EINT2 (MTK_PIN_NO(128) | 1) +#define PINMUX_GPIO128__FUNC_DSI1_TE (MTK_PIN_NO(128) | 2) +#define PINMUX_GPIO128__FUNC_SPI_CS_2 (MTK_PIN_NO(128) | 3) + +#define PINMUX_GPIO129__FUNC_GPIO129 (MTK_PIN_NO(129) | 0) +#define PINMUX_GPIO129__FUNC_I2S3_WS (MTK_PIN_NO(129) | 1) +#define PINMUX_GPIO129__FUNC_I2S2_WS (MTK_PIN_NO(129) | 2) +#define PINMUX_GPIO129__FUNC_PWM0 (MTK_PIN_NO(129) | 3) + +#define PINMUX_GPIO130__FUNC_GPIO130 (MTK_PIN_NO(130) | 0) +#define PINMUX_GPIO130__FUNC_I2S3_BCK (MTK_PIN_NO(130) | 1) +#define PINMUX_GPIO130__FUNC_I2S2_BCK (MTK_PIN_NO(130) | 2) +#define PINMUX_GPIO130__FUNC_PWM1 (MTK_PIN_NO(130) | 3) + +#define PINMUX_GPIO131__FUNC_GPIO131 (MTK_PIN_NO(131) | 0) +#define PINMUX_GPIO131__FUNC_I2S3_MCK (MTK_PIN_NO(131) | 1) +#define PINMUX_GPIO131__FUNC_I2S2_MCK (MTK_PIN_NO(131) | 2) +#define PINMUX_GPIO131__FUNC_PWM2 (MTK_PIN_NO(131) | 3) + +#define PINMUX_GPIO132__FUNC_GPIO132 (MTK_PIN_NO(132) | 0) +#define PINMUX_GPIO132__FUNC_I2S3_DO_1 (MTK_PIN_NO(132) | 1) +#define PINMUX_GPIO132__FUNC_I2S2_DI_1 (MTK_PIN_NO(132) | 2) +#define PINMUX_GPIO132__FUNC_PWM3 (MTK_PIN_NO(132) | 3) + +#define PINMUX_GPIO133__FUNC_GPIO133 (MTK_PIN_NO(133) | 0) +#define PINMUX_GPIO133__FUNC_I2S3_DO_2 (MTK_PIN_NO(133) | 1) +#define PINMUX_GPIO133__FUNC_I2S2_DI_2 (MTK_PIN_NO(133) | 2) +#define PINMUX_GPIO133__FUNC_PWM4 (MTK_PIN_NO(133) | 3) + +#define PINMUX_GPIO134__FUNC_GPIO134 (MTK_PIN_NO(134) | 0) +#define PINMUX_GPIO134__FUNC_I2S3_DO_3 (MTK_PIN_NO(134) | 1) +#define PINMUX_GPIO134__FUNC_DISP_PWM1 (MTK_PIN_NO(134) | 2) +#define PINMUX_GPIO134__FUNC_I2S1_DO_1 (MTK_PIN_NO(134) | 3) +#define PINMUX_GPIO134__FUNC_PWM5 (MTK_PIN_NO(134) | 4) + +#define PINMUX_GPIO135__FUNC_GPIO135 (MTK_PIN_NO(135) | 0) +#define PINMUX_GPIO135__FUNC_I2S3_DO_4 (MTK_PIN_NO(135) | 1) +#define PINMUX_GPIO135__FUNC_DSI1_TE (MTK_PIN_NO(135) | 2) +#define PINMUX_GPIO135__FUNC_I2S1_DO_2 (MTK_PIN_NO(135) | 3) +#define PINMUX_GPIO135__FUNC_PWM6 (MTK_PIN_NO(135) | 4) + +#define PINMUX_GPIO136__FUNC_GPIO136 (MTK_PIN_NO(136) | 0) +#define PINMUX_GPIO136__FUNC_SDA3 (MTK_PIN_NO(136) | 1) + +#define PINMUX_GPIO137__FUNC_GPIO137 (MTK_PIN_NO(137) | 0) +#define PINMUX_GPIO137__FUNC_SCL3 (MTK_PIN_NO(137) | 1) + +#define PINMUX_GPIO138__FUNC_GPIO138 (MTK_PIN_NO(138) | 0) +#define PINMUX_GPIO138__FUNC_DPI_CK (MTK_PIN_NO(138) | 1) +#define PINMUX_GPIO138__FUNC_NLD6 (MTK_PIN_NO(138) | 2) +#define PINMUX_GPIO138__FUNC_UTXD0 (MTK_PIN_NO(138) | 3) +#define PINMUX_GPIO138__FUNC_USB_DRVVBUS (MTK_PIN_NO(138) | 4) +#define PINMUX_GPIO138__FUNC_IRDA_PDN (MTK_PIN_NO(138) | 5) + +#define PINMUX_GPIO139__FUNC_GPIO139 (MTK_PIN_NO(139) | 0) +#define PINMUX_GPIO139__FUNC_DPI_DE (MTK_PIN_NO(139) | 1) +#define PINMUX_GPIO139__FUNC_NLD7 (MTK_PIN_NO(139) | 2) +#define PINMUX_GPIO139__FUNC_URXD0 (MTK_PIN_NO(139) | 3) +#define PINMUX_GPIO139__FUNC_MD_UTXD (MTK_PIN_NO(139) | 4) +#define PINMUX_GPIO139__FUNC_IRDA_RXD (MTK_PIN_NO(139) | 5) + +#define PINMUX_GPIO140__FUNC_GPIO140 (MTK_PIN_NO(140) | 0) +#define PINMUX_GPIO140__FUNC_DPI_D0 (MTK_PIN_NO(140) | 1) +#define PINMUX_GPIO140__FUNC_NREB (MTK_PIN_NO(140) | 2) +#define PINMUX_GPIO140__FUNC_UCTS0 (MTK_PIN_NO(140) | 3) +#define PINMUX_GPIO140__FUNC_MD_URXD (MTK_PIN_NO(140) | 4) +#define PINMUX_GPIO140__FUNC_IRDA_TXD (MTK_PIN_NO(140) | 5) + +#define PINMUX_GPIO141__FUNC_GPIO141 (MTK_PIN_NO(141) | 0) +#define PINMUX_GPIO141__FUNC_DPI_D1 (MTK_PIN_NO(141) | 1) +#define PINMUX_GPIO141__FUNC_NRNB0 (MTK_PIN_NO(141) | 2) +#define PINMUX_GPIO141__FUNC_URTS0 (MTK_PIN_NO(141) | 3) +#define PINMUX_GPIO141__FUNC_LTE_UTXD (MTK_PIN_NO(141) | 4) +#define PINMUX_GPIO141__FUNC_I2S2_WS (MTK_PIN_NO(141) | 5) + +#define PINMUX_GPIO142__FUNC_GPIO142 (MTK_PIN_NO(142) | 0) +#define PINMUX_GPIO142__FUNC_DPI_D2 (MTK_PIN_NO(142) | 1) +#define PINMUX_GPIO142__FUNC_NWEB (MTK_PIN_NO(142) | 2) +#define PINMUX_GPIO142__FUNC_UTXD1 (MTK_PIN_NO(142) | 3) +#define PINMUX_GPIO142__FUNC_LTE_URXD (MTK_PIN_NO(142) | 4) +#define PINMUX_GPIO142__FUNC_I2S2_BCK (MTK_PIN_NO(142) | 5) + +#define PINMUX_GPIO143__FUNC_GPIO143 (MTK_PIN_NO(143) | 0) +#define PINMUX_GPIO143__FUNC_DPI_D3 (MTK_PIN_NO(143) | 1) +#define PINMUX_GPIO143__FUNC_NCEB0 (MTK_PIN_NO(143) | 2) +#define PINMUX_GPIO143__FUNC_URXD1 (MTK_PIN_NO(143) | 3) +#define PINMUX_GPIO143__FUNC_TDD_TXD (MTK_PIN_NO(143) | 4) +#define PINMUX_GPIO143__FUNC_I2S2_MCK (MTK_PIN_NO(143) | 5) + +#define PINMUX_GPIO144__FUNC_GPIO144 (MTK_PIN_NO(144) | 0) +#define PINMUX_GPIO144__FUNC_DPI_D4 (MTK_PIN_NO(144) | 1) +#define PINMUX_GPIO144__FUNC_NALE (MTK_PIN_NO(144) | 2) +#define PINMUX_GPIO144__FUNC_UCTS1 (MTK_PIN_NO(144) | 3) +#define PINMUX_GPIO144__FUNC_TDD_TMS (MTK_PIN_NO(144) | 4) +#define PINMUX_GPIO144__FUNC_I2S2_DI_1 (MTK_PIN_NO(144) | 5) + +#define PINMUX_GPIO145__FUNC_GPIO145 (MTK_PIN_NO(145) | 0) +#define PINMUX_GPIO145__FUNC_DPI_D5 (MTK_PIN_NO(145) | 1) +#define PINMUX_GPIO145__FUNC_NCLE (MTK_PIN_NO(145) | 2) +#define PINMUX_GPIO145__FUNC_URTS1 (MTK_PIN_NO(145) | 3) +#define PINMUX_GPIO145__FUNC_TDD_TCK (MTK_PIN_NO(145) | 4) +#define PINMUX_GPIO145__FUNC_I2S2_DI_2 (MTK_PIN_NO(145) | 5) + +#define PINMUX_GPIO146__FUNC_GPIO146 (MTK_PIN_NO(146) | 0) +#define PINMUX_GPIO146__FUNC_DPI_D6 (MTK_PIN_NO(146) | 1) +#define PINMUX_GPIO146__FUNC_NLD8 (MTK_PIN_NO(146) | 2) +#define PINMUX_GPIO146__FUNC_UTXD2 (MTK_PIN_NO(146) | 3) +#define PINMUX_GPIO146__FUNC_TDD_TDI (MTK_PIN_NO(146) | 4) + +#define PINMUX_GPIO147__FUNC_GPIO147 (MTK_PIN_NO(147) | 0) +#define PINMUX_GPIO147__FUNC_DPI_D7 (MTK_PIN_NO(147) | 1) +#define PINMUX_GPIO147__FUNC_NLD9 (MTK_PIN_NO(147) | 2) +#define PINMUX_GPIO147__FUNC_URXD2 (MTK_PIN_NO(147) | 3) +#define PINMUX_GPIO147__FUNC_TDD_TDO (MTK_PIN_NO(147) | 4) +#define PINMUX_GPIO147__FUNC_I2S1_WS (MTK_PIN_NO(147) | 5) + +#define PINMUX_GPIO148__FUNC_GPIO148 (MTK_PIN_NO(148) | 0) +#define PINMUX_GPIO148__FUNC_DPI_D8 (MTK_PIN_NO(148) | 1) +#define PINMUX_GPIO148__FUNC_NLD10 (MTK_PIN_NO(148) | 2) +#define PINMUX_GPIO148__FUNC_UCTS2 (MTK_PIN_NO(148) | 3) +#define PINMUX_GPIO148__FUNC_TDD_TRSTN (MTK_PIN_NO(148) | 4) +#define PINMUX_GPIO148__FUNC_I2S1_BCK (MTK_PIN_NO(148) | 5) + +#define PINMUX_GPIO149__FUNC_GPIO149 (MTK_PIN_NO(149) | 0) +#define PINMUX_GPIO149__FUNC_DPI_D9 (MTK_PIN_NO(149) | 1) +#define PINMUX_GPIO149__FUNC_NLD11 (MTK_PIN_NO(149) | 2) +#define PINMUX_GPIO149__FUNC_URTS2 (MTK_PIN_NO(149) | 3) +#define PINMUX_GPIO149__FUNC_LTE_MD32_JTAG_TMS (MTK_PIN_NO(149) | 4) +#define PINMUX_GPIO149__FUNC_I2S1_MCK (MTK_PIN_NO(149) | 5) + +#define PINMUX_GPIO150__FUNC_GPIO150 (MTK_PIN_NO(150) | 0) +#define PINMUX_GPIO150__FUNC_DPI_D10 (MTK_PIN_NO(150) | 1) +#define PINMUX_GPIO150__FUNC_NLD12 (MTK_PIN_NO(150) | 2) +#define PINMUX_GPIO150__FUNC_UTXD3 (MTK_PIN_NO(150) | 3) +#define PINMUX_GPIO150__FUNC_LTE_MD32_JTAG_TCK (MTK_PIN_NO(150) | 4) +#define PINMUX_GPIO150__FUNC_I2S1_DO_1 (MTK_PIN_NO(150) | 5) + +#define PINMUX_GPIO151__FUNC_GPIO151 (MTK_PIN_NO(151) | 0) +#define PINMUX_GPIO151__FUNC_DPI_D11 (MTK_PIN_NO(151) | 1) +#define PINMUX_GPIO151__FUNC_NLD13 (MTK_PIN_NO(151) | 2) +#define PINMUX_GPIO151__FUNC_URXD3 (MTK_PIN_NO(151) | 3) +#define PINMUX_GPIO151__FUNC_LTE_MD32_JTAG_TDI (MTK_PIN_NO(151) | 4) +#define PINMUX_GPIO151__FUNC_I2S1_DO_2 (MTK_PIN_NO(151) | 5) + +#define PINMUX_GPIO152__FUNC_GPIO152 (MTK_PIN_NO(152) | 0) +#define PINMUX_GPIO152__FUNC_DPI_HSYNC (MTK_PIN_NO(152) | 1) +#define PINMUX_GPIO152__FUNC_NLD14 (MTK_PIN_NO(152) | 2) +#define PINMUX_GPIO152__FUNC_UCTS3 (MTK_PIN_NO(152) | 3) +#define PINMUX_GPIO152__FUNC_LTE_MD32_JTAG_TDO (MTK_PIN_NO(152) | 4) +#define PINMUX_GPIO152__FUNC_DSI1_TE (MTK_PIN_NO(152) | 5) + +#define PINMUX_GPIO153__FUNC_GPIO153 (MTK_PIN_NO(153) | 0) +#define PINMUX_GPIO153__FUNC_DPI_VSYNC (MTK_PIN_NO(153) | 1) +#define PINMUX_GPIO153__FUNC_NLD15 (MTK_PIN_NO(153) | 2) +#define PINMUX_GPIO153__FUNC_URTS3 (MTK_PIN_NO(153) | 3) +#define PINMUX_GPIO153__FUNC_LTE_MD32_JTAG_TRST (MTK_PIN_NO(153) | 4) +#define PINMUX_GPIO153__FUNC_DISP_PWM1 (MTK_PIN_NO(153) | 5) + +#define PINMUX_GPIO154__FUNC_GPIO154 (MTK_PIN_NO(154) | 0) +#define PINMUX_GPIO154__FUNC_MSDC0_DAT0 (MTK_PIN_NO(154) | 1) +#define PINMUX_GPIO154__FUNC_NLD8 (MTK_PIN_NO(154) | 2) + +#define PINMUX_GPIO155__FUNC_GPIO155 (MTK_PIN_NO(155) | 0) +#define PINMUX_GPIO155__FUNC_MSDC0_DAT1 (MTK_PIN_NO(155) | 1) +#define PINMUX_GPIO155__FUNC_NLD9 (MTK_PIN_NO(155) | 2) + +#define PINMUX_GPIO156__FUNC_GPIO156 (MTK_PIN_NO(156) | 0) +#define PINMUX_GPIO156__FUNC_MSDC0_DAT2 (MTK_PIN_NO(156) | 1) +#define PINMUX_GPIO156__FUNC_NLD10 (MTK_PIN_NO(156) | 2) + +#define PINMUX_GPIO157__FUNC_GPIO157 (MTK_PIN_NO(157) | 0) +#define PINMUX_GPIO157__FUNC_MSDC0_DAT3 (MTK_PIN_NO(157) | 1) +#define PINMUX_GPIO157__FUNC_NLD11 (MTK_PIN_NO(157) | 2) + +#define PINMUX_GPIO158__FUNC_GPIO158 (MTK_PIN_NO(158) | 0) +#define PINMUX_GPIO158__FUNC_MSDC0_DAT4 (MTK_PIN_NO(158) | 1) +#define PINMUX_GPIO158__FUNC_NLD12 (MTK_PIN_NO(158) | 2) + +#define PINMUX_GPIO159__FUNC_GPIO159 (MTK_PIN_NO(159) | 0) +#define PINMUX_GPIO159__FUNC_MSDC0_DAT5 (MTK_PIN_NO(159) | 1) +#define PINMUX_GPIO159__FUNC_NLD13 (MTK_PIN_NO(159) | 2) + +#define PINMUX_GPIO160__FUNC_GPIO160 (MTK_PIN_NO(160) | 0) +#define PINMUX_GPIO160__FUNC_MSDC0_DAT6 (MTK_PIN_NO(160) | 1) +#define PINMUX_GPIO160__FUNC_NLD14 (MTK_PIN_NO(160) | 2) + +#define PINMUX_GPIO161__FUNC_GPIO161 (MTK_PIN_NO(161) | 0) +#define PINMUX_GPIO161__FUNC_MSDC0_DAT7 (MTK_PIN_NO(161) | 1) +#define PINMUX_GPIO161__FUNC_NLD15 (MTK_PIN_NO(161) | 2) + +#define PINMUX_GPIO162__FUNC_GPIO162 (MTK_PIN_NO(162) | 0) +#define PINMUX_GPIO162__FUNC_MSDC0_CMD (MTK_PIN_NO(162) | 1) + +#define PINMUX_GPIO163__FUNC_GPIO163 (MTK_PIN_NO(163) | 0) +#define PINMUX_GPIO163__FUNC_MSDC0_CLK (MTK_PIN_NO(163) | 1) + +#define PINMUX_GPIO164__FUNC_GPIO164 (MTK_PIN_NO(164) | 0) +#define PINMUX_GPIO164__FUNC_MSDC0_DSL (MTK_PIN_NO(164) | 1) + +#define PINMUX_GPIO165__FUNC_GPIO165 (MTK_PIN_NO(165) | 0) +#define PINMUX_GPIO165__FUNC_MSDC0_RSTB (MTK_PIN_NO(165) | 1) + +#define PINMUX_GPIO166__FUNC_GPIO166 (MTK_PIN_NO(166) | 0) +#define PINMUX_GPIO166__FUNC_SPI_CK_0 (MTK_PIN_NO(166) | 1) +#define PINMUX_GPIO166__FUNC_PWM0 (MTK_PIN_NO(166) | 3) + +#define PINMUX_GPIO167__FUNC_GPIO167 (MTK_PIN_NO(167) | 0) +#define PINMUX_GPIO167__FUNC_SPI_MI_0 (MTK_PIN_NO(167) | 1) +#define PINMUX_GPIO167__FUNC_PWM1 (MTK_PIN_NO(167) | 3) +#define PINMUX_GPIO167__FUNC_SPI_MO_0 (MTK_PIN_NO(167) | 4) + +#define PINMUX_GPIO168__FUNC_GPIO168 (MTK_PIN_NO(168) | 0) +#define PINMUX_GPIO168__FUNC_SPI_MO_0 (MTK_PIN_NO(168) | 1) +#define PINMUX_GPIO168__FUNC_MD_EINT3 (MTK_PIN_NO(168) | 2) +#define PINMUX_GPIO168__FUNC_PWM2 (MTK_PIN_NO(168) | 3) +#define PINMUX_GPIO168__FUNC_SPI_MI_0 (MTK_PIN_NO(168) | 4) + +#define PINMUX_GPIO169__FUNC_GPIO169 (MTK_PIN_NO(169) | 0) +#define PINMUX_GPIO169__FUNC_SPI_CS_0 (MTK_PIN_NO(169) | 1) +#define PINMUX_GPIO169__FUNC_MD_EINT4 (MTK_PIN_NO(169) | 2) +#define PINMUX_GPIO169__FUNC_PWM3 (MTK_PIN_NO(169) | 3) + +#define PINMUX_GPIO170__FUNC_GPIO170 (MTK_PIN_NO(170) | 0) +#define PINMUX_GPIO170__FUNC_MSDC1_CMD (MTK_PIN_NO(170) | 1) + +#define PINMUX_GPIO171__FUNC_GPIO171 (MTK_PIN_NO(171) | 0) +#define PINMUX_GPIO171__FUNC_MSDC1_DAT0 (MTK_PIN_NO(171) | 1) + +#define PINMUX_GPIO172__FUNC_GPIO172 (MTK_PIN_NO(172) | 0) +#define PINMUX_GPIO172__FUNC_MSDC1_DAT1 (MTK_PIN_NO(172) | 1) + +#define PINMUX_GPIO173__FUNC_GPIO173 (MTK_PIN_NO(173) | 0) +#define PINMUX_GPIO173__FUNC_MSDC1_DAT2 (MTK_PIN_NO(173) | 1) + +#define PINMUX_GPIO174__FUNC_GPIO174 (MTK_PIN_NO(174) | 0) +#define PINMUX_GPIO174__FUNC_MSDC1_DAT3 (MTK_PIN_NO(174) | 1) + +#define PINMUX_GPIO175__FUNC_GPIO175 (MTK_PIN_NO(175) | 0) +#define PINMUX_GPIO175__FUNC_MSDC1_CLK (MTK_PIN_NO(175) | 1) + +#define PINMUX_GPIO176__FUNC_GPIO176 (MTK_PIN_NO(176) | 0) +#define PINMUX_GPIO176__FUNC_PWRAP_SPIMI (MTK_PIN_NO(176) | 1) +#define PINMUX_GPIO176__FUNC_PWRAP_SPIMO (MTK_PIN_NO(176) | 2) + +#define PINMUX_GPIO177__FUNC_GPIO177 (MTK_PIN_NO(177) | 0) +#define PINMUX_GPIO177__FUNC_PWRAP_SPIMO (MTK_PIN_NO(177) | 1) +#define PINMUX_GPIO177__FUNC_PWRAP_SPIMI (MTK_PIN_NO(177) | 2) + +#define PINMUX_GPIO178__FUNC_GPIO178 (MTK_PIN_NO(178) | 0) +#define PINMUX_GPIO178__FUNC_PWRAP_SPICK (MTK_PIN_NO(178) | 1) + +#define PINMUX_GPIO179__FUNC_GPIO179 (MTK_PIN_NO(179) | 0) +#define PINMUX_GPIO179__FUNC_PWRAP_SPICS (MTK_PIN_NO(179) | 1) + +#define PINMUX_GPIO180__FUNC_GPIO180 (MTK_PIN_NO(180) | 0) +#define PINMUX_GPIO180__FUNC_AUD_CLK_MOSI (MTK_PIN_NO(180) | 1) +#define PINMUX_GPIO180__FUNC_I2S1_WS (MTK_PIN_NO(180) | 2) +#define PINMUX_GPIO180__FUNC_I2S2_WS (MTK_PIN_NO(180) | 3) +#define PINMUX_GPIO180__FUNC_I2S0_WS (MTK_PIN_NO(180) | 4) + +#define PINMUX_GPIO181__FUNC_GPIO181 (MTK_PIN_NO(181) | 0) +#define PINMUX_GPIO181__FUNC_AUD_DAT_MISO_1 (MTK_PIN_NO(181) | 1) +#define PINMUX_GPIO181__FUNC_I2S1_BCK (MTK_PIN_NO(181) | 2) +#define PINMUX_GPIO181__FUNC_I2S2_BCK (MTK_PIN_NO(181) | 3) +#define PINMUX_GPIO181__FUNC_I2S0_BCK (MTK_PIN_NO(181) | 4) + +#define PINMUX_GPIO182__FUNC_GPIO182 (MTK_PIN_NO(182) | 0) +#define PINMUX_GPIO182__FUNC_AUD_DAT_MOSI_1 (MTK_PIN_NO(182) | 1) +#define PINMUX_GPIO182__FUNC_I2S1_MCK (MTK_PIN_NO(182) | 2) +#define PINMUX_GPIO182__FUNC_I2S2_MCK (MTK_PIN_NO(182) | 3) +#define PINMUX_GPIO182__FUNC_I2S0_MCK (MTK_PIN_NO(182) | 4) + +#define PINMUX_GPIO183__FUNC_GPIO183 (MTK_PIN_NO(183) | 0) +#define PINMUX_GPIO183__FUNC_AUD_DAT_MISO_2 (MTK_PIN_NO(183) | 1) +#define PINMUX_GPIO183__FUNC_I2S1_DO_1 (MTK_PIN_NO(183) | 2) +#define PINMUX_GPIO183__FUNC_I2S2_DI_1 (MTK_PIN_NO(183) | 3) +#define PINMUX_GPIO183__FUNC_I2S0_DO (MTK_PIN_NO(183) | 4) + +#define PINMUX_GPIO184__FUNC_GPIO184 (MTK_PIN_NO(184) | 0) +#define PINMUX_GPIO184__FUNC_AUD_DAT_MOSI_2 (MTK_PIN_NO(184) | 1) +#define PINMUX_GPIO184__FUNC_I2S1_DO_2 (MTK_PIN_NO(184) | 2) +#define PINMUX_GPIO184__FUNC_I2S2_DI_2 (MTK_PIN_NO(184) | 3) +#define PINMUX_GPIO184__FUNC_I2S0_DI (MTK_PIN_NO(184) | 4) + +#define PINMUX_GPIO185__FUNC_GPIO185 (MTK_PIN_NO(185) | 0) +#define PINMUX_GPIO185__FUNC_RTC32K_CK (MTK_PIN_NO(185) | 1) + +#define PINMUX_GPIO186__FUNC_GPIO186 (MTK_PIN_NO(186) | 0) +#define PINMUX_GPIO186__FUNC_DISP_PWM0 (MTK_PIN_NO(186) | 1) +#define PINMUX_GPIO186__FUNC_DISP_PWM1 (MTK_PIN_NO(186) | 2) + +#define PINMUX_GPIO187__FUNC_GPIO187 (MTK_PIN_NO(187) | 0) +#define PINMUX_GPIO187__FUNC_SRCLKENAI (MTK_PIN_NO(187) | 1) + +#define PINMUX_GPIO188__FUNC_GPIO188 (MTK_PIN_NO(188) | 0) +#define PINMUX_GPIO188__FUNC_SRCLKENAI2 (MTK_PIN_NO(188) | 1) + +#define PINMUX_GPIO189__FUNC_GPIO189 (MTK_PIN_NO(189) | 0) +#define PINMUX_GPIO189__FUNC_SRCLKENA0 (MTK_PIN_NO(189) | 1) + +#define PINMUX_GPIO190__FUNC_GPIO190 (MTK_PIN_NO(190) | 0) +#define PINMUX_GPIO190__FUNC_SRCLKENA1 (MTK_PIN_NO(190) | 1) + +#define PINMUX_GPIO191__FUNC_GPIO191 (MTK_PIN_NO(191) | 0) +#define PINMUX_GPIO191__FUNC_WATCHDOG_AO (MTK_PIN_NO(191) | 1) + +#define PINMUX_GPIO192__FUNC_GPIO192 (MTK_PIN_NO(192) | 0) +#define PINMUX_GPIO192__FUNC_I2S0_WS (MTK_PIN_NO(192) | 1) +#define PINMUX_GPIO192__FUNC_I2S1_WS (MTK_PIN_NO(192) | 2) +#define PINMUX_GPIO192__FUNC_I2S2_WS (MTK_PIN_NO(192) | 3) +#define PINMUX_GPIO192__FUNC_NCEB1 (MTK_PIN_NO(192) | 4) + +#define PINMUX_GPIO193__FUNC_GPIO193 (MTK_PIN_NO(193) | 0) +#define PINMUX_GPIO193__FUNC_I2S0_BCK (MTK_PIN_NO(193) | 1) +#define PINMUX_GPIO193__FUNC_I2S1_BCK (MTK_PIN_NO(193) | 2) +#define PINMUX_GPIO193__FUNC_I2S2_BCK (MTK_PIN_NO(193) | 3) +#define PINMUX_GPIO193__FUNC_NRNB1 (MTK_PIN_NO(193) | 4) + +#define PINMUX_GPIO194__FUNC_GPIO194 (MTK_PIN_NO(194) | 0) +#define PINMUX_GPIO194__FUNC_I2S0_MCK (MTK_PIN_NO(194) | 1) +#define PINMUX_GPIO194__FUNC_I2S1_MCK (MTK_PIN_NO(194) | 2) +#define PINMUX_GPIO194__FUNC_I2S2_MCK (MTK_PIN_NO(194) | 3) + +#define PINMUX_GPIO195__FUNC_GPIO195 (MTK_PIN_NO(195) | 0) +#define PINMUX_GPIO195__FUNC_I2S0_DO (MTK_PIN_NO(195) | 1) +#define PINMUX_GPIO195__FUNC_I2S1_DO_1 (MTK_PIN_NO(195) | 2) +#define PINMUX_GPIO195__FUNC_I2S2_DI_1 (MTK_PIN_NO(195) | 3) + +#define PINMUX_GPIO196__FUNC_GPIO196 (MTK_PIN_NO(196) | 0) +#define PINMUX_GPIO196__FUNC_I2S0_DI (MTK_PIN_NO(196) | 1) +#define PINMUX_GPIO196__FUNC_I2S1_DO_2 (MTK_PIN_NO(196) | 2) +#define PINMUX_GPIO196__FUNC_I2S2_DI_2 (MTK_PIN_NO(196) | 3) + + +#endif diff --git a/include/dt-bindings/reset/stm32mp13-resets.h b/include/dt-bindings/reset/stm32mp13-resets.h new file mode 100644 index 0000000000000000000000000000000000000000..934864e90da62e7fe2ef90ad30f96dfb5ac44412 --- /dev/null +++ b/include/dt-bindings/reset/stm32mp13-resets.h @@ -0,0 +1,100 @@ +/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */ +/* + * Copyright (C) STMicroelectronics 2018 - All Rights Reserved + * Author: Gabriel Fernandez for STMicroelectronics. + */ + +#ifndef _DT_BINDINGS_STM32MP13_RESET_H_ +#define _DT_BINDINGS_STM32MP13_RESET_H_ + +#define TIM2_R 13568 +#define TIM3_R 13569 +#define TIM4_R 13570 +#define TIM5_R 13571 +#define TIM6_R 13572 +#define TIM7_R 13573 +#define LPTIM1_R 13577 +#define SPI2_R 13579 +#define SPI3_R 13580 +#define USART3_R 13583 +#define UART4_R 13584 +#define UART5_R 13585 +#define UART7_R 13586 +#define UART8_R 13587 +#define I2C1_R 13589 +#define I2C2_R 13590 +#define SPDIF_R 13594 +#define TIM1_R 13632 +#define TIM8_R 13633 +#define SPI1_R 13640 +#define USART6_R 13645 +#define SAI1_R 13648 +#define SAI2_R 13649 +#define DFSDM_R 13652 +#define FDCAN_R 13656 +#define LPTIM2_R 13696 +#define LPTIM3_R 13697 +#define LPTIM4_R 13698 +#define LPTIM5_R 13699 +#define SYSCFG_R 13707 +#define VREF_R 13709 +#define DTS_R 13712 +#define PMBCTRL_R 13713 +#define LTDC_R 13760 +#define DCMIPP_R 13761 +#define DDRPERFM_R 13768 +#define USBPHY_R 13776 +#define STGEN_R 13844 +#define USART1_R 13888 +#define USART2_R 13889 +#define SPI4_R 13890 +#define SPI5_R 13891 +#define I2C3_R 13892 +#define I2C4_R 13893 +#define I2C5_R 13894 +#define TIM12_R 13895 +#define TIM13_R 13896 +#define TIM14_R 13897 +#define TIM15_R 13898 +#define TIM16_R 13899 +#define TIM17_R 13900 +#define DMA1_R 13952 +#define DMA2_R 13953 +#define DMAMUX1_R 13954 +#define DMA3_R 13955 +#define DMAMUX2_R 13956 +#define ADC1_R 13957 +#define ADC2_R 13958 +#define USBO_R 13960 +#define GPIOA_R 14080 +#define GPIOB_R 14081 +#define GPIOC_R 14082 +#define GPIOD_R 14083 +#define GPIOE_R 14084 +#define GPIOF_R 14085 +#define GPIOG_R 14086 +#define GPIOH_R 14087 +#define GPIOI_R 14088 +#define TSC_R 14095 +#define PKA_R 14146 +#define SAES_R 14147 +#define CRYP1_R 14148 +#define HASH1_R 14149 +#define RNG1_R 14150 +#define AXIMC_R 14160 +#define MDMA_R 14208 +#define MCE_R 14209 +#define ETH1MAC_R 14218 +#define FMC_R 14220 +#define QSPI_R 14222 +#define SDMMC1_R 14224 +#define SDMMC2_R 14225 +#define CRC1_R 14228 +#define USBH_R 14232 +#define ETH2MAC_R 14238 + +/* SCMI reset domain identifiers */ +#define RST_SCMI_LTDC 0 +#define RST_SCMI_MDMA 1 + +#endif /* _DT_BINDINGS_STM32MP13_RESET_H_ */ diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 03465db16b68950816e09035c4a844e86e0e494c..4f82a5bc6d987fe9ef1f6ddfb253d9ba0e087fc2 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -520,9 +520,6 @@ int acpi_check_resource_conflict(const struct resource *res); int acpi_check_region(resource_size_t start, resource_size_t n, const char *name); -acpi_status acpi_release_memory(acpi_handle handle, struct resource *res, - u32 level); - int acpi_resources_are_enforced(void); #ifdef CONFIG_HIBERNATION @@ -550,10 +547,16 @@ struct acpi_osc_context { acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context); -/* Indexes into _OSC Capabilities Buffer (DWORDs 2 & 3 are device-specific) */ +/* Number of _OSC capability DWORDS depends on bridge type */ +#define OSC_PCI_CAPABILITY_DWORDS 3 +#define OSC_CXL_CAPABILITY_DWORDS 5 + +/* Indexes into _OSC Capabilities Buffer (DWORDs 2 to 5 are device-specific) */ #define OSC_QUERY_DWORD 0 /* DWORD 1 */ #define OSC_SUPPORT_DWORD 1 /* DWORD 2 */ #define OSC_CONTROL_DWORD 2 /* DWORD 3 */ +#define OSC_EXT_SUPPORT_DWORD 3 /* DWORD 4 */ +#define OSC_EXT_CONTROL_DWORD 4 /* DWORD 5 */ /* _OSC Capabilities DWORD 1: Query/Control and Error Returns (generic) */ #define OSC_QUERY_ENABLE 0x00000001 /* input */ @@ -610,6 +613,29 @@ extern u32 osc_sb_native_usb4_control; #define OSC_PCI_EXPRESS_LTR_CONTROL 0x00000020 #define OSC_PCI_EXPRESS_DPC_CONTROL 0x00000080 +/* CXL _OSC: Capabilities DWORD 4: Support Field */ +#define OSC_CXL_1_1_PORT_REG_ACCESS_SUPPORT 0x00000001 +#define OSC_CXL_2_0_PORT_DEV_REG_ACCESS_SUPPORT 0x00000002 +#define OSC_CXL_PROTOCOL_ERR_REPORTING_SUPPORT 0x00000004 +#define OSC_CXL_NATIVE_HP_SUPPORT 0x00000008 + +/* CXL _OSC: Capabilities DWORD 5: Control Field */ +#define OSC_CXL_ERROR_REPORTING_CONTROL 0x00000001 + +static inline u32 acpi_osc_ctx_get_pci_control(struct acpi_osc_context *context) +{ + u32 *ret = context->ret.pointer; + + return ret[OSC_CONTROL_DWORD]; +} + +static inline u32 acpi_osc_ctx_get_cxl_control(struct acpi_osc_context *context) +{ + u32 *ret = context->ret.pointer; + + return ret[OSC_EXT_CONTROL_DWORD]; +} + #define ACPI_GSB_ACCESS_ATTRIB_QUICK 0x00000002 #define ACPI_GSB_ACCESS_ATTRIB_SEND_RCV 0x00000004 #define ACPI_GSB_ACCESS_ATTRIB_BYTE 0x00000006 @@ -1006,6 +1032,17 @@ static inline int acpi_register_wakeup_handler(int wake_irq, static inline void acpi_unregister_wakeup_handler( bool (*wakeup)(void *context), void *context) { } +struct acpi_osc_context; +static inline u32 acpi_osc_ctx_get_pci_control(struct acpi_osc_context *context) +{ + return 0; +} + +static inline u32 acpi_osc_ctx_get_cxl_control(struct acpi_osc_context *context) +{ + return 0; +} + #endif /* !CONFIG_ACPI */ #ifdef CONFIG_ACPI_HOTPLUG_IOAPIC diff --git a/include/linux/amba/bus.h b/include/linux/amba/bus.h index 6562f543c3e04d07ef93613439e1736e263eb598..2ddce9bcd00ed2dd23e6088e0b665a2f2ba8eb21 100644 --- a/include/linux/amba/bus.h +++ b/include/linux/amba/bus.h @@ -79,6 +79,14 @@ struct amba_driver { void (*remove)(struct amba_device *); void (*shutdown)(struct amba_device *); const struct amba_id *id_table; + /* + * For most device drivers, no need to care about this flag as long as + * all DMAs are handled through the kernel DMA API. For some special + * ones, for example VFIO drivers, they know how to manage the DMA + * themselves and set this flag so that the IOMMU layer will allow them + * to setup and manage their own I/O address space. + */ + bool driver_managed_dma; }; /* diff --git a/include/linux/bootconfig.h b/include/linux/bootconfig.h index a4665c7ab07cb754f2b7fb71c443eadc3b11c1bd..1611f9db878e763699519a8b8efa3b714654e1e0 100644 --- a/include/linux/bootconfig.h +++ b/include/linux/bootconfig.h @@ -289,4 +289,14 @@ int __init xbc_get_info(int *node_size, size_t *data_size); /* XBC cleanup data structures */ void __init xbc_exit(void); +/* XBC embedded bootconfig data in kernel */ +#ifdef CONFIG_BOOT_CONFIG_EMBED +const char * __init xbc_get_embedded_bootconfig(size_t *size); +#else +static inline const char *xbc_get_embedded_bootconfig(size_t *size) +{ + return NULL; +} +#endif + #endif diff --git a/include/linux/compat.h b/include/linux/compat.h index 01fddf72a81f081d4392b56aa3734123f8fa7a29..594357881b0b3b5a0e06d9c07a6626fc4a517a2a 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h @@ -259,6 +259,37 @@ struct compat_rlimit { compat_ulong_t rlim_max; }; +#ifdef __ARCH_NEED_COMPAT_FLOCK64_PACKED +#define __ARCH_COMPAT_FLOCK64_PACK __attribute__((packed)) +#else +#define __ARCH_COMPAT_FLOCK64_PACK +#endif + +struct compat_flock { + short l_type; + short l_whence; + compat_off_t l_start; + compat_off_t l_len; +#ifdef __ARCH_COMPAT_FLOCK_EXTRA_SYSID + __ARCH_COMPAT_FLOCK_EXTRA_SYSID +#endif + compat_pid_t l_pid; +#ifdef __ARCH_COMPAT_FLOCK_PAD + __ARCH_COMPAT_FLOCK_PAD +#endif +}; + +struct compat_flock64 { + short l_type; + short l_whence; + compat_loff_t l_start; + compat_loff_t l_len; + compat_pid_t l_pid; +#ifdef __ARCH_COMPAT_FLOCK64_PAD + __ARCH_COMPAT_FLOCK64_PAD +#endif +} __ARCH_COMPAT_FLOCK64_PACK; + struct compat_rusage { struct old_timeval32 ru_utime; struct old_timeval32 ru_stime; @@ -896,6 +927,43 @@ asmlinkage long compat_sys_sigaction(int sig, /* obsolete: net/socket.c */ asmlinkage long compat_sys_socketcall(int call, u32 __user *args); +#ifdef __ARCH_WANT_COMPAT_TRUNCATE64 +asmlinkage long compat_sys_truncate64(const char __user *pathname, compat_arg_u64(len)); +#endif + +#ifdef __ARCH_WANT_COMPAT_FTRUNCATE64 +asmlinkage long compat_sys_ftruncate64(unsigned int fd, compat_arg_u64(len)); +#endif + +#ifdef __ARCH_WANT_COMPAT_FALLOCATE +asmlinkage long compat_sys_fallocate(int fd, int mode, compat_arg_u64(offset), + compat_arg_u64(len)); +#endif + +#ifdef __ARCH_WANT_COMPAT_PREAD64 +asmlinkage long compat_sys_pread64(unsigned int fd, char __user *buf, size_t count, + compat_arg_u64(pos)); +#endif + +#ifdef __ARCH_WANT_COMPAT_PWRITE64 +asmlinkage long compat_sys_pwrite64(unsigned int fd, const char __user *buf, size_t count, + compat_arg_u64(pos)); +#endif + +#ifdef __ARCH_WANT_COMPAT_SYNC_FILE_RANGE +asmlinkage long compat_sys_sync_file_range(int fd, compat_arg_u64(pos), + compat_arg_u64(nbytes), unsigned int flags); +#endif + +#ifdef __ARCH_WANT_COMPAT_FADVISE64_64 +asmlinkage long compat_sys_fadvise64_64(int fd, compat_arg_u64(pos), + compat_arg_u64(len), int advice); +#endif + +#ifdef __ARCH_WANT_COMPAT_READAHEAD +asmlinkage long compat_sys_readahead(int fd, compat_arg_u64(offset), size_t count); +#endif + #endif /* CONFIG_ARCH_HAS_SYSCALL_WRAPPER */ /** diff --git a/include/linux/dax.h b/include/linux/dax.h index 9fc5f99a0ae2c02a471c679ae04feb733aafe9fa..e7b81634c52add9c673da3597703a04f0f055701 100644 --- a/include/linux/dax.h +++ b/include/linux/dax.h @@ -14,6 +14,11 @@ struct iomap_ops; struct iomap_iter; struct iomap; +enum dax_access_mode { + DAX_ACCESS, + DAX_RECOVERY_WRITE, +}; + struct dax_operations { /* * direct_access: translate a device-relative @@ -21,7 +26,7 @@ struct dax_operations { * number of pages available for DAX at that pfn. */ long (*direct_access)(struct dax_device *, pgoff_t, long, - void **, pfn_t *); + enum dax_access_mode, void **, pfn_t *); /* * Validate whether this device is usable as an fsdax backing * device. @@ -30,6 +35,12 @@ struct dax_operations { sector_t, sector_t); /* zero_page_range: required operation. Zero page range */ int (*zero_page_range)(struct dax_device *, pgoff_t, size_t); + /* + * recovery_write: recover a poisoned range by DAX device driver + * capable of clearing poison. + */ + size_t (*recovery_write)(struct dax_device *dax_dev, pgoff_t pgoff, + void *addr, size_t bytes, struct iov_iter *iter); }; #if IS_ENABLED(CONFIG_DAX) @@ -40,6 +51,8 @@ void dax_write_cache(struct dax_device *dax_dev, bool wc); bool dax_write_cache_enabled(struct dax_device *dax_dev); bool dax_synchronous(struct dax_device *dax_dev); void set_dax_synchronous(struct dax_device *dax_dev); +size_t dax_recovery_write(struct dax_device *dax_dev, pgoff_t pgoff, + void *addr, size_t bytes, struct iov_iter *i); /* * Check if given mapping is supported by the file / underlying device. */ @@ -87,6 +100,11 @@ static inline bool daxdev_mapping_supported(struct vm_area_struct *vma, { return !(vma->vm_flags & VM_SYNC); } +static inline size_t dax_recovery_write(struct dax_device *dax_dev, + pgoff_t pgoff, void *addr, size_t bytes, struct iov_iter *i) +{ + return 0; +} #endif void set_dax_nocache(struct dax_device *dax_dev); @@ -178,7 +196,7 @@ static inline void dax_read_unlock(int id) bool dax_alive(struct dax_device *dax_dev); void *dax_get_private(struct dax_device *dax_dev); long dax_direct_access(struct dax_device *dax_dev, pgoff_t pgoff, long nr_pages, - void **kaddr, pfn_t *pfn); + enum dax_access_mode mode, void **kaddr, pfn_t *pfn); size_t dax_copy_from_iter(struct dax_device *dax_dev, pgoff_t pgoff, void *addr, size_t bytes, struct iov_iter *i); size_t dax_copy_to_iter(struct dax_device *dax_dev, pgoff_t pgoff, void *addr, diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h index c2a3758c4aaaf7489a995872bae0835c6cab105e..47a01c7cffdf3694ebcfc2653cf468e01a8698fc 100644 --- a/include/linux/device-mapper.h +++ b/include/linux/device-mapper.h @@ -20,6 +20,7 @@ struct dm_table; struct dm_report_zones_args; struct mapped_device; struct bio_vec; +enum dax_access_mode; /* * Type of table, mapped_device's mempool and request_queue @@ -146,10 +147,19 @@ typedef int (*dm_busy_fn) (struct dm_target *ti); * >= 0 : the number of bytes accessible at the address */ typedef long (*dm_dax_direct_access_fn) (struct dm_target *ti, pgoff_t pgoff, - long nr_pages, void **kaddr, pfn_t *pfn); + long nr_pages, enum dax_access_mode node, void **kaddr, + pfn_t *pfn); typedef int (*dm_dax_zero_page_range_fn)(struct dm_target *ti, pgoff_t pgoff, size_t nr_pages); +/* + * Returns: + * != 0 : number of bytes transferred + * 0 : recovery write failed + */ +typedef size_t (*dm_dax_recovery_write_fn)(struct dm_target *ti, pgoff_t pgoff, + void *addr, size_t bytes, struct iov_iter *i); + void dm_error(const char *message); struct dm_dev { @@ -199,6 +209,7 @@ struct target_type { dm_io_hints_fn io_hints; dm_dax_direct_access_fn direct_access; dm_dax_zero_page_range_fn dax_zero_page_range; + dm_dax_recovery_write_fn dax_recovery_write; /* For internal device-mapper use. */ struct list_head list; diff --git a/include/linux/device.h b/include/linux/device.h index 93459724dcdebfbf64d56aebab5070bda6015d95..073f1b0126ac9559f73c77c8dd95f6881c209452 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -400,8 +400,6 @@ struct dev_msi_info { * This identifies the device type and carries type-specific * information. * @mutex: Mutex to synchronize calls to its driver. - * @lockdep_mutex: An optional debug lock that a subsystem can use as a - * peer lock to gain localized lockdep coverage of the device_lock. * @bus: Type of bus device is on. * @driver: Which driver has allocated this * @platform_data: Platform data specific to the device. @@ -499,9 +497,6 @@ struct device { core doesn't touch it */ void *driver_data; /* Driver data, set and get with dev_set_drvdata/dev_get_drvdata */ -#ifdef CONFIG_PROVE_LOCKING - struct mutex lockdep_mutex; -#endif struct mutex mutex; /* mutex to synchronize calls to * its driver. */ @@ -850,6 +845,49 @@ static inline bool device_supports_offline(struct device *dev) return dev->bus && dev->bus->offline && dev->bus->online; } +#define __device_lock_set_class(dev, name, key) \ +do { \ + struct device *__d2 __maybe_unused = dev; \ + lock_set_class(&__d2->mutex.dep_map, name, key, 0, _THIS_IP_); \ +} while (0) + +/** + * device_lock_set_class - Specify a temporary lock class while a device + * is attached to a driver + * @dev: device to modify + * @key: lock class key data + * + * This must be called with the device_lock() already held, for example + * from driver ->probe(). Take care to only override the default + * lockdep_no_validate class. + */ +#ifdef CONFIG_LOCKDEP +#define device_lock_set_class(dev, key) \ +do { \ + struct device *__d = dev; \ + dev_WARN_ONCE(__d, !lockdep_match_class(&__d->mutex, \ + &__lockdep_no_validate__), \ + "overriding existing custom lock class\n"); \ + __device_lock_set_class(__d, #key, key); \ +} while (0) +#else +#define device_lock_set_class(dev, key) __device_lock_set_class(dev, #key, key) +#endif + +/** + * device_lock_reset_class - Return a device to the default lockdep novalidate state + * @dev: device to modify + * + * This must be called with the device_lock() already held, for example + * from driver ->remove(). + */ +#define device_lock_reset_class(dev) \ +do { \ + struct device *__d __maybe_unused = dev; \ + lock_set_novalidate_class(&__d->mutex.dep_map, "&dev->mutex", \ + _THIS_IP_); \ +} while (0) + void lock_device_hotplug(void); void unlock_device_hotplug(void); int lock_device_hotplug_sysfs(void); diff --git a/include/linux/device/bus.h b/include/linux/device/bus.h index a039ab809753fd46c94d61e38c345daa281f620e..d8b29ccd07e564a2422276553e497013ab0a8a50 100644 --- a/include/linux/device/bus.h +++ b/include/linux/device/bus.h @@ -59,6 +59,8 @@ struct fwnode_handle; * bus supports. * @dma_configure: Called to setup DMA configuration on a device on * this bus. + * @dma_cleanup: Called to cleanup DMA configuration on a device on + * this bus. * @pm: Power management operations of this bus, callback the specific * device driver's pm-ops. * @iommu_ops: IOMMU specific operations for this bus, used to attach IOMMU @@ -103,6 +105,7 @@ struct bus_type { int (*num_vf)(struct device *dev); int (*dma_configure)(struct device *dev); + void (*dma_cleanup)(struct device *dev); const struct dev_pm_ops *pm; diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h index 842d4f7ca752d0bc490b0acb4a1013649bc422f1..b46b88e6aa0d114d38b690dd503a0e7a5ef4737c 100644 --- a/include/linux/dmaengine.h +++ b/include/linux/dmaengine.h @@ -870,7 +870,6 @@ struct dma_device { struct device *dev; struct module *owner; struct ida chan_ida; - struct mutex chan_mutex; /* to protect chan_ida */ u32 src_addr_widths; u32 dst_addr_widths; @@ -1031,6 +1030,14 @@ static inline struct dma_async_tx_descriptor *dmaengine_prep_interleaved_dma( return chan->device->device_prep_interleaved_dma(chan, xt, flags); } +/** + * dmaengine_prep_dma_memset() - Prepare a DMA memset descriptor. + * @chan: The channel to be used for this descriptor + * @dest: Address of buffer to be set + * @value: Treated as a single byte value that fills the destination buffer + * @len: The total size of dest + * @flags: DMA engine flags + */ static inline struct dma_async_tx_descriptor *dmaengine_prep_dma_memset( struct dma_chan *chan, dma_addr_t dest, int value, size_t len, unsigned long flags) diff --git a/include/linux/fsl/mc.h b/include/linux/fsl/mc.h index 7b6c42bfb660fc200a37586577428917d1fda070..27efef8affb1a4756052f6bef1cde0987840bcd0 100644 --- a/include/linux/fsl/mc.h +++ b/include/linux/fsl/mc.h @@ -32,6 +32,13 @@ struct fsl_mc_io; * @shutdown: Function called at shutdown time to quiesce the device * @suspend: Function called when a device is stopped * @resume: Function called when a device is resumed + * @driver_managed_dma: Device driver doesn't use kernel DMA API for DMA. + * For most device drivers, no need to care about this flag + * as long as all DMAs are handled through the kernel DMA API. + * For some special ones, for example VFIO drivers, they know + * how to manage the DMA themselves and set this flag so that + * the IOMMU layer will allow them to setup and manage their + * own I/O address space. * * Generic DPAA device driver object for device drivers that are registered * with a DPRC bus. This structure is to be embedded in each device-specific @@ -45,6 +52,7 @@ struct fsl_mc_driver { void (*shutdown)(struct fsl_mc_device *dev); int (*suspend)(struct fsl_mc_device *dev, pm_message_t state); int (*resume)(struct fsl_mc_device *dev); + bool driver_managed_dma; }; #define to_fsl_mc_driver(_drv) \ diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h index 3eb03d88320dce89db56ac5c82c02d6bd3542e03..979f6bfa2c25ccbbc1f06b46414f2c6f908c4f76 100644 --- a/include/linux/ftrace.h +++ b/include/linux/ftrace.h @@ -452,8 +452,8 @@ static inline void stack_tracer_enable(void) { } #ifdef CONFIG_DYNAMIC_FTRACE -int ftrace_arch_code_modify_prepare(void); -int ftrace_arch_code_modify_post_process(void); +void ftrace_arch_code_modify_prepare(void); +void ftrace_arch_code_modify_post_process(void); enum ftrace_bug_type { FTRACE_BUG_UNKNOWN, diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index 09792529cff2c50a701bd2cb6d8e7f50049a1bb0..654184cdb719c3085782854fc3e08ccd3b8c3f6f 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -502,6 +502,18 @@ struct gpio_chip { */ int (*of_xlate)(struct gpio_chip *gc, const struct of_phandle_args *gpiospec, u32 *flags); + + /** + * @of_gpio_ranges_fallback: + * + * Optional hook for the case that no gpio-ranges property is defined + * within the device tree node "np" (usually DT before introduction + * of gpio-ranges). So this callback is helpful to provide the + * necessary backward compatibility for the pin ranges. + */ + int (*of_gpio_ranges_fallback)(struct gpio_chip *gc, + struct device_node *np); + #endif /* CONFIG_OF_GPIO */ }; diff --git a/include/linux/hisi_acc_qm.h b/include/linux/hisi_acc_qm.h index 177f7b7cd4147a075fee782c496e3e22277d3f89..6cabafffd0ddaa228b5d1d13e098e79a90250037 100644 --- a/include/linux/hisi_acc_qm.h +++ b/include/linux/hisi_acc_qm.h @@ -168,6 +168,12 @@ enum qm_vf_state { QM_NOT_READY, }; +struct dfx_diff_registers { + u32 *regs; + u32 reg_offset; + u32 reg_len; +}; + struct qm_dfx { atomic64_t err_irq_cnt; atomic64_t aeq_irq_cnt; @@ -190,6 +196,11 @@ struct qm_debug { struct dentry *debug_root; struct dentry *qm_d; struct debugfs_file files[DEBUG_FILE_NUM]; + unsigned int *qm_last_words; + /* ACC engines recoreding last regs */ + unsigned int *last_words; + struct dfx_diff_registers *qm_diff_regs; + struct dfx_diff_registers *acc_diff_regs; }; struct qm_shaper_factor { @@ -243,6 +254,7 @@ struct hisi_qm_err_ini { void (*open_sva_prefetch)(struct hisi_qm *qm); void (*close_sva_prefetch)(struct hisi_qm *qm); void (*log_dev_hw_err)(struct hisi_qm *qm, u32 err_sts); + void (*show_last_dfx_regs)(struct hisi_qm *qm); void (*err_info_init)(struct hisi_qm *qm); }; @@ -433,21 +445,22 @@ int hisi_qm_init(struct hisi_qm *qm); void hisi_qm_uninit(struct hisi_qm *qm); int hisi_qm_start(struct hisi_qm *qm); int hisi_qm_stop(struct hisi_qm *qm, enum qm_stop_reason r); -struct hisi_qp *hisi_qm_create_qp(struct hisi_qm *qm, u8 alg_type); int hisi_qm_start_qp(struct hisi_qp *qp, unsigned long arg); int hisi_qm_stop_qp(struct hisi_qp *qp); -void hisi_qm_release_qp(struct hisi_qp *qp); int hisi_qp_send(struct hisi_qp *qp, const void *msg); -int hisi_qm_get_free_qp_num(struct hisi_qm *qm); -int hisi_qm_get_vft(struct hisi_qm *qm, u32 *base, u32 *number); void hisi_qm_debug_init(struct hisi_qm *qm); -enum qm_hw_ver hisi_qm_get_hw_version(struct pci_dev *pdev); void hisi_qm_debug_regs_clear(struct hisi_qm *qm); int hisi_qm_sriov_enable(struct pci_dev *pdev, int max_vfs); int hisi_qm_sriov_disable(struct pci_dev *pdev, bool is_frozen); int hisi_qm_sriov_configure(struct pci_dev *pdev, int num_vfs); void hisi_qm_dev_err_init(struct hisi_qm *qm); void hisi_qm_dev_err_uninit(struct hisi_qm *qm); +int hisi_qm_diff_regs_init(struct hisi_qm *qm, + struct dfx_diff_registers *dregs, int reg_len); +void hisi_qm_diff_regs_uninit(struct hisi_qm *qm, int reg_len); +void hisi_qm_acc_diff_regs_dump(struct hisi_qm *qm, struct seq_file *s, + struct dfx_diff_registers *dregs, int regs_len); + pci_ers_result_t hisi_qm_dev_err_detected(struct pci_dev *pdev, pci_channel_state_t state); pci_ers_result_t hisi_qm_dev_slot_reset(struct pci_dev *pdev); diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h index 0f2894d0133371bcf2bc7a27e9dd7e245f9f913f..e4cff27d1198c24873da7565da8ec873eb837077 100644 --- a/include/linux/hugetlb.h +++ b/include/linux/hugetlb.h @@ -528,6 +528,11 @@ unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr, unsigned long flags); #endif /* HAVE_ARCH_HUGETLB_UNMAPPED_AREA */ +unsigned long +generic_hugetlb_get_unmapped_area(struct file *file, unsigned long addr, + unsigned long len, unsigned long pgoff, + unsigned long flags); + /* * huegtlb page specific state flags. These flags are located in page.private * of the hugetlb head page. Functions created via the below macros should be diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h index fe2e0179ed51e3a3b6271dd04e200c0c25129193..a2464295c14acd1f354b07eb590ac6b06388e32f 100644 --- a/include/linux/hyperv.h +++ b/include/linux/hyperv.h @@ -230,15 +230,19 @@ static inline u32 hv_get_avail_to_write_percent( * two 16 bit quantities: major_number. minor_number. * * 0 . 13 (Windows Server 2008) - * 1 . 1 (Windows 7) - * 2 . 4 (Windows 8) - * 3 . 0 (Windows 8 R2) + * 1 . 1 (Windows 7, WS2008 R2) + * 2 . 4 (Windows 8, WS2012) + * 3 . 0 (Windows 8.1, WS2012 R2) * 4 . 0 (Windows 10) * 4 . 1 (Windows 10 RS3) * 5 . 0 (Newer Windows 10) * 5 . 1 (Windows 10 RS4) * 5 . 2 (Windows Server 2019, RS5) * 5 . 3 (Windows Server 2022) + * + * The WS2008 and WIN7 versions are listed here for + * completeness but are no longer supported in the + * Linux kernel. */ #define VERSION_WS2008 ((0 << 16) | (13)) @@ -788,6 +792,7 @@ struct vmbus_requestor { #define VMBUS_NO_RQSTOR U64_MAX #define VMBUS_RQST_ERROR (U64_MAX - 1) +#define VMBUS_RQST_ADDR_ANY U64_MAX /* NetVSC-specific */ #define VMBUS_RQST_ID_NO_RESPONSE (U64_MAX - 2) /* StorVSC-specific */ @@ -1041,13 +1046,36 @@ struct vmbus_channel { u32 max_pkt_size; }; +#define lock_requestor(channel, flags) \ +do { \ + struct vmbus_requestor *rqstor = &(channel)->requestor; \ + \ + spin_lock_irqsave(&rqstor->req_lock, flags); \ +} while (0) + +static __always_inline void unlock_requestor(struct vmbus_channel *channel, + unsigned long flags) +{ + struct vmbus_requestor *rqstor = &channel->requestor; + + spin_unlock_irqrestore(&rqstor->req_lock, flags); +} + u64 vmbus_next_request_id(struct vmbus_channel *channel, u64 rqst_addr); +u64 __vmbus_request_addr_match(struct vmbus_channel *channel, u64 trans_id, + u64 rqst_addr); +u64 vmbus_request_addr_match(struct vmbus_channel *channel, u64 trans_id, + u64 rqst_addr); u64 vmbus_request_addr(struct vmbus_channel *channel, u64 trans_id); +static inline bool is_hvsock_offer(const struct vmbus_channel_offer_channel *o) +{ + return !!(o->offer.chn_flags & VMBUS_CHANNEL_TLNPI_PROVIDER_OFFER); +} + static inline bool is_hvsock_channel(const struct vmbus_channel *c) { - return !!(c->offermsg.offer.chn_flags & - VMBUS_CHANNEL_TLNPI_PROVIDER_OFFER); + return is_hvsock_offer(&c->offermsg); } static inline bool is_sub_channel(const struct vmbus_channel *c) @@ -1161,6 +1189,13 @@ extern int vmbus_open(struct vmbus_channel *channel, extern void vmbus_close(struct vmbus_channel *channel); +extern int vmbus_sendpacket_getid(struct vmbus_channel *channel, + void *buffer, + u32 bufferLen, + u64 requestid, + u64 *trans_id, + enum vmbus_packet_type type, + u32 flags); extern int vmbus_sendpacket(struct vmbus_channel *channel, void *buffer, u32 bufferLen, @@ -1451,12 +1486,14 @@ void vmbus_free_mmio(resource_size_t start, resource_size_t size); 0x80, 0x2e, 0x27, 0xed, 0xe1, 0x9f) /* - * Linux doesn't support the 3 devices: the first two are for - * Automatic Virtual Machine Activation, and the third is for - * Remote Desktop Virtualization. + * Linux doesn't support these 4 devices: the first two are for + * Automatic Virtual Machine Activation, the third is for + * Remote Desktop Virtualization, and the fourth is Initial + * Machine Configuration (IMC) used only by Windows guests. * {f8e65716-3cb3-4a06-9a60-1889c5cccab5} * {3375baf4-9e15-4b30-b765-67acb10d607b} * {276aacf4-ac15-426c-98dd-7521ad3f01fe} + * {c376c1c3-d276-48d2-90a9-c04748072c60} */ #define HV_AVMA1_GUID \ @@ -1471,6 +1508,10 @@ void vmbus_free_mmio(resource_size_t start, resource_size_t size); .guid = GUID_INIT(0x276aacf4, 0xac15, 0x426c, 0x98, 0xdd, \ 0x75, 0x21, 0xad, 0x3f, 0x01, 0xfe) +#define HV_IMC_GUID \ + .guid = GUID_INIT(0xc376c1c3, 0xd276, 0x48d2, 0x90, 0xa9, \ + 0xc0, 0x47, 0x48, 0x07, 0x2c, 0x60) + /* * Common header for Hyper-V ICs */ @@ -1663,56 +1704,34 @@ static inline u32 hv_pkt_datalen(const struct vmpacket_descriptor *desc) return (desc->len8 << 3) - (desc->offset8 << 3); } - -struct vmpacket_descriptor * -hv_pkt_iter_first_raw(struct vmbus_channel *channel); +/* Get packet length associated with descriptor */ +static inline u32 hv_pkt_len(const struct vmpacket_descriptor *desc) +{ + return desc->len8 << 3; +} struct vmpacket_descriptor * hv_pkt_iter_first(struct vmbus_channel *channel); struct vmpacket_descriptor * __hv_pkt_iter_next(struct vmbus_channel *channel, - const struct vmpacket_descriptor *pkt, - bool copy); + const struct vmpacket_descriptor *pkt); void hv_pkt_iter_close(struct vmbus_channel *channel); static inline struct vmpacket_descriptor * -hv_pkt_iter_next_pkt(struct vmbus_channel *channel, - const struct vmpacket_descriptor *pkt, - bool copy) +hv_pkt_iter_next(struct vmbus_channel *channel, + const struct vmpacket_descriptor *pkt) { struct vmpacket_descriptor *nxt; - nxt = __hv_pkt_iter_next(channel, pkt, copy); + nxt = __hv_pkt_iter_next(channel, pkt); if (!nxt) hv_pkt_iter_close(channel); return nxt; } -/* - * Get next packet descriptor without copying it out of the ring buffer - * If at end of list, return NULL and update host. - */ -static inline struct vmpacket_descriptor * -hv_pkt_iter_next_raw(struct vmbus_channel *channel, - const struct vmpacket_descriptor *pkt) -{ - return hv_pkt_iter_next_pkt(channel, pkt, false); -} - -/* - * Get next packet descriptor from iterator - * If at end of list, return NULL and update host. - */ -static inline struct vmpacket_descriptor * -hv_pkt_iter_next(struct vmbus_channel *channel, - const struct vmpacket_descriptor *pkt) -{ - return hv_pkt_iter_next_pkt(channel, pkt, true); -} - #define foreach_vmbus_pkt(pkt, channel) \ for (pkt = hv_pkt_iter_first(channel); pkt; \ pkt = hv_pkt_iter_next(channel, pkt)) diff --git a/include/linux/intel-iommu.h b/include/linux/intel-iommu.h index 2f9891cb3d0014a30948a09a59f1366e5715bb28..4f29139bbfc39866c49ed6e0d68532ecb692655e 100644 --- a/include/linux/intel-iommu.h +++ b/include/linux/intel-iommu.h @@ -539,7 +539,8 @@ struct dmar_domain { u8 has_iotlb_device: 1; u8 iommu_coherency: 1; /* indicate coherency of iommu access */ - u8 iommu_snooping: 1; /* indicate snooping control feature */ + u8 force_snooping : 1; /* Create IOPTEs with snoop control */ + u8 set_pte_snp:1; struct list_head devices; /* all devices' list */ struct iova_domain iovad; /* iova's that belong to this domain */ diff --git a/include/linux/intel-svm.h b/include/linux/intel-svm.h index b3b125b332aac78715fcaf73bb9733c7af415c27..207ef06ba3e1d3a1c21091ab745f1d4166266ea1 100644 --- a/include/linux/intel-svm.h +++ b/include/linux/intel-svm.h @@ -9,7 +9,7 @@ #define __INTEL_SVM_H__ /* Page Request Queue depth */ -#define PRQ_ORDER 2 +#define PRQ_ORDER 4 #define PRQ_RING_MASK ((0x1000 << PRQ_ORDER) - 0x20) #define PRQ_DEPTH ((0x1000 << PRQ_ORDER) >> 5) diff --git a/include/linux/iommu.h b/include/linux/iommu.h index 9208eca4b0d1ace8d1d4c4e10216d43b387be44e..5e1afe169549f90877dd6d5d1d77926b7bd3263a 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -103,10 +103,11 @@ static inline bool iommu_is_dma_domain(struct iommu_domain *domain) } enum iommu_cap { - IOMMU_CAP_CACHE_COHERENCY, /* IOMMU can enforce cache coherent DMA - transactions */ + IOMMU_CAP_CACHE_COHERENCY, /* IOMMU_CACHE is supported */ IOMMU_CAP_INTR_REMAP, /* IOMMU supports interrupt isolation */ IOMMU_CAP_NOEXEC, /* IOMMU_NOEXEC flag */ + IOMMU_CAP_PRE_BOOT_PROTECTION, /* Firmware says it used the IOMMU for + DMA protection and we should too */ }; /* These are the possible reserved region types */ @@ -272,6 +273,9 @@ struct iommu_ops { * @iotlb_sync: Flush all queued ranges from the hardware TLBs and empty flush * queue * @iova_to_phys: translate iova to physical address + * @enforce_cache_coherency: Prevent any kind of DMA from bypassing IOMMU_CACHE, + * including no-snoop TLPs on PCIe or other platform + * specific mechanisms. * @enable_nesting: Enable nesting * @set_pgtable_quirks: Set io page table quirks (IO_PGTABLE_QUIRK_*) * @free: Release the domain after use. @@ -300,6 +304,7 @@ struct iommu_domain_ops { phys_addr_t (*iova_to_phys)(struct iommu_domain *domain, dma_addr_t iova); + bool (*enforce_cache_coherency)(struct iommu_domain *domain); int (*enable_nesting)(struct iommu_domain *domain); int (*set_pgtable_quirks)(struct iommu_domain *domain, unsigned long quirks); @@ -407,16 +412,10 @@ static inline const struct iommu_ops *dev_iommu_ops(struct device *dev) return dev->iommu->iommu_dev->ops; } -#define IOMMU_GROUP_NOTIFY_ADD_DEVICE 1 /* Device added */ -#define IOMMU_GROUP_NOTIFY_DEL_DEVICE 2 /* Pre Device removed */ -#define IOMMU_GROUP_NOTIFY_BIND_DRIVER 3 /* Pre Driver bind */ -#define IOMMU_GROUP_NOTIFY_BOUND_DRIVER 4 /* Post Driver bind */ -#define IOMMU_GROUP_NOTIFY_UNBIND_DRIVER 5 /* Pre Driver unbind */ -#define IOMMU_GROUP_NOTIFY_UNBOUND_DRIVER 6 /* Post Driver unbind */ - extern int bus_set_iommu(struct bus_type *bus, const struct iommu_ops *ops); extern int bus_iommu_probe(struct bus_type *bus); extern bool iommu_present(struct bus_type *bus); +extern bool device_iommu_capable(struct device *dev, enum iommu_cap cap); extern bool iommu_capable(struct bus_type *bus, enum iommu_cap cap); extern struct iommu_domain *iommu_domain_alloc(struct bus_type *bus); extern struct iommu_group *iommu_group_get_by_id(int id); @@ -478,10 +477,6 @@ extern int iommu_group_for_each_dev(struct iommu_group *group, void *data, extern struct iommu_group *iommu_group_get(struct device *dev); extern struct iommu_group *iommu_group_ref_get(struct iommu_group *group); extern void iommu_group_put(struct iommu_group *group); -extern int iommu_group_register_notifier(struct iommu_group *group, - struct notifier_block *nb); -extern int iommu_group_unregister_notifier(struct iommu_group *group, - struct notifier_block *nb); extern int iommu_register_device_fault_handler(struct device *dev, iommu_dev_fault_handler_t handler, void *data); @@ -675,6 +670,13 @@ struct iommu_sva *iommu_sva_bind_device(struct device *dev, void iommu_sva_unbind_device(struct iommu_sva *handle); u32 iommu_sva_get_pasid(struct iommu_sva *handle); +int iommu_device_use_default_domain(struct device *dev); +void iommu_device_unuse_default_domain(struct device *dev); + +int iommu_group_claim_dma_owner(struct iommu_group *group, void *owner); +void iommu_group_release_dma_owner(struct iommu_group *group); +bool iommu_group_dma_owner_claimed(struct iommu_group *group); + #else /* CONFIG_IOMMU_API */ struct iommu_ops {}; @@ -689,6 +691,11 @@ static inline bool iommu_present(struct bus_type *bus) return false; } +static inline bool device_iommu_capable(struct device *dev, enum iommu_cap cap) +{ + return false; +} + static inline bool iommu_capable(struct bus_type *bus, enum iommu_cap cap) { return false; @@ -871,18 +878,6 @@ static inline void iommu_group_put(struct iommu_group *group) { } -static inline int iommu_group_register_notifier(struct iommu_group *group, - struct notifier_block *nb) -{ - return -ENODEV; -} - -static inline int iommu_group_unregister_notifier(struct iommu_group *group, - struct notifier_block *nb) -{ - return 0; -} - static inline int iommu_register_device_fault_handler(struct device *dev, iommu_dev_fault_handler_t handler, @@ -1031,6 +1026,30 @@ static inline struct iommu_fwspec *dev_iommu_fwspec_get(struct device *dev) { return NULL; } + +static inline int iommu_device_use_default_domain(struct device *dev) +{ + return 0; +} + +static inline void iommu_device_unuse_default_domain(struct device *dev) +{ +} + +static inline int +iommu_group_claim_dma_owner(struct iommu_group *group, void *owner) +{ + return -ENODEV; +} + +static inline void iommu_group_release_dma_owner(struct iommu_group *group) +{ +} + +static inline bool iommu_group_dma_owner_claimed(struct iommu_group *group) +{ + return false; +} #endif /* CONFIG_IOMMU_API */ /** diff --git a/include/linux/kexec.h b/include/linux/kexec.h index fcd5035209f19a510d8ede7103e1ea161088574c..ce6536f1d269970856ecabad52f7a7604f27e210 100644 --- a/include/linux/kexec.h +++ b/include/linux/kexec.h @@ -219,7 +219,7 @@ struct crash_mem { extern int crash_exclude_mem_range(struct crash_mem *mem, unsigned long long mstart, unsigned long long mend); -extern int crash_prepare_elf64_headers(struct crash_mem *mem, int kernel_map, +extern int crash_prepare_elf64_headers(struct crash_mem *mem, int need_kernel_map, void **addr, unsigned long *sz); #ifndef arch_kexec_apply_relocations_add diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h index 157168769fc26f6855b80ba8a9ac6c33748bd277..55041d2f884de12bcb58b2ddd8124609195607cc 100644 --- a/include/linux/kprobes.h +++ b/include/linux/kprobes.h @@ -424,7 +424,7 @@ void unregister_kretprobe(struct kretprobe *rp); int register_kretprobes(struct kretprobe **rps, int num); void unregister_kretprobes(struct kretprobe **rps, int num); -#ifdef CONFIG_KRETPROBE_ON_RETHOOK +#if defined(CONFIG_KRETPROBE_ON_RETHOOK) || !defined(CONFIG_KRETPROBES) #define kprobe_flush_task(tk) do {} while (0) #else void kprobe_flush_task(struct task_struct *tk); diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h index 37951c17908e717723639edc31869dd27dbc92ad..b6829b970093665db5f1fd783f1617de76409003 100644 --- a/include/linux/lockdep.h +++ b/include/linux/lockdep.h @@ -286,6 +286,9 @@ extern void lock_set_class(struct lockdep_map *lock, const char *name, struct lock_class_key *key, unsigned int subclass, unsigned long ip); +#define lock_set_novalidate_class(l, n, i) \ + lock_set_class(l, n, &__lockdep_no_validate__, 0, i) + static inline void lock_set_subclass(struct lockdep_map *lock, unsigned int subclass, unsigned long ip) { @@ -353,7 +356,8 @@ static inline void lockdep_set_selftest_task(struct task_struct *task) # define lock_acquire(l, s, t, r, c, n, i) do { } while (0) # define lock_release(l, i) do { } while (0) # define lock_downgrade(l, i) do { } while (0) -# define lock_set_class(l, n, k, s, i) do { } while (0) +# define lock_set_class(l, n, key, s, i) do { (void)(key); } while (0) +# define lock_set_novalidate_class(l, n, i) do { } while (0) # define lock_set_subclass(l, s, i) do { } while (0) # define lockdep_init() do { } while (0) # define lockdep_init_map_type(lock, name, key, sub, inner, outer, type) \ diff --git a/include/linux/mfd/hi655x-pmic.h b/include/linux/mfd/hi655x-pmic.h index af5d97239c0d6b945d4cf6dc07a887ca0e30b7b6..6a012784dd1b9b72e09adfef58c169c48a66e007 100644 --- a/include/linux/mfd/hi655x-pmic.h +++ b/include/linux/mfd/hi655x-pmic.h @@ -12,6 +12,8 @@ #ifndef __HI655X_PMIC_H #define __HI655X_PMIC_H +#include + /* Hi655x registers are mapped to memory bus in 4 bytes stride */ #define HI655X_STRIDE 4 #define HI655X_BUS_ADDR(x) ((x) << 2) @@ -53,7 +55,7 @@ struct hi655x_pmic { struct resource *res; struct device *dev; struct regmap *regmap; - int gpio; + struct gpio_desc *gpio; unsigned int ver; struct regmap_irq_chip_data *irq_data; }; diff --git a/include/linux/mfd/mt6359/registers.h b/include/linux/mfd/mt6359/registers.h index 2135c9695918c6807a0cc822fb81f9200f559311..2a4394a27b1ca119c0eac2a8961674bb64c80939 100644 --- a/include/linux/mfd/mt6359/registers.h +++ b/include/linux/mfd/mt6359/registers.h @@ -8,6 +8,8 @@ /* PMIC Registers */ #define MT6359_SWCID 0xa +#define MT6359_TOPSTATUS 0x2a +#define MT6359_TOP_RST_MISC 0x14c #define MT6359_MISC_TOP_INT_CON0 0x188 #define MT6359_MISC_TOP_INT_STATUS0 0x194 #define MT6359_TOP_INT_STATUS0 0x19e diff --git a/include/linux/mfd/tps65218.h b/include/linux/mfd/tps65218.h index f4ca367e34733ab347100ea4ee5d23785ddc6d1c..122e24ddbd4bb1c0da3511f998781698e936cc2d 100644 --- a/include/linux/mfd/tps65218.h +++ b/include/linux/mfd/tps65218.h @@ -1,7 +1,7 @@ /* * linux/mfd/tps65218.h * - * Functions to access TPS65219 power management chip. + * Functions to access TPS65218 power management chip. * * Copyright (C) 2014 Texas Instruments Incorporated - https://www.ti.com/ * diff --git a/include/linux/namei.h b/include/linux/namei.h index e89329bb3134e8b99add6f91db42b9bd3b33185c..caeb08a98536cc43b53652b4ab70d0adb99252c3 100644 --- a/include/linux/namei.h +++ b/include/linux/namei.h @@ -69,6 +69,12 @@ extern struct dentry *lookup_one_len(const char *, struct dentry *, int); extern struct dentry *lookup_one_len_unlocked(const char *, struct dentry *, int); extern struct dentry *lookup_positive_unlocked(const char *, struct dentry *, int); struct dentry *lookup_one(struct user_namespace *, const char *, struct dentry *, int); +struct dentry *lookup_one_unlocked(struct user_namespace *mnt_userns, + const char *name, struct dentry *base, + int len); +struct dentry *lookup_one_positive_unlocked(struct user_namespace *mnt_userns, + const char *name, + struct dentry *base, int len); extern int follow_down_one(struct path *); extern int follow_down(struct path *); diff --git a/include/linux/notifier.h b/include/linux/notifier.h index 87069b8459af99287e3f695b68b5f267a9973074..aef88c2d117366bfc0cab51264312a445cf585e3 100644 --- a/include/linux/notifier.h +++ b/include/linux/notifier.h @@ -150,6 +150,11 @@ extern int raw_notifier_chain_register(struct raw_notifier_head *nh, extern int srcu_notifier_chain_register(struct srcu_notifier_head *nh, struct notifier_block *nb); +extern int atomic_notifier_chain_register_unique_prio( + struct atomic_notifier_head *nh, struct notifier_block *nb); +extern int blocking_notifier_chain_register_unique_prio( + struct blocking_notifier_head *nh, struct notifier_block *nb); + extern int atomic_notifier_chain_unregister(struct atomic_notifier_head *nh, struct notifier_block *nb); extern int blocking_notifier_chain_unregister(struct blocking_notifier_head *nh, @@ -173,6 +178,8 @@ extern int blocking_notifier_call_chain_robust(struct blocking_notifier_head *nh extern int raw_notifier_call_chain_robust(struct raw_notifier_head *nh, unsigned long val_up, unsigned long val_down, void *v); +extern bool atomic_notifier_call_chain_is_empty(struct atomic_notifier_head *nh); + #define NOTIFY_DONE 0x0000 /* Don't care */ #define NOTIFY_OK 0x0001 /* Suits me */ #define NOTIFY_STOP_MASK 0x8000 /* Don't call further */ diff --git a/include/linux/of_irq.h b/include/linux/of_irq.h index aaf219bd0354c9b9336ecd18cfd90d418508807c..83fccd0c9bba219192ea30604071287a399898e1 100644 --- a/include/linux/of_irq.h +++ b/include/linux/of_irq.h @@ -20,12 +20,12 @@ typedef int (*of_irq_init_cb_t)(struct device_node *, struct device_node *); #if defined(CONFIG_PPC32) && defined(CONFIG_PPC_PMAC) extern unsigned int of_irq_workarounds; extern struct device_node *of_irq_dflt_pic; -extern int of_irq_parse_oldworld(struct device_node *device, int index, - struct of_phandle_args *out_irq); +int of_irq_parse_oldworld(const struct device_node *device, int index, + struct of_phandle_args *out_irq); #else /* CONFIG_PPC32 && CONFIG_PPC_PMAC */ #define of_irq_workarounds (0) #define of_irq_dflt_pic (NULL) -static inline int of_irq_parse_oldworld(struct device_node *device, int index, +static inline int of_irq_parse_oldworld(const struct device_node *device, int index, struct of_phandle_args *out_irq) { return -EINVAL; diff --git a/include/linux/pci.h b/include/linux/pci.h index 3266ac08f8ecbbe286917af7736d850477cd3c8b..993674b327171bffdd77ddf648a65a6fb6297b58 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -891,6 +891,13 @@ struct module; * created once it is bound to the driver. * @driver: Driver model structure. * @dynids: List of dynamically added device IDs. + * @driver_managed_dma: Device driver doesn't use kernel DMA API for DMA. + * For most device drivers, no need to care about this flag + * as long as all DMAs are handled through the kernel DMA API. + * For some special ones, for example VFIO drivers, they know + * how to manage the DMA themselves and set this flag so that + * the IOMMU layer will allow them to setup and manage their + * own I/O address space. */ struct pci_driver { struct list_head node; @@ -909,6 +916,7 @@ struct pci_driver { const struct attribute_group **dev_groups; struct device_driver driver; struct pci_dynids dynids; + bool driver_managed_dma; }; static inline struct pci_driver *to_pci_driver(struct device_driver *drv) diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h index 7c96f169d2740ca7c843e24ba76d3d925dedb936..b3d9c744f1e599517abf1b631ee53dd1e195fb17 100644 --- a/include/linux/platform_device.h +++ b/include/linux/platform_device.h @@ -210,6 +210,14 @@ struct platform_driver { struct device_driver driver; const struct platform_device_id *id_table; bool prevent_deferred_probe; + /* + * For most device drivers, no need to care about this flag as long as + * all DMAs are handled through the kernel DMA API. For some special + * ones, for example VFIO drivers, they know how to manage the DMA + * themselves and set this flag so that the IOMMU layer will allow them + * to setup and manage their own I/O address space. + */ + bool driver_managed_dma; }; #define to_platform_driver(drv) (container_of((drv), struct platform_driver, \ @@ -328,8 +336,6 @@ extern int platform_pm_restore(struct device *dev); #define platform_pm_restore NULL #endif -extern int platform_dma_configure(struct device *dev); - #ifdef CONFIG_PM_SLEEP #define USE_PLATFORM_PM_SLEEP_OPS \ .suspend = platform_pm_suspend, \ diff --git a/include/linux/pm.h b/include/linux/pm.h index ffe9419585012b1b490808a4f7de3c0111e0c72a..871c9c49ec9d2b08a7cfbeb76be43906719bfbb2 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h @@ -21,7 +21,6 @@ * Callbacks for platform drivers to implement. */ extern void (*pm_power_off)(void); -extern void (*pm_power_off_prepare)(void); struct device; /* we have a circular dep with device.h */ #ifdef CONFIG_VT_CONSOLE_SLEEP @@ -36,6 +35,15 @@ static inline void pm_vt_switch_unregister(struct device *dev) } #endif /* CONFIG_VT_CONSOLE_SLEEP */ +#ifdef CONFIG_CXL_SUSPEND +bool cxl_mem_active(void); +#else +static inline bool cxl_mem_active(void) +{ + return false; +} +#endif + /* * Device power management */ diff --git a/include/linux/pm_opp.h b/include/linux/pm_opp.h index 0d85a63a1f780c56e086616dbf9f42999aaaa774..6708b4ec244d40d535b99cb7917b14b2e83754c6 100644 --- a/include/linux/pm_opp.h +++ b/include/linux/pm_opp.h @@ -117,18 +117,25 @@ unsigned long dev_pm_opp_get_suspend_opp_freq(struct device *dev); struct dev_pm_opp *dev_pm_opp_find_freq_exact(struct device *dev, unsigned long freq, bool available); -struct dev_pm_opp *dev_pm_opp_find_level_exact(struct device *dev, - unsigned int level); -struct dev_pm_opp *dev_pm_opp_find_level_ceil(struct device *dev, - unsigned int *level); - struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev, unsigned long *freq); struct dev_pm_opp *dev_pm_opp_find_freq_ceil_by_volt(struct device *dev, unsigned long u_volt); +struct dev_pm_opp *dev_pm_opp_find_level_exact(struct device *dev, + unsigned int level); +struct dev_pm_opp *dev_pm_opp_find_level_ceil(struct device *dev, + unsigned int *level); + struct dev_pm_opp *dev_pm_opp_find_freq_ceil(struct device *dev, unsigned long *freq); + +struct dev_pm_opp *dev_pm_opp_find_bw_ceil(struct device *dev, + unsigned int *bw, int index); + +struct dev_pm_opp *dev_pm_opp_find_bw_floor(struct device *dev, + unsigned int *bw, int index); + void dev_pm_opp_put(struct dev_pm_opp *opp); int dev_pm_opp_add(struct device *dev, unsigned long freq, @@ -243,12 +250,6 @@ static inline unsigned long dev_pm_opp_get_suspend_opp_freq(struct device *dev) return 0; } -static inline struct dev_pm_opp *dev_pm_opp_find_freq_exact(struct device *dev, - unsigned long freq, bool available) -{ - return ERR_PTR(-EOPNOTSUPP); -} - static inline struct dev_pm_opp *dev_pm_opp_find_level_exact(struct device *dev, unsigned int level) { @@ -261,6 +262,12 @@ static inline struct dev_pm_opp *dev_pm_opp_find_level_ceil(struct device *dev, return ERR_PTR(-EOPNOTSUPP); } +static inline struct dev_pm_opp *dev_pm_opp_find_freq_exact(struct device *dev, + unsigned long freq, bool available) +{ + return ERR_PTR(-EOPNOTSUPP); +} + static inline struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev, unsigned long *freq) { @@ -279,6 +286,18 @@ static inline struct dev_pm_opp *dev_pm_opp_find_freq_ceil(struct device *dev, return ERR_PTR(-EOPNOTSUPP); } +static inline struct dev_pm_opp *dev_pm_opp_find_bw_ceil(struct device *dev, + unsigned int *bw, int index) +{ + return ERR_PTR(-EOPNOTSUPP); +} + +static inline struct dev_pm_opp *dev_pm_opp_find_bw_floor(struct device *dev, + unsigned int *bw, int index) +{ + return ERR_PTR(-EOPNOTSUPP); +} + static inline void dev_pm_opp_put(struct dev_pm_opp *opp) {} static inline int dev_pm_opp_add(struct device *dev, unsigned long freq, diff --git a/include/linux/reboot.h b/include/linux/reboot.h index a2429648d8315dcbf8e1c52ccb4f867d68e7e49d..e5d9ef886179c0924a12f98ca8e378a1462e3606 100644 --- a/include/linux/reboot.h +++ b/include/linux/reboot.h @@ -7,6 +7,7 @@ #include struct device; +struct sys_off_handler; #define SYS_DOWN 0x0001 /* Notify of system down */ #define SYS_RESTART SYS_DOWN @@ -62,6 +63,95 @@ extern void machine_shutdown(void); struct pt_regs; extern void machine_crash_shutdown(struct pt_regs *); +void do_kernel_power_off(void); + +/* + * sys-off handler API. + */ + +/* + * Standard sys-off priority levels. Users are expected to set priorities + * relative to the standard levels. + * + * SYS_OFF_PRIO_PLATFORM: Use this for platform-level handlers. + * + * SYS_OFF_PRIO_LOW: Use this for handler of last resort. + * + * SYS_OFF_PRIO_DEFAULT: Use this for normal handlers. + * + * SYS_OFF_PRIO_HIGH: Use this for higher priority handlers. + * + * SYS_OFF_PRIO_FIRMWARE: Use this if handler uses firmware call. + */ +#define SYS_OFF_PRIO_PLATFORM -256 +#define SYS_OFF_PRIO_LOW -128 +#define SYS_OFF_PRIO_DEFAULT 0 +#define SYS_OFF_PRIO_HIGH 192 +#define SYS_OFF_PRIO_FIRMWARE 224 + +enum sys_off_mode { + /** + * @SYS_OFF_MODE_POWER_OFF_PREPARE: + * + * Handlers prepare system to be powered off. Handlers are + * allowed to sleep. + */ + SYS_OFF_MODE_POWER_OFF_PREPARE, + + /** + * @SYS_OFF_MODE_POWER_OFF: + * + * Handlers power-off system. Handlers are disallowed to sleep. + */ + SYS_OFF_MODE_POWER_OFF, + + /** + * @SYS_OFF_MODE_RESTART: + * + * Handlers restart system. Handlers are disallowed to sleep. + */ + SYS_OFF_MODE_RESTART, +}; + +/** + * struct sys_off_data - sys-off callback argument + * + * @mode: Mode ID. Currently used only by the sys-off restart mode, + * see enum reboot_mode for the available modes. + * @cb_data: User's callback data. + * @cmd: Command string. Currently used only by the sys-off restart mode, + * NULL otherwise. + */ +struct sys_off_data { + int mode; + void *cb_data; + const char *cmd; +}; + +struct sys_off_handler * +register_sys_off_handler(enum sys_off_mode mode, + int priority, + int (*callback)(struct sys_off_data *data), + void *cb_data); +void unregister_sys_off_handler(struct sys_off_handler *handler); + +int devm_register_sys_off_handler(struct device *dev, + enum sys_off_mode mode, + int priority, + int (*callback)(struct sys_off_data *data), + void *cb_data); + +int devm_register_power_off_handler(struct device *dev, + int (*callback)(struct sys_off_data *data), + void *cb_data); + +int devm_register_restart_handler(struct device *dev, + int (*callback)(struct sys_off_data *data), + void *cb_data); + +int register_platform_power_off(void (*power_off)(void)); +void unregister_platform_power_off(void (*power_off)(void)); + /* * Architecture independent implemenations of sys_reboot commands. */ @@ -70,6 +160,7 @@ extern void kernel_restart_prepare(char *cmd); extern void kernel_restart(char *cmd); extern void kernel_halt(void); extern void kernel_power_off(void); +extern bool kernel_can_power_off(void); void ctrl_alt_del(void); diff --git a/include/linux/sched/mm.h b/include/linux/sched/mm.h index 1ad1f4bfa02556554db80ae5a493be3d08ce994e..8cd975a8bfebc2e7892c58f355ac61f8be2a2f81 100644 --- a/include/linux/sched/mm.h +++ b/include/linux/sched/mm.h @@ -137,7 +137,7 @@ static inline void mm_update_next_owner(struct mm_struct *mm) #ifdef CONFIG_MMU #ifndef arch_get_mmap_end -#define arch_get_mmap_end(addr) (TASK_SIZE) +#define arch_get_mmap_end(addr, len, flags) (TASK_SIZE) #endif #ifndef arch_get_mmap_base @@ -153,6 +153,15 @@ extern unsigned long arch_get_unmapped_area_topdown(struct file *filp, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags); + +unsigned long +generic_get_unmapped_area(struct file *filp, unsigned long addr, + unsigned long len, unsigned long pgoff, + unsigned long flags); +unsigned long +generic_get_unmapped_area_topdown(struct file *filp, unsigned long addr, + unsigned long len, unsigned long pgoff, + unsigned long flags); #else static inline void arch_pick_mmap_layout(struct mm_struct *mm, struct rlimit *rlim_stack) {} diff --git a/include/linux/set_memory.h b/include/linux/set_memory.h index f36be5166c1977a7729760c90a5c91f453c7f32a..369769ce7399d7e31b4252ebbaf13f97647b960a 100644 --- a/include/linux/set_memory.h +++ b/include/linux/set_memory.h @@ -42,14 +42,14 @@ static inline bool can_set_direct_map(void) #endif #endif /* CONFIG_ARCH_HAS_SET_DIRECT_MAP */ -#ifndef set_mce_nospec -static inline int set_mce_nospec(unsigned long pfn, bool unmap) +#ifdef CONFIG_X86_64 +int set_mce_nospec(unsigned long pfn); +int clear_mce_nospec(unsigned long pfn); +#else +static inline int set_mce_nospec(unsigned long pfn) { return 0; } -#endif - -#ifndef clear_mce_nospec static inline int clear_mce_nospec(unsigned long pfn) { return 0; diff --git a/include/linux/soc/renesas/r9a06g032-sysctrl.h b/include/linux/soc/renesas/r9a06g032-sysctrl.h new file mode 100644 index 0000000000000000000000000000000000000000..066dfb15cbddde70862126a744712ccc7f66840b --- /dev/null +++ b/include/linux/soc/renesas/r9a06g032-sysctrl.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __LINUX_SOC_RENESAS_R9A06G032_SYSCTRL_H__ +#define __LINUX_SOC_RENESAS_R9A06G032_SYSCTRL_H__ + +#ifdef CONFIG_CLK_R9A06G032 +int r9a06g032_sysctrl_set_dmamux(u32 mask, u32 val); +#else +static inline int r9a06g032_sysctrl_set_dmamux(u32 mask, u32 val) { return -ENODEV; } +#endif + +#endif /* __LINUX_SOC_RENESAS_R9A06G032_SYSCTRL_H__ */ diff --git a/include/linux/thunderbolt.h b/include/linux/thunderbolt.h index 124e13cb1469c6e3b020c95e2bc153b9bf60c833..7a8ad984e65185018e915cce13c2e2c2c046e144 100644 --- a/include/linux/thunderbolt.h +++ b/include/linux/thunderbolt.h @@ -465,6 +465,7 @@ static inline struct tb_xdomain *tb_service_parent(struct tb_service *svc) * @msix_ida: Used to allocate MSI-X vectors for rings * @going_away: The host controller device is about to disappear so when * this flag is set, avoid touching the hardware anymore. + * @iommu_dma_protection: An IOMMU will isolate external-facing ports. * @interrupt_work: Work scheduled to handle ring interrupt when no * MSI-X is used. * @hop_count: Number of rings (end point hops) supported by NHI. @@ -479,6 +480,7 @@ struct tb_nhi { struct tb_ring **rx_rings; struct ida msix_ida; bool going_away; + bool iommu_dma_protection; struct work_struct interrupt_work; u32 hop_count; unsigned long quirks; diff --git a/include/uapi/asm-generic/fcntl.h b/include/uapi/asm-generic/fcntl.h index ecd0f5bdfc1d617aede5900454f86076b924baf0..f13d37b60775475cb38347116800b9b452a08ff9 100644 --- a/include/uapi/asm-generic/fcntl.h +++ b/include/uapi/asm-generic/fcntl.h @@ -116,13 +116,13 @@ #define F_GETSIG 11 /* for sockets. */ #endif -#ifndef CONFIG_64BIT +#if __BITS_PER_LONG == 32 || defined(__KERNEL__) #ifndef F_GETLK64 #define F_GETLK64 12 /* using 'struct flock64' */ #define F_SETLK64 13 #define F_SETLKW64 14 #endif -#endif +#endif /* __BITS_PER_LONG == 32 || defined(__KERNEL__) */ #ifndef F_SETOWN_EX #define F_SETOWN_EX 15 @@ -192,25 +192,19 @@ struct f_owner_ex { #define F_LINUX_SPECIFIC_BASE 1024 -#ifndef HAVE_ARCH_STRUCT_FLOCK -#ifndef __ARCH_FLOCK_PAD -#define __ARCH_FLOCK_PAD -#endif - struct flock { short l_type; short l_whence; __kernel_off_t l_start; __kernel_off_t l_len; __kernel_pid_t l_pid; - __ARCH_FLOCK_PAD -}; +#ifdef __ARCH_FLOCK_EXTRA_SYSID + __ARCH_FLOCK_EXTRA_SYSID #endif - -#ifndef HAVE_ARCH_STRUCT_FLOCK64 -#ifndef __ARCH_FLOCK64_PAD -#define __ARCH_FLOCK64_PAD +#ifdef __ARCH_FLOCK_PAD + __ARCH_FLOCK_PAD #endif +}; struct flock64 { short l_type; @@ -218,8 +212,9 @@ struct flock64 { __kernel_loff_t l_start; __kernel_loff_t l_len; __kernel_pid_t l_pid; +#ifdef __ARCH_FLOCK64_PAD __ARCH_FLOCK64_PAD -}; #endif +}; #endif /* _ASM_GENERIC_FCNTL_H */ diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/unistd.h index 1c48b0ae3ba30229ff3104b5c8258e1a70373475..45fa180cc56adf335ebfa7c2c6bf85b9704e25fa 100644 --- a/include/uapi/asm-generic/unistd.h +++ b/include/uapi/asm-generic/unistd.h @@ -383,7 +383,7 @@ __SYSCALL(__NR_syslog, sys_syslog) /* kernel/ptrace.c */ #define __NR_ptrace 117 -__SYSCALL(__NR_ptrace, sys_ptrace) +__SC_COMP(__NR_ptrace, sys_ptrace, compat_sys_ptrace) /* kernel/sched/core.c */ #define __NR_sched_setparam 118 @@ -779,7 +779,7 @@ __SYSCALL(__NR_rseq, sys_rseq) #define __NR_kexec_file_load 294 __SYSCALL(__NR_kexec_file_load, sys_kexec_file_load) /* 295 through 402 are unassigned to sync up with generic numbers, don't use */ -#if __BITS_PER_LONG == 32 +#if defined(__SYSCALL_COMPAT) || __BITS_PER_LONG == 32 #define __NR_clock_gettime64 403 __SYSCALL(__NR_clock_gettime64, sys_clock_gettime) #define __NR_clock_settime64 404 diff --git a/include/uapi/linux/cxl_mem.h b/include/uapi/linux/cxl_mem.h index 8d206f27bb6d78f19767edc2f43814c62a9d6dd5..c71021a2a9edf5309e3ff1afce7d146142b9ba77 100644 --- a/include/uapi/linux/cxl_mem.h +++ b/include/uapi/linux/cxl_mem.h @@ -68,8 +68,8 @@ static const struct { * struct cxl_command_info - Command information returned from a query. * @id: ID number for the command. * @flags: Flags that specify command behavior. - * @size_in: Expected input size, or -1 if variable length. - * @size_out: Expected output size, or -1 if variable length. + * @size_in: Expected input size, or ~0 if variable length. + * @size_out: Expected output size, or ~0 if variable length. * * Represents a single command that is supported by both the driver and the * hardware. This is returned as part of an array from the query ioctl. The @@ -78,7 +78,7 @@ static const struct { * * - @id = 10 * - @flags = 0 - * - @size_in = -1 + * - @size_in = ~0 * - @size_out = 0 * * See struct cxl_mem_query_commands. @@ -89,8 +89,8 @@ struct cxl_command_info { __u32 flags; #define CXL_MEM_COMMAND_FLAG_MASK GENMASK(0, 0) - __s32 size_in; - __s32 size_out; + __u32 size_in; + __u32 size_out; }; /** @@ -169,13 +169,13 @@ struct cxl_send_command { __u32 retval; struct { - __s32 size; + __u32 size; __u32 rsvd; __u64 payload; } in; struct { - __s32 size; + __u32 size; __u32 rsvd; __u64 payload; } out; diff --git a/include/uapi/linux/idxd.h b/include/uapi/linux/idxd.h index a8f0ff75c43073fe313afe8ba6f26612e2c5feda..bce7c43657d547d96355e20cbea6b5af0c33e823 100644 --- a/include/uapi/linux/idxd.h +++ b/include/uapi/linux/idxd.h @@ -53,6 +53,11 @@ enum idxd_scmd_stat { /* IAX */ #define IDXD_OP_FLAG_RD_SRC2_AECS 0x010000 +#define IDXD_OP_FLAG_RD_SRC2_2ND 0x020000 +#define IDXD_OP_FLAG_WR_SRC2_AECS_COMP 0x040000 +#define IDXD_OP_FLAG_WR_SRC2_AECS_OVFL 0x080000 +#define IDXD_OP_FLAG_SRC2_STS 0x100000 +#define IDXD_OP_FLAG_CRC_RFC3720 0x200000 /* Opcode */ enum dsa_opcode { @@ -81,6 +86,18 @@ enum iax_opcode { IAX_OPCODE_MEMMOVE, IAX_OPCODE_DECOMPRESS = 0x42, IAX_OPCODE_COMPRESS, + IAX_OPCODE_CRC64, + IAX_OPCODE_ZERO_DECOMP_32 = 0x48, + IAX_OPCODE_ZERO_DECOMP_16, + IAX_OPCODE_DECOMP_32 = 0x4c, + IAX_OPCODE_DECOMP_16, + IAX_OPCODE_SCAN = 0x50, + IAX_OPCODE_SET_MEMBER, + IAX_OPCODE_EXTRACT, + IAX_OPCODE_SELECT, + IAX_OPCODE_RLE_BURST, + IAX_OPCDE_FIND_UNIQUE, + IAX_OPCODE_EXPAND, }; /* Completion record status */ @@ -120,6 +137,7 @@ enum iax_completion_status { IAX_COMP_NONE = 0, IAX_COMP_SUCCESS, IAX_COMP_PAGE_FAULT_IR = 0x04, + IAX_COMP_ANALYTICS_ERROR = 0x0a, IAX_COMP_OUTBUF_OVERFLOW, IAX_COMP_BAD_OPCODE = 0x10, IAX_COMP_INVALID_FLAGS, @@ -140,7 +158,10 @@ enum iax_completion_status { IAX_COMP_WATCHDOG, IAX_COMP_INVALID_COMP_FLAG = 0x30, IAX_COMP_INVALID_FILTER_FLAG, - IAX_COMP_INVALID_NUM_ELEMS = 0x33, + IAX_COMP_INVALID_INPUT_SIZE, + IAX_COMP_INVALID_NUM_ELEMS, + IAX_COMP_INVALID_SRC1_WIDTH, + IAX_COMP_INVALID_INVERT_OUT, }; #define DSA_COMP_STATUS_MASK 0x7f @@ -319,8 +340,12 @@ struct iax_completion_record { uint32_t output_size; uint8_t output_bits; uint8_t rsvd3; - uint16_t rsvd4; - uint64_t rsvd5[4]; + uint16_t xor_csum; + uint32_t crc; + uint32_t min; + uint32_t max; + uint32_t sum; + uint64_t rsvd4[2]; } __attribute__((packed)); struct iax_raw_completion_record { diff --git a/include/video/radeon.h b/include/video/radeon.h index 005eae19ec098e3417b6fedff0f8b8a5c573efa6..72f94ccfa725bb2260658e4e907d37847a1d9480 100644 --- a/include/video/radeon.h +++ b/include/video/radeon.h @@ -750,7 +750,7 @@ #define WAIT_DMA_GUI_IDLE (1 << 9) #define WAIT_2D_IDLECLEAN (1 << 16) -/* SURFACE_CNTL bit consants */ +/* SURFACE_CNTL bit constants */ #define SURF_TRANSLATION_DIS (1 << 8) #define NONSURF_AP0_SWP_16BPP (1 << 20) #define NONSURF_AP0_SWP_32BPP (1 << 21) diff --git a/init/Kconfig b/init/Kconfig index 26040cbfa28a454c3fc0fb9bd3ed471440ad8d1b..4fa7c31d27cf5a1d03d61e3939dfcfe47d0141c9 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -378,6 +378,10 @@ config SYSVIPC_SYSCTL depends on SYSCTL default y +config SYSVIPC_COMPAT + def_bool y + depends on COMPAT && SYSVIPC + config POSIX_MQUEUE bool "POSIX Message Queues" depends on NET @@ -1338,7 +1342,7 @@ endif config BOOT_CONFIG bool "Boot config support" - select BLK_DEV_INITRD + select BLK_DEV_INITRD if !BOOT_CONFIG_EMBED help Extra boot config allows system admin to pass a config file as complemental extension of kernel cmdline when booting. @@ -1348,6 +1352,25 @@ config BOOT_CONFIG If unsure, say Y. +config BOOT_CONFIG_EMBED + bool "Embed bootconfig file in the kernel" + depends on BOOT_CONFIG + help + Embed a bootconfig file given by BOOT_CONFIG_EMBED_FILE in the + kernel. Usually, the bootconfig file is loaded with the initrd + image. But if the system doesn't support initrd, this option will + help you by embedding a bootconfig file while building the kernel. + + If unsure, say N. + +config BOOT_CONFIG_EMBED_FILE + string "Embedded bootconfig file path" + depends on BOOT_CONFIG_EMBED + help + Specify a bootconfig file which will be embedded to the kernel. + This bootconfig will be used if there is no initrd or no other + bootconfig in the initrd. + config INITRAMFS_PRESERVE_MTIME bool "Preserve cpio archive mtimes in initramfs" default y diff --git a/init/main.c b/init/main.c index 3f0c8c69acd655613dc244e326be9f89c8a37917..87995c382031527b8621fba2cf874ff6e980d8be 100644 --- a/init/main.c +++ b/init/main.c @@ -264,7 +264,7 @@ static int __init loglevel(char *str) early_param("loglevel", loglevel); #ifdef CONFIG_BLK_DEV_INITRD -static void * __init get_boot_config_from_initrd(u32 *_size, u32 *_csum) +static void * __init get_boot_config_from_initrd(size_t *_size) { u32 size, csum; char *data; @@ -298,17 +298,20 @@ found: return NULL; } + if (xbc_calc_checksum(data, size) != csum) { + pr_err("bootconfig checksum failed\n"); + return NULL; + } + /* Remove bootconfig from initramfs/initrd */ initrd_end = (unsigned long)data; if (_size) *_size = size; - if (_csum) - *_csum = csum; return data; } #else -static void * __init get_boot_config_from_initrd(u32 *_size, u32 *_csum) +static void * __init get_boot_config_from_initrd(size_t *_size) { return NULL; } @@ -405,14 +408,16 @@ static int __init warn_bootconfig(char *str) static void __init setup_boot_config(void) { static char tmp_cmdline[COMMAND_LINE_SIZE] __initdata; - const char *msg; - int pos; - u32 size, csum; - char *data, *err; - int ret; + const char *msg, *data; + int pos, ret; + size_t size; + char *err; /* Cut out the bootconfig data even if we have no bootconfig option */ - data = get_boot_config_from_initrd(&size, &csum); + data = get_boot_config_from_initrd(&size); + /* If there is no bootconfig in initrd, try embedded one. */ + if (!data) + data = xbc_get_embedded_bootconfig(&size); strlcpy(tmp_cmdline, boot_command_line, COMMAND_LINE_SIZE); err = parse_args("bootconfig", tmp_cmdline, NULL, 0, 0, 0, NULL, @@ -431,13 +436,8 @@ static void __init setup_boot_config(void) } if (size >= XBC_DATA_MAX) { - pr_err("bootconfig size %d greater than max size %d\n", - size, XBC_DATA_MAX); - return; - } - - if (xbc_calc_checksum(data, size) != csum) { - pr_err("bootconfig checksum failed\n"); + pr_err("bootconfig size %ld greater than max size %d\n", + (long)size, XBC_DATA_MAX); return; } @@ -450,7 +450,7 @@ static void __init setup_boot_config(void) msg, pos); } else { xbc_get_info(&ret, NULL); - pr_info("Load bootconfig: %d bytes %d nodes\n", size, ret); + pr_info("Load bootconfig: %ld bytes %d nodes\n", (long)size, ret); /* keys starting with "kernel." are passed via cmdline */ extra_command_line = xbc_make_cmdline("kernel"); /* Also, "init." keys are init arguments */ @@ -469,7 +469,7 @@ static void __init exit_boot_config(void) static void __init setup_boot_config(void) { /* Remove bootconfig data from initrd */ - get_boot_config_from_initrd(NULL, NULL); + get_boot_config_from_initrd(NULL); } static int __init warn_bootconfig(char *str) diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c index c108a2a8875463479a5df735250d68b5aebc13a9..145321a5e798a647f299b1728a61231d166621ce 100644 --- a/kernel/kexec_file.c +++ b/kernel/kexec_file.c @@ -1226,7 +1226,7 @@ int crash_exclude_mem_range(struct crash_mem *mem, return 0; } -int crash_prepare_elf64_headers(struct crash_mem *mem, int kernel_map, +int crash_prepare_elf64_headers(struct crash_mem *mem, int need_kernel_map, void **addr, unsigned long *sz) { Elf64_Ehdr *ehdr; @@ -1290,7 +1290,7 @@ int crash_prepare_elf64_headers(struct crash_mem *mem, int kernel_map, phdr++; /* Prepare PT_LOAD type program header for kernel text region */ - if (kernel_map) { + if (need_kernel_map) { phdr->p_type = PT_LOAD; phdr->p_flags = PF_R|PF_W|PF_X; phdr->p_vaddr = (unsigned long) _text; diff --git a/kernel/kprobes.c b/kernel/kprobes.c index dd58c0be9ce25675b3523c801f5b96e7963fa780..f214f8c088ede745a468e7f4cf4ee62135d0e4eb 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c @@ -1257,79 +1257,6 @@ void kprobe_busy_end(void) preempt_enable(); } -#if !defined(CONFIG_KRETPROBE_ON_RETHOOK) -static void free_rp_inst_rcu(struct rcu_head *head) -{ - struct kretprobe_instance *ri = container_of(head, struct kretprobe_instance, rcu); - - if (refcount_dec_and_test(&ri->rph->ref)) - kfree(ri->rph); - kfree(ri); -} -NOKPROBE_SYMBOL(free_rp_inst_rcu); - -static void recycle_rp_inst(struct kretprobe_instance *ri) -{ - struct kretprobe *rp = get_kretprobe(ri); - - if (likely(rp)) - freelist_add(&ri->freelist, &rp->freelist); - else - call_rcu(&ri->rcu, free_rp_inst_rcu); -} -NOKPROBE_SYMBOL(recycle_rp_inst); - -/* - * This function is called from delayed_put_task_struct() when a task is - * dead and cleaned up to recycle any kretprobe instances associated with - * this task. These left over instances represent probed functions that - * have been called but will never return. - */ -void kprobe_flush_task(struct task_struct *tk) -{ - struct kretprobe_instance *ri; - struct llist_node *node; - - /* Early boot, not yet initialized. */ - if (unlikely(!kprobes_initialized)) - return; - - kprobe_busy_begin(); - - node = __llist_del_all(&tk->kretprobe_instances); - while (node) { - ri = container_of(node, struct kretprobe_instance, llist); - node = node->next; - - recycle_rp_inst(ri); - } - - kprobe_busy_end(); -} -NOKPROBE_SYMBOL(kprobe_flush_task); - -static inline void free_rp_inst(struct kretprobe *rp) -{ - struct kretprobe_instance *ri; - struct freelist_node *node; - int count = 0; - - node = rp->freelist.head; - while (node) { - ri = container_of(node, struct kretprobe_instance, freelist); - node = node->next; - - kfree(ri); - count++; - } - - if (refcount_sub_and_test(count, &rp->rph->ref)) { - kfree(rp->rph); - rp->rph = NULL; - } -} -#endif /* !CONFIG_KRETPROBE_ON_RETHOOK */ - /* Add the new probe to 'ap->list'. */ static int add_new_kprobe(struct kprobe *ap, struct kprobe *p) { @@ -1928,6 +1855,77 @@ static struct notifier_block kprobe_exceptions_nb = { #ifdef CONFIG_KRETPROBES #if !defined(CONFIG_KRETPROBE_ON_RETHOOK) +static void free_rp_inst_rcu(struct rcu_head *head) +{ + struct kretprobe_instance *ri = container_of(head, struct kretprobe_instance, rcu); + + if (refcount_dec_and_test(&ri->rph->ref)) + kfree(ri->rph); + kfree(ri); +} +NOKPROBE_SYMBOL(free_rp_inst_rcu); + +static void recycle_rp_inst(struct kretprobe_instance *ri) +{ + struct kretprobe *rp = get_kretprobe(ri); + + if (likely(rp)) + freelist_add(&ri->freelist, &rp->freelist); + else + call_rcu(&ri->rcu, free_rp_inst_rcu); +} +NOKPROBE_SYMBOL(recycle_rp_inst); + +/* + * This function is called from delayed_put_task_struct() when a task is + * dead and cleaned up to recycle any kretprobe instances associated with + * this task. These left over instances represent probed functions that + * have been called but will never return. + */ +void kprobe_flush_task(struct task_struct *tk) +{ + struct kretprobe_instance *ri; + struct llist_node *node; + + /* Early boot, not yet initialized. */ + if (unlikely(!kprobes_initialized)) + return; + + kprobe_busy_begin(); + + node = __llist_del_all(&tk->kretprobe_instances); + while (node) { + ri = container_of(node, struct kretprobe_instance, llist); + node = node->next; + + recycle_rp_inst(ri); + } + + kprobe_busy_end(); +} +NOKPROBE_SYMBOL(kprobe_flush_task); + +static inline void free_rp_inst(struct kretprobe *rp) +{ + struct kretprobe_instance *ri; + struct freelist_node *node; + int count = 0; + + node = rp->freelist.head; + while (node) { + ri = container_of(node, struct kretprobe_instance, freelist); + node = node->next; + + kfree(ri); + count++; + } + + if (refcount_sub_and_test(count, &rp->rph->ref)) { + kfree(rp->rph); + rp->rph = NULL; + } +} + /* This assumes the 'tsk' is the current task or the is not running. */ static kprobe_opcode_t *__kretprobe_find_ret_addr(struct task_struct *tsk, struct llist_node **cur) diff --git a/kernel/notifier.c b/kernel/notifier.c index ba005ebf4730639900526926b156891cd954a4fc..0d5bd62c480ed3c76c6f3bcc3813f7eabb513aa9 100644 --- a/kernel/notifier.c +++ b/kernel/notifier.c @@ -20,7 +20,8 @@ BLOCKING_NOTIFIER_HEAD(reboot_notifier_list); */ static int notifier_chain_register(struct notifier_block **nl, - struct notifier_block *n) + struct notifier_block *n, + bool unique_priority) { while ((*nl) != NULL) { if (unlikely((*nl) == n)) { @@ -30,6 +31,8 @@ static int notifier_chain_register(struct notifier_block **nl, } if (n->priority > (*nl)->priority) break; + if (n->priority == (*nl)->priority && unique_priority) + return -EBUSY; nl = &((*nl)->next); } n->next = *nl; @@ -144,12 +147,35 @@ int atomic_notifier_chain_register(struct atomic_notifier_head *nh, int ret; spin_lock_irqsave(&nh->lock, flags); - ret = notifier_chain_register(&nh->head, n); + ret = notifier_chain_register(&nh->head, n, false); spin_unlock_irqrestore(&nh->lock, flags); return ret; } EXPORT_SYMBOL_GPL(atomic_notifier_chain_register); +/** + * atomic_notifier_chain_register_unique_prio - Add notifier to an atomic notifier chain + * @nh: Pointer to head of the atomic notifier chain + * @n: New entry in notifier chain + * + * Adds a notifier to an atomic notifier chain if there is no other + * notifier registered using the same priority. + * + * Returns 0 on success, %-EEXIST or %-EBUSY on error. + */ +int atomic_notifier_chain_register_unique_prio(struct atomic_notifier_head *nh, + struct notifier_block *n) +{ + unsigned long flags; + int ret; + + spin_lock_irqsave(&nh->lock, flags); + ret = notifier_chain_register(&nh->head, n, true); + spin_unlock_irqrestore(&nh->lock, flags); + return ret; +} +EXPORT_SYMBOL_GPL(atomic_notifier_chain_register_unique_prio); + /** * atomic_notifier_chain_unregister - Remove notifier from an atomic notifier chain * @nh: Pointer to head of the atomic notifier chain @@ -204,23 +230,27 @@ int atomic_notifier_call_chain(struct atomic_notifier_head *nh, EXPORT_SYMBOL_GPL(atomic_notifier_call_chain); NOKPROBE_SYMBOL(atomic_notifier_call_chain); +/** + * atomic_notifier_call_chain_is_empty - Check whether notifier chain is empty + * @nh: Pointer to head of the atomic notifier chain + * + * Checks whether notifier chain is empty. + * + * Returns true is notifier chain is empty, false otherwise. + */ +bool atomic_notifier_call_chain_is_empty(struct atomic_notifier_head *nh) +{ + return !rcu_access_pointer(nh->head); +} + /* * Blocking notifier chain routines. All access to the chain is * synchronized by an rwsem. */ -/** - * blocking_notifier_chain_register - Add notifier to a blocking notifier chain - * @nh: Pointer to head of the blocking notifier chain - * @n: New entry in notifier chain - * - * Adds a notifier to a blocking notifier chain. - * Must be called in process context. - * - * Returns 0 on success, %-EEXIST on error. - */ -int blocking_notifier_chain_register(struct blocking_notifier_head *nh, - struct notifier_block *n) +static int __blocking_notifier_chain_register(struct blocking_notifier_head *nh, + struct notifier_block *n, + bool unique_priority) { int ret; @@ -230,15 +260,48 @@ int blocking_notifier_chain_register(struct blocking_notifier_head *nh, * such times we must not call down_write(). */ if (unlikely(system_state == SYSTEM_BOOTING)) - return notifier_chain_register(&nh->head, n); + return notifier_chain_register(&nh->head, n, unique_priority); down_write(&nh->rwsem); - ret = notifier_chain_register(&nh->head, n); + ret = notifier_chain_register(&nh->head, n, unique_priority); up_write(&nh->rwsem); return ret; } + +/** + * blocking_notifier_chain_register - Add notifier to a blocking notifier chain + * @nh: Pointer to head of the blocking notifier chain + * @n: New entry in notifier chain + * + * Adds a notifier to a blocking notifier chain. + * Must be called in process context. + * + * Returns 0 on success, %-EEXIST on error. + */ +int blocking_notifier_chain_register(struct blocking_notifier_head *nh, + struct notifier_block *n) +{ + return __blocking_notifier_chain_register(nh, n, false); +} EXPORT_SYMBOL_GPL(blocking_notifier_chain_register); +/** + * blocking_notifier_chain_register_unique_prio - Add notifier to a blocking notifier chain + * @nh: Pointer to head of the blocking notifier chain + * @n: New entry in notifier chain + * + * Adds a notifier to an blocking notifier chain if there is no other + * notifier registered using the same priority. + * + * Returns 0 on success, %-EEXIST or %-EBUSY on error. + */ +int blocking_notifier_chain_register_unique_prio(struct blocking_notifier_head *nh, + struct notifier_block *n) +{ + return __blocking_notifier_chain_register(nh, n, true); +} +EXPORT_SYMBOL_GPL(blocking_notifier_chain_register_unique_prio); + /** * blocking_notifier_chain_unregister - Remove notifier from a blocking notifier chain * @nh: Pointer to head of the blocking notifier chain @@ -341,7 +404,7 @@ EXPORT_SYMBOL_GPL(blocking_notifier_call_chain); int raw_notifier_chain_register(struct raw_notifier_head *nh, struct notifier_block *n) { - return notifier_chain_register(&nh->head, n); + return notifier_chain_register(&nh->head, n, false); } EXPORT_SYMBOL_GPL(raw_notifier_chain_register); @@ -420,10 +483,10 @@ int srcu_notifier_chain_register(struct srcu_notifier_head *nh, * such times we must not call mutex_lock(). */ if (unlikely(system_state == SYSTEM_BOOTING)) - return notifier_chain_register(&nh->head, n); + return notifier_chain_register(&nh->head, n, false); mutex_lock(&nh->mutex); - ret = notifier_chain_register(&nh->head, n); + ret = notifier_chain_register(&nh->head, n, false); mutex_unlock(&nh->mutex); return ret; } diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c index 938d5c78b42115d75e340dd3a01e279d4483dbd6..20a66bf9f465926bca80c99716142db16fca9792 100644 --- a/kernel/power/hibernate.c +++ b/kernel/power/hibernate.c @@ -83,7 +83,7 @@ bool hibernation_available(void) { return nohibernate == 0 && !security_locked_down(LOCKDOWN_HIBERNATION) && - !secretmem_active(); + !secretmem_active() && !cxl_mem_active(); } /** diff --git a/kernel/power/main.c b/kernel/power/main.c index 5242bf2ee469aa70b1de15939385ff17758445fc..e3694034b753664d91e981b6455e005d36feed16 100644 --- a/kernel/power/main.c +++ b/kernel/power/main.c @@ -127,7 +127,9 @@ static ssize_t mem_sleep_show(struct kobject *kobj, struct kobj_attribute *attr, char *s = buf; suspend_state_t i; - for (i = PM_SUSPEND_MIN; i < PM_SUSPEND_MAX; i++) + for (i = PM_SUSPEND_MIN; i < PM_SUSPEND_MAX; i++) { + if (i >= PM_SUSPEND_MEM && cxl_mem_active()) + continue; if (mem_sleep_states[i]) { const char *label = mem_sleep_states[i]; @@ -136,6 +138,7 @@ static ssize_t mem_sleep_show(struct kobject *kobj, struct kobj_attribute *attr, else s += sprintf(s, "%s ", label); } + } /* Convert the last space to a newline if needed. */ if (s != buf) diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c index f245efafbeeb74598f5ee4108a81bb989e781f56..d5e3d5f11e4e9583fe249ca4ad27f87fdafa7b6b 100644 --- a/kernel/power/suspend.c +++ b/kernel/power/suspend.c @@ -238,7 +238,8 @@ EXPORT_SYMBOL_GPL(suspend_valid_only_mem); static bool sleep_state_supported(suspend_state_t state) { - return state == PM_SUSPEND_TO_IDLE || valid_state(state); + return state == PM_SUSPEND_TO_IDLE || + (valid_state(state) && !cxl_mem_active()); } static int platform_suspend_prepare(suspend_state_t state) diff --git a/kernel/reboot.c b/kernel/reboot.c index 8aa434a8941aa303626288c629a9410a31e8aa99..6f918d1dfcd9904442172807f28ec70bb053d2f3 100644 --- a/kernel/reboot.c +++ b/kernel/reboot.c @@ -49,12 +49,20 @@ int reboot_cpu; enum reboot_type reboot_type = BOOT_ACPI; int reboot_force; +struct sys_off_handler { + struct notifier_block nb; + int (*sys_off_cb)(struct sys_off_data *data); + void *cb_data; + enum sys_off_mode mode; + bool blocking; + void *list; +}; + /* - * If set, this is used for preparing the system to power off. + * Temporary stub that prevents linkage failure while we're in process + * of removing all uses of legacy pm_power_off() around the kernel. */ - -void (*pm_power_off_prepare)(void); -EXPORT_SYMBOL_GPL(pm_power_off_prepare); +void __weak (*pm_power_off)(void); /** * emergency_restart - reboot the system @@ -282,6 +290,316 @@ void kernel_halt(void) } EXPORT_SYMBOL_GPL(kernel_halt); +/* + * Notifier list for kernel code which wants to be called + * to prepare system for power off. + */ +static BLOCKING_NOTIFIER_HEAD(power_off_prep_handler_list); + +/* + * Notifier list for kernel code which wants to be called + * to power off system. + */ +static ATOMIC_NOTIFIER_HEAD(power_off_handler_list); + +static int sys_off_notify(struct notifier_block *nb, + unsigned long mode, void *cmd) +{ + struct sys_off_handler *handler; + struct sys_off_data data = {}; + + handler = container_of(nb, struct sys_off_handler, nb); + data.cb_data = handler->cb_data; + data.mode = mode; + data.cmd = cmd; + + return handler->sys_off_cb(&data); +} + +/** + * register_sys_off_handler - Register sys-off handler + * @mode: Sys-off mode + * @priority: Handler priority + * @callback: Callback function + * @cb_data: Callback argument + * + * Registers system power-off or restart handler that will be invoked + * at the step corresponding to the given sys-off mode. Handler's callback + * should return NOTIFY_DONE to permit execution of the next handler in + * the call chain or NOTIFY_STOP to break the chain (in error case for + * example). + * + * Multiple handlers can be registered at the default priority level. + * + * Only one handler can be registered at the non-default priority level, + * otherwise ERR_PTR(-EBUSY) is returned. + * + * Returns a new instance of struct sys_off_handler on success, or + * an ERR_PTR()-encoded error code otherwise. + */ +struct sys_off_handler * +register_sys_off_handler(enum sys_off_mode mode, + int priority, + int (*callback)(struct sys_off_data *data), + void *cb_data) +{ + struct sys_off_handler *handler; + int err; + + handler = kzalloc(sizeof(*handler), GFP_KERNEL); + if (!handler) + return ERR_PTR(-ENOMEM); + + switch (mode) { + case SYS_OFF_MODE_POWER_OFF_PREPARE: + handler->list = &power_off_prep_handler_list; + handler->blocking = true; + break; + + case SYS_OFF_MODE_POWER_OFF: + handler->list = &power_off_handler_list; + break; + + case SYS_OFF_MODE_RESTART: + handler->list = &restart_handler_list; + break; + + default: + kfree(handler); + return ERR_PTR(-EINVAL); + } + + handler->nb.notifier_call = sys_off_notify; + handler->nb.priority = priority; + handler->sys_off_cb = callback; + handler->cb_data = cb_data; + handler->mode = mode; + + if (handler->blocking) { + if (priority == SYS_OFF_PRIO_DEFAULT) + err = blocking_notifier_chain_register(handler->list, + &handler->nb); + else + err = blocking_notifier_chain_register_unique_prio(handler->list, + &handler->nb); + } else { + if (priority == SYS_OFF_PRIO_DEFAULT) + err = atomic_notifier_chain_register(handler->list, + &handler->nb); + else + err = atomic_notifier_chain_register_unique_prio(handler->list, + &handler->nb); + } + + if (err) { + kfree(handler); + return ERR_PTR(err); + } + + return handler; +} +EXPORT_SYMBOL_GPL(register_sys_off_handler); + +/** + * unregister_sys_off_handler - Unregister sys-off handler + * @handler: Sys-off handler + * + * Unregisters given sys-off handler. + */ +void unregister_sys_off_handler(struct sys_off_handler *handler) +{ + int err; + + if (!handler) + return; + + if (handler->blocking) + err = blocking_notifier_chain_unregister(handler->list, + &handler->nb); + else + err = atomic_notifier_chain_unregister(handler->list, + &handler->nb); + + /* sanity check, shall never happen */ + WARN_ON(err); + + kfree(handler); +} +EXPORT_SYMBOL_GPL(unregister_sys_off_handler); + +static void devm_unregister_sys_off_handler(void *data) +{ + struct sys_off_handler *handler = data; + + unregister_sys_off_handler(handler); +} + +/** + * devm_register_sys_off_handler - Register sys-off handler + * @dev: Device that registers handler + * @mode: Sys-off mode + * @priority: Handler priority + * @callback: Callback function + * @cb_data: Callback argument + * + * Registers resource-managed sys-off handler. + * + * Returns zero on success, or error code on failure. + */ +int devm_register_sys_off_handler(struct device *dev, + enum sys_off_mode mode, + int priority, + int (*callback)(struct sys_off_data *data), + void *cb_data) +{ + struct sys_off_handler *handler; + + handler = register_sys_off_handler(mode, priority, callback, cb_data); + if (IS_ERR(handler)) + return PTR_ERR(handler); + + return devm_add_action_or_reset(dev, devm_unregister_sys_off_handler, + handler); +} +EXPORT_SYMBOL_GPL(devm_register_sys_off_handler); + +/** + * devm_register_power_off_handler - Register power-off handler + * @dev: Device that registers callback + * @callback: Callback function + * @cb_data: Callback's argument + * + * Registers resource-managed sys-off handler with a default priority + * and using power-off mode. + * + * Returns zero on success, or error code on failure. + */ +int devm_register_power_off_handler(struct device *dev, + int (*callback)(struct sys_off_data *data), + void *cb_data) +{ + return devm_register_sys_off_handler(dev, + SYS_OFF_MODE_POWER_OFF, + SYS_OFF_PRIO_DEFAULT, + callback, cb_data); +} +EXPORT_SYMBOL_GPL(devm_register_power_off_handler); + +/** + * devm_register_restart_handler - Register restart handler + * @dev: Device that registers callback + * @callback: Callback function + * @cb_data: Callback's argument + * + * Registers resource-managed sys-off handler with a default priority + * and using restart mode. + * + * Returns zero on success, or error code on failure. + */ +int devm_register_restart_handler(struct device *dev, + int (*callback)(struct sys_off_data *data), + void *cb_data) +{ + return devm_register_sys_off_handler(dev, + SYS_OFF_MODE_RESTART, + SYS_OFF_PRIO_DEFAULT, + callback, cb_data); +} +EXPORT_SYMBOL_GPL(devm_register_restart_handler); + +static struct sys_off_handler *platform_power_off_handler; + +static int platform_power_off_notify(struct sys_off_data *data) +{ + void (*platform_power_power_off_cb)(void) = data->cb_data; + + platform_power_power_off_cb(); + + return NOTIFY_DONE; +} + +/** + * register_platform_power_off - Register platform-level power-off callback + * @power_off: Power-off callback + * + * Registers power-off callback that will be called as last step + * of the power-off sequence. This callback is expected to be invoked + * for the last resort. Only one platform power-off callback is allowed + * to be registered at a time. + * + * Returns zero on success, or error code on failure. + */ +int register_platform_power_off(void (*power_off)(void)) +{ + struct sys_off_handler *handler; + + handler = register_sys_off_handler(SYS_OFF_MODE_POWER_OFF, + SYS_OFF_PRIO_PLATFORM, + platform_power_off_notify, + power_off); + if (IS_ERR(handler)) + return PTR_ERR(handler); + + platform_power_off_handler = handler; + + return 0; +} +EXPORT_SYMBOL_GPL(register_platform_power_off); + +/** + * unregister_platform_power_off - Unregister platform-level power-off callback + * @power_off: Power-off callback + * + * Unregisters previously registered platform power-off callback. + */ +void unregister_platform_power_off(void (*power_off)(void)) +{ + if (platform_power_off_handler && + platform_power_off_handler->cb_data == power_off) { + unregister_sys_off_handler(platform_power_off_handler); + platform_power_off_handler = NULL; + } +} +EXPORT_SYMBOL_GPL(unregister_platform_power_off); + +static int legacy_pm_power_off(struct sys_off_data *data) +{ + if (pm_power_off) + pm_power_off(); + + return NOTIFY_DONE; +} + +static void do_kernel_power_off_prepare(void) +{ + blocking_notifier_call_chain(&power_off_prep_handler_list, 0, NULL); +} + +/** + * do_kernel_power_off - Execute kernel power-off handler call chain + * + * Expected to be called as last step of the power-off sequence. + * + * Powers off the system immediately if a power-off handler function has + * been registered. Otherwise does nothing. + */ +void do_kernel_power_off(void) +{ + atomic_notifier_call_chain(&power_off_handler_list, 0, NULL); +} + +/** + * kernel_can_power_off - check whether system can be powered off + * + * Returns true if power-off handler is registered and system can be + * powered off, false otherwise. + */ +bool kernel_can_power_off(void) +{ + return !atomic_notifier_call_chain_is_empty(&power_off_handler_list); +} +EXPORT_SYMBOL_GPL(kernel_can_power_off); + /** * kernel_power_off - power_off the system * @@ -290,8 +608,7 @@ EXPORT_SYMBOL_GPL(kernel_halt); void kernel_power_off(void) { kernel_shutdown_prepare(SYSTEM_POWER_OFF); - if (pm_power_off_prepare) - pm_power_off_prepare(); + do_kernel_power_off_prepare(); migrate_to_reboot_cpu(); syscore_shutdown(); pr_emerg("Power down\n"); @@ -314,6 +631,7 @@ SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd, void __user *, arg) { struct pid_namespace *pid_ns = task_active_pid_ns(current); + struct sys_off_handler *sys_off = NULL; char buffer[256]; int ret = 0; @@ -338,10 +656,25 @@ SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd, if (ret) return ret; + /* + * Register sys-off handlers for legacy PM callback. This allows + * legacy PM callbacks temporary co-exist with the new sys-off API. + * + * TODO: Remove legacy handlers once all legacy PM users will be + * switched to the sys-off based APIs. + */ + if (pm_power_off) { + sys_off = register_sys_off_handler(SYS_OFF_MODE_POWER_OFF, + SYS_OFF_PRIO_DEFAULT, + legacy_pm_power_off, NULL); + if (IS_ERR(sys_off)) + return PTR_ERR(sys_off); + } + /* Instead of trying to make the power_off code look like * halt when pm_power_off is not set do it the easy way. */ - if ((cmd == LINUX_REBOOT_CMD_POWER_OFF) && !pm_power_off) + if ((cmd == LINUX_REBOOT_CMD_POWER_OFF) && !kernel_can_power_off()) cmd = LINUX_REBOOT_CMD_HALT; mutex_lock(&system_transition_mutex); @@ -395,6 +728,7 @@ SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd, break; } mutex_unlock(&system_transition_mutex); + unregister_sys_off_handler(sys_off); return ret; } diff --git a/kernel/trace/Makefile b/kernel/trace/Makefile index d77cd8032213877ce1b5815717eb72fc5d08c750..0d261774d6f38b7d116a76e5ec04265936e55e4a 100644 --- a/kernel/trace/Makefile +++ b/kernel/trace/Makefile @@ -31,6 +31,10 @@ ifdef CONFIG_GCOV_PROFILE_FTRACE GCOV_PROFILE := y endif +# Functions in this file could be invoked from early interrupt +# code and produce random code coverage. +KCOV_INSTRUMENT_trace_preemptirq.o := n + CFLAGS_bpf_trace.o := -I$(src) CFLAGS_trace_benchmark.o := -I$(src) diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index f8db59c3a601b7f1299e970960e2a33ef45f53c2..e750fe141a6063547c0dda2432dc6cfceec9879a 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -45,6 +45,8 @@ #include "trace_output.h" #include "trace_stat.h" +#define FTRACE_INVALID_FUNCTION "__ftrace_invalid_address__" + #define FTRACE_WARN_ON(cond) \ ({ \ int ___r = cond; \ @@ -119,7 +121,7 @@ struct ftrace_ops __rcu *ftrace_ops_list __read_mostly = &ftrace_list_end; ftrace_func_t ftrace_trace_function __read_mostly = ftrace_stub; struct ftrace_ops global_ops; -/* Defined by vmlinux.lds.h see the commment above arch_ftrace_ops_list_func for details */ +/* Defined by vmlinux.lds.h see the comment above arch_ftrace_ops_list_func for details */ void ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip, struct ftrace_ops *op, struct ftrace_regs *fregs); @@ -952,7 +954,6 @@ static struct tracer_stat function_stats __initdata = { static __init void ftrace_profile_tracefs(struct dentry *d_tracer) { struct ftrace_profile_stat *stat; - struct dentry *entry; char *name; int ret; int cpu; @@ -983,11 +984,9 @@ static __init void ftrace_profile_tracefs(struct dentry *d_tracer) } } - entry = tracefs_create_file("function_profile_enabled", - TRACE_MODE_WRITE, d_tracer, NULL, - &ftrace_profile_fops); - if (!entry) - pr_warn("Could not create tracefs 'function_profile_enabled' entry\n"); + trace_create_file("function_profile_enabled", + TRACE_MODE_WRITE, d_tracer, NULL, + &ftrace_profile_fops); } #else /* CONFIG_FUNCTION_PROFILER */ @@ -2707,18 +2706,16 @@ ftrace_nop_initialize(struct module *mod, struct dyn_ftrace *rec) * archs can override this function if they must do something * before the modifying code is performed. */ -int __weak ftrace_arch_code_modify_prepare(void) +void __weak ftrace_arch_code_modify_prepare(void) { - return 0; } /* * archs can override this function if they must do something * after the modifying code is performed. */ -int __weak ftrace_arch_code_modify_post_process(void) +void __weak ftrace_arch_code_modify_post_process(void) { - return 0; } void ftrace_modify_all_code(int command) @@ -2804,12 +2801,7 @@ void __weak arch_ftrace_update_code(int command) static void ftrace_run_update_code(int command) { - int ret; - - ret = ftrace_arch_code_modify_prepare(); - FTRACE_WARN_ON(ret); - if (ret) - return; + ftrace_arch_code_modify_prepare(); /* * By default we use stop_machine() to modify the code. @@ -2819,8 +2811,7 @@ static void ftrace_run_update_code(int command) */ arch_ftrace_update_code(command); - ret = ftrace_arch_code_modify_post_process(); - FTRACE_WARN_ON(ret); + ftrace_arch_code_modify_post_process(); } static void ftrace_run_modify_code(struct ftrace_ops *ops, int command, @@ -3631,6 +3622,105 @@ static void add_trampoline_func(struct seq_file *m, struct ftrace_ops *ops, seq_printf(m, " ->%pS", ptr); } +#ifdef FTRACE_MCOUNT_MAX_OFFSET +/* + * Weak functions can still have an mcount/fentry that is saved in + * the __mcount_loc section. These can be detected by having a + * symbol offset of greater than FTRACE_MCOUNT_MAX_OFFSET, as the + * symbol found by kallsyms is not the function that the mcount/fentry + * is part of. The offset is much greater in these cases. + * + * Test the record to make sure that the ip points to a valid kallsyms + * and if not, mark it disabled. + */ +static int test_for_valid_rec(struct dyn_ftrace *rec) +{ + char str[KSYM_SYMBOL_LEN]; + unsigned long offset; + const char *ret; + + ret = kallsyms_lookup(rec->ip, NULL, &offset, NULL, str); + + /* Weak functions can cause invalid addresses */ + if (!ret || offset > FTRACE_MCOUNT_MAX_OFFSET) { + rec->flags |= FTRACE_FL_DISABLED; + return 0; + } + return 1; +} + +static struct workqueue_struct *ftrace_check_wq __initdata; +static struct work_struct ftrace_check_work __initdata; + +/* + * Scan all the mcount/fentry entries to make sure they are valid. + */ +static __init void ftrace_check_work_func(struct work_struct *work) +{ + struct ftrace_page *pg; + struct dyn_ftrace *rec; + + mutex_lock(&ftrace_lock); + do_for_each_ftrace_rec(pg, rec) { + test_for_valid_rec(rec); + } while_for_each_ftrace_rec(); + mutex_unlock(&ftrace_lock); +} + +static int __init ftrace_check_for_weak_functions(void) +{ + INIT_WORK(&ftrace_check_work, ftrace_check_work_func); + + ftrace_check_wq = alloc_workqueue("ftrace_check_wq", WQ_UNBOUND, 0); + + queue_work(ftrace_check_wq, &ftrace_check_work); + return 0; +} + +static int __init ftrace_check_sync(void) +{ + /* Make sure the ftrace_check updates are finished */ + if (ftrace_check_wq) + destroy_workqueue(ftrace_check_wq); + return 0; +} + +late_initcall_sync(ftrace_check_sync); +subsys_initcall(ftrace_check_for_weak_functions); + +static int print_rec(struct seq_file *m, unsigned long ip) +{ + unsigned long offset; + char str[KSYM_SYMBOL_LEN]; + char *modname; + const char *ret; + + ret = kallsyms_lookup(ip, NULL, &offset, &modname, str); + /* Weak functions can cause invalid addresses */ + if (!ret || offset > FTRACE_MCOUNT_MAX_OFFSET) { + snprintf(str, KSYM_SYMBOL_LEN, "%s_%ld", + FTRACE_INVALID_FUNCTION, offset); + ret = NULL; + } + + seq_puts(m, str); + if (modname) + seq_printf(m, " [%s]", modname); + return ret == NULL ? -1 : 0; +} +#else +static inline int test_for_valid_rec(struct dyn_ftrace *rec) +{ + return 1; +} + +static inline int print_rec(struct seq_file *m, unsigned long ip) +{ + seq_printf(m, "%ps", (void *)ip); + return 0; +} +#endif + static int t_show(struct seq_file *m, void *v) { struct ftrace_iterator *iter = m->private; @@ -3655,7 +3745,13 @@ static int t_show(struct seq_file *m, void *v) if (!rec) return 0; - seq_printf(m, "%ps", (void *)rec->ip); + if (print_rec(m, rec->ip)) { + /* This should only happen when a rec is disabled */ + WARN_ON_ONCE(!(rec->flags & FTRACE_FL_DISABLED)); + seq_putc(m, '\n'); + return 0; + } + if (iter->flags & FTRACE_ITER_ENABLED) { struct ftrace_ops *ops; @@ -3973,6 +4069,24 @@ add_rec_by_index(struct ftrace_hash *hash, struct ftrace_glob *func_g, return 0; } +#ifdef FTRACE_MCOUNT_MAX_OFFSET +static int lookup_ip(unsigned long ip, char **modname, char *str) +{ + unsigned long offset; + + kallsyms_lookup(ip, NULL, &offset, modname, str); + if (offset > FTRACE_MCOUNT_MAX_OFFSET) + return -1; + return 0; +} +#else +static int lookup_ip(unsigned long ip, char **modname, char *str) +{ + kallsyms_lookup(ip, NULL, NULL, modname, str); + return 0; +} +#endif + static int ftrace_match_record(struct dyn_ftrace *rec, struct ftrace_glob *func_g, struct ftrace_glob *mod_g, int exclude_mod) @@ -3980,7 +4094,12 @@ ftrace_match_record(struct dyn_ftrace *rec, struct ftrace_glob *func_g, char str[KSYM_SYMBOL_LEN]; char *modname; - kallsyms_lookup(rec->ip, NULL, NULL, &modname, str); + if (lookup_ip(rec->ip, &modname, str)) { + /* This should only happen when a rec is disabled */ + WARN_ON_ONCE(system_state == SYSTEM_RUNNING && + !(rec->flags & FTRACE_FL_DISABLED)); + return 0; + } if (mod_g) { int mod_matches = (modname) ? ftrace_match(modname, mod_g) : 0; @@ -4431,7 +4550,7 @@ int ftrace_func_mapper_add_ip(struct ftrace_func_mapper *mapper, * @ip: The instruction pointer address to remove the data from * * Returns the data if it is found, otherwise NULL. - * Note, if the data pointer is used as the data itself, (see + * Note, if the data pointer is used as the data itself, (see * ftrace_func_mapper_find_ip(), then the return value may be meaningless, * if the data pointer was set to zero. */ @@ -4526,8 +4645,8 @@ register_ftrace_function_probe(char *glob, struct trace_array *tr, struct ftrace_probe_ops *probe_ops, void *data) { + struct ftrace_func_probe *probe = NULL, *iter; struct ftrace_func_entry *entry; - struct ftrace_func_probe *probe; struct ftrace_hash **orig_hash; struct ftrace_hash *old_hash; struct ftrace_hash *hash; @@ -4546,11 +4665,13 @@ register_ftrace_function_probe(char *glob, struct trace_array *tr, mutex_lock(&ftrace_lock); /* Check if the probe_ops is already registered */ - list_for_each_entry(probe, &tr->func_probes, list) { - if (probe->probe_ops == probe_ops) + list_for_each_entry(iter, &tr->func_probes, list) { + if (iter->probe_ops == probe_ops) { + probe = iter; break; + } } - if (&probe->list == &tr->func_probes) { + if (!probe) { probe = kzalloc(sizeof(*probe), GFP_KERNEL); if (!probe) { mutex_unlock(&ftrace_lock); @@ -4668,9 +4789,9 @@ int unregister_ftrace_function_probe_func(char *glob, struct trace_array *tr, struct ftrace_probe_ops *probe_ops) { + struct ftrace_func_probe *probe = NULL, *iter; struct ftrace_ops_hash old_hash_ops; struct ftrace_func_entry *entry; - struct ftrace_func_probe *probe; struct ftrace_glob func_g; struct ftrace_hash **orig_hash; struct ftrace_hash *old_hash; @@ -4698,11 +4819,13 @@ unregister_ftrace_function_probe_func(char *glob, struct trace_array *tr, mutex_lock(&ftrace_lock); /* Check if the probe_ops is already registered */ - list_for_each_entry(probe, &tr->func_probes, list) { - if (probe->probe_ops == probe_ops) + list_for_each_entry(iter, &tr->func_probes, list) { + if (iter->probe_ops == probe_ops) { + probe = iter; break; + } } - if (&probe->list == &tr->func_probes) + if (!probe) goto err_unlock_ftrace; ret = -EINVAL; @@ -5161,8 +5284,6 @@ int register_ftrace_direct(unsigned long ip, unsigned long addr) goto out_unlock; ret = ftrace_set_filter_ip(&direct_ops, ip, 0, 0); - if (ret) - remove_hash_entry(direct_functions, entry); if (!ret && !(direct_ops.flags & FTRACE_OPS_FL_ENABLED)) { ret = register_ftrace_function(&direct_ops); @@ -5171,6 +5292,7 @@ int register_ftrace_direct(unsigned long ip, unsigned long addr) } if (ret) { + remove_hash_entry(direct_functions, entry); kfree(entry); if (!direct->count) { list_del_rcu(&direct->next); @@ -6793,6 +6915,13 @@ void ftrace_module_enable(struct module *mod) !within_module_init(rec->ip, mod)) break; + /* Weak functions should still be ignored */ + if (!test_for_valid_rec(rec)) { + /* Clear all other flags. Should not be enabled anyway */ + rec->flags = FTRACE_FL_DISABLED; + continue; + } + cnt = 0; /* @@ -6829,11 +6958,16 @@ void ftrace_module_enable(struct module *mod) void ftrace_module_init(struct module *mod) { + int ret; + if (ftrace_disabled || !mod->num_ftrace_callsites) return; - ftrace_process_locs(mod, mod->ftrace_callsites, - mod->ftrace_callsites + mod->num_ftrace_callsites); + ret = ftrace_process_locs(mod, mod->ftrace_callsites, + mod->ftrace_callsites + mod->num_ftrace_callsites); + if (ret) + pr_warn("ftrace: failed to allocate entries for module '%s' functions\n", + mod->name); } static void save_ftrace_mod_rec(struct ftrace_mod_map *mod_map, @@ -7166,15 +7300,19 @@ void __init ftrace_init(void) pr_info("ftrace: allocating %ld entries in %ld pages\n", count, count / ENTRIES_PER_PAGE + 1); - last_ftrace_enabled = ftrace_enabled = 1; - ret = ftrace_process_locs(NULL, __start_mcount_loc, __stop_mcount_loc); + if (ret) { + pr_warn("ftrace: failed to allocate entries for functions\n"); + goto failed; + } pr_info("ftrace: allocated %ld pages with %ld groups\n", ftrace_number_of_pages, ftrace_number_of_groups); + last_ftrace_enabled = ftrace_enabled = 1; + set_ftrace_early_filters(); return; diff --git a/kernel/trace/pid_list.c b/kernel/trace/pid_list.c index a2ef1d18126aa83a6864066bde25a7b8311ecc31..95106d02b32d82a32b7c54566a40d546e066f4d9 100644 --- a/kernel/trace/pid_list.c +++ b/kernel/trace/pid_list.c @@ -118,9 +118,9 @@ static inline unsigned int pid_join(unsigned int upper1, /** * trace_pid_list_is_set - test if the pid is set in the list * @pid_list: The pid list to test - * @pid: The pid to to see if set in the list. + * @pid: The pid to see if set in the list. * - * Tests if @pid is is set in the @pid_list. This is usually called + * Tests if @pid is set in the @pid_list. This is usually called * from the scheduler when a task is scheduled. Its pid is checked * if it should be traced or not. * diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index 05dfc7a12d3d066a8f70acf098c2650338c8c22f..d59b6a328b7feca1fa9cb947ed7c7e5d07cd22e2 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c @@ -29,6 +29,14 @@ #include +/* + * The "absolute" timestamp in the buffer is only 59 bits. + * If a clock has the 5 MSBs set, it needs to be saved and + * reinserted. + */ +#define TS_MSB (0xf8ULL << 56) +#define ABS_TS_MASK (~TS_MSB) + static void update_pages_handler(struct work_struct *work); /* @@ -468,6 +476,7 @@ struct rb_time_struct { local_t cnt; local_t top; local_t bottom; + local_t msb; }; #else #include @@ -569,7 +578,6 @@ struct ring_buffer_iter { * For the ring buffer, 64 bit required operations for the time is * the following: * - * - Only need 59 bits (uses 60 to make it even). * - Reads may fail if it interrupted a modification of the time stamp. * It will succeed if it did not interrupt another write even if * the read itself is interrupted by a write. @@ -594,6 +602,7 @@ struct ring_buffer_iter { */ #define RB_TIME_SHIFT 30 #define RB_TIME_VAL_MASK ((1 << RB_TIME_SHIFT) - 1) +#define RB_TIME_MSB_SHIFT 60 static inline int rb_time_cnt(unsigned long val) { @@ -613,7 +622,7 @@ static inline u64 rb_time_val(unsigned long top, unsigned long bottom) static inline bool __rb_time_read(rb_time_t *t, u64 *ret, unsigned long *cnt) { - unsigned long top, bottom; + unsigned long top, bottom, msb; unsigned long c; /* @@ -625,6 +634,7 @@ static inline bool __rb_time_read(rb_time_t *t, u64 *ret, unsigned long *cnt) c = local_read(&t->cnt); top = local_read(&t->top); bottom = local_read(&t->bottom); + msb = local_read(&t->msb); } while (c != local_read(&t->cnt)); *cnt = rb_time_cnt(top); @@ -633,7 +643,8 @@ static inline bool __rb_time_read(rb_time_t *t, u64 *ret, unsigned long *cnt) if (*cnt != rb_time_cnt(bottom)) return false; - *ret = rb_time_val(top, bottom); + /* The shift to msb will lose its cnt bits */ + *ret = rb_time_val(top, bottom) | ((u64)msb << RB_TIME_MSB_SHIFT); return true; } @@ -649,10 +660,12 @@ static inline unsigned long rb_time_val_cnt(unsigned long val, unsigned long cnt return (val & RB_TIME_VAL_MASK) | ((cnt & 3) << RB_TIME_SHIFT); } -static inline void rb_time_split(u64 val, unsigned long *top, unsigned long *bottom) +static inline void rb_time_split(u64 val, unsigned long *top, unsigned long *bottom, + unsigned long *msb) { *top = (unsigned long)((val >> RB_TIME_SHIFT) & RB_TIME_VAL_MASK); *bottom = (unsigned long)(val & RB_TIME_VAL_MASK); + *msb = (unsigned long)(val >> RB_TIME_MSB_SHIFT); } static inline void rb_time_val_set(local_t *t, unsigned long val, unsigned long cnt) @@ -663,15 +676,16 @@ static inline void rb_time_val_set(local_t *t, unsigned long val, unsigned long static void rb_time_set(rb_time_t *t, u64 val) { - unsigned long cnt, top, bottom; + unsigned long cnt, top, bottom, msb; - rb_time_split(val, &top, &bottom); + rb_time_split(val, &top, &bottom, &msb); /* Writes always succeed with a valid number even if it gets interrupted. */ do { cnt = local_inc_return(&t->cnt); rb_time_val_set(&t->top, top, cnt); rb_time_val_set(&t->bottom, bottom, cnt); + rb_time_val_set(&t->msb, val >> RB_TIME_MSB_SHIFT, cnt); } while (cnt != local_read(&t->cnt)); } @@ -686,8 +700,8 @@ rb_time_read_cmpxchg(local_t *l, unsigned long expect, unsigned long set) static int rb_time_cmpxchg(rb_time_t *t, u64 expect, u64 set) { - unsigned long cnt, top, bottom; - unsigned long cnt2, top2, bottom2; + unsigned long cnt, top, bottom, msb; + unsigned long cnt2, top2, bottom2, msb2; u64 val; /* The cmpxchg always fails if it interrupted an update */ @@ -703,16 +717,18 @@ static int rb_time_cmpxchg(rb_time_t *t, u64 expect, u64 set) cnt2 = cnt + 1; - rb_time_split(val, &top, &bottom); + rb_time_split(val, &top, &bottom, &msb); top = rb_time_val_cnt(top, cnt); bottom = rb_time_val_cnt(bottom, cnt); - rb_time_split(set, &top2, &bottom2); + rb_time_split(set, &top2, &bottom2, &msb2); top2 = rb_time_val_cnt(top2, cnt2); bottom2 = rb_time_val_cnt(bottom2, cnt2); if (!rb_time_read_cmpxchg(&t->cnt, cnt, cnt2)) return false; + if (!rb_time_read_cmpxchg(&t->msb, msb, msb2)) + return false; if (!rb_time_read_cmpxchg(&t->top, top, top2)) return false; if (!rb_time_read_cmpxchg(&t->bottom, bottom, bottom2)) @@ -783,6 +799,24 @@ static inline void verify_event(struct ring_buffer_per_cpu *cpu_buffer, } #endif +/* + * The absolute time stamp drops the 5 MSBs and some clocks may + * require them. The rb_fix_abs_ts() will take a previous full + * time stamp, and add the 5 MSB of that time stamp on to the + * saved absolute time stamp. Then they are compared in case of + * the unlikely event that the latest time stamp incremented + * the 5 MSB. + */ +static inline u64 rb_fix_abs_ts(u64 abs, u64 save_ts) +{ + if (save_ts & TS_MSB) { + abs |= save_ts & TS_MSB; + /* Check for overflow */ + if (unlikely(abs < save_ts)) + abs += 1ULL << 59; + } + return abs; +} static inline u64 rb_time_stamp(struct trace_buffer *buffer); @@ -811,8 +845,10 @@ u64 ring_buffer_event_time_stamp(struct trace_buffer *buffer, u64 ts; /* If the event includes an absolute time, then just use that */ - if (event->type_len == RINGBUF_TYPE_TIME_STAMP) - return rb_event_time_stamp(event); + if (event->type_len == RINGBUF_TYPE_TIME_STAMP) { + ts = rb_event_time_stamp(event); + return rb_fix_abs_ts(ts, cpu_buffer->tail_page->page->time_stamp); + } nest = local_read(&cpu_buffer->committing); verify_event(cpu_buffer, event); @@ -2754,8 +2790,15 @@ static void rb_add_timestamp(struct ring_buffer_per_cpu *cpu_buffer, (RB_ADD_STAMP_FORCE | RB_ADD_STAMP_ABSOLUTE); if (unlikely(info->delta > (1ULL << 59))) { + /* + * Some timers can use more than 59 bits, and when a timestamp + * is added to the buffer, it will lose those bits. + */ + if (abs && (info->ts & TS_MSB)) { + info->delta &= ABS_TS_MASK; + /* did the clock go backwards */ - if (info->before == info->after && info->before > info->ts) { + } else if (info->before == info->after && info->before > info->ts) { /* not interrupted */ static int once; @@ -3304,7 +3347,7 @@ static void dump_buffer_page(struct buffer_data_page *bpage, case RINGBUF_TYPE_TIME_STAMP: delta = rb_event_time_stamp(event); - ts = delta; + ts = rb_fix_abs_ts(delta, ts); pr_warn(" [%lld] absolute:%lld TIME STAMP\n", ts, delta); break; @@ -3380,7 +3423,7 @@ static void check_buffer(struct ring_buffer_per_cpu *cpu_buffer, case RINGBUF_TYPE_TIME_STAMP: delta = rb_event_time_stamp(event); - ts = delta; + ts = rb_fix_abs_ts(delta, ts); break; case RINGBUF_TYPE_PADDING: @@ -4367,6 +4410,7 @@ rb_update_read_stamp(struct ring_buffer_per_cpu *cpu_buffer, case RINGBUF_TYPE_TIME_STAMP: delta = rb_event_time_stamp(event); + delta = rb_fix_abs_ts(delta, cpu_buffer->read_stamp); cpu_buffer->read_stamp = delta; return; @@ -4397,6 +4441,7 @@ rb_update_iter_read_stamp(struct ring_buffer_iter *iter, case RINGBUF_TYPE_TIME_STAMP: delta = rb_event_time_stamp(event); + delta = rb_fix_abs_ts(delta, iter->read_stamp); iter->read_stamp = delta; return; @@ -4650,6 +4695,7 @@ rb_buffer_peek(struct ring_buffer_per_cpu *cpu_buffer, u64 *ts, case RINGBUF_TYPE_TIME_STAMP: if (ts) { *ts = rb_event_time_stamp(event); + *ts = rb_fix_abs_ts(*ts, reader->page->time_stamp); ring_buffer_normalize_time_stamp(cpu_buffer->buffer, cpu_buffer->cpu, ts); } @@ -4741,6 +4787,7 @@ rb_iter_peek(struct ring_buffer_iter *iter, u64 *ts) case RINGBUF_TYPE_TIME_STAMP: if (ts) { *ts = rb_event_time_stamp(event); + *ts = rb_fix_abs_ts(*ts, iter->head_page->page->time_stamp); ring_buffer_normalize_time_stamp(cpu_buffer->buffer, cpu_buffer->cpu, ts); } @@ -6011,10 +6058,10 @@ static __init int test_ringbuffer(void) pr_info(" total events: %ld\n", total_lost + total_read); pr_info(" recorded len bytes: %ld\n", total_len); pr_info(" recorded size bytes: %ld\n", total_size); - if (total_lost) + if (total_lost) { pr_info(" With dropped events, record len and size may not match\n" " alloced and written from above\n"); - if (!total_lost) { + } else { if (RB_WARN_ON(buffer, total_len != total_alloc || total_size != total_written)) break; diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index de431182125e5f29fd132dbae0a4323b95223caf..5f9055f19f7f031a02f946b205876dd879ca7525 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -722,13 +722,16 @@ int trace_pid_write(struct trace_pid_list *filtered_pids, pos = 0; ret = trace_get_user(&parser, ubuf, cnt, &pos); - if (ret < 0 || !trace_parser_loaded(&parser)) + if (ret < 0) break; read += ret; ubuf += ret; cnt -= ret; + if (!trace_parser_loaded(&parser)) + break; + ret = -EINVAL; if (kstrtoul(parser.buffer, 0, &val)) break; @@ -754,7 +757,6 @@ int trace_pid_write(struct trace_pid_list *filtered_pids, if (!nr_pids) { /* Cleared the list of pids */ trace_pid_list_free(pid_list); - read = ret; pid_list = NULL; } @@ -1175,7 +1177,7 @@ void tracing_snapshot_cond(struct trace_array *tr, void *cond_data) EXPORT_SYMBOL_GPL(tracing_snapshot_cond); /** - * tracing_snapshot_cond_data - get the user data associated with a snapshot + * tracing_cond_snapshot_data - get the user data associated with a snapshot * @tr: The tracing instance * * When the user enables a conditional snapshot using @@ -1543,6 +1545,7 @@ static struct { { ktime_get_mono_fast_ns, "mono", 1 }, { ktime_get_raw_fast_ns, "mono_raw", 1 }, { ktime_get_boot_fast_ns, "boot", 1 }, + { ktime_get_tai_fast_ns, "tai", 1 }, ARCH_TRACE_CLOCKS }; @@ -2836,7 +2839,7 @@ trace_event_buffer_lock_reserve(struct trace_buffer **current_rb, } EXPORT_SYMBOL_GPL(trace_event_buffer_lock_reserve); -static DEFINE_SPINLOCK(tracepoint_iter_lock); +static DEFINE_RAW_SPINLOCK(tracepoint_iter_lock); static DEFINE_MUTEX(tracepoint_printk_mutex); static void output_printk(struct trace_event_buffer *fbuffer) @@ -2864,14 +2867,14 @@ static void output_printk(struct trace_event_buffer *fbuffer) event = &fbuffer->trace_file->event_call->event; - spin_lock_irqsave(&tracepoint_iter_lock, flags); + raw_spin_lock_irqsave(&tracepoint_iter_lock, flags); trace_seq_init(&iter->seq); iter->ent = fbuffer->entry; event_call->event.funcs->trace(iter, 0, event); trace_seq_putc(&iter->seq, 0); printk("%s", iter->seq.buffer); - spin_unlock_irqrestore(&tracepoint_iter_lock, flags); + raw_spin_unlock_irqrestore(&tracepoint_iter_lock, flags); } int tracepoint_printk_sysctl(struct ctl_table *table, int write, @@ -4250,7 +4253,7 @@ static void print_func_help_header_irq(struct array_buffer *buf, struct seq_file unsigned int flags) { bool tgid = flags & TRACE_ITER_RECORD_TGID; - const char *space = " "; + static const char space[] = " "; int prec = tgid ? 12 : 2; print_event_info(buf, m); @@ -4274,9 +4277,7 @@ print_trace_header(struct seq_file *m, struct trace_iterator *iter) struct tracer *type = iter->trace; unsigned long entries; unsigned long total; - const char *name = "preemption"; - - name = type->name; + const char *name = type->name; get_total_entries(buf, &total, &entries); @@ -5470,7 +5471,7 @@ static const char readme_msg[] = " error_log\t- error log for failed commands (that support it)\n" " buffer_size_kb\t- view and modify size of per cpu buffer\n" " buffer_total_size_kb - view total size of all cpu buffers\n\n" - " trace_clock\t\t-change the clock used to order events\n" + " trace_clock\t\t- change the clock used to order events\n" " local: Per cpu clock but may not be synced across CPUs\n" " global: Synced across CPUs but slows tracing down.\n" " counter: Not a clock, but just an increment\n" @@ -5479,7 +5480,7 @@ static const char readme_msg[] = #ifdef CONFIG_X86_64 " x86-tsc: TSC cycle counter\n" #endif - "\n timestamp_mode\t-view the mode used to timestamp events\n" + "\n timestamp_mode\t- view the mode used to timestamp events\n" " delta: Delta difference against a buffer-wide timestamp\n" " absolute: Absolute (standalone) timestamp\n" "\n trace_marker\t\t- Writes into this file writes into the kernel buffer\n" @@ -6327,12 +6328,18 @@ static void tracing_set_nop(struct trace_array *tr) tr->current_trace = &nop_trace; } +static bool tracer_options_updated; + static void add_tracer_options(struct trace_array *tr, struct tracer *t) { /* Only enable if the directory has been created already. */ if (!tr->dir) return; + /* Only create trace option files after update_tracer_options finish */ + if (!tracer_options_updated) + return; + create_trace_option_files(tr, t); } @@ -6449,7 +6456,7 @@ tracing_set_trace_write(struct file *filp, const char __user *ubuf, { struct trace_array *tr = filp->private_data; char buf[MAX_TRACER_SIZE+1]; - int i; + char *name; size_t ret; int err; @@ -6463,11 +6470,9 @@ tracing_set_trace_write(struct file *filp, const char __user *ubuf, buf[cnt] = 0; - /* strip ending whitespace. */ - for (i = cnt - 1; i > 0 && isspace(buf[i]); i--) - buf[i] = 0; + name = strim(buf); - err = tracing_set_tracer(tr, buf); + err = tracing_set_tracer(tr, name); if (err) return err; @@ -9171,6 +9176,7 @@ static void __update_tracer_options(struct trace_array *tr) static void update_tracer_options(struct trace_array *tr) { mutex_lock(&trace_types_lock); + tracer_options_updated = true; __update_tracer_options(tr); mutex_unlock(&trace_types_lock); } @@ -9603,6 +9609,7 @@ extern struct trace_eval_map *__stop_ftrace_eval_maps[]; static struct workqueue_struct *eval_map_wq __initdata; static struct work_struct eval_map_work __initdata; +static struct work_struct tracerfs_init_work __initdata; static void __init eval_map_work_func(struct work_struct *work) { @@ -9628,6 +9635,8 @@ static int __init trace_eval_init(void) return 0; } +subsys_initcall(trace_eval_init); + static int __init trace_eval_sync(void) { /* Make sure the eval map updates are finished */ @@ -9710,15 +9719,8 @@ static struct notifier_block trace_module_nb = { }; #endif /* CONFIG_MODULES */ -static __init int tracer_init_tracefs(void) +static __init void tracer_init_tracefs_work_func(struct work_struct *work) { - int ret; - - trace_access_lock_init(); - - ret = tracing_init_dentry(); - if (ret) - return 0; event_trace_init(); @@ -9740,8 +9742,6 @@ static __init int tracer_init_tracefs(void) trace_create_file("saved_tgids", TRACE_MODE_READ, NULL, NULL, &tracing_saved_tgids_fops); - trace_eval_init(); - trace_create_eval_file(NULL); #ifdef CONFIG_MODULES @@ -9756,6 +9756,24 @@ static __init int tracer_init_tracefs(void) create_trace_instances(NULL); update_tracer_options(&global_trace); +} + +static __init int tracer_init_tracefs(void) +{ + int ret; + + trace_access_lock_init(); + + ret = tracing_init_dentry(); + if (ret) + return 0; + + if (eval_map_wq) { + INIT_WORK(&tracerfs_init_work, tracer_init_tracefs_work_func); + queue_work(eval_map_wq, &tracerfs_init_work); + } else { + tracer_init_tracefs_work_func(NULL); + } return 0; } diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index 07d990270e2aa1c7a01f65b55795ca5ece08f2e6..ff816fb41e48e226a00e6703bc1213f13e0f17cc 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h @@ -1573,13 +1573,12 @@ struct enable_trigger_data { }; extern int event_enable_trigger_print(struct seq_file *m, - struct event_trigger_ops *ops, - struct event_trigger_data *data); -extern void event_enable_trigger_free(struct event_trigger_ops *ops, struct event_trigger_data *data); +extern void event_enable_trigger_free(struct event_trigger_data *data); extern int event_enable_trigger_parse(struct event_command *cmd_ops, struct trace_event_file *file, - char *glob, char *cmd, char *param); + char *glob, char *cmd, + char *param_and_filter); extern int event_enable_register_trigger(char *glob, struct event_trigger_data *data, struct trace_event_file *file); @@ -1587,8 +1586,7 @@ extern void event_enable_unregister_trigger(char *glob, struct event_trigger_data *test, struct trace_event_file *file); extern void trigger_data_free(struct event_trigger_data *data); -extern int event_trigger_init(struct event_trigger_ops *ops, - struct event_trigger_data *data); +extern int event_trigger_init(struct event_trigger_data *data); extern int trace_event_trigger_enable_disable(struct trace_event_file *file, int trigger_enable); extern void update_cond_flag(struct trace_event_file *file); @@ -1629,10 +1627,11 @@ extern void event_trigger_reset_filter(struct event_command *cmd_ops, extern int event_trigger_register(struct event_command *cmd_ops, struct trace_event_file *file, char *glob, - char *cmd, - char *trigger, - struct event_trigger_data *trigger_data, - int *n_registered); + struct event_trigger_data *trigger_data); +extern void event_trigger_unregister(struct event_command *cmd_ops, + struct trace_event_file *file, + char *glob, + struct event_trigger_data *trigger_data); /** * struct event_trigger_ops - callbacks for trace event triggers @@ -1686,12 +1685,9 @@ struct event_trigger_ops { struct trace_buffer *buffer, void *rec, struct ring_buffer_event *rbe); - int (*init)(struct event_trigger_ops *ops, - struct event_trigger_data *data); - void (*free)(struct event_trigger_ops *ops, - struct event_trigger_data *data); + int (*init)(struct event_trigger_data *data); + void (*free)(struct event_trigger_data *data); int (*print)(struct seq_file *m, - struct event_trigger_ops *ops, struct event_trigger_data *data); }; diff --git a/kernel/trace/trace_boot.c b/kernel/trace/trace_boot.c index 0580287d7a0d1ed5e0280b2b29e058739db1bdce..778200dd8edea48ae9f36de6d3d7c7c019d6a557 100644 --- a/kernel/trace/trace_boot.c +++ b/kernel/trace/trace_boot.c @@ -300,7 +300,7 @@ trace_boot_hist_add_handlers(struct xbc_node *hnode, char **bufp, { struct xbc_node *node; const char *p, *handler; - int ret; + int ret = 0; handler = xbc_node_get_data(hnode); diff --git a/kernel/trace/trace_dynevent.c b/kernel/trace/trace_dynevent.c index e34e8182ee4b5ecafe8f39b5ae0f779db6dc735d..076b447a1b88944b382ae6ec8d98b6d58b280388 100644 --- a/kernel/trace/trace_dynevent.c +++ b/kernel/trace/trace_dynevent.c @@ -255,19 +255,14 @@ static const struct file_operations dynamic_events_ops = { /* Make a tracefs interface for controlling dynamic events */ static __init int init_dynamic_event(void) { - struct dentry *entry; int ret; ret = tracing_init_dentry(); if (ret) return 0; - entry = tracefs_create_file("dynamic_events", TRACE_MODE_WRITE, NULL, - NULL, &dynamic_events_ops); - - /* Event list interface */ - if (!entry) - pr_warn("Could not create tracefs 'dynamic_events' entry\n"); + trace_create_file("dynamic_events", TRACE_MODE_WRITE, NULL, + NULL, &dynamic_events_ops); return 0; } diff --git a/kernel/trace/trace_eprobe.c b/kernel/trace/trace_eprobe.c index 541aa13581b95c697a850973028c43a7db250d4c..7d4478525c66965ff7c497904a569c73dec61355 100644 --- a/kernel/trace/trace_eprobe.c +++ b/kernel/trace/trace_eprobe.c @@ -511,20 +511,17 @@ __eprobe_trace_func(struct eprobe_data *edata, void *rec) * functions are just stubs to fulfill what is needed to use the trigger * infrastructure. */ -static int eprobe_trigger_init(struct event_trigger_ops *ops, - struct event_trigger_data *data) +static int eprobe_trigger_init(struct event_trigger_data *data) { return 0; } -static void eprobe_trigger_free(struct event_trigger_ops *ops, - struct event_trigger_data *data) +static void eprobe_trigger_free(struct event_trigger_data *data) { } static int eprobe_trigger_print(struct seq_file *m, - struct event_trigger_ops *ops, struct event_trigger_data *data) { /* Do not print eprobe event triggers */ @@ -549,7 +546,8 @@ static struct event_trigger_ops eprobe_trigger_ops = { static int eprobe_trigger_cmd_parse(struct event_command *cmd_ops, struct trace_event_file *file, - char *glob, char *cmd, char *param) + char *glob, char *cmd, + char *param_and_filter) { return -1; } @@ -650,7 +648,7 @@ static struct trace_event_functions eprobe_funcs = { static int disable_eprobe(struct trace_eprobe *ep, struct trace_array *tr) { - struct event_trigger_data *trigger; + struct event_trigger_data *trigger = NULL, *iter; struct trace_event_file *file; struct eprobe_data *edata; @@ -658,14 +656,16 @@ static int disable_eprobe(struct trace_eprobe *ep, if (!file) return -ENOENT; - list_for_each_entry(trigger, &file->triggers, list) { - if (!(trigger->flags & EVENT_TRIGGER_FL_PROBE)) + list_for_each_entry(iter, &file->triggers, list) { + if (!(iter->flags & EVENT_TRIGGER_FL_PROBE)) continue; - edata = trigger->private_data; - if (edata->ep == ep) + edata = iter->private_data; + if (edata->ep == ep) { + trigger = iter; break; + } } - if (list_entry_is_head(trigger, &file->triggers, list)) + if (!trigger) return -ENODEV; list_del_rcu(&trigger->list); diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index f97de82d1342ac3ab280be6b54e008c5621fbff1..181f08186d32c01663b00b2d43b4b8877d2588e8 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c @@ -392,12 +392,6 @@ static void test_event_printk(struct trace_event_call *call) if (!(dereference_flags & (1ULL << arg))) goto next_arg; - /* Check for __get_sockaddr */; - if (str_has_prefix(fmt + i, "__get_sockaddr(")) { - dereference_flags &= ~(1ULL << arg); - goto next_arg; - } - /* Find the REC-> in the argument */ c = strchr(fmt + i, ','); r = strstr(fmt + i, "REC->"); @@ -413,7 +407,14 @@ static void test_event_printk(struct trace_event_call *call) a = strchr(fmt + i, '&'); if ((a && (a < r)) || test_field(r, call)) dereference_flags &= ~(1ULL << arg); + } else if ((r = strstr(fmt + i, "__get_dynamic_array(")) && + (!c || r < c)) { + dereference_flags &= ~(1ULL << arg); + } else if ((r = strstr(fmt + i, "__get_sockaddr(")) && + (!c || r < c)) { + dereference_flags &= ~(1ULL << arg); } + next_arg: i--; arg++; @@ -1723,9 +1724,9 @@ static LIST_HEAD(event_subsystems); static int subsystem_open(struct inode *inode, struct file *filp) { + struct trace_subsystem_dir *dir = NULL, *iter_dir; + struct trace_array *tr = NULL, *iter_tr; struct event_subsystem *system = NULL; - struct trace_subsystem_dir *dir = NULL; /* Initialize for gcc */ - struct trace_array *tr; int ret; if (tracing_is_disabled()) @@ -1734,10 +1735,12 @@ static int subsystem_open(struct inode *inode, struct file *filp) /* Make sure the system still exists */ mutex_lock(&event_mutex); mutex_lock(&trace_types_lock); - list_for_each_entry(tr, &ftrace_trace_arrays, list) { - list_for_each_entry(dir, &tr->systems, list) { - if (dir == inode->i_private) { + list_for_each_entry(iter_tr, &ftrace_trace_arrays, list) { + list_for_each_entry(iter_dir, &iter_tr->systems, list) { + if (iter_dir == inode->i_private) { /* Don't open systems with no events */ + tr = iter_tr; + dir = iter_dir; if (dir->nr_events) { __get_system_dir(dir); system = dir->subsystem; @@ -1753,9 +1756,6 @@ static int subsystem_open(struct inode *inode, struct file *filp) if (!system) return -ENODEV; - /* Some versions of gcc think dir can be uninitialized here */ - WARN_ON(!dir); - /* Still need to increment the ref count of the system */ if (trace_array_get(tr) < 0) { put_system(dir); @@ -2280,8 +2280,8 @@ static struct dentry * event_subsystem_dir(struct trace_array *tr, const char *name, struct trace_event_file *file, struct dentry *parent) { + struct event_subsystem *system, *iter; struct trace_subsystem_dir *dir; - struct event_subsystem *system; struct dentry *entry; /* First see if we did not already create this dir */ @@ -2295,13 +2295,13 @@ event_subsystem_dir(struct trace_array *tr, const char *name, } /* Now see if the system itself exists. */ - list_for_each_entry(system, &event_subsystems, list) { - if (strcmp(system->name, name) == 0) + system = NULL; + list_for_each_entry(iter, &event_subsystems, list) { + if (strcmp(iter->name, name) == 0) { + system = iter; break; + } } - /* Reset system variable when not found */ - if (&system->list == &event_subsystems) - system = NULL; dir = kmalloc(sizeof(*dir), GFP_KERNEL); if (!dir) @@ -3546,12 +3546,10 @@ create_event_toplevel_files(struct dentry *parent, struct trace_array *tr) struct dentry *d_events; struct dentry *entry; - entry = tracefs_create_file("set_event", TRACE_MODE_WRITE, parent, - tr, &ftrace_set_event_fops); - if (!entry) { - pr_warn("Could not create tracefs 'set_event' entry\n"); + entry = trace_create_file("set_event", TRACE_MODE_WRITE, parent, + tr, &ftrace_set_event_fops); + if (!entry) return -ENOMEM; - } d_events = tracefs_create_dir("events", parent); if (!d_events) { @@ -3566,16 +3564,12 @@ create_event_toplevel_files(struct dentry *parent, struct trace_array *tr) /* There are not as crucial, just warn if they are not created */ - entry = tracefs_create_file("set_event_pid", TRACE_MODE_WRITE, parent, - tr, &ftrace_set_event_pid_fops); - if (!entry) - pr_warn("Could not create tracefs 'set_event_pid' entry\n"); + trace_create_file("set_event_pid", TRACE_MODE_WRITE, parent, + tr, &ftrace_set_event_pid_fops); - entry = tracefs_create_file("set_event_notrace_pid", - TRACE_MODE_WRITE, parent, tr, - &ftrace_set_event_notrace_pid_fops); - if (!entry) - pr_warn("Could not create tracefs 'set_event_notrace_pid' entry\n"); + trace_create_file("set_event_notrace_pid", + TRACE_MODE_WRITE, parent, tr, + &ftrace_set_event_notrace_pid_fops); /* ring buffer internal formats */ trace_create_file("header_page", TRACE_MODE_READ, d_events, @@ -3790,17 +3784,14 @@ static __init int event_trace_init_fields(void) __init int event_trace_init(void) { struct trace_array *tr; - struct dentry *entry; int ret; tr = top_trace_array(); if (!tr) return -ENODEV; - entry = tracefs_create_file("available_events", TRACE_MODE_READ, - NULL, tr, &ftrace_avail_fops); - if (!entry) - pr_warn("Could not create tracefs 'available_events' entry\n"); + trace_create_file("available_events", TRACE_MODE_READ, + NULL, tr, &ftrace_avail_fops); ret = early_event_add_tracer(NULL, tr); if (ret) diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c index b458a9afa2c00ef73bd826335e2bc5ee3d4d22bf..4b1057ab9d96825f42e87c367263bf122db11819 100644 --- a/kernel/trace/trace_events_filter.c +++ b/kernel/trace/trace_events_filter.c @@ -1816,7 +1816,7 @@ static void create_filter_finish(struct filter_parse_error *pe) * create_filter - create a filter for a trace_event_call * @tr: the trace array associated with these events * @call: trace_event_call to create a filter for - * @filter_str: filter string + * @filter_string: filter string * @set_str: remember @filter_str and enable detailed error in filter * @filterp: out param for created filter (always updated on return) * Must be a pointer that references a NULL pointer. diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c index 44db5ba9cabb885a8538b882c28f04aaa1f40fa3..48e82e141d54591a28e55670a5f6863e6dbcc962 100644 --- a/kernel/trace/trace_events_hist.c +++ b/kernel/trace/trace_events_hist.c @@ -2093,8 +2093,11 @@ static int init_var_ref(struct hist_field *ref_field, return err; free: kfree(ref_field->system); + ref_field->system = NULL; kfree(ref_field->event_name); + ref_field->event_name = NULL; kfree(ref_field->name); + ref_field->name = NULL; goto out; } @@ -2785,7 +2788,8 @@ static char *find_trigger_filter(struct hist_trigger_data *hist_data, static struct event_command trigger_hist_cmd; static int event_hist_trigger_parse(struct event_command *cmd_ops, struct trace_event_file *file, - char *glob, char *cmd, char *param); + char *glob, char *cmd, + char *param_and_filter); static bool compatible_keys(struct hist_trigger_data *target_hist_data, struct hist_trigger_data *hist_data, @@ -4161,7 +4165,7 @@ static int create_val_field(struct hist_trigger_data *hist_data, return __create_val_field(hist_data, val_idx, file, NULL, field_str, 0); } -static const char *no_comm = "(no comm)"; +static const char no_comm[] = "(no comm)"; static u64 hist_field_execname(struct hist_field *hist_field, struct tracing_map_elt *elt, @@ -5252,7 +5256,7 @@ static void hist_trigger_show(struct seq_file *m, seq_puts(m, "\n\n"); seq_puts(m, "# event histogram\n#\n# trigger info: "); - data->ops->print(m, data->ops, data); + data->ops->print(m, data); seq_puts(m, "#\n\n"); hist_data = data->private_data; @@ -5484,7 +5488,7 @@ static void hist_trigger_debug_show(struct seq_file *m, seq_puts(m, "\n\n"); seq_puts(m, "# event histogram\n#\n# trigger info: "); - data->ops->print(m, data->ops, data); + data->ops->print(m, data); seq_puts(m, "#\n\n"); hist_data = data->private_data; @@ -5621,7 +5625,6 @@ static void hist_field_print(struct seq_file *m, struct hist_field *hist_field) } static int event_hist_trigger_print(struct seq_file *m, - struct event_trigger_ops *ops, struct event_trigger_data *data) { struct hist_trigger_data *hist_data = data->private_data; @@ -5729,8 +5732,7 @@ static int event_hist_trigger_print(struct seq_file *m, return 0; } -static int event_hist_trigger_init(struct event_trigger_ops *ops, - struct event_trigger_data *data) +static int event_hist_trigger_init(struct event_trigger_data *data) { struct hist_trigger_data *hist_data = data->private_data; @@ -5758,8 +5760,7 @@ static void unregister_field_var_hists(struct hist_trigger_data *hist_data) } } -static void event_hist_trigger_free(struct event_trigger_ops *ops, - struct event_trigger_data *data) +static void event_hist_trigger_free(struct event_trigger_data *data) { struct hist_trigger_data *hist_data = data->private_data; @@ -5788,25 +5789,23 @@ static struct event_trigger_ops event_hist_trigger_ops = { .free = event_hist_trigger_free, }; -static int event_hist_trigger_named_init(struct event_trigger_ops *ops, - struct event_trigger_data *data) +static int event_hist_trigger_named_init(struct event_trigger_data *data) { data->ref++; save_named_trigger(data->named_data->name, data); - event_hist_trigger_init(ops, data->named_data); + event_hist_trigger_init(data->named_data); return 0; } -static void event_hist_trigger_named_free(struct event_trigger_ops *ops, - struct event_trigger_data *data) +static void event_hist_trigger_named_free(struct event_trigger_data *data) { if (WARN_ON_ONCE(data->ref <= 0)) return; - event_hist_trigger_free(ops, data->named_data); + event_hist_trigger_free(data->named_data); data->ref--; if (!data->ref) { @@ -5933,6 +5932,48 @@ static bool hist_trigger_match(struct event_trigger_data *data, return true; } +static bool existing_hist_update_only(char *glob, + struct event_trigger_data *data, + struct trace_event_file *file) +{ + struct hist_trigger_data *hist_data = data->private_data; + struct event_trigger_data *test, *named_data = NULL; + bool updated = false; + + if (!hist_data->attrs->pause && !hist_data->attrs->cont && + !hist_data->attrs->clear) + goto out; + + if (hist_data->attrs->name) { + named_data = find_named_trigger(hist_data->attrs->name); + if (named_data) { + if (!hist_trigger_match(data, named_data, named_data, + true)) + goto out; + } + } + + if (hist_data->attrs->name && !named_data) + goto out; + + list_for_each_entry(test, &file->triggers, list) { + if (test->cmd_ops->trigger_type == ETT_EVENT_HIST) { + if (!hist_trigger_match(data, test, named_data, false)) + continue; + if (hist_data->attrs->pause) + test->paused = true; + else if (hist_data->attrs->cont) + test->paused = false; + else if (hist_data->attrs->clear) + hist_clear(test); + updated = true; + goto out; + } + } + out: + return updated; +} + static int hist_register_trigger(char *glob, struct event_trigger_data *data, struct trace_event_file *file) @@ -5961,19 +6002,11 @@ static int hist_register_trigger(char *glob, list_for_each_entry(test, &file->triggers, list) { if (test->cmd_ops->trigger_type == ETT_EVENT_HIST) { - if (!hist_trigger_match(data, test, named_data, false)) - continue; - if (hist_data->attrs->pause) - test->paused = true; - else if (hist_data->attrs->cont) - test->paused = false; - else if (hist_data->attrs->clear) - hist_clear(test); - else { + if (hist_trigger_match(data, test, named_data, false)) { hist_err(tr, HIST_ERR_TRIGGER_EEXIST, 0); ret = -EEXIST; + goto out; } - goto out; } } new: @@ -5993,7 +6026,7 @@ static int hist_register_trigger(char *glob, } if (data->ops->init) { - ret = data->ops->init(data->ops, data); + ret = data->ops->init(data); if (ret < 0) goto out; } @@ -6012,8 +6045,6 @@ static int hist_register_trigger(char *glob, if (named_data) destroy_hist_data(hist_data); - - ret++; out: return ret; } @@ -6089,20 +6120,19 @@ static void hist_unregister_trigger(char *glob, struct event_trigger_data *data, struct trace_event_file *file) { + struct event_trigger_data *test = NULL, *iter, *named_data = NULL; struct hist_trigger_data *hist_data = data->private_data; - struct event_trigger_data *test, *named_data = NULL; - bool unregistered = false; lockdep_assert_held(&event_mutex); if (hist_data->attrs->name) named_data = find_named_trigger(hist_data->attrs->name); - list_for_each_entry(test, &file->triggers, list) { - if (test->cmd_ops->trigger_type == ETT_EVENT_HIST) { - if (!hist_trigger_match(data, test, named_data, false)) + list_for_each_entry(iter, &file->triggers, list) { + if (iter->cmd_ops->trigger_type == ETT_EVENT_HIST) { + if (!hist_trigger_match(data, iter, named_data, false)) continue; - unregistered = true; + test = iter; list_del_rcu(&test->list); trace_event_trigger_enable_disable(file, 0); update_cond_flag(file); @@ -6110,11 +6140,11 @@ static void hist_unregister_trigger(char *glob, } } - if (unregistered && test->ops->free) - test->ops->free(test->ops, test); + if (test && test->ops->free) + test->ops->free(test); if (hist_data->enable_timestamps) { - if (!hist_data->remove || unregistered) + if (!hist_data->remove || test) tracing_set_filter_buffering(file->tr, false); } } @@ -6164,57 +6194,57 @@ static void hist_unreg_all(struct trace_event_file *file) if (hist_data->enable_timestamps) tracing_set_filter_buffering(file->tr, false); if (test->ops->free) - test->ops->free(test->ops, test); + test->ops->free(test); } } } static int event_hist_trigger_parse(struct event_command *cmd_ops, struct trace_event_file *file, - char *glob, char *cmd, char *param) + char *glob, char *cmd, + char *param_and_filter) { unsigned int hist_trigger_bits = TRACING_MAP_BITS_DEFAULT; struct event_trigger_data *trigger_data; struct hist_trigger_attrs *attrs; - struct event_trigger_ops *trigger_ops; struct hist_trigger_data *hist_data; + char *param, *filter, *p, *start; struct synth_event *se; const char *se_name; - bool remove = false; - char *trigger, *p, *start; + bool remove; int ret = 0; lockdep_assert_held(&event_mutex); - WARN_ON(!glob); + if (WARN_ON(!glob)) + return -EINVAL; - if (strlen(glob)) { + if (glob[0]) { hist_err_clear(); - last_cmd_set(file, param); + last_cmd_set(file, param_and_filter); } - if (!param) - return -EINVAL; + remove = event_trigger_check_remove(glob); - if (glob[0] == '!') - remove = true; + if (event_trigger_empty_param(param_and_filter)) + return -EINVAL; /* * separate the trigger from the filter (k:v [if filter]) * allowing for whitespace in the trigger */ - p = trigger = param; + p = param = param_and_filter; do { p = strstr(p, "if"); if (!p) break; - if (p == param) + if (p == param_and_filter) return -EINVAL; if (*(p - 1) != ' ' && *(p - 1) != '\t') { p++; continue; } - if (p >= param + strlen(param) - (sizeof("if") - 1) - 1) + if (p >= param_and_filter + strlen(param_and_filter) - (sizeof("if") - 1) - 1) return -EINVAL; if (*(p + sizeof("if") - 1) != ' ' && *(p + sizeof("if") - 1) != '\t') { p++; @@ -6224,24 +6254,24 @@ static int event_hist_trigger_parse(struct event_command *cmd_ops, } while (1); if (!p) - param = NULL; + filter = NULL; else { *(p - 1) = '\0'; - param = strstrip(p); - trigger = strstrip(trigger); + filter = strstrip(p); + param = strstrip(param); } /* * To simplify arithmetic expression parsing, replace occurrences of * '.sym-offset' modifier with '.symXoffset' */ - start = strstr(trigger, ".sym-offset"); + start = strstr(param, ".sym-offset"); while (start) { *(start + 4) = 'X'; start = strstr(start + 11, ".sym-offset"); } - attrs = parse_hist_trigger_attrs(file->tr, trigger); + attrs = parse_hist_trigger_attrs(file->tr, param); if (IS_ERR(attrs)) return PTR_ERR(attrs); @@ -6254,29 +6284,15 @@ static int event_hist_trigger_parse(struct event_command *cmd_ops, return PTR_ERR(hist_data); } - trigger_ops = cmd_ops->get_trigger_ops(cmd, trigger); - - trigger_data = kzalloc(sizeof(*trigger_data), GFP_KERNEL); + trigger_data = event_trigger_alloc(cmd_ops, cmd, param, hist_data); if (!trigger_data) { ret = -ENOMEM; goto out_free; } - trigger_data->count = -1; - trigger_data->ops = trigger_ops; - trigger_data->cmd_ops = cmd_ops; - - INIT_LIST_HEAD(&trigger_data->list); - RCU_INIT_POINTER(trigger_data->filter, NULL); - - trigger_data->private_data = hist_data; - - /* if param is non-empty, it's supposed to be a filter */ - if (param && cmd_ops->set_filter) { - ret = cmd_ops->set_filter(param, trigger_data, file); - if (ret < 0) - goto out_free; - } + ret = event_trigger_set_filter(cmd_ops, file, filter, trigger_data); + if (ret < 0) + goto out_free; if (remove) { if (!have_hist_trigger_match(trigger_data, file)) @@ -6287,7 +6303,7 @@ static int event_hist_trigger_parse(struct event_command *cmd_ops, goto out_free; } - cmd_ops->unreg(glob+1, trigger_data, file); + event_trigger_unregister(cmd_ops, file, glob+1, trigger_data); se_name = trace_event_name(file->event_call); se = find_synth_event(se_name); if (se) @@ -6296,17 +6312,11 @@ static int event_hist_trigger_parse(struct event_command *cmd_ops, goto out_free; } - ret = cmd_ops->reg(glob, trigger_data, file); - /* - * The above returns on success the # of triggers registered, - * but if it didn't register any it returns zero. Consider no - * triggers registered a failure too. - */ - if (!ret) { - if (!(attrs->pause || attrs->cont || attrs->clear)) - ret = -ENOENT; + if (existing_hist_update_only(glob, trigger_data, file)) goto out_free; - } else if (ret < 0) + + ret = event_trigger_register(cmd_ops, file, glob, trigger_data); + if (ret < 0) goto out_free; if (get_named_trigger_data(trigger_data)) @@ -6331,18 +6341,15 @@ enable: se = find_synth_event(se_name); if (se) se->ref++; - /* Just return zero, not the number of registered triggers */ - ret = 0; out: if (ret == 0) hist_err_clear(); return ret; out_unreg: - cmd_ops->unreg(glob+1, trigger_data, file); + event_trigger_unregister(cmd_ops, file, glob+1, trigger_data); out_free: - if (cmd_ops->set_filter) - cmd_ops->set_filter(NULL, trigger_data, NULL); + event_trigger_reset_filter(cmd_ops, trigger_data); remove_hist_vars(hist_data); @@ -6463,7 +6470,7 @@ static void hist_enable_unreg_all(struct trace_event_file *file) update_cond_flag(file); trace_event_trigger_enable_disable(file, 0); if (test->ops->free) - test->ops->free(test->ops, test); + test->ops->free(test); } } } diff --git a/kernel/trace/trace_events_trigger.c b/kernel/trace/trace_events_trigger.c index 7eb9d04f1c2ea27c0396901eaea9d434b9f55535..cb866c3141af2323001595386dd22a6eff4e9a35 100644 --- a/kernel/trace/trace_events_trigger.c +++ b/kernel/trace/trace_events_trigger.c @@ -188,7 +188,7 @@ static int trigger_show(struct seq_file *m, void *v) } data = list_entry(v, struct event_trigger_data, list); - data->ops->print(m, data->ops, data); + data->ops->print(m, data); return 0; } @@ -432,7 +432,6 @@ event_trigger_print(const char *name, struct seq_file *m, /** * event_trigger_init - Generic event_trigger_ops @init implementation - * @ops: The trigger ops associated with the trigger * @data: Trigger-specific data * * Common implementation of event trigger initialization. @@ -442,8 +441,7 @@ event_trigger_print(const char *name, struct seq_file *m, * * Return: 0 on success, errno otherwise */ -int event_trigger_init(struct event_trigger_ops *ops, - struct event_trigger_data *data) +int event_trigger_init(struct event_trigger_data *data) { data->ref++; return 0; @@ -451,7 +449,6 @@ int event_trigger_init(struct event_trigger_ops *ops, /** * event_trigger_free - Generic event_trigger_ops @free implementation - * @ops: The trigger ops associated with the trigger * @data: Trigger-specific data * * Common implementation of event trigger de-initialization. @@ -460,8 +457,7 @@ int event_trigger_init(struct event_trigger_ops *ops, * implementations. */ static void -event_trigger_free(struct event_trigger_ops *ops, - struct event_trigger_data *data) +event_trigger_free(struct event_trigger_data *data) { if (WARN_ON_ONCE(data->ref <= 0)) return; @@ -515,7 +511,7 @@ clear_event_triggers(struct trace_array *tr) trace_event_trigger_enable_disable(file, 0); list_del_rcu(&data->list); if (data->ops->free) - data->ops->free(data->ops, data); + data->ops->free(data); } } } @@ -581,19 +577,18 @@ static int register_trigger(char *glob, } if (data->ops->init) { - ret = data->ops->init(data->ops, data); + ret = data->ops->init(data); if (ret < 0) goto out; } list_add_rcu(&data->list, &file->triggers); - ret++; update_cond_flag(file); - if (trace_event_trigger_enable_disable(file, 1) < 0) { + ret = trace_event_trigger_enable_disable(file, 1); + if (ret < 0) { list_del_rcu(&data->list); update_cond_flag(file); - ret--; } out: return ret; @@ -614,14 +609,13 @@ static void unregister_trigger(char *glob, struct event_trigger_data *test, struct trace_event_file *file) { - struct event_trigger_data *data; - bool unregistered = false; + struct event_trigger_data *data = NULL, *iter; lockdep_assert_held(&event_mutex); - list_for_each_entry(data, &file->triggers, list) { - if (data->cmd_ops->trigger_type == test->cmd_ops->trigger_type) { - unregistered = true; + list_for_each_entry(iter, &file->triggers, list) { + if (iter->cmd_ops->trigger_type == test->cmd_ops->trigger_type) { + data = iter; list_del_rcu(&data->list); trace_event_trigger_enable_disable(file, 0); update_cond_flag(file); @@ -629,8 +623,8 @@ static void unregister_trigger(char *glob, } } - if (unregistered && data->ops->free) - data->ops->free(data->ops, data); + if (data && data->ops->free) + data->ops->free(data); } /* @@ -744,15 +738,15 @@ bool event_trigger_empty_param(const char *param) /** * event_trigger_separate_filter - separate an event trigger from a filter - * @param: The param string containing trigger and possibly filter - * @trigger: outparam, will be filled with a pointer to the trigger + * @param_and_filter: String containing trigger and possibly filter + * @param: outparam, will be filled with a pointer to the trigger * @filter: outparam, will be filled with a pointer to the filter * @param_required: Specifies whether or not the param string is required * * Given a param string of the form '[trigger] [if filter]', this * function separates the filter from the trigger and returns the - * trigger in *trigger and the filter in *filter. Either the *trigger - * or the *filter may be set to NULL by this function - if not set to + * trigger in @param and the filter in @filter. Either the @param + * or the @filter may be set to NULL by this function - if not set to * NULL, they will contain strings corresponding to the trigger and * filter. * @@ -927,48 +921,37 @@ void event_trigger_reset_filter(struct event_command *cmd_ops, * @cmd_ops: The event_command operations for the trigger * @file: The event file for the trigger's event * @glob: The trigger command string, with optional remove(!) operator - * @cmd: The cmd string - * @param: The param string * @trigger_data: The trigger_data for the trigger - * @n_registered: optional outparam, the number of triggers registered * * Register an event trigger. The @cmd_ops are used to call the - * cmd_ops->reg() function which actually does the registration. The - * cmd_ops->reg() function returns the number of triggers registered, - * which is assigned to n_registered, if n_registered is non-NULL. + * cmd_ops->reg() function which actually does the registration. * * Return: 0 on success, errno otherwise */ int event_trigger_register(struct event_command *cmd_ops, struct trace_event_file *file, char *glob, - char *cmd, - char *param, - struct event_trigger_data *trigger_data, - int *n_registered) + struct event_trigger_data *trigger_data) { - int ret; - - if (n_registered) - *n_registered = 0; - - ret = cmd_ops->reg(glob, trigger_data, file); - /* - * The above returns on success the # of functions enabled, - * but if it didn't find any functions it returns zero. - * Consider no functions a failure too. - */ - if (!ret) { - cmd_ops->unreg(glob, trigger_data, file); - ret = -ENOENT; - } else if (ret > 0) { - if (n_registered) - *n_registered = ret; - /* Just return zero, not the number of enabled functions */ - ret = 0; - } + return cmd_ops->reg(glob, trigger_data, file); +} - return ret; +/** + * event_trigger_unregister - unregister an event trigger + * @cmd_ops: The event_command operations for the trigger + * @file: The event file for the trigger's event + * @glob: The trigger command string, with optional remove(!) operator + * @trigger_data: The trigger_data for the trigger + * + * Unregister an event trigger. The @cmd_ops are used to call the + * cmd_ops->unreg() function which actually does the unregistration. + */ +void event_trigger_unregister(struct event_command *cmd_ops, + struct trace_event_file *file, + char *glob, + struct event_trigger_data *trigger_data) +{ + cmd_ops->unreg(glob, trigger_data, file); } /* @@ -981,7 +964,7 @@ int event_trigger_register(struct event_command *cmd_ops, * @file: The trace_event_file associated with the event * @glob: The raw string used to register the trigger * @cmd: The cmd portion of the string used to register the trigger - * @param: The params portion of the string used to register the trigger + * @param_and_filter: The param and filter portion of the string used to register the trigger * * Common implementation for event command parsing and trigger * instantiation. @@ -994,94 +977,53 @@ int event_trigger_register(struct event_command *cmd_ops, static int event_trigger_parse(struct event_command *cmd_ops, struct trace_event_file *file, - char *glob, char *cmd, char *param) + char *glob, char *cmd, char *param_and_filter) { struct event_trigger_data *trigger_data; - struct event_trigger_ops *trigger_ops; - char *trigger = NULL; - char *number; + char *param, *filter; + bool remove; int ret; - /* separate the trigger from the filter (t:n [if filter]) */ - if (param && isdigit(param[0])) { - trigger = strsep(¶m, " \t"); - if (param) { - param = skip_spaces(param); - if (!*param) - param = NULL; - } - } + remove = event_trigger_check_remove(glob); - trigger_ops = cmd_ops->get_trigger_ops(cmd, trigger); + ret = event_trigger_separate_filter(param_and_filter, ¶m, &filter, false); + if (ret) + return ret; ret = -ENOMEM; - trigger_data = kzalloc(sizeof(*trigger_data), GFP_KERNEL); + trigger_data = event_trigger_alloc(cmd_ops, cmd, param, file); if (!trigger_data) goto out; - trigger_data->count = -1; - trigger_data->ops = trigger_ops; - trigger_data->cmd_ops = cmd_ops; - trigger_data->private_data = file; - INIT_LIST_HEAD(&trigger_data->list); - INIT_LIST_HEAD(&trigger_data->named_list); - - if (glob[0] == '!') { - cmd_ops->unreg(glob+1, trigger_data, file); + if (remove) { + event_trigger_unregister(cmd_ops, file, glob+1, trigger_data); kfree(trigger_data); ret = 0; goto out; } - if (trigger) { - number = strsep(&trigger, ":"); - - ret = -EINVAL; - if (!strlen(number)) - goto out_free; - - /* - * We use the callback data field (which is a pointer) - * as our counter. - */ - ret = kstrtoul(number, 0, &trigger_data->count); - if (ret) - goto out_free; - } - - if (!param) /* if param is non-empty, it's supposed to be a filter */ - goto out_reg; - - if (!cmd_ops->set_filter) - goto out_reg; + ret = event_trigger_parse_num(param, trigger_data); + if (ret) + goto out_free; - ret = cmd_ops->set_filter(param, trigger_data, file); + ret = event_trigger_set_filter(cmd_ops, file, filter, trigger_data); if (ret < 0) goto out_free; - out_reg: /* Up the trigger_data count to make sure reg doesn't free it on failure */ - event_trigger_init(trigger_ops, trigger_data); - ret = cmd_ops->reg(glob, trigger_data, file); - /* - * The above returns on success the # of functions enabled, - * but if it didn't find any functions it returns zero. - * Consider no functions a failure too. - */ - if (!ret) { - cmd_ops->unreg(glob, trigger_data, file); - ret = -ENOENT; - } else if (ret > 0) - ret = 0; + event_trigger_init(trigger_data); + + ret = event_trigger_register(cmd_ops, file, glob, trigger_data); + if (ret) + goto out_free; /* Down the counter of trigger_data or free it if not used anymore */ - event_trigger_free(trigger_ops, trigger_data); + event_trigger_free(trigger_data); out: return ret; out_free: - if (cmd_ops->set_filter) - cmd_ops->set_filter(NULL, trigger_data, NULL); + event_trigger_reset_filter(cmd_ops, trigger_data); kfree(trigger_data); goto out; } @@ -1401,16 +1343,14 @@ traceoff_count_trigger(struct event_trigger_data *data, } static int -traceon_trigger_print(struct seq_file *m, struct event_trigger_ops *ops, - struct event_trigger_data *data) +traceon_trigger_print(struct seq_file *m, struct event_trigger_data *data) { return event_trigger_print("traceon", m, (void *)data->count, data->filter_str); } static int -traceoff_trigger_print(struct seq_file *m, struct event_trigger_ops *ops, - struct event_trigger_data *data) +traceoff_trigger_print(struct seq_file *m, struct event_trigger_data *data) { return event_trigger_print("traceoff", m, (void *)data->count, data->filter_str); @@ -1521,8 +1461,7 @@ register_snapshot_trigger(char *glob, } static int -snapshot_trigger_print(struct seq_file *m, struct event_trigger_ops *ops, - struct event_trigger_data *data) +snapshot_trigger_print(struct seq_file *m, struct event_trigger_data *data) { return event_trigger_print("snapshot", m, (void *)data->count, data->filter_str); @@ -1617,8 +1556,7 @@ stacktrace_count_trigger(struct event_trigger_data *data, } static int -stacktrace_trigger_print(struct seq_file *m, struct event_trigger_ops *ops, - struct event_trigger_data *data) +stacktrace_trigger_print(struct seq_file *m, struct event_trigger_data *data) { return event_trigger_print("stacktrace", m, (void *)data->count, data->filter_str); @@ -1708,7 +1646,6 @@ event_enable_count_trigger(struct event_trigger_data *data, } int event_enable_trigger_print(struct seq_file *m, - struct event_trigger_ops *ops, struct event_trigger_data *data) { struct enable_trigger_data *enable_data = data->private_data; @@ -1733,8 +1670,7 @@ int event_enable_trigger_print(struct seq_file *m, return 0; } -void event_enable_trigger_free(struct event_trigger_ops *ops, - struct event_trigger_data *data) +void event_enable_trigger_free(struct event_trigger_data *data) { struct enable_trigger_data *enable_data = data->private_data; @@ -1781,39 +1717,33 @@ static struct event_trigger_ops event_disable_count_trigger_ops = { int event_enable_trigger_parse(struct event_command *cmd_ops, struct trace_event_file *file, - char *glob, char *cmd, char *param) + char *glob, char *cmd, char *param_and_filter) { struct trace_event_file *event_enable_file; struct enable_trigger_data *enable_data; struct event_trigger_data *trigger_data; - struct event_trigger_ops *trigger_ops; struct trace_array *tr = file->tr; + char *param, *filter; + bool enable, remove; const char *system; const char *event; bool hist = false; - char *trigger; - char *number; - bool enable; int ret; - if (!param) - return -EINVAL; + remove = event_trigger_check_remove(glob); - /* separate the trigger from the filter (s:e:n [if filter]) */ - trigger = strsep(¶m, " \t"); - if (!trigger) + if (event_trigger_empty_param(param_and_filter)) return -EINVAL; - if (param) { - param = skip_spaces(param); - if (!*param) - param = NULL; - } - system = strsep(&trigger, ":"); - if (!trigger) + ret = event_trigger_separate_filter(param_and_filter, ¶m, &filter, true); + if (ret) + return ret; + + system = strsep(¶m, ":"); + if (!param) return -EINVAL; - event = strsep(&trigger, ":"); + event = strsep(¶m, ":"); ret = -EINVAL; event_enable_file = find_event_file(tr, system, event); @@ -1829,32 +1759,24 @@ int event_enable_trigger_parse(struct event_command *cmd_ops, #else enable = strcmp(cmd, ENABLE_EVENT_STR) == 0; #endif - trigger_ops = cmd_ops->get_trigger_ops(cmd, trigger); - ret = -ENOMEM; - trigger_data = kzalloc(sizeof(*trigger_data), GFP_KERNEL); - if (!trigger_data) - goto out; enable_data = kzalloc(sizeof(*enable_data), GFP_KERNEL); - if (!enable_data) { - kfree(trigger_data); + if (!enable_data) goto out; - } - - trigger_data->count = -1; - trigger_data->ops = trigger_ops; - trigger_data->cmd_ops = cmd_ops; - INIT_LIST_HEAD(&trigger_data->list); - RCU_INIT_POINTER(trigger_data->filter, NULL); enable_data->hist = hist; enable_data->enable = enable; enable_data->file = event_enable_file; - trigger_data->private_data = enable_data; - if (glob[0] == '!') { - cmd_ops->unreg(glob+1, trigger_data, file); + trigger_data = event_trigger_alloc(cmd_ops, cmd, param, enable_data); + if (!trigger_data) { + kfree(enable_data); + goto out; + } + + if (remove) { + event_trigger_unregister(cmd_ops, file, glob+1, trigger_data); kfree(trigger_data); kfree(enable_data); ret = 0; @@ -1862,35 +1784,16 @@ int event_enable_trigger_parse(struct event_command *cmd_ops, } /* Up the trigger_data count to make sure nothing frees it on failure */ - event_trigger_init(trigger_ops, trigger_data); - - if (trigger) { - number = strsep(&trigger, ":"); - - ret = -EINVAL; - if (!strlen(number)) - goto out_free; - - /* - * We use the callback data field (which is a pointer) - * as our counter. - */ - ret = kstrtoul(number, 0, &trigger_data->count); - if (ret) - goto out_free; - } + event_trigger_init(trigger_data); - if (!param) /* if param is non-empty, it's supposed to be a filter */ - goto out_reg; - - if (!cmd_ops->set_filter) - goto out_reg; + ret = event_trigger_parse_num(param, trigger_data); + if (ret) + goto out_free; - ret = cmd_ops->set_filter(param, trigger_data, file); + ret = event_trigger_set_filter(cmd_ops, file, filter, trigger_data); if (ret < 0) goto out_free; - out_reg: /* Don't let event modules unload while probe registered */ ret = trace_event_try_get_ref(event_enable_file->event_call); if (!ret) { @@ -1901,32 +1804,23 @@ int event_enable_trigger_parse(struct event_command *cmd_ops, ret = trace_event_enable_disable(event_enable_file, 1, 1); if (ret < 0) goto out_put; - ret = cmd_ops->reg(glob, trigger_data, file); - /* - * The above returns on success the # of functions enabled, - * but if it didn't find any functions it returns zero. - * Consider no functions a failure too. - */ - if (!ret) { - ret = -ENOENT; - goto out_disable; - } else if (ret < 0) + + ret = event_trigger_register(cmd_ops, file, glob, trigger_data); + if (ret) goto out_disable; - /* Just return zero, not the number of enabled functions */ - ret = 0; - event_trigger_free(trigger_ops, trigger_data); + + event_trigger_free(trigger_data); out: return ret; - out_disable: trace_event_enable_disable(event_enable_file, 0, 1); out_put: trace_event_put_ref(event_enable_file->event_call); out_free: - if (cmd_ops->set_filter) - cmd_ops->set_filter(NULL, trigger_data, NULL); - event_trigger_free(trigger_ops, trigger_data); + event_trigger_reset_filter(cmd_ops, trigger_data); + event_trigger_free(trigger_data); kfree(enable_data); + goto out; } @@ -1953,19 +1847,18 @@ int event_enable_register_trigger(char *glob, } if (data->ops->init) { - ret = data->ops->init(data->ops, data); + ret = data->ops->init(data); if (ret < 0) goto out; } list_add_rcu(&data->list, &file->triggers); - ret++; update_cond_flag(file); - if (trace_event_trigger_enable_disable(file, 1) < 0) { + ret = trace_event_trigger_enable_disable(file, 1); + if (ret < 0) { list_del_rcu(&data->list); update_cond_flag(file); - ret--; } out: return ret; @@ -1976,19 +1869,18 @@ void event_enable_unregister_trigger(char *glob, struct trace_event_file *file) { struct enable_trigger_data *test_enable_data = test->private_data; + struct event_trigger_data *data = NULL, *iter; struct enable_trigger_data *enable_data; - struct event_trigger_data *data; - bool unregistered = false; lockdep_assert_held(&event_mutex); - list_for_each_entry(data, &file->triggers, list) { - enable_data = data->private_data; + list_for_each_entry(iter, &file->triggers, list) { + enable_data = iter->private_data; if (enable_data && - (data->cmd_ops->trigger_type == + (iter->cmd_ops->trigger_type == test->cmd_ops->trigger_type) && (enable_data->file == test_enable_data->file)) { - unregistered = true; + data = iter; list_del_rcu(&data->list); trace_event_trigger_enable_disable(file, 0); update_cond_flag(file); @@ -1996,8 +1888,8 @@ void event_enable_unregister_trigger(char *glob, } } - if (unregistered && data->ops->free) - data->ops->free(data->ops, data); + if (data && data->ops->free) + data->ops->free(data); } static struct event_trigger_ops * diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c index 47cebef78532c28e877e6213fb2746e0869d362d..93507330462c128e885f6bd5859a773ccdec5dbd 100644 --- a/kernel/trace/trace_kprobe.c +++ b/kernel/trace/trace_kprobe.c @@ -1907,25 +1907,18 @@ core_initcall(init_kprobe_trace_early); static __init int init_kprobe_trace(void) { int ret; - struct dentry *entry; ret = tracing_init_dentry(); if (ret) return 0; - entry = tracefs_create_file("kprobe_events", TRACE_MODE_WRITE, - NULL, NULL, &kprobe_events_ops); - /* Event list interface */ - if (!entry) - pr_warn("Could not create tracefs 'kprobe_events' entry\n"); + trace_create_file("kprobe_events", TRACE_MODE_WRITE, + NULL, NULL, &kprobe_events_ops); /* Profile interface */ - entry = tracefs_create_file("kprobe_profile", TRACE_MODE_READ, - NULL, NULL, &kprobe_profile_ops); - - if (!entry) - pr_warn("Could not create tracefs 'kprobe_profile' entry\n"); + trace_create_file("kprobe_profile", TRACE_MODE_READ, + NULL, NULL, &kprobe_profile_ops); setup_boot_kprobe_events(); diff --git a/kernel/trace/trace_osnoise.c b/kernel/trace/trace_osnoise.c index afb92e2f0aeab5327a727d464e9150815050feba..313439920a8ce90d27f13eab9931c08e29ebaf2b 100644 --- a/kernel/trace/trace_osnoise.c +++ b/kernel/trace/trace_osnoise.c @@ -1578,11 +1578,27 @@ static enum hrtimer_restart timerlat_irq(struct hrtimer *timer) trace_timerlat_sample(&s); - notify_new_max_latency(diff); + if (osnoise_data.stop_tracing) { + if (time_to_us(diff) >= osnoise_data.stop_tracing) { + + /* + * At this point, if stop_tracing is set and <= print_stack, + * print_stack is set and would be printed in the thread handler. + * + * Thus, print the stack trace as it is helpful to define the + * root cause of an IRQ latency. + */ + if (osnoise_data.stop_tracing <= osnoise_data.print_stack) { + timerlat_save_stack(0); + timerlat_dump_stack(time_to_us(diff)); + } - if (osnoise_data.stop_tracing) - if (time_to_us(diff) >= osnoise_data.stop_tracing) osnoise_stop_tracing(); + notify_new_max_latency(diff); + + return HRTIMER_NORESTART; + } + } wake_up_process(tlat->kthread); diff --git a/kernel/trace/trace_output.c b/kernel/trace/trace_output.c index 8aa493d25c73eb5ebcee1fe8a7d251e5a2601fb5..67f47ea27921d5575b29b55bc97d7bfdb1d91dd6 100644 --- a/kernel/trace/trace_output.c +++ b/kernel/trace/trace_output.c @@ -692,7 +692,7 @@ static LIST_HEAD(ftrace_event_list); static int trace_search_list(struct list_head **list) { - struct trace_event *e; + struct trace_event *e = NULL, *iter; int next = __TRACE_LAST_TYPE; if (list_empty(&ftrace_event_list)) { @@ -704,9 +704,11 @@ static int trace_search_list(struct list_head **list) * We used up all possible max events, * lets see if somebody freed one. */ - list_for_each_entry(e, &ftrace_event_list, list) { - if (e->type != next) + list_for_each_entry(iter, &ftrace_event_list, list) { + if (iter->type != next) { + e = iter; break; + } next++; } @@ -714,7 +716,10 @@ static int trace_search_list(struct list_head **list) if (next > TRACE_EVENT_TYPE_MAX) return 0; - *list = &e->list; + if (e) + *list = &e->list; + else + *list = &ftrace_event_list; return next; } @@ -778,9 +783,8 @@ int register_trace_event(struct trace_event *event) list_add_tail(&event->list, list); - } else if (event->type > __TRACE_LAST_TYPE) { - printk(KERN_WARNING "Need to add type to trace.h\n"); - WARN_ON(1); + } else if (WARN(event->type > __TRACE_LAST_TYPE, + "Need to add type to trace.h")) { goto out; } else { /* Is this event already used */ @@ -1571,13 +1575,8 @@ __init static int init_events(void) for (i = 0; events[i]; i++) { event = events[i]; - ret = register_trace_event(event); - if (!ret) { - printk(KERN_WARNING "event %d failed to register\n", - event->type); - WARN_ON_ONCE(1); - } + WARN_ONCE(!ret, "event %d failed to register", event->type); } return 0; diff --git a/kernel/trace/trace_recursion_record.c b/kernel/trace/trace_recursion_record.c index 4d4b78c8ca257b0b8beaa3b2cd41b4fe8512567c..a520b11afb0dd3d0b9d7329a61f384ebd109af5f 100644 --- a/kernel/trace/trace_recursion_record.c +++ b/kernel/trace/trace_recursion_record.c @@ -224,12 +224,9 @@ static const struct file_operations recursed_functions_fops = { __init static int create_recursed_functions(void) { - struct dentry *dentry; - dentry = trace_create_file("recursed_functions", TRACE_MODE_WRITE, - NULL, NULL, &recursed_functions_fops); - if (!dentry) - pr_warn("WARNING: Failed to create recursed_functions\n"); + trace_create_file("recursed_functions", TRACE_MODE_WRITE, + NULL, NULL, &recursed_functions_fops); return 0; } diff --git a/kernel/trace/trace_selftest.c b/kernel/trace/trace_selftest.c index abcadbe933bb7662725b7ed4b4930bd73bd3ff01..a2d301f58ceda90cd3485db8f74627f955e73eb6 100644 --- a/kernel/trace/trace_selftest.c +++ b/kernel/trace/trace_selftest.c @@ -895,6 +895,9 @@ trace_selftest_startup_function_graph(struct tracer *trace, ret = -1; goto out; } + + /* Enable tracing on all functions again */ + ftrace_set_global_filter(NULL, 0, 1); #endif /* Don't test dynamic tracing, the function tracer already did */ diff --git a/kernel/trace/trace_syscalls.c b/kernel/trace/trace_syscalls.c index f755bde42fd07c1be41445f02b895a4e4828cf88..b69e207012c99080f510da221639573da45d82cd 100644 --- a/kernel/trace/trace_syscalls.c +++ b/kernel/trace/trace_syscalls.c @@ -154,7 +154,7 @@ print_syscall_enter(struct trace_iterator *iter, int flags, goto end; /* parameter types */ - if (tr->trace_flags & TRACE_ITER_VERBOSE) + if (tr && tr->trace_flags & TRACE_ITER_VERBOSE) trace_seq_printf(s, "%s ", entry->types[i]); /* parameter values */ @@ -296,9 +296,7 @@ static void ftrace_syscall_enter(void *data, struct pt_regs *regs, long id) struct trace_event_file *trace_file; struct syscall_trace_enter *entry; struct syscall_metadata *sys_data; - struct ring_buffer_event *event; - struct trace_buffer *buffer; - unsigned int trace_ctx; + struct trace_event_buffer fbuffer; unsigned long args[6]; int syscall_nr; int size; @@ -321,20 +319,16 @@ static void ftrace_syscall_enter(void *data, struct pt_regs *regs, long id) size = sizeof(*entry) + sizeof(unsigned long) * sys_data->nb_args; - trace_ctx = tracing_gen_ctx(); - - event = trace_event_buffer_lock_reserve(&buffer, trace_file, - sys_data->enter_event->event.type, size, trace_ctx); - if (!event) + entry = trace_event_buffer_reserve(&fbuffer, trace_file, size); + if (!entry) return; - entry = ring_buffer_event_data(event); + entry = ring_buffer_event_data(fbuffer.event); entry->nr = syscall_nr; syscall_get_arguments(current, regs, args); memcpy(entry->args, args, sizeof(unsigned long) * sys_data->nb_args); - event_trigger_unlock_commit(trace_file, buffer, event, entry, - trace_ctx); + trace_event_buffer_commit(&fbuffer); } static void ftrace_syscall_exit(void *data, struct pt_regs *regs, long ret) @@ -343,9 +337,7 @@ static void ftrace_syscall_exit(void *data, struct pt_regs *regs, long ret) struct trace_event_file *trace_file; struct syscall_trace_exit *entry; struct syscall_metadata *sys_data; - struct ring_buffer_event *event; - struct trace_buffer *buffer; - unsigned int trace_ctx; + struct trace_event_buffer fbuffer; int syscall_nr; syscall_nr = trace_get_syscall_nr(current, regs); @@ -364,20 +356,15 @@ static void ftrace_syscall_exit(void *data, struct pt_regs *regs, long ret) if (!sys_data) return; - trace_ctx = tracing_gen_ctx(); - - event = trace_event_buffer_lock_reserve(&buffer, trace_file, - sys_data->exit_event->event.type, sizeof(*entry), - trace_ctx); - if (!event) + entry = trace_event_buffer_reserve(&fbuffer, trace_file, sizeof(*entry)); + if (!entry) return; - entry = ring_buffer_event_data(event); + entry = ring_buffer_event_data(fbuffer.event); entry->nr = syscall_nr; entry->ret = syscall_get_return_value(current, regs); - event_trigger_unlock_commit(trace_file, buffer, event, entry, - trace_ctx); + trace_event_buffer_commit(&fbuffer); } static int reg_event_syscall_enter(struct trace_event_file *file, diff --git a/kernel/trace/tracing_map.c b/kernel/trace/tracing_map.c index 9628b557184688485b586b3d130c414cc09e6442..9901708ce6b8a5333a2ab3e5ff8a172f206cab8c 100644 --- a/kernel/trace/tracing_map.c +++ b/kernel/trace/tracing_map.c @@ -1045,7 +1045,8 @@ static void sort_secondary(struct tracing_map *map, /** * tracing_map_sort_entries - Sort the current set of tracing_map_elts in a map * @map: The tracing_map - * @sort_key: The sort key to use for sorting + * @sort_keys: The sort key to use for sorting + * @n_sort_keys: hitcount, always have at least one * @sort_entries: outval: pointer to allocated and sorted array of entries * * tracing_map_sort_entries() sorts the current set of entries in the diff --git a/lib/.gitignore b/lib/.gitignore index e5e217b8307b44ba593af0d6396359933ce4fa07..54596b634ecbfff06dff6f6e10a535b0982e6a3a 100644 --- a/lib/.gitignore +++ b/lib/.gitignore @@ -1,6 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-only /crc32table.h /crc64table.h +/default.bconf /gen_crc32table /gen_crc64table /oid_registry_data.c diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 4cea85a833214fed013227bbd0b8442ff884ccaa..2e24db4bff1921483ad1bd1e181d242e6cd55345 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -1490,29 +1490,6 @@ config CSD_LOCK_WAIT_DEBUG include the IPI handler function currently executing (if any) and relevant stack traces. -choice - prompt "Lock debugging: prove subsystem device_lock() correctness" - depends on PROVE_LOCKING - help - For subsystems that have instrumented their usage of the device_lock() - with nested annotations, enable lock dependency checking. The locking - hierarchy 'subclass' identifiers are not compatible across - sub-systems, so only one can be enabled at a time. - -config PROVE_NVDIMM_LOCKING - bool "NVDIMM" - depends on LIBNVDIMM - help - Enable lockdep to validate nd_device_lock() usage. - -config PROVE_CXL_LOCKING - bool "CXL" - depends on CXL_BUS - help - Enable lockdep to validate cxl_device_lock() usage. - -endchoice - endmenu # lock debugging config TRACE_IRQFLAGS diff --git a/lib/Makefile b/lib/Makefile index 89fcae891361f000550b451d13825589ea92cc91..ea54294d73bf4a4832d1862cc2121872c62ca4c4 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -281,7 +281,15 @@ $(foreach file, $(libfdt_files), \ $(eval CFLAGS_$(file) = -I $(srctree)/scripts/dtc/libfdt)) lib-$(CONFIG_LIBFDT) += $(libfdt_files) -lib-$(CONFIG_BOOT_CONFIG) += bootconfig.o +obj-$(CONFIG_BOOT_CONFIG) += bootconfig.o +obj-$(CONFIG_BOOT_CONFIG_EMBED) += bootconfig-data.o + +$(obj)/bootconfig-data.o: $(obj)/default.bconf + +targets += default.bconf +filechk_defbconf = cat $(or $(real-prereqs), /dev/null) +$(obj)/default.bconf: $(CONFIG_BOOT_CONFIG_EMBED_FILE) FORCE + $(call filechk,defbconf) obj-$(CONFIG_RBTREE_TEST) += rbtree_test.o obj-$(CONFIG_INTERVAL_TREE_TEST) += interval_tree_test.o diff --git a/lib/bootconfig-data.S b/lib/bootconfig-data.S new file mode 100644 index 0000000000000000000000000000000000000000..ef85ba1a82f4a319d025f0ba1ccc82e8e5d28755 --- /dev/null +++ b/lib/bootconfig-data.S @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Embed default bootconfig in the kernel. + */ + .section .init.rodata, "aw" + .global embedded_bootconfig_data +embedded_bootconfig_data: + .incbin "lib/default.bconf" + .global embedded_bootconfig_data_end +embedded_bootconfig_data_end: diff --git a/lib/bootconfig.c b/lib/bootconfig.c index 74f3201ab8e59e6201c02b5e97839cb148c9c880..c59d26068a6401990343e26c03002fcc4022ef98 100644 --- a/lib/bootconfig.c +++ b/lib/bootconfig.c @@ -12,6 +12,19 @@ #include #include #include + +#ifdef CONFIG_BOOT_CONFIG_EMBED +/* embedded_bootconfig_data is defined in bootconfig-data.S */ +extern __visible const char embedded_bootconfig_data[]; +extern __visible const char embedded_bootconfig_data_end[]; + +const char * __init xbc_get_embedded_bootconfig(size_t *size) +{ + *size = embedded_bootconfig_data_end - embedded_bootconfig_data; + return (*size) ? embedded_bootconfig_data : NULL; +} +#endif + #else /* !__KERNEL__ */ /* * NOTE: This is only for tools/bootconfig, because tools/bootconfig will diff --git a/lib/crypto/Kconfig b/lib/crypto/Kconfig index a80b8c4dc2cfdeae03696fc549211e6220386399..9856e291f41410b490ba411685924326f0a71c3e 100644 --- a/lib/crypto/Kconfig +++ b/lib/crypto/Kconfig @@ -85,7 +85,6 @@ config CRYPTO_LIB_POLY1305_RSIZE default 11 if X86_64 default 9 if ARM || ARM64 default 1 - depends on CRYPTO_LIB_POLY1305 config CRYPTO_ARCH_HAVE_LIB_POLY1305 tristate @@ -124,10 +123,4 @@ config CRYPTO_LIB_CHACHA20POLY1305 config CRYPTO_LIB_SHA256 tristate -config CRYPTO_LIB_SM3 - tristate - -config CRYPTO_LIB_SM4 - tristate - endmenu diff --git a/lib/crypto/Makefile b/lib/crypto/Makefile index 6c872d05d1e6207031c40a2005009abf913a7ec2..26be2bbe09c59e3792368ab228e9f3dae09f778e 100644 --- a/lib/crypto/Makefile +++ b/lib/crypto/Makefile @@ -37,12 +37,6 @@ libpoly1305-y += poly1305.o obj-$(CONFIG_CRYPTO_LIB_SHA256) += libsha256.o libsha256-y := sha256.o -obj-$(CONFIG_CRYPTO_LIB_SM3) += libsm3.o -libsm3-y := sm3.o - -obj-$(CONFIG_CRYPTO_LIB_SM4) += libsm4.o -libsm4-y := sm4.o - ifneq ($(CONFIG_CRYPTO_MANAGER_DISABLE_TESTS),y) libblake2s-y += blake2s-selftest.o libchacha20poly1305-y += chacha20poly1305-selftest.o diff --git a/mm/fadvise.c b/mm/fadvise.c index 338f1602201299463d56e62543616d5d53abd8d2..c76ee665355a4663e2713f59509d183c90bf7258 100644 --- a/mm/fadvise.c +++ b/mm/fadvise.c @@ -214,5 +214,16 @@ SYSCALL_DEFINE4(fadvise64, int, fd, loff_t, offset, size_t, len, int, advice) return ksys_fadvise64_64(fd, offset, len, advice); } +#endif + +#if defined(CONFIG_COMPAT) && defined(__ARCH_WANT_COMPAT_FADVISE64_64) + +COMPAT_SYSCALL_DEFINE6(fadvise64_64, int, fd, compat_arg_u64_dual(offset), + compat_arg_u64_dual(len), int, advice) +{ + return ksys_fadvise64_64(fd, compat_arg_u64_glue(offset), + compat_arg_u64_glue(len), advice); +} + #endif #endif diff --git a/mm/mmap.c b/mm/mmap.c index 2b9305ed0dda6df1f9b42c92572cd2dd0a82e0e1..61e6135c54ef6b7c4781783eb15c0ef440d1e661 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -2140,15 +2140,15 @@ unsigned long vm_unmapped_area(struct vm_unmapped_area_info *info) * * This function "knows" that -ENOMEM has the bits set. */ -#ifndef HAVE_ARCH_UNMAPPED_AREA unsigned long -arch_get_unmapped_area(struct file *filp, unsigned long addr, - unsigned long len, unsigned long pgoff, unsigned long flags) +generic_get_unmapped_area(struct file *filp, unsigned long addr, + unsigned long len, unsigned long pgoff, + unsigned long flags) { struct mm_struct *mm = current->mm; struct vm_area_struct *vma, *prev; struct vm_unmapped_area_info info; - const unsigned long mmap_end = arch_get_mmap_end(addr); + const unsigned long mmap_end = arch_get_mmap_end(addr, len, flags); if (len > mmap_end - mmap_min_addr) return -ENOMEM; @@ -2173,22 +2173,30 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, info.align_offset = 0; return vm_unmapped_area(&info); } + +#ifndef HAVE_ARCH_UNMAPPED_AREA +unsigned long +arch_get_unmapped_area(struct file *filp, unsigned long addr, + unsigned long len, unsigned long pgoff, + unsigned long flags) +{ + return generic_get_unmapped_area(filp, addr, len, pgoff, flags); +} #endif /* * This mmap-allocator allocates new areas top-down from below the * stack's low limit (the base): */ -#ifndef HAVE_ARCH_UNMAPPED_AREA_TOPDOWN unsigned long -arch_get_unmapped_area_topdown(struct file *filp, unsigned long addr, - unsigned long len, unsigned long pgoff, - unsigned long flags) +generic_get_unmapped_area_topdown(struct file *filp, unsigned long addr, + unsigned long len, unsigned long pgoff, + unsigned long flags) { struct vm_area_struct *vma, *prev; struct mm_struct *mm = current->mm; struct vm_unmapped_area_info info; - const unsigned long mmap_end = arch_get_mmap_end(addr); + const unsigned long mmap_end = arch_get_mmap_end(addr, len, flags); /* requested length too big for entire address space */ if (len > mmap_end - mmap_min_addr) @@ -2231,6 +2239,15 @@ arch_get_unmapped_area_topdown(struct file *filp, unsigned long addr, return addr; } + +#ifndef HAVE_ARCH_UNMAPPED_AREA_TOPDOWN +unsigned long +arch_get_unmapped_area_topdown(struct file *filp, unsigned long addr, + unsigned long len, unsigned long pgoff, + unsigned long flags) +{ + return generic_get_unmapped_area_topdown(filp, addr, len, pgoff, flags); +} #endif unsigned long diff --git a/mm/readahead.c b/mm/readahead.c index b78921b547547a4c6d2150996306140971fe0f1a..415c39d764eaebc0696f270ef5a98117c8e51348 100644 --- a/mm/readahead.c +++ b/mm/readahead.c @@ -749,6 +749,13 @@ SYSCALL_DEFINE3(readahead, int, fd, loff_t, offset, size_t, count) return ksys_readahead(fd, offset, count); } +#if defined(CONFIG_COMPAT) && defined(__ARCH_WANT_COMPAT_READAHEAD) +COMPAT_SYSCALL_DEFINE4(readahead, int, fd, compat_arg_u64_dual(offset), size_t, count) +{ + return ksys_readahead(fd, compat_arg_u64_glue(offset), count); +} +#endif + /** * readahead_expand - Expand a readahead request * @ractl: The request to be expanded diff --git a/mm/util.c b/mm/util.c index 12fbab129662efc625a35c9dd73eb875e95ec84e..edf44a1dc3d41cbd4e8081186fc6fb4013bd82bf 100644 --- a/mm/util.c +++ b/mm/util.c @@ -381,7 +381,7 @@ unsigned long randomize_page(unsigned long start, unsigned long range) } #ifdef CONFIG_ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT -unsigned long arch_randomize_brk(struct mm_struct *mm) +unsigned long __weak arch_randomize_brk(struct mm_struct *mm) { /* Is the current task 32bit ? */ if (!IS_ENABLED(CONFIG_64BIT) || is_compat_task()) diff --git a/net/vmw_vsock/hyperv_transport.c b/net/vmw_vsock/hyperv_transport.c index e111e13b666049dcacb565878dfe7bf47b16e1d2..fd98229e3db30988b983761b9c809ce059d6d9b2 100644 --- a/net/vmw_vsock/hyperv_transport.c +++ b/net/vmw_vsock/hyperv_transport.c @@ -78,6 +78,9 @@ struct hvs_send_buf { ALIGN((payload_len), 8) + \ VMBUS_PKT_TRAILER_SIZE) +/* Upper bound on the size of a VMbus packet for hv_sock */ +#define HVS_MAX_PKT_SIZE HVS_PKT_LEN(HVS_MTU_SIZE) + union hvs_service_id { guid_t srv_id; @@ -378,6 +381,8 @@ static void hvs_open_connection(struct vmbus_channel *chan) rcvbuf = ALIGN(rcvbuf, HV_HYP_PAGE_SIZE); } + chan->max_pkt_size = HVS_MAX_PKT_SIZE; + ret = vmbus_open(chan, sndbuf, rcvbuf, NULL, 0, hvs_channel_cb, conn_from_host ? new : sk); if (ret != 0) { @@ -572,12 +577,18 @@ static bool hvs_dgram_allow(u32 cid, u32 port) static int hvs_update_recv_data(struct hvsock *hvs) { struct hvs_recv_buf *recv_buf; - u32 payload_len; + u32 pkt_len, payload_len; + + pkt_len = hv_pkt_len(hvs->recv_desc); + + if (pkt_len < HVS_HEADER_LEN) + return -EIO; recv_buf = (struct hvs_recv_buf *)(hvs->recv_desc + 1); payload_len = recv_buf->hdr.data_size; - if (payload_len > HVS_MTU_SIZE) + if (payload_len > pkt_len - HVS_HEADER_LEN || + payload_len > HVS_MTU_SIZE) return -EIO; if (payload_len == 0) @@ -602,7 +613,9 @@ static ssize_t hvs_stream_dequeue(struct vsock_sock *vsk, struct msghdr *msg, return -EOPNOTSUPP; if (need_refill) { - hvs->recv_desc = hv_pkt_iter_first_raw(hvs->chan); + hvs->recv_desc = hv_pkt_iter_first(hvs->chan); + if (!hvs->recv_desc) + return -ENOBUFS; ret = hvs_update_recv_data(hvs); if (ret) return ret; @@ -616,7 +629,7 @@ static ssize_t hvs_stream_dequeue(struct vsock_sock *vsk, struct msghdr *msg, hvs->recv_data_len -= to_read; if (hvs->recv_data_len == 0) { - hvs->recv_desc = hv_pkt_iter_next_raw(hvs->chan, hvs->recv_desc); + hvs->recv_desc = hv_pkt_iter_next(hvs->chan, hvs->recv_desc); if (hvs->recv_desc) { ret = hvs_update_recv_data(hvs); if (ret) diff --git a/sound/core/Makefile b/sound/core/Makefile index 350d704ced984665796b43d990c95eab48186d86..2762f03d9b7bc52a5af9eee423c83d68ffd3d880 100644 --- a/sound/core/Makefile +++ b/sound/core/Makefile @@ -9,9 +9,7 @@ ifneq ($(CONFIG_SND_PROC_FS),) snd-y += info.o snd-$(CONFIG_SND_OSSEMUL) += info_oss.o endif -ifneq ($(CONFIG_M68K),y) snd-$(CONFIG_ISA_DMA_API) += isadma.o -endif snd-$(CONFIG_SND_OSSEMUL) += sound_oss.o snd-$(CONFIG_SND_VMASTER) += vmaster.o snd-$(CONFIG_SND_JACK) += ctljack.o jack.o diff --git a/sound/isa/Kconfig b/sound/isa/Kconfig index 570b88e0b201835b8daa2fdd1ec3b08d3003ec89..6ffa48dd5983035684a5359196b53d93ac1d6b18 100644 --- a/sound/isa/Kconfig +++ b/sound/isa/Kconfig @@ -22,7 +22,7 @@ config SND_SB16_DSP menuconfig SND_ISA bool "ISA sound devices" depends on ISA || COMPILE_TEST - depends on ISA_DMA_API && !M68K + depends on ISA_DMA_API default y help Support for sound devices connected via the ISA bus. diff --git a/tools/arch/arm64/include/uapi/asm/perf_regs.h b/tools/arch/arm64/include/uapi/asm/perf_regs.h index d54daafa89e3ff21782fff617d52d89b9dd388b6..fd157f46727e9af774d9dfd5a6cccc6d3d88e32c 100644 --- a/tools/arch/arm64/include/uapi/asm/perf_regs.h +++ b/tools/arch/arm64/include/uapi/asm/perf_regs.h @@ -36,6 +36,11 @@ enum perf_event_arm_regs { PERF_REG_ARM64_LR, PERF_REG_ARM64_SP, PERF_REG_ARM64_PC, - PERF_REG_ARM64_MAX, + + /* Extended/pseudo registers */ + PERF_REG_ARM64_VG = 46, // SVE Vector Granule + + PERF_REG_ARM64_MAX = PERF_REG_ARM64_PC + 1, + PERF_REG_ARM64_EXTENDED_MAX = PERF_REG_ARM64_VG + 1 }; #endif /* _ASM_ARM64_PERF_REGS_H */ diff --git a/tools/arch/x86/include/asm/msr-index.h b/tools/arch/x86/include/asm/msr-index.h index ee15311b6be1d99e2bea11bd4c03a8a36fd8c706..403e83b4adc88ea3d61337279920de39f75df6ae 100644 --- a/tools/arch/x86/include/asm/msr-index.h +++ b/tools/arch/x86/include/asm/msr-index.h @@ -76,6 +76,8 @@ /* Abbreviated from Intel SDM name IA32_CORE_CAPABILITIES */ #define MSR_IA32_CORE_CAPS 0x000000cf +#define MSR_IA32_CORE_CAPS_INTEGRITY_CAPS_BIT 2 +#define MSR_IA32_CORE_CAPS_INTEGRITY_CAPS BIT(MSR_IA32_CORE_CAPS_INTEGRITY_CAPS_BIT) #define MSR_IA32_CORE_CAPS_SPLIT_LOCK_DETECT_BIT 5 #define MSR_IA32_CORE_CAPS_SPLIT_LOCK_DETECT BIT(MSR_IA32_CORE_CAPS_SPLIT_LOCK_DETECT_BIT) @@ -154,6 +156,11 @@ #define MSR_IA32_POWER_CTL 0x000001fc #define MSR_IA32_POWER_CTL_BIT_EE 19 +/* Abbreviated from Intel SDM name IA32_INTEGRITY_CAPABILITIES */ +#define MSR_INTEGRITY_CAPS 0x000002d9 +#define MSR_INTEGRITY_CAPS_PERIODIC_BIST_BIT 4 +#define MSR_INTEGRITY_CAPS_PERIODIC_BIST BIT(MSR_INTEGRITY_CAPS_PERIODIC_BIST_BIT) + #define MSR_LBR_NHM_FROM 0x00000680 #define MSR_LBR_NHM_TO 0x000006c0 #define MSR_LBR_CORE_FROM 0x00000040 @@ -312,6 +319,7 @@ /* Run Time Average Power Limiting (RAPL) Interface */ +#define MSR_VR_CURRENT_CONFIG 0x00000601 #define MSR_RAPL_POWER_UNIT 0x00000606 #define MSR_PKG_POWER_LIMIT 0x00000610 @@ -502,8 +510,10 @@ #define MSR_AMD64_SEV 0xc0010131 #define MSR_AMD64_SEV_ENABLED_BIT 0 #define MSR_AMD64_SEV_ES_ENABLED_BIT 1 +#define MSR_AMD64_SEV_SNP_ENABLED_BIT 2 #define MSR_AMD64_SEV_ENABLED BIT_ULL(MSR_AMD64_SEV_ENABLED_BIT) #define MSR_AMD64_SEV_ES_ENABLED BIT_ULL(MSR_AMD64_SEV_ES_ENABLED_BIT) +#define MSR_AMD64_SEV_SNP_ENABLED BIT_ULL(MSR_AMD64_SEV_SNP_ENABLED_BIT) #define MSR_AMD64_VIRT_SPEC_CTRL 0xc001011f @@ -524,6 +534,11 @@ #define AMD_CPPC_DES_PERF(x) (((x) & 0xff) << 16) #define AMD_CPPC_ENERGY_PERF_PREF(x) (((x) & 0xff) << 24) +/* AMD Performance Counter Global Status and Control MSRs */ +#define MSR_AMD64_PERF_CNTR_GLOBAL_STATUS 0xc0000300 +#define MSR_AMD64_PERF_CNTR_GLOBAL_CTL 0xc0000301 +#define MSR_AMD64_PERF_CNTR_GLOBAL_STATUS_CLR 0xc0000302 + /* Fam 17h MSRs */ #define MSR_F17H_IRPERF 0xc00000e9 @@ -688,6 +703,10 @@ #define MSR_IA32_PERF_CTL 0x00000199 #define INTEL_PERF_CTL_MASK 0xffff +/* AMD Branch Sampling configuration */ +#define MSR_AMD_DBG_EXTN_CFG 0xc000010f +#define MSR_AMD_SAMP_BR_FROM 0xc0010300 + #define MSR_IA32_MPERF 0x000000e7 #define MSR_IA32_APERF 0x000000e8 diff --git a/tools/build/Makefile.feature b/tools/build/Makefile.feature index c6a48d0ef9ff06489a7a32340f2ee90e1b159efc..888a0421d43b9606a8d288e6e17be44a0781587c 100644 --- a/tools/build/Makefile.feature +++ b/tools/build/Makefile.feature @@ -99,6 +99,10 @@ FEATURE_TESTS_EXTRA := \ clang \ libbpf \ libbpf-btf__load_from_kernel_by_id \ + libbpf-bpf_prog_load \ + libbpf-bpf_object__next_program \ + libbpf-bpf_object__next_map \ + libbpf-bpf_create_map \ libpfm4 \ libdebuginfod \ clang-bpf-co-re diff --git a/tools/build/feature/Makefile b/tools/build/feature/Makefile index cb4a2a4fa2e48ebf444a0b1604b0a2619b26a58c..7c2a17e23c30aca0dde40c3db469d40766acc65a 100644 --- a/tools/build/feature/Makefile +++ b/tools/build/feature/Makefile @@ -58,6 +58,11 @@ FILES= \ test-bpf.bin \ test-libbpf.bin \ test-libbpf-btf__load_from_kernel_by_id.bin \ + test-libbpf-bpf_prog_load.bin \ + test-libbpf-bpf_map_create.bin \ + test-libbpf-bpf_object__next_program.bin \ + test-libbpf-bpf_object__next_map.bin \ + test-libbpf-btf__raw_data.bin \ test-get_cpuid.bin \ test-sdt.bin \ test-cxx.bin \ @@ -291,6 +296,21 @@ $(OUTPUT)test-libbpf.bin: $(OUTPUT)test-libbpf-btf__load_from_kernel_by_id.bin: $(BUILD) -lbpf +$(OUTPUT)test-libbpf-bpf_prog_load.bin: + $(BUILD) -lbpf + +$(OUTPUT)test-libbpf-bpf_map_create.bin: + $(BUILD) -lbpf + +$(OUTPUT)test-libbpf-bpf_object__next_program.bin: + $(BUILD) -lbpf + +$(OUTPUT)test-libbpf-bpf_object__next_map.bin: + $(BUILD) -lbpf + +$(OUTPUT)test-libbpf-btf__raw_data.bin: + $(BUILD) -lbpf + $(OUTPUT)test-sdt.bin: $(BUILD) diff --git a/tools/build/feature/test-libbpf-bpf_map_create.c b/tools/build/feature/test-libbpf-bpf_map_create.c new file mode 100644 index 0000000000000000000000000000000000000000..b9f550e332c8fdab1ccb4dc8aa40e95d598b28e1 --- /dev/null +++ b/tools/build/feature/test-libbpf-bpf_map_create.c @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 +#include + +int main(void) +{ + return bpf_map_create(0 /* map_type */, NULL /* map_name */, 0, /* key_size */, + 0 /* value_size */, 0 /* max_entries */, NULL /* opts */); +} diff --git a/tools/build/feature/test-libbpf-bpf_object__next_map.c b/tools/build/feature/test-libbpf-bpf_object__next_map.c new file mode 100644 index 0000000000000000000000000000000000000000..64adb519e97e83f4519cfcbf7ab887049177edbe --- /dev/null +++ b/tools/build/feature/test-libbpf-bpf_object__next_map.c @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 +#include + +int main(void) +{ + bpf_object__next_map(NULL /* obj */, NULL /* prev */); + return 0; +} diff --git a/tools/build/feature/test-libbpf-bpf_object__next_program.c b/tools/build/feature/test-libbpf-bpf_object__next_program.c new file mode 100644 index 0000000000000000000000000000000000000000..8bf4fd26b5452c3e16e5959701479b5dec2be593 --- /dev/null +++ b/tools/build/feature/test-libbpf-bpf_object__next_program.c @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 +#include + +int main(void) +{ + bpf_object__next_program(NULL /* obj */, NULL /* prev */); + return 0; +} diff --git a/tools/build/feature/test-libbpf-bpf_prog_load.c b/tools/build/feature/test-libbpf-bpf_prog_load.c new file mode 100644 index 0000000000000000000000000000000000000000..47f516d63ebc5f87ef9a5fd9569b8db656d66518 --- /dev/null +++ b/tools/build/feature/test-libbpf-bpf_prog_load.c @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0 +#include + +int main(void) +{ + return bpf_prog_load(0 /* prog_type */, NULL /* prog_name */, + NULL /* license */, NULL /* insns */, + 0 /* insn_cnt */, NULL /* opts */); +} diff --git a/tools/build/feature/test-libbpf-btf__load_from_kernel_by_id.c b/tools/build/feature/test-libbpf-btf__load_from_kernel_by_id.c index f7c084428735a73de2baeb0bff9e152b039ad771..a17647f7d5a43643158650eac56c36ddfb48dae8 100644 --- a/tools/build/feature/test-libbpf-btf__load_from_kernel_by_id.c +++ b/tools/build/feature/test-libbpf-btf__load_from_kernel_by_id.c @@ -1,7 +1,8 @@ // SPDX-License-Identifier: GPL-2.0 -#include +#include int main(void) { - return btf__load_from_kernel_by_id(20151128, NULL); + btf__load_from_kernel_by_id(20151128); + return 0; } diff --git a/tools/build/feature/test-libbpf-btf__raw_data.c b/tools/build/feature/test-libbpf-btf__raw_data.c new file mode 100644 index 0000000000000000000000000000000000000000..57da31dd75812983e1e4eb5c14924f40a189890b --- /dev/null +++ b/tools/build/feature/test-libbpf-btf__raw_data.c @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 +#include + +int main(void) +{ + btf__raw_data(NULL /* btf_ro */, NULL /* size */); + return 0; +} diff --git a/tools/include/uapi/asm-generic/fcntl.h b/tools/include/uapi/asm-generic/fcntl.h index ac190958c981442f1c2072097487705039c8706b..0197042b7dfbd8550b1691a74ad2cd6bf7a5bdba 100644 --- a/tools/include/uapi/asm-generic/fcntl.h +++ b/tools/include/uapi/asm-generic/fcntl.h @@ -115,13 +115,11 @@ #define F_GETSIG 11 /* for sockets. */ #endif -#ifndef CONFIG_64BIT #ifndef F_GETLK64 #define F_GETLK64 12 /* using 'struct flock64' */ #define F_SETLK64 13 #define F_SETLKW64 14 #endif -#endif #ifndef F_SETOWN_EX #define F_SETOWN_EX 15 @@ -187,25 +185,19 @@ struct f_owner_ex { #define F_LINUX_SPECIFIC_BASE 1024 -#ifndef HAVE_ARCH_STRUCT_FLOCK -#ifndef __ARCH_FLOCK_PAD -#define __ARCH_FLOCK_PAD -#endif - struct flock { short l_type; short l_whence; __kernel_off_t l_start; __kernel_off_t l_len; __kernel_pid_t l_pid; - __ARCH_FLOCK_PAD -}; +#ifdef __ARCH_FLOCK_EXTRA_SYSID + __ARCH_FLOCK_EXTRA_SYSID #endif - -#ifndef HAVE_ARCH_STRUCT_FLOCK64 -#ifndef __ARCH_FLOCK64_PAD -#define __ARCH_FLOCK64_PAD +#ifdef __ARCH_FLOCK_PAD + __ARCH_FLOCK_PAD #endif +}; struct flock64 { short l_type; @@ -213,8 +205,9 @@ struct flock64 { __kernel_loff_t l_start; __kernel_loff_t l_len; __kernel_pid_t l_pid; +#ifdef __ARCH_FLOCK64_PAD __ARCH_FLOCK64_PAD -}; #endif +}; #endif /* _ASM_GENERIC_FCNTL_H */ diff --git a/tools/include/uapi/asm-generic/unistd.h b/tools/include/uapi/asm-generic/unistd.h index 1c48b0ae3ba30229ff3104b5c8258e1a70373475..45fa180cc56adf335ebfa7c2c6bf85b9704e25fa 100644 --- a/tools/include/uapi/asm-generic/unistd.h +++ b/tools/include/uapi/asm-generic/unistd.h @@ -383,7 +383,7 @@ __SYSCALL(__NR_syslog, sys_syslog) /* kernel/ptrace.c */ #define __NR_ptrace 117 -__SYSCALL(__NR_ptrace, sys_ptrace) +__SC_COMP(__NR_ptrace, sys_ptrace, compat_sys_ptrace) /* kernel/sched/core.c */ #define __NR_sched_setparam 118 @@ -779,7 +779,7 @@ __SYSCALL(__NR_rseq, sys_rseq) #define __NR_kexec_file_load 294 __SYSCALL(__NR_kexec_file_load, sys_kexec_file_load) /* 295 through 402 are unassigned to sync up with generic numbers, don't use */ -#if __BITS_PER_LONG == 32 +#if defined(__SYSCALL_COMPAT) || __BITS_PER_LONG == 32 #define __NR_clock_gettime64 403 __SYSCALL(__NR_clock_gettime64, sys_clock_gettime) #define __NR_clock_settime64 404 diff --git a/tools/lib/perf/evlist.c b/tools/lib/perf/evlist.c index ed66f2e384645c16e3ca768a0684bb9cbcf04a23..e6c98a6e3908e20f8c68946f677b7161540f0e47 100644 --- a/tools/lib/perf/evlist.c +++ b/tools/lib/perf/evlist.c @@ -23,6 +23,7 @@ #include #include #include +#include "internal.h" void perf_evlist__init(struct perf_evlist *evlist) { @@ -39,10 +40,11 @@ static void __perf_evlist__propagate_maps(struct perf_evlist *evlist, * We already have cpus for evsel (via PMU sysfs) so * keep it, if there's no target cpu list defined. */ - if (!evsel->own_cpus || evlist->has_user_cpus) { - perf_cpu_map__put(evsel->cpus); - evsel->cpus = perf_cpu_map__get(evlist->user_requested_cpus); - } else if (!evsel->system_wide && perf_cpu_map__empty(evlist->user_requested_cpus)) { + if (!evsel->own_cpus || + (!evsel->system_wide && evlist->has_user_cpus) || + (!evsel->system_wide && + !evsel->requires_cpu && + perf_cpu_map__empty(evlist->user_requested_cpus))) { perf_cpu_map__put(evsel->cpus); evsel->cpus = perf_cpu_map__get(evlist->user_requested_cpus); } else if (evsel->cpus != evsel->own_cpus) { @@ -50,8 +52,11 @@ static void __perf_evlist__propagate_maps(struct perf_evlist *evlist, evsel->cpus = perf_cpu_map__get(evsel->own_cpus); } - perf_thread_map__put(evsel->threads); - evsel->threads = perf_thread_map__get(evlist->threads); + if (!evsel->system_wide) { + perf_thread_map__put(evsel->threads); + evsel->threads = perf_thread_map__get(evlist->threads); + } + evlist->all_cpus = perf_cpu_map__merge(evlist->all_cpus, evsel->cpus); } @@ -298,7 +303,7 @@ add: int perf_evlist__alloc_pollfd(struct perf_evlist *evlist) { - int nr_cpus = perf_cpu_map__nr(evlist->user_requested_cpus); + int nr_cpus = perf_cpu_map__nr(evlist->all_cpus); int nr_threads = perf_thread_map__nr(evlist->threads); int nfds = 0; struct perf_evsel *evsel; @@ -428,9 +433,9 @@ static void perf_evlist__set_mmap_first(struct perf_evlist *evlist, struct perf_ static int mmap_per_evsel(struct perf_evlist *evlist, struct perf_evlist_mmap_ops *ops, int idx, struct perf_mmap_param *mp, int cpu_idx, - int thread, int *_output, int *_output_overwrite) + int thread, int *_output, int *_output_overwrite, int *nr_mmaps) { - struct perf_cpu evlist_cpu = perf_cpu_map__cpu(evlist->user_requested_cpus, cpu_idx); + struct perf_cpu evlist_cpu = perf_cpu_map__cpu(evlist->all_cpus, cpu_idx); struct perf_evsel *evsel; int revent; @@ -484,6 +489,8 @@ mmap_per_evsel(struct perf_evlist *evlist, struct perf_evlist_mmap_ops *ops, if (ops->mmap(map, mp, *output, evlist_cpu) < 0) return -1; + *nr_mmaps += 1; + if (!idx) perf_evlist__set_mmap_first(evlist, map, overwrite); } else { @@ -512,35 +519,13 @@ mmap_per_evsel(struct perf_evlist *evlist, struct perf_evlist_mmap_ops *ops, return 0; } -static int -mmap_per_thread(struct perf_evlist *evlist, struct perf_evlist_mmap_ops *ops, - struct perf_mmap_param *mp) -{ - int thread; - int nr_threads = perf_thread_map__nr(evlist->threads); - - for (thread = 0; thread < nr_threads; thread++) { - int output = -1; - int output_overwrite = -1; - - if (mmap_per_evsel(evlist, ops, thread, mp, 0, thread, - &output, &output_overwrite)) - goto out_unmap; - } - - return 0; - -out_unmap: - perf_evlist__munmap(evlist); - return -1; -} - static int mmap_per_cpu(struct perf_evlist *evlist, struct perf_evlist_mmap_ops *ops, struct perf_mmap_param *mp) { int nr_threads = perf_thread_map__nr(evlist->threads); - int nr_cpus = perf_cpu_map__nr(evlist->user_requested_cpus); + int nr_cpus = perf_cpu_map__nr(evlist->all_cpus); + int nr_mmaps = 0; int cpu, thread; for (cpu = 0; cpu < nr_cpus; cpu++) { @@ -549,11 +534,14 @@ mmap_per_cpu(struct perf_evlist *evlist, struct perf_evlist_mmap_ops *ops, for (thread = 0; thread < nr_threads; thread++) { if (mmap_per_evsel(evlist, ops, cpu, mp, cpu, - thread, &output, &output_overwrite)) + thread, &output, &output_overwrite, &nr_mmaps)) goto out_unmap; } } + if (nr_mmaps != evlist->nr_mmaps) + pr_err("Miscounted nr_mmaps %d vs %d\n", nr_mmaps, evlist->nr_mmaps); + return 0; out_unmap: @@ -565,9 +553,14 @@ static int perf_evlist__nr_mmaps(struct perf_evlist *evlist) { int nr_mmaps; - nr_mmaps = perf_cpu_map__nr(evlist->user_requested_cpus); - if (perf_cpu_map__empty(evlist->user_requested_cpus)) - nr_mmaps = perf_thread_map__nr(evlist->threads); + /* One for each CPU */ + nr_mmaps = perf_cpu_map__nr(evlist->all_cpus); + if (perf_cpu_map__empty(evlist->all_cpus)) { + /* Plus one for each thread */ + nr_mmaps += perf_thread_map__nr(evlist->threads); + /* Minus the per-thread CPU (-1) */ + nr_mmaps -= 1; + } return nr_mmaps; } @@ -577,7 +570,6 @@ int perf_evlist__mmap_ops(struct perf_evlist *evlist, struct perf_mmap_param *mp) { struct perf_evsel *evsel; - const struct perf_cpu_map *cpus = evlist->user_requested_cpus; if (!ops || !ops->get || !ops->mmap) return -EINVAL; @@ -596,9 +588,6 @@ int perf_evlist__mmap_ops(struct perf_evlist *evlist, if (evlist->pollfd.entries == NULL && perf_evlist__alloc_pollfd(evlist) < 0) return -ENOMEM; - if (perf_cpu_map__empty(cpus)) - return mmap_per_thread(evlist, ops, mp); - return mmap_per_cpu(evlist, ops, mp); } diff --git a/tools/lib/perf/include/internal/evsel.h b/tools/lib/perf/include/internal/evsel.h index cfc9ebd7968e9a674108900e63fbf7ba27aee621..2a912a1f19898c1e8a8ac473709ee6d079a7dbe4 100644 --- a/tools/lib/perf/include/internal/evsel.h +++ b/tools/lib/perf/include/internal/evsel.h @@ -49,7 +49,18 @@ struct perf_evsel { /* parse modifier helper */ int nr_members; + /* + * system_wide is for events that need to be on every CPU, irrespective + * of user requested CPUs or threads. Map propagation will set cpus to + * this event's own_cpus, whereby they will contribute to evlist + * all_cpus. + */ bool system_wide; + /* + * Some events, for example uncore events, require a CPU. + * i.e. it cannot be the 'any CPU' value of -1. + */ + bool requires_cpu; int idx; }; diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt index 465be4e62a1728b1195bedb3e97c190143c5ee7b..b4e9ef7edfef41ac38f844c8a04c95d4ca3c1ebf 100644 --- a/tools/perf/Documentation/perf-record.txt +++ b/tools/perf/Documentation/perf-record.txt @@ -758,6 +758,16 @@ include::intel-hybrid.txt[] If the URLs is not specified, the value of DEBUGINFOD_URLS system environment variable is used. +--off-cpu:: + Enable off-cpu profiling with BPF. The BPF program will collect + task scheduling information with (user) stacktrace and save them + as sample data of a software event named "offcpu-time". The + sample period will have the time the task slept in nanoseconds. + + Note that BPF can collect stack traces using frame pointer ("fp") + only, as of now. So the applications built without the frame + pointer might see bogus addresses. + SEE ALSO -------- linkperf:perf-stat[1], linkperf:perf-list[1], linkperf:perf-intel-pt[1] diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config index e0304e70f18298eaf95b91503aedb7e0d0f059ca..73e0762092feba3052e0cbc32026a88d41fdc5ef 100644 --- a/tools/perf/Makefile.config +++ b/tools/perf/Makefile.config @@ -573,11 +573,36 @@ ifndef NO_LIBELF ifeq ($(feature-libbpf-btf__load_from_kernel_by_id), 1) CFLAGS += -DHAVE_LIBBPF_BTF__LOAD_FROM_KERNEL_BY_ID endif + $(call feature_check,libbpf-bpf_prog_load) + ifeq ($(feature-libbpf-bpf_prog_load), 1) + CFLAGS += -DHAVE_LIBBPF_BPF_PROG_LOAD + endif + $(call feature_check,libbpf-bpf_object__next_program) + ifeq ($(feature-libbpf-bpf_object__next_program), 1) + CFLAGS += -DHAVE_LIBBPF_BPF_OBJECT__NEXT_PROGRAM + endif + $(call feature_check,libbpf-bpf_object__next_map) + ifeq ($(feature-libbpf-bpf_object__next_map), 1) + CFLAGS += -DHAVE_LIBBPF_BPF_OBJECT__NEXT_MAP + endif + $(call feature_check,libbpf-btf__raw_data) + ifeq ($(feature-libbpf-btf__raw_data), 1) + CFLAGS += -DHAVE_LIBBPF_BTF__RAW_DATA + endif + $(call feature_check,libbpf-bpf_map_create) + ifeq ($(feature-libbpf-bpf_map_create), 1) + CFLAGS += -DHAVE_LIBBPF_BPF_MAP_CREATE + endif else dummy := $(error Error: No libbpf devel library found, please install libbpf-devel); endif else CFLAGS += -DHAVE_LIBBPF_BTF__LOAD_FROM_KERNEL_BY_ID + CFLAGS += -DHAVE_LIBBPF_BPF_PROG_LOAD + CFLAGS += -DHAVE_LIBBPF_BPF_OBJECT__NEXT_PROGRAM + CFLAGS += -DHAVE_LIBBPF_BPF_OBJECT__NEXT_MAP + CFLAGS += -DHAVE_LIBBPF_BTF__RAW_DATA + CFLAGS += -DHAVE_LIBBPF_BPF_MAP_CREATE endif endif diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf index 6e5aded855ccf49df4fbd065e9bb16417279f2ed..8f738e11356d44aca5efc8728754c37f5152e3d7 100644 --- a/tools/perf/Makefile.perf +++ b/tools/perf/Makefile.perf @@ -1038,6 +1038,7 @@ SKEL_TMP_OUT := $(abspath $(SKEL_OUT)/.tmp) SKELETONS := $(SKEL_OUT)/bpf_prog_profiler.skel.h SKELETONS += $(SKEL_OUT)/bperf_leader.skel.h $(SKEL_OUT)/bperf_follower.skel.h SKELETONS += $(SKEL_OUT)/bperf_cgroup.skel.h $(SKEL_OUT)/func_latency.skel.h +SKELETONS += $(SKEL_OUT)/off_cpu.skel.h $(SKEL_TMP_OUT) $(LIBBPF_OUTPUT): $(Q)$(MKDIR) -p $@ diff --git a/tools/perf/arch/arm64/util/perf_regs.c b/tools/perf/arch/arm64/util/perf_regs.c index 476b037eea1caa0fe72f8a210c8b8462f36e92e8..006692c9b0408921f6d26f042c53378a8aedd747 100644 --- a/tools/perf/arch/arm64/util/perf_regs.c +++ b/tools/perf/arch/arm64/util/perf_regs.c @@ -2,13 +2,19 @@ #include #include #include +#include #include #include +#include "../../../perf-sys.h" #include "../../../util/debug.h" #include "../../../util/event.h" #include "../../../util/perf_regs.h" +#ifndef HWCAP_SVE +#define HWCAP_SVE (1 << 22) +#endif + const struct sample_reg sample_reg_masks[] = { SMPL_REG(x0, PERF_REG_ARM64_X0), SMPL_REG(x1, PERF_REG_ARM64_X1), @@ -43,6 +49,7 @@ const struct sample_reg sample_reg_masks[] = { SMPL_REG(lr, PERF_REG_ARM64_LR), SMPL_REG(sp, PERF_REG_ARM64_SP), SMPL_REG(pc, PERF_REG_ARM64_PC), + SMPL_REG(vg, PERF_REG_ARM64_VG), SMPL_REG_END }; @@ -131,3 +138,34 @@ int arch_sdt_arg_parse_op(char *old_op, char **new_op) return SDT_ARG_VALID; } + +uint64_t arch__user_reg_mask(void) +{ + struct perf_event_attr attr = { + .type = PERF_TYPE_HARDWARE, + .config = PERF_COUNT_HW_CPU_CYCLES, + .sample_type = PERF_SAMPLE_REGS_USER, + .disabled = 1, + .exclude_kernel = 1, + .sample_period = 1, + .sample_regs_user = PERF_REGS_MASK + }; + int fd; + + if (getauxval(AT_HWCAP) & HWCAP_SVE) + attr.sample_regs_user |= SMPL_REG_MASK(PERF_REG_ARM64_VG); + + /* + * Check if the pmu supports perf extended regs, before + * returning the register mask to sample. + */ + if (attr.sample_regs_user != PERF_REGS_MASK) { + event_attr_init(&attr); + fd = sys_perf_event_open(&attr, 0, -1, -1, 0); + if (fd != -1) { + close(fd); + return attr.sample_regs_user; + } + } + return PERF_REGS_MASK; +} diff --git a/tools/perf/arch/arm64/util/unwind-libunwind.c b/tools/perf/arch/arm64/util/unwind-libunwind.c index 5aecf88e3de6becc3b1e252b71a70fc4654fd38e..871af599229805dc03ac1780d8b87afd0eea6f08 100644 --- a/tools/perf/arch/arm64/util/unwind-libunwind.c +++ b/tools/perf/arch/arm64/util/unwind-libunwind.c @@ -10,77 +10,8 @@ int LIBUNWIND__ARCH_REG_ID(int regnum) { - switch (regnum) { - case UNW_AARCH64_X0: - return PERF_REG_ARM64_X0; - case UNW_AARCH64_X1: - return PERF_REG_ARM64_X1; - case UNW_AARCH64_X2: - return PERF_REG_ARM64_X2; - case UNW_AARCH64_X3: - return PERF_REG_ARM64_X3; - case UNW_AARCH64_X4: - return PERF_REG_ARM64_X4; - case UNW_AARCH64_X5: - return PERF_REG_ARM64_X5; - case UNW_AARCH64_X6: - return PERF_REG_ARM64_X6; - case UNW_AARCH64_X7: - return PERF_REG_ARM64_X7; - case UNW_AARCH64_X8: - return PERF_REG_ARM64_X8; - case UNW_AARCH64_X9: - return PERF_REG_ARM64_X9; - case UNW_AARCH64_X10: - return PERF_REG_ARM64_X10; - case UNW_AARCH64_X11: - return PERF_REG_ARM64_X11; - case UNW_AARCH64_X12: - return PERF_REG_ARM64_X12; - case UNW_AARCH64_X13: - return PERF_REG_ARM64_X13; - case UNW_AARCH64_X14: - return PERF_REG_ARM64_X14; - case UNW_AARCH64_X15: - return PERF_REG_ARM64_X15; - case UNW_AARCH64_X16: - return PERF_REG_ARM64_X16; - case UNW_AARCH64_X17: - return PERF_REG_ARM64_X17; - case UNW_AARCH64_X18: - return PERF_REG_ARM64_X18; - case UNW_AARCH64_X19: - return PERF_REG_ARM64_X19; - case UNW_AARCH64_X20: - return PERF_REG_ARM64_X20; - case UNW_AARCH64_X21: - return PERF_REG_ARM64_X21; - case UNW_AARCH64_X22: - return PERF_REG_ARM64_X22; - case UNW_AARCH64_X23: - return PERF_REG_ARM64_X23; - case UNW_AARCH64_X24: - return PERF_REG_ARM64_X24; - case UNW_AARCH64_X25: - return PERF_REG_ARM64_X25; - case UNW_AARCH64_X26: - return PERF_REG_ARM64_X26; - case UNW_AARCH64_X27: - return PERF_REG_ARM64_X27; - case UNW_AARCH64_X28: - return PERF_REG_ARM64_X28; - case UNW_AARCH64_X29: - return PERF_REG_ARM64_X29; - case UNW_AARCH64_X30: - return PERF_REG_ARM64_LR; - case UNW_AARCH64_SP: - return PERF_REG_ARM64_SP; - case UNW_AARCH64_PC: - return PERF_REG_ARM64_PC; - default: - pr_err("unwind: invalid reg id %d\n", regnum); + if (regnum < 0 || regnum >= PERF_REG_ARM64_EXTENDED_MAX) return -EINVAL; - } - return -EINVAL; + return regnum; } diff --git a/tools/perf/arch/x86/util/intel-pt.c b/tools/perf/arch/x86/util/intel-pt.c index 2eaac4638aab94db1d27e0bcc2e70283f375e912..06c2cdfd8f2fa7d5053021cf89a6ed9a56adb611 100644 --- a/tools/perf/arch/x86/util/intel-pt.c +++ b/tools/perf/arch/x86/util/intel-pt.c @@ -811,18 +811,11 @@ static int intel_pt_recording_options(struct auxtrace_record *itr, if (!cpu_wide && perf_can_record_cpu_wide()) { struct evsel *switch_evsel; - err = parse_events(evlist, "dummy:u", NULL); - if (err) - return err; + switch_evsel = evlist__add_dummy_on_all_cpus(evlist); + if (!switch_evsel) + return -ENOMEM; - switch_evsel = evlist__last(evlist); - - switch_evsel->core.attr.freq = 0; - switch_evsel->core.attr.sample_period = 1; switch_evsel->core.attr.context_switch = 1; - - switch_evsel->core.system_wide = true; - switch_evsel->no_aux_samples = true; switch_evsel->immediate = true; evsel__set_sample_bit(switch_evsel, TID); @@ -871,20 +864,22 @@ static int intel_pt_recording_options(struct auxtrace_record *itr, /* Add dummy event to keep tracking */ if (opts->full_auxtrace) { + bool need_system_wide_tracking; struct evsel *tracking_evsel; - err = parse_events(evlist, "dummy:u", NULL); - if (err) - return err; + /* + * User space tasks can migrate between CPUs, so when tracing + * selected CPUs, sideband for all CPUs is still needed. + */ + need_system_wide_tracking = evlist->core.has_user_cpus && + !intel_pt_evsel->core.attr.exclude_user; - tracking_evsel = evlist__last(evlist); + tracking_evsel = evlist__add_aux_dummy(evlist, need_system_wide_tracking); + if (!tracking_evsel) + return -ENOMEM; evlist__set_tracking_event(evlist, tracking_evsel); - tracking_evsel->core.attr.freq = 0; - tracking_evsel->core.attr.sample_period = 1; - - tracking_evsel->no_aux_samples = true; if (need_immediate) tracking_evsel->immediate = true; diff --git a/tools/perf/builtin-c2c.c b/tools/perf/builtin-c2c.c index c8230c48125ff7a6db39da4360e6a8194d8edd11..80b525c065edc2070de8bf8b7a86e6e13aec256d 100644 --- a/tools/perf/builtin-c2c.c +++ b/tools/perf/builtin-c2c.c @@ -2801,9 +2801,7 @@ static int perf_c2c__report(int argc, const char **argv) "the input file to process"), OPT_INCR('N', "node-info", &c2c.node_info, "show extra node info in report (repeat for more info)"), -#ifdef HAVE_SLANG_SUPPORT OPT_BOOLEAN(0, "stdio", &c2c.use_stdio, "Use the stdio interface"), -#endif OPT_BOOLEAN(0, "stats", &c2c.stats_only, "Display only statistic tables (implies --stdio)"), OPT_BOOLEAN(0, "full-symbols", &c2c.symbol_full, @@ -2833,6 +2831,10 @@ static int perf_c2c__report(int argc, const char **argv) if (argc) usage_with_options(report_c2c_usage, options); +#ifndef HAVE_SLANG_SUPPORT + c2c.use_stdio = true; +#endif + if (c2c.stats_only) c2c.use_stdio = true; diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index a5cf6a99d67f78c42885d58101e2994839a6b30b..9a71f0330137ea03663bf3dffb6c43755269c690 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -49,6 +49,7 @@ #include "util/clockid.h" #include "util/pmu-hybrid.h" #include "util/evlist-hybrid.h" +#include "util/off_cpu.h" #include "asm/bug.h" #include "perf.h" #include "cputopo.h" @@ -162,6 +163,7 @@ struct record { bool buildid_mmap; bool timestamp_filename; bool timestamp_boundary; + bool off_cpu; struct switch_output switch_output; unsigned long long samples; unsigned long output_max_size; /* = 0: unlimited */ @@ -869,7 +871,6 @@ static int record__auxtrace_init(struct record *rec __maybe_unused) static int record__config_text_poke(struct evlist *evlist) { struct evsel *evsel; - int err; /* Nothing to do if text poke is already configured */ evlist__for_each_entry(evlist, evsel) { @@ -877,32 +878,23 @@ static int record__config_text_poke(struct evlist *evlist) return 0; } - err = parse_events(evlist, "dummy:u", NULL); - if (err) - return err; - - evsel = evlist__last(evlist); + evsel = evlist__add_dummy_on_all_cpus(evlist); + if (!evsel) + return -ENOMEM; - evsel->core.attr.freq = 0; - evsel->core.attr.sample_period = 1; evsel->core.attr.text_poke = 1; evsel->core.attr.ksymbol = 1; - - evsel->core.system_wide = true; - evsel->no_aux_samples = true; evsel->immediate = true; - - /* Text poke must be collected on all CPUs */ - perf_cpu_map__put(evsel->core.own_cpus); - evsel->core.own_cpus = perf_cpu_map__new(NULL); - perf_cpu_map__put(evsel->core.cpus); - evsel->core.cpus = perf_cpu_map__get(evsel->core.own_cpus); - evsel__set_sample_bit(evsel, TIME); return 0; } +static int record__config_off_cpu(struct record *rec) +{ + return off_cpu_prepare(rec->evlist, &rec->opts.target, &rec->opts); +} + static bool record__kcore_readable(struct machine *machine) { char kcore[PATH_MAX]; @@ -982,14 +974,20 @@ static void record__thread_data_close_pipes(struct record_thread *thread_data) } } +static bool evlist__per_thread(struct evlist *evlist) +{ + return cpu_map__is_dummy(evlist->core.user_requested_cpus); +} + static int record__thread_data_init_maps(struct record_thread *thread_data, struct evlist *evlist) { int m, tm, nr_mmaps = evlist->core.nr_mmaps; struct mmap *mmap = evlist->mmap; struct mmap *overwrite_mmap = evlist->overwrite_mmap; - struct perf_cpu_map *cpus = evlist->core.user_requested_cpus; + struct perf_cpu_map *cpus = evlist->core.all_cpus; + bool per_thread = evlist__per_thread(evlist); - if (cpu_map__is_dummy(cpus)) + if (per_thread) thread_data->nr_mmaps = nr_mmaps; else thread_data->nr_mmaps = bitmap_weight(thread_data->mask->maps.bits, @@ -1010,7 +1008,7 @@ static int record__thread_data_init_maps(struct record_thread *thread_data, stru thread_data->nr_mmaps, thread_data->maps, thread_data->overwrite_maps); for (m = 0, tm = 0; m < nr_mmaps && tm < thread_data->nr_mmaps; m++) { - if (cpu_map__is_dummy(cpus) || + if (per_thread || test_bit(perf_cpu_map__cpu(cpus, m).cpu, thread_data->mask->maps.bits)) { if (thread_data->maps) { thread_data->maps[tm] = &mmap[m]; @@ -1885,7 +1883,7 @@ static int record__synthesize(struct record *rec, bool tail) return err; } - err = perf_event__synthesize_cpu_map(&rec->tool, rec->evlist->core.user_requested_cpus, + err = perf_event__synthesize_cpu_map(&rec->tool, rec->evlist->core.all_cpus, process_synthesized_event, NULL); if (err < 0) { pr_err("Couldn't synthesize cpu map.\n"); @@ -2600,6 +2598,9 @@ out_free_threads: } else status = err; + if (rec->off_cpu) + rec->bytes_written += off_cpu_write(rec->session); + record__synthesize(rec, true); /* this will be recalculated during process_buildids() */ rec->samples = 0; @@ -3324,6 +3325,7 @@ static struct option __record_options[] = { OPT_CALLBACK_OPTARG(0, "threads", &record.opts, NULL, "spec", "write collected trace data into several data files using parallel threads", record__parse_threads), + OPT_BOOLEAN(0, "off-cpu", &record.off_cpu, "Enable off-cpu analysis"), OPT_END() }; @@ -3683,12 +3685,12 @@ static int record__init_thread_default_masks(struct record *rec, struct perf_cpu static int record__init_thread_masks(struct record *rec) { int ret = 0; - struct perf_cpu_map *cpus = rec->evlist->core.user_requested_cpus; + struct perf_cpu_map *cpus = rec->evlist->core.all_cpus; if (!record__threads_enabled(rec)) return record__init_thread_default_masks(rec, cpus); - if (cpu_map__is_dummy(cpus)) { + if (evlist__per_thread(rec->evlist)) { pr_err("--per-thread option is mutually exclusive to parallel streaming mode.\n"); return -EINVAL; } @@ -3743,6 +3745,12 @@ int cmd_record(int argc, const char **argv) set_nobuild('\0', "vmlinux", true); # undef set_nobuild # undef REASON +#endif + +#ifndef HAVE_BPF_SKEL +# define set_nobuild(s, l, m, c) set_option_nobuild(record_options, s, l, m, c) + set_nobuild('\0', "off-cpu", "no BUILD_BPF_SKEL=1", true); +# undef set_nobuild #endif rec->opts.affinity = PERF_AFFINITY_SYS; @@ -3981,6 +3989,14 @@ int cmd_record(int argc, const char **argv) } } + if (rec->off_cpu) { + err = record__config_off_cpu(rec); + if (err) { + pr_err("record__config_off_cpu failed, error %d\n", err); + goto out; + } + } + if (record_opts__config(&rec->opts)) { err = -EINVAL; goto out; diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 7e6cc8bdf0613659fadf73a9737abe2c502e62bf..4ce87a8eb7d7ed4e4aa7b519bce3f24684abe31c 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -382,9 +382,6 @@ static int read_counter_cpu(struct evsel *counter, struct timespec *rs, int cpu_ if (!counter->supported) return -ENOENT; - if (counter->core.system_wide) - nthreads = 1; - for (thread = 0; thread < nthreads; thread++) { struct perf_counts_values *count; @@ -2261,7 +2258,7 @@ static void setup_system_wide(int forks) struct evsel *counter; evlist__for_each_entry(evsel_list, counter) { - if (!counter->core.system_wide && + if (!counter->core.requires_cpu && strcmp(counter->name, "duration_time")) { return; } diff --git a/tools/perf/pmu-events/jevents.c b/tools/perf/pmu-events/jevents.c index cee61c4ed59e68007e2bc848777d3f9e7faee584..e597e4bac90fd848c73d231f51fc23ff614549b4 100644 --- a/tools/perf/pmu-events/jevents.c +++ b/tools/perf/pmu-events/jevents.c @@ -605,7 +605,7 @@ static int json_events(const char *fn, } else if (json_streq(map, field, "ExtSel")) { char *code = NULL; addfield(map, &code, "", "", val); - eventcode |= strtoul(code, NULL, 0) << 21; + eventcode |= strtoul(code, NULL, 0) << 8; free(code); } else if (json_streq(map, field, "EventName")) { addfield(map, &je.name, "", "", val); diff --git a/tools/perf/scripts/python/arm-cs-trace-disasm.py b/tools/perf/scripts/python/arm-cs-trace-disasm.py new file mode 100755 index 0000000000000000000000000000000000000000..5f57d9829956ca0ea2ad1978613ef8002c831c36 --- /dev/null +++ b/tools/perf/scripts/python/arm-cs-trace-disasm.py @@ -0,0 +1,272 @@ +# SPDX-License-Identifier: GPL-2.0 +# arm-cs-trace-disasm.py: ARM CoreSight Trace Dump With Disassember +# +# Author: Tor Jeremiassen +# Mathieu Poirier +# Leo Yan +# Al Grant + +from __future__ import print_function +import os +from os import path +import sys +import re +from subprocess import * +from optparse import OptionParser, make_option + +from perf_trace_context import perf_set_itrace_options, \ + perf_sample_insn, perf_sample_srccode + +# Below are some example commands for using this script. +# +# Output disassembly with objdump: +# perf script -s scripts/python/arm-cs-trace-disasm.py \ +# -- -d objdump -k path/to/vmlinux +# Output disassembly with llvm-objdump: +# perf script -s scripts/python/arm-cs-trace-disasm.py \ +# -- -d llvm-objdump-11 -k path/to/vmlinux +# Output only source line and symbols: +# perf script -s scripts/python/arm-cs-trace-disasm.py + +# Command line parsing. +option_list = [ + # formatting options for the bottom entry of the stack + make_option("-k", "--vmlinux", dest="vmlinux_name", + help="Set path to vmlinux file"), + make_option("-d", "--objdump", dest="objdump_name", + help="Set path to objdump executable file"), + make_option("-v", "--verbose", dest="verbose", + action="store_true", default=False, + help="Enable debugging log") +] + +parser = OptionParser(option_list=option_list) +(options, args) = parser.parse_args() + +# Initialize global dicts and regular expression +disasm_cache = dict() +cpu_data = dict() +disasm_re = re.compile("^\s*([0-9a-fA-F]+):") +disasm_func_re = re.compile("^\s*([0-9a-fA-F]+)\s.*:") +cache_size = 64*1024 + +glb_source_file_name = None +glb_line_number = None +glb_dso = None + +def get_optional(perf_dict, field): + if field in perf_dict: + return perf_dict[field] + return "[unknown]" + +def get_offset(perf_dict, field): + if field in perf_dict: + return f"+0x{perf_dict[field]:x}" + return "" + +def get_dso_file_path(dso_name, dso_build_id): + if (dso_name == "[kernel.kallsyms]" or dso_name == "vmlinux"): + if (options.vmlinux_name): + return options.vmlinux_name; + else: + return dso_name + + if (dso_name == "[vdso]") : + append = "/vdso" + else: + append = "/elf" + + dso_path = f"{os.environ['PERF_BUILDID_DIR']}/{dso_name}/{dso_build_id}{append}" + # Replace duplicate slash chars to single slash char + dso_path = dso_path.replace('//', '/', 1) + return dso_path + +def read_disam(dso_fname, dso_start, start_addr, stop_addr): + addr_range = str(start_addr) + ":" + str(stop_addr) + ":" + dso_fname + + # Don't let the cache get too big, clear it when it hits max size + if (len(disasm_cache) > cache_size): + disasm_cache.clear(); + + if addr_range in disasm_cache: + disasm_output = disasm_cache[addr_range]; + else: + start_addr = start_addr - dso_start; + stop_addr = stop_addr - dso_start; + disasm = [ options.objdump_name, "-d", "-z", + f"--start-address=0x{start_addr:x}", + f"--stop-address=0x{stop_addr:x}" ] + disasm += [ dso_fname ] + disasm_output = check_output(disasm).decode('utf-8').split('\n') + disasm_cache[addr_range] = disasm_output + + return disasm_output + +def print_disam(dso_fname, dso_start, start_addr, stop_addr): + for line in read_disam(dso_fname, dso_start, start_addr, stop_addr): + m = disasm_func_re.search(line) + if m is None: + m = disasm_re.search(line) + if m is None: + continue + print(f"\t{line}") + +def print_sample(sample): + print(f"Sample = {{ cpu: {sample['cpu']:04} addr: 0x{sample['addr']:016x} " \ + f"phys_addr: 0x{sample['phys_addr']:016x} ip: 0x{sample['ip']:016x} " \ + f"pid: {sample['pid']} tid: {sample['tid']} period: {sample['period']} time: {sample['time']} }}") + +def trace_begin(): + print('ARM CoreSight Trace Data Assembler Dump') + +def trace_end(): + print('End') + +def trace_unhandled(event_name, context, event_fields_dict): + print(' '.join(['%s=%s'%(k,str(v))for k,v in sorted(event_fields_dict.items())])) + +def common_start_str(comm, sample): + sec = int(sample["time"] / 1000000000) + ns = sample["time"] % 1000000000 + cpu = sample["cpu"] + pid = sample["pid"] + tid = sample["tid"] + return f"{comm:>16} {pid:>5}/{tid:<5} [{cpu:04}] {sec:9}.{ns:09} " + +# This code is copied from intel-pt-events.py for printing source code +# line and symbols. +def print_srccode(comm, param_dict, sample, symbol, dso): + ip = sample["ip"] + if symbol == "[unknown]": + start_str = common_start_str(comm, sample) + ("%x" % ip).rjust(16).ljust(40) + else: + offs = get_offset(param_dict, "symoff") + start_str = common_start_str(comm, sample) + (symbol + offs).ljust(40) + + global glb_source_file_name + global glb_line_number + global glb_dso + + source_file_name, line_number, source_line = perf_sample_srccode(perf_script_context) + if source_file_name: + if glb_line_number == line_number and glb_source_file_name == source_file_name: + src_str = "" + else: + if len(source_file_name) > 40: + src_file = ("..." + source_file_name[-37:]) + " " + else: + src_file = source_file_name.ljust(41) + + if source_line is None: + src_str = src_file + str(line_number).rjust(4) + " " + else: + src_str = src_file + str(line_number).rjust(4) + " " + source_line + glb_dso = None + elif dso == glb_dso: + src_str = "" + else: + src_str = dso + glb_dso = dso + + glb_line_number = line_number + glb_source_file_name = source_file_name + + print(f"{start_str}{src_str}") + +def process_event(param_dict): + global cache_size + global options + + sample = param_dict["sample"] + comm = param_dict["comm"] + + name = param_dict["ev_name"] + dso = get_optional(param_dict, "dso") + dso_bid = get_optional(param_dict, "dso_bid") + dso_start = get_optional(param_dict, "dso_map_start") + dso_end = get_optional(param_dict, "dso_map_end") + symbol = get_optional(param_dict, "symbol") + + if (options.verbose == True): + print(f"Event type: {name}") + print_sample(sample) + + # If cannot find dso so cannot dump assembler, bail out + if (dso == '[unknown]'): + return + + # Validate dso start and end addresses + if ((dso_start == '[unknown]') or (dso_end == '[unknown]')): + print(f"Failed to find valid dso map for dso {dso}") + return + + if (name[0:12] == "instructions"): + print_srccode(comm, param_dict, sample, symbol, dso) + return + + # Don't proceed if this event is not a branch sample, . + if (name[0:8] != "branches"): + return + + cpu = sample["cpu"] + ip = sample["ip"] + addr = sample["addr"] + + # Initialize CPU data if it's empty, and directly return back + # if this is the first tracing event for this CPU. + if (cpu_data.get(str(cpu) + 'addr') == None): + cpu_data[str(cpu) + 'addr'] = addr + return + + # The format for packet is: + # + # +------------+------------+------------+ + # sample_prev: | addr | ip | cpu | + # +------------+------------+------------+ + # sample_next: | addr | ip | cpu | + # +------------+------------+------------+ + # + # We need to combine the two continuous packets to get the instruction + # range for sample_prev::cpu: + # + # [ sample_prev::addr .. sample_next::ip ] + # + # For this purose, sample_prev::addr is stored into cpu_data structure + # and read back for 'start_addr' when the new packet comes, and we need + # to use sample_next::ip to calculate 'stop_addr', plusing extra 4 for + # 'stop_addr' is for the sake of objdump so the final assembler dump can + # include last instruction for sample_next::ip. + start_addr = cpu_data[str(cpu) + 'addr'] + stop_addr = ip + 4 + + # Record for previous sample packet + cpu_data[str(cpu) + 'addr'] = addr + + # Handle CS_ETM_TRACE_ON packet if start_addr=0 and stop_addr=4 + if (start_addr == 0 and stop_addr == 4): + print(f"CPU{cpu}: CS_ETM_TRACE_ON packet is inserted") + return + + if (start_addr < int(dso_start) or start_addr > int(dso_end)): + print(f"Start address 0x{start_addr:x} is out of range [ 0x{dso_start:x} .. 0x{dso_end:x} ] for dso {dso}") + return + + if (stop_addr < int(dso_start) or stop_addr > int(dso_end)): + print(f"Stop address 0x{stop_addr:x} is out of range [ 0x{dso_start:x} .. 0x{dso_end:x} ] for dso {dso}") + return + + if (options.objdump_name != None): + # It doesn't need to decrease virtual memory offset for disassembly + # for kernel dso, so in this case we set vm_start to zero. + if (dso == "[kernel.kallsyms]"): + dso_vm_start = 0 + else: + dso_vm_start = int(dso_start) + + dso_fname = get_dso_file_path(dso, dso_bid) + if path.exists(dso_fname): + print_disam(dso_fname, dso_vm_start, start_addr, stop_addr) + else: + print(f"Failed to find dso {dso} for address range [ 0x{start_addr:x} .. 0x{stop_addr:x} ]") + + print_srccode(comm, param_dict, sample, symbol, dso) diff --git a/tools/perf/tests/shell/lib/perf_csv_output_lint.py b/tools/perf/tests/shell/lib/perf_csv_output_lint.py new file mode 100644 index 0000000000000000000000000000000000000000..714f283cfb1b330d5699f7d6d6d98280a0f9a9e7 --- /dev/null +++ b/tools/perf/tests/shell/lib/perf_csv_output_lint.py @@ -0,0 +1,48 @@ +#!/usr/bin/python +# SPDX-License-Identifier: GPL-2.0 + +import argparse +import sys + +# Basic sanity check of perf CSV output as specified in the man page. +# Currently just checks the number of fields per line in output. + +ap = argparse.ArgumentParser() +ap.add_argument('--no-args', action='store_true') +ap.add_argument('--interval', action='store_true') +ap.add_argument('--system-wide-no-aggr', action='store_true') +ap.add_argument('--system-wide', action='store_true') +ap.add_argument('--event', action='store_true') +ap.add_argument('--per-core', action='store_true') +ap.add_argument('--per-thread', action='store_true') +ap.add_argument('--per-die', action='store_true') +ap.add_argument('--per-node', action='store_true') +ap.add_argument('--per-socket', action='store_true') +ap.add_argument('--separator', default=',', nargs='?') +args = ap.parse_args() + +Lines = sys.stdin.readlines() + +def check_csv_output(exp): + for line in Lines: + if 'failed' not in line: + count = line.count(args.separator) + if count != exp: + sys.stdout.write(''.join(Lines)) + raise RuntimeError(f'wrong number of fields. expected {exp} in {line}') + +try: + if args.no_args or args.system_wide or args.event: + expected_items = 6 + elif args.interval or args.per_thread or args.system_wide_no_aggr: + expected_items = 7 + elif args.per_core or args.per_socket or args.per_node or args.per_die: + expected_items = 8 + else: + ap.print_help() + raise RuntimeError('No checking option specified') + check_csv_output(expected_items) + +except: + sys.stdout.write('Test failed for input: ' + ''.join(Lines)) + raise diff --git a/tools/perf/tests/shell/record_offcpu.sh b/tools/perf/tests/shell/record_offcpu.sh new file mode 100755 index 0000000000000000000000000000000000000000..96e0739f7478ad8a7c3390ddfff3632a582d947c --- /dev/null +++ b/tools/perf/tests/shell/record_offcpu.sh @@ -0,0 +1,60 @@ +#!/bin/sh +# perf record offcpu profiling tests +# SPDX-License-Identifier: GPL-2.0 + +set -e + +err=0 +perfdata=$(mktemp /tmp/__perf_test.perf.data.XXXXX) + +cleanup() { + rm -f ${perfdata} + rm -f ${perfdata}.old + trap - exit term int +} + +trap_cleanup() { + cleanup + exit 1 +} +trap trap_cleanup exit term int + +test_offcpu() { + echo "Basic off-cpu test" + if [ `id -u` != 0 ] + then + echo "Basic off-cpu test [Skipped permission]" + err=2 + return + fi + if perf record --off-cpu -o ${perfdata} --quiet true 2>&1 | grep BUILD_BPF_SKEL + then + echo "Basic off-cpu test [Skipped missing BPF support]" + err=2 + return + fi + if ! perf record --off-cpu -e dummy -o ${perfdata} sleep 1 2> /dev/null + then + echo "Basic off-cpu test [Failed record]" + err=1 + return + fi + if ! perf evlist -i ${perfdata} | grep -q "offcpu-time" + then + echo "Basic off-cpu test [Failed record]" + err=1 + return + fi + if ! perf report -i ${perfdata} -q --percent-limit=90 | egrep -q sleep + then + echo "Basic off-cpu test [Failed missing output]" + err=1 + return + fi + echo "Basic off-cpu test [Success]" +} + +test_offcpu + +cleanup +exit $err diff --git a/tools/perf/tests/shell/stat+csv_output.sh b/tools/perf/tests/shell/stat+csv_output.sh new file mode 100755 index 0000000000000000000000000000000000000000..983220ef3cb4efe13b48b03ffc4529cbdbe60260 --- /dev/null +++ b/tools/perf/tests/shell/stat+csv_output.sh @@ -0,0 +1,147 @@ +#!/bin/bash +# perf stat CSV output linter +# SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) +# Tests various perf stat CSV output commands for the +# correct number of fields and the CSV separator set to ','. + +set -e + +pythonchecker=$(dirname $0)/lib/perf_csv_output_lint.py +if [ "x$PYTHON" == "x" ] +then + if which python3 > /dev/null + then + PYTHON=python3 + elif which python > /dev/null + then + PYTHON=python + else + echo Skipping test, python not detected please set environment variable PYTHON. + exit 2 + fi +fi + +# Return true if perf_event_paranoid is > $1 and not running as root. +function ParanoidAndNotRoot() +{ + [ $(id -u) != 0 ] && [ $(cat /proc/sys/kernel/perf_event_paranoid) -gt $1 ] +} + +check_no_args() +{ + echo -n "Checking CSV output: no args " + perf stat -x, true 2>&1 | $PYTHON $pythonchecker --no-args + echo "[Success]" +} + +check_system_wide() +{ + echo -n "Checking CSV output: system wide " + if ParanoidAndNotRoot 0 + then + echo "[Skip] paranoid and not root" + return + fi + perf stat -x, -a true 2>&1 | $PYTHON $pythonchecker --system-wide + echo "[Success]" +} + +check_system_wide_no_aggr() +{ + echo -n "Checking CSV output: system wide " + if ParanoidAndNotRoot 0 + then + echo "[Skip] paranoid and not root" + return + fi + echo -n "Checking CSV output: system wide no aggregation " + perf stat -x, -A -a --no-merge true 2>&1 | $PYTHON $pythonchecker --system-wide-no-aggr + echo "[Success]" +} + +check_interval() +{ + echo -n "Checking CSV output: interval " + perf stat -x, -I 1000 true 2>&1 | $PYTHON $pythonchecker --interval + echo "[Success]" +} + + +check_event() +{ + echo -n "Checking CSV output: event " + perf stat -x, -e cpu-clock true 2>&1 | $PYTHON $pythonchecker --event + echo "[Success]" +} + +check_per_core() +{ + echo -n "Checking CSV output: per core " + if ParanoidAndNotRoot 0 + then + echo "[Skip] paranoid and not root" + return + fi + perf stat -x, --per-core -a true 2>&1 | $PYTHON $pythonchecker --per-core + echo "[Success]" +} + +check_per_thread() +{ + echo -n "Checking CSV output: per thread " + if ParanoidAndNotRoot 0 + then + echo "[Skip] paranoid and not root" + return + fi + perf stat -x, --per-thread -a true 2>&1 | $PYTHON $pythonchecker --per-thread + echo "[Success]" +} + +check_per_die() +{ + echo -n "Checking CSV output: per die " + if ParanoidAndNotRoot 0 + then + echo "[Skip] paranoid and not root" + return + fi + perf stat -x, --per-die -a true 2>&1 | $PYTHON $pythonchecker --per-die + echo "[Success]" +} + +check_per_node() +{ + echo -n "Checking CSV output: per node " + if ParanoidAndNotRoot 0 + then + echo "[Skip] paranoid and not root" + return + fi + perf stat -x, --per-node -a true 2>&1 | $PYTHON $pythonchecker --per-node + echo "[Success]" +} + +check_per_socket() +{ + echo -n "Checking CSV output: per socket " + if ParanoidAndNotRoot 0 + then + echo "[Skip] paranoid and not root" + return + fi + perf stat -x, --per-socket -a true 2>&1 | $PYTHON $pythonchecker --per-socket + echo "[Success]" +} + +check_no_args +check_system_wide +check_system_wide_no_aggr +check_interval +check_event +check_per_core +check_per_thread +check_per_die +check_per_node +check_per_socket +exit 0 diff --git a/tools/perf/tests/shell/test_intel_pt.sh b/tools/perf/tests/shell/test_intel_pt.sh new file mode 100755 index 0000000000000000000000000000000000000000..a3298643884d9de295c45aacffdec158ec3aacc4 --- /dev/null +++ b/tools/perf/tests/shell/test_intel_pt.sh @@ -0,0 +1,71 @@ +#!/bin/sh +# Miscellaneous Intel PT testing +# SPDX-License-Identifier: GPL-2.0 + +set -e + +# Skip if no Intel PT +perf list | grep -q 'intel_pt//' || exit 2 + +skip_cnt=0 +ok_cnt=0 +err_cnt=0 + +tmpfile=`mktemp` +perfdatafile=`mktemp` + +can_cpu_wide() +{ + perf record -o ${tmpfile} -B -N --no-bpf-event -e dummy:u -C $1 true 2>&1 >/dev/null || return 2 + return 0 +} + +test_system_wide_side_band() +{ + # Need CPU 0 and CPU 1 + can_cpu_wide 0 || return $? + can_cpu_wide 1 || return $? + + # Record on CPU 0 a task running on CPU 1 + perf record -B -N --no-bpf-event -o ${perfdatafile} -e intel_pt//u -C 0 -- taskset --cpu-list 1 uname + + # Should get MMAP events from CPU 1 because they can be needed to decode + mmap_cnt=`perf script -i ${perfdatafile} --no-itrace --show-mmap-events -C 1 2>/dev/null | grep MMAP | wc -l` + + if [ ${mmap_cnt} -gt 0 ] ; then + return 0 + fi + + echo "Failed to record MMAP events on CPU 1 when tracing CPU 0" + return 1 +} + +count_result() +{ + if [ $1 -eq 2 ] ; then + skip_cnt=`expr ${skip_cnt} \+ 1` + return + fi + if [ $1 -eq 0 ] ; then + ok_cnt=`expr ${ok_cnt} \+ 1` + return + fi + err_cnt=`expr ${err_cnt} \+ 1` +} + +test_system_wide_side_band + +count_result $? + +rm -f ${tmpfile} +rm -f ${perfdatafile} + +if [ ${err_cnt} -gt 0 ] ; then + exit 1 +fi + +if [ ${ok_cnt} -gt 0 ] ; then + exit 0 +fi + +exit 2 diff --git a/tools/perf/util/Build b/tools/perf/util/Build index 9a7209a99e164cb1690dd133de61fe64f1c0fa62..a51267d88ca901ac1f85670c6252fbb75a58cca4 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -147,6 +147,7 @@ perf-$(CONFIG_LIBBPF) += bpf_map.o perf-$(CONFIG_PERF_BPF_SKEL) += bpf_counter.o perf-$(CONFIG_PERF_BPF_SKEL) += bpf_counter_cgroup.o perf-$(CONFIG_PERF_BPF_SKEL) += bpf_ftrace.o +perf-$(CONFIG_PERF_BPF_SKEL) += bpf_off_cpu.o perf-$(CONFIG_BPF_PROLOGUE) += bpf-prologue.o perf-$(CONFIG_LIBELF) += symbol-elf.o perf-$(CONFIG_LIBELF) += probe-file.o diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c index b11549ae39dff80ac77d7b69841c14e4be9b1c73..511dd3caa1bcfa7cc0d8f33874acfc8442823ac7 100644 --- a/tools/perf/util/auxtrace.c +++ b/tools/perf/util/auxtrace.c @@ -125,7 +125,7 @@ int auxtrace_mmap__mmap(struct auxtrace_mmap *mm, mm->tid = mp->tid; mm->cpu = mp->cpu.cpu; - if (!mp->len) { + if (!mp->len || !mp->mmap_needed) { mm->base = NULL; return 0; } @@ -168,13 +168,20 @@ void auxtrace_mmap_params__init(struct auxtrace_mmap_params *mp, } void auxtrace_mmap_params__set_idx(struct auxtrace_mmap_params *mp, - struct evlist *evlist, int idx, - bool per_cpu) + struct evlist *evlist, + struct evsel *evsel, int idx) { + bool per_cpu = !perf_cpu_map__empty(evlist->core.user_requested_cpus); + + mp->mmap_needed = evsel->needs_auxtrace_mmap; + + if (!mp->mmap_needed) + return; + mp->idx = idx; if (per_cpu) { - mp->cpu = perf_cpu_map__cpu(evlist->core.user_requested_cpus, idx); + mp->cpu = perf_cpu_map__cpu(evlist->core.all_cpus, idx); if (evlist->core.threads) mp->tid = perf_thread_map__pid(evlist->core.threads, 0); else diff --git a/tools/perf/util/auxtrace.h b/tools/perf/util/auxtrace.h index dc38b6f57232838afeae8f77637db9dbb569942e..cd0d25c2751cc36e3fd17e7138e2c89719f6b47d 100644 --- a/tools/perf/util/auxtrace.h +++ b/tools/perf/util/auxtrace.h @@ -344,6 +344,10 @@ struct auxtrace_mmap { * @idx: index of this mmap * @tid: tid for a per-thread mmap (also set if there is only 1 tid on a per-cpu * mmap) otherwise %0 + * @mmap_needed: set to %false for non-auxtrace events. This is needed because + * auxtrace mmapping is done in the same code path as non-auxtrace + * mmapping but not every evsel that needs non-auxtrace mmapping + * also needs auxtrace mmapping. * @cpu: cpu number for a per-cpu mmap otherwise %-1 */ struct auxtrace_mmap_params { @@ -353,6 +357,7 @@ struct auxtrace_mmap_params { int prot; int idx; pid_t tid; + bool mmap_needed; struct perf_cpu cpu; }; @@ -490,8 +495,8 @@ void auxtrace_mmap_params__init(struct auxtrace_mmap_params *mp, unsigned int auxtrace_pages, bool auxtrace_overwrite); void auxtrace_mmap_params__set_idx(struct auxtrace_mmap_params *mp, - struct evlist *evlist, int idx, - bool per_cpu); + struct evlist *evlist, + struct evsel *evsel, int idx); typedef int (*process_auxtrace_t)(struct perf_tool *tool, struct mmap *map, @@ -863,8 +868,8 @@ void auxtrace_mmap_params__init(struct auxtrace_mmap_params *mp, unsigned int auxtrace_pages, bool auxtrace_overwrite); void auxtrace_mmap_params__set_idx(struct auxtrace_mmap_params *mp, - struct evlist *evlist, int idx, - bool per_cpu); + struct evlist *evlist, + struct evsel *evsel, int idx); #define ITRACE_HELP "" diff --git a/tools/perf/util/bpf-event.c b/tools/perf/util/bpf-event.c index 8271ab764eb56c7bf5df40324c72d00a0b85430d..eee64ddb766df883783f7fb49e470731256206de 100644 --- a/tools/perf/util/bpf-event.c +++ b/tools/perf/util/bpf-event.c @@ -35,11 +35,12 @@ struct btf *btf__load_from_kernel_by_id(__u32 id) } #endif -int __weak bpf_prog_load(enum bpf_prog_type prog_type, - const char *prog_name __maybe_unused, - const char *license, - const struct bpf_insn *insns, size_t insn_cnt, - const struct bpf_prog_load_opts *opts) +#ifndef HAVE_LIBBPF_BPF_PROG_LOAD +int bpf_prog_load(enum bpf_prog_type prog_type, + const char *prog_name __maybe_unused, + const char *license, + const struct bpf_insn *insns, size_t insn_cnt, + const struct bpf_prog_load_opts *opts) { #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" @@ -47,8 +48,10 @@ int __weak bpf_prog_load(enum bpf_prog_type prog_type, opts->kern_version, opts->log_buf, opts->log_size); #pragma GCC diagnostic pop } +#endif -struct bpf_program * __weak +#ifndef HAVE_LIBBPF_BPF_OBJECT__NEXT_PROGRAM +struct bpf_program * bpf_object__next_program(const struct bpf_object *obj, struct bpf_program *prev) { #pragma GCC diagnostic push @@ -56,8 +59,10 @@ bpf_object__next_program(const struct bpf_object *obj, struct bpf_program *prev) return bpf_program__next(prev, obj); #pragma GCC diagnostic pop } +#endif -struct bpf_map * __weak +#ifndef HAVE_LIBBPF_BPF_OBJECT__NEXT_MAP +struct bpf_map * bpf_object__next_map(const struct bpf_object *obj, const struct bpf_map *prev) { #pragma GCC diagnostic push @@ -65,8 +70,10 @@ bpf_object__next_map(const struct bpf_object *obj, const struct bpf_map *prev) return bpf_map__next(prev, obj); #pragma GCC diagnostic pop } +#endif -const void * __weak +#ifndef HAVE_LIBBPF_BTF__RAW_DATA +const void * btf__raw_data(const struct btf *btf_ro, __u32 *size) { #pragma GCC diagnostic push @@ -74,6 +81,7 @@ btf__raw_data(const struct btf *btf_ro, __u32 *size) return btf__get_raw_data(btf_ro, size); #pragma GCC diagnostic pop } +#endif static int snprintf_hex(char *buf, size_t size, unsigned char *data, size_t len) { diff --git a/tools/perf/util/bpf_counter.c b/tools/perf/util/bpf_counter.c index d4931f54e1dd38ea2751fa01996eb357c37a9de0..ef1c15e4aeba5ed4ed6835b76df868b707b70ee5 100644 --- a/tools/perf/util/bpf_counter.c +++ b/tools/perf/util/bpf_counter.c @@ -312,7 +312,10 @@ static bool bperf_attr_map_compatible(int attr_map_fd) (map_info.value_size == sizeof(struct perf_event_attr_map_entry)); } -int __weak +#ifndef HAVE_LIBBPF_BPF_MAP_CREATE +LIBBPF_API int bpf_create_map(enum bpf_map_type map_type, int key_size, + int value_size, int max_entries, __u32 map_flags); +int bpf_map_create(enum bpf_map_type map_type, const char *map_name __maybe_unused, __u32 key_size, @@ -325,6 +328,7 @@ bpf_map_create(enum bpf_map_type map_type, return bpf_create_map(map_type, key_size, value_size, max_entries, 0); #pragma GCC diagnostic pop } +#endif static int bperf_lock_attr_map(struct target *target) { diff --git a/tools/perf/util/bpf_off_cpu.c b/tools/perf/util/bpf_off_cpu.c new file mode 100644 index 0000000000000000000000000000000000000000..b73e84a022648b422029141c3136aeda1dd0062a --- /dev/null +++ b/tools/perf/util/bpf_off_cpu.c @@ -0,0 +1,338 @@ +// SPDX-License-Identifier: GPL-2.0 +#include "util/bpf_counter.h" +#include "util/debug.h" +#include "util/evsel.h" +#include "util/evlist.h" +#include "util/off_cpu.h" +#include "util/perf-hooks.h" +#include "util/record.h" +#include "util/session.h" +#include "util/target.h" +#include "util/cpumap.h" +#include "util/thread_map.h" +#include "util/cgroup.h" +#include + +#include "bpf_skel/off_cpu.skel.h" + +#define MAX_STACKS 32 +/* we don't need actual timestamp, just want to put the samples at last */ +#define OFF_CPU_TIMESTAMP (~0ull << 32) + +static struct off_cpu_bpf *skel; + +struct off_cpu_key { + u32 pid; + u32 tgid; + u32 stack_id; + u32 state; + u64 cgroup_id; +}; + +union off_cpu_data { + struct perf_event_header hdr; + u64 array[1024 / sizeof(u64)]; +}; + +static int off_cpu_config(struct evlist *evlist) +{ + struct evsel *evsel; + struct perf_event_attr attr = { + .type = PERF_TYPE_SOFTWARE, + .config = PERF_COUNT_SW_BPF_OUTPUT, + .size = sizeof(attr), /* to capture ABI version */ + }; + char *evname = strdup(OFFCPU_EVENT); + + if (evname == NULL) + return -ENOMEM; + + evsel = evsel__new(&attr); + if (!evsel) { + free(evname); + return -ENOMEM; + } + + evsel->core.attr.freq = 1; + evsel->core.attr.sample_period = 1; + /* off-cpu analysis depends on stack trace */ + evsel->core.attr.sample_type = PERF_SAMPLE_CALLCHAIN; + + evlist__add(evlist, evsel); + + free(evsel->name); + evsel->name = evname; + + return 0; +} + +static void off_cpu_start(void *arg) +{ + struct evlist *evlist = arg; + + /* update task filter for the given workload */ + if (!skel->bss->has_cpu && !skel->bss->has_task && + perf_thread_map__pid(evlist->core.threads, 0) != -1) { + int fd; + u32 pid; + u8 val = 1; + + skel->bss->has_task = 1; + fd = bpf_map__fd(skel->maps.task_filter); + pid = perf_thread_map__pid(evlist->core.threads, 0); + bpf_map_update_elem(fd, &pid, &val, BPF_ANY); + } + + skel->bss->enabled = 1; +} + +static void off_cpu_finish(void *arg __maybe_unused) +{ + skel->bss->enabled = 0; + off_cpu_bpf__destroy(skel); +} + +/* v5.18 kernel added prev_state arg, so it needs to check the signature */ +static void check_sched_switch_args(void) +{ + const struct btf *btf = bpf_object__btf(skel->obj); + const struct btf_type *t1, *t2, *t3; + u32 type_id; + + type_id = btf__find_by_name_kind(btf, "bpf_trace_sched_switch", + BTF_KIND_TYPEDEF); + if ((s32)type_id < 0) + return; + + t1 = btf__type_by_id(btf, type_id); + if (t1 == NULL) + return; + + t2 = btf__type_by_id(btf, t1->type); + if (t2 == NULL || !btf_is_ptr(t2)) + return; + + t3 = btf__type_by_id(btf, t2->type); + if (t3 && btf_is_func_proto(t3) && btf_vlen(t3) == 4) { + /* new format: pass prev_state as 4th arg */ + skel->rodata->has_prev_state = true; + } +} + +int off_cpu_prepare(struct evlist *evlist, struct target *target, + struct record_opts *opts) +{ + int err, fd, i; + int ncpus = 1, ntasks = 1, ncgrps = 1; + + if (off_cpu_config(evlist) < 0) { + pr_err("Failed to config off-cpu BPF event\n"); + return -1; + } + + skel = off_cpu_bpf__open(); + if (!skel) { + pr_err("Failed to open off-cpu BPF skeleton\n"); + return -1; + } + + /* don't need to set cpu filter for system-wide mode */ + if (target->cpu_list) { + ncpus = perf_cpu_map__nr(evlist->core.user_requested_cpus); + bpf_map__set_max_entries(skel->maps.cpu_filter, ncpus); + } + + if (target__has_task(target)) { + ntasks = perf_thread_map__nr(evlist->core.threads); + bpf_map__set_max_entries(skel->maps.task_filter, ntasks); + } + + if (evlist__first(evlist)->cgrp) { + ncgrps = evlist->core.nr_entries - 1; /* excluding a dummy */ + bpf_map__set_max_entries(skel->maps.cgroup_filter, ncgrps); + + if (!cgroup_is_v2("perf_event")) + skel->rodata->uses_cgroup_v1 = true; + } + + if (opts->record_cgroup) { + skel->rodata->needs_cgroup = true; + + if (!cgroup_is_v2("perf_event")) + skel->rodata->uses_cgroup_v1 = true; + } + + set_max_rlimit(); + check_sched_switch_args(); + + err = off_cpu_bpf__load(skel); + if (err) { + pr_err("Failed to load off-cpu skeleton\n"); + goto out; + } + + if (target->cpu_list) { + u32 cpu; + u8 val = 1; + + skel->bss->has_cpu = 1; + fd = bpf_map__fd(skel->maps.cpu_filter); + + for (i = 0; i < ncpus; i++) { + cpu = perf_cpu_map__cpu(evlist->core.user_requested_cpus, i).cpu; + bpf_map_update_elem(fd, &cpu, &val, BPF_ANY); + } + } + + if (target__has_task(target)) { + u32 pid; + u8 val = 1; + + skel->bss->has_task = 1; + fd = bpf_map__fd(skel->maps.task_filter); + + for (i = 0; i < ntasks; i++) { + pid = perf_thread_map__pid(evlist->core.threads, i); + bpf_map_update_elem(fd, &pid, &val, BPF_ANY); + } + } + + if (evlist__first(evlist)->cgrp) { + struct evsel *evsel; + u8 val = 1; + + skel->bss->has_cgroup = 1; + fd = bpf_map__fd(skel->maps.cgroup_filter); + + evlist__for_each_entry(evlist, evsel) { + struct cgroup *cgrp = evsel->cgrp; + + if (cgrp == NULL) + continue; + + if (!cgrp->id && read_cgroup_id(cgrp) < 0) { + pr_err("Failed to read cgroup id of %s\n", + cgrp->name); + goto out; + } + + bpf_map_update_elem(fd, &cgrp->id, &val, BPF_ANY); + } + } + + err = off_cpu_bpf__attach(skel); + if (err) { + pr_err("Failed to attach off-cpu BPF skeleton\n"); + goto out; + } + + if (perf_hooks__set_hook("record_start", off_cpu_start, evlist) || + perf_hooks__set_hook("record_end", off_cpu_finish, evlist)) { + pr_err("Failed to attach off-cpu skeleton\n"); + goto out; + } + + return 0; + +out: + off_cpu_bpf__destroy(skel); + return -1; +} + +int off_cpu_write(struct perf_session *session) +{ + int bytes = 0, size; + int fd, stack; + u64 sample_type, val, sid = 0; + struct evsel *evsel; + struct perf_data_file *file = &session->data->file; + struct off_cpu_key prev, key; + union off_cpu_data data = { + .hdr = { + .type = PERF_RECORD_SAMPLE, + .misc = PERF_RECORD_MISC_USER, + }, + }; + u64 tstamp = OFF_CPU_TIMESTAMP; + + skel->bss->enabled = 0; + + evsel = evlist__find_evsel_by_str(session->evlist, OFFCPU_EVENT); + if (evsel == NULL) { + pr_err("%s evsel not found\n", OFFCPU_EVENT); + return 0; + } + + sample_type = evsel->core.attr.sample_type; + + if (sample_type & (PERF_SAMPLE_ID | PERF_SAMPLE_IDENTIFIER)) { + if (evsel->core.id) + sid = evsel->core.id[0]; + } + + fd = bpf_map__fd(skel->maps.off_cpu); + stack = bpf_map__fd(skel->maps.stacks); + memset(&prev, 0, sizeof(prev)); + + while (!bpf_map_get_next_key(fd, &prev, &key)) { + int n = 1; /* start from perf_event_header */ + int ip_pos = -1; + + bpf_map_lookup_elem(fd, &key, &val); + + if (sample_type & PERF_SAMPLE_IDENTIFIER) + data.array[n++] = sid; + if (sample_type & PERF_SAMPLE_IP) { + ip_pos = n; + data.array[n++] = 0; /* will be updated */ + } + if (sample_type & PERF_SAMPLE_TID) + data.array[n++] = (u64)key.pid << 32 | key.tgid; + if (sample_type & PERF_SAMPLE_TIME) + data.array[n++] = tstamp; + if (sample_type & PERF_SAMPLE_ID) + data.array[n++] = sid; + if (sample_type & PERF_SAMPLE_CPU) + data.array[n++] = 0; + if (sample_type & PERF_SAMPLE_PERIOD) + data.array[n++] = val; + if (sample_type & PERF_SAMPLE_CALLCHAIN) { + int len = 0; + + /* data.array[n] is callchain->nr (updated later) */ + data.array[n + 1] = PERF_CONTEXT_USER; + data.array[n + 2] = 0; + + bpf_map_lookup_elem(stack, &key.stack_id, &data.array[n + 2]); + while (data.array[n + 2 + len]) + len++; + + /* update length of callchain */ + data.array[n] = len + 1; + + /* update sample ip with the first callchain entry */ + if (ip_pos >= 0) + data.array[ip_pos] = data.array[n + 2]; + + /* calculate sample callchain data array length */ + n += len + 2; + } + if (sample_type & PERF_SAMPLE_CGROUP) + data.array[n++] = key.cgroup_id; + /* TODO: handle more sample types */ + + size = n * sizeof(u64); + data.hdr.size = size; + bytes += size; + + if (perf_data_file__write(file, &data, size) < 0) { + pr_err("failed to write perf data, error: %m\n"); + return bytes; + } + + prev = key; + /* increase dummy timestamp to sort later samples */ + tstamp++; + } + return bytes; +} diff --git a/tools/perf/util/bpf_skel/off_cpu.bpf.c b/tools/perf/util/bpf_skel/off_cpu.bpf.c new file mode 100644 index 0000000000000000000000000000000000000000..792ae2847080c6ccd6428306091ef06c634a9fb2 --- /dev/null +++ b/tools/perf/util/bpf_skel/off_cpu.bpf.c @@ -0,0 +1,229 @@ +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +// Copyright (c) 2022 Google +#include "vmlinux.h" +#include +#include +#include + +/* task->flags for off-cpu analysis */ +#define PF_KTHREAD 0x00200000 /* I am a kernel thread */ + +/* task->state for off-cpu analysis */ +#define TASK_INTERRUPTIBLE 0x0001 +#define TASK_UNINTERRUPTIBLE 0x0002 + +#define MAX_STACKS 32 +#define MAX_ENTRIES 102400 + +struct tstamp_data { + __u32 stack_id; + __u32 state; + __u64 timestamp; +}; + +struct offcpu_key { + __u32 pid; + __u32 tgid; + __u32 stack_id; + __u32 state; + __u64 cgroup_id; +}; + +struct { + __uint(type, BPF_MAP_TYPE_STACK_TRACE); + __uint(key_size, sizeof(__u32)); + __uint(value_size, MAX_STACKS * sizeof(__u64)); + __uint(max_entries, MAX_ENTRIES); +} stacks SEC(".maps"); + +struct { + __uint(type, BPF_MAP_TYPE_TASK_STORAGE); + __uint(map_flags, BPF_F_NO_PREALLOC); + __type(key, int); + __type(value, struct tstamp_data); +} tstamp SEC(".maps"); + +struct { + __uint(type, BPF_MAP_TYPE_HASH); + __uint(key_size, sizeof(struct offcpu_key)); + __uint(value_size, sizeof(__u64)); + __uint(max_entries, MAX_ENTRIES); +} off_cpu SEC(".maps"); + +struct { + __uint(type, BPF_MAP_TYPE_HASH); + __uint(key_size, sizeof(__u32)); + __uint(value_size, sizeof(__u8)); + __uint(max_entries, 1); +} cpu_filter SEC(".maps"); + +struct { + __uint(type, BPF_MAP_TYPE_HASH); + __uint(key_size, sizeof(__u32)); + __uint(value_size, sizeof(__u8)); + __uint(max_entries, 1); +} task_filter SEC(".maps"); + +struct { + __uint(type, BPF_MAP_TYPE_HASH); + __uint(key_size, sizeof(__u64)); + __uint(value_size, sizeof(__u8)); + __uint(max_entries, 1); +} cgroup_filter SEC(".maps"); + +/* old kernel task_struct definition */ +struct task_struct___old { + long state; +} __attribute__((preserve_access_index)); + +int enabled = 0; +int has_cpu = 0; +int has_task = 0; +int has_cgroup = 0; + +const volatile bool has_prev_state = false; +const volatile bool needs_cgroup = false; +const volatile bool uses_cgroup_v1 = false; + +/* + * Old kernel used to call it task_struct->state and now it's '__state'. + * Use BPF CO-RE "ignored suffix rule" to deal with it like below: + * + * https://nakryiko.com/posts/bpf-core-reference-guide/#handling-incompatible-field-and-type-changes + */ +static inline int get_task_state(struct task_struct *t) +{ + if (bpf_core_field_exists(t->__state)) + return BPF_CORE_READ(t, __state); + + /* recast pointer to capture task_struct___old type for compiler */ + struct task_struct___old *t_old = (void *)t; + + /* now use old "state" name of the field */ + return BPF_CORE_READ(t_old, state); +} + +static inline __u64 get_cgroup_id(struct task_struct *t) +{ + struct cgroup *cgrp; + + if (uses_cgroup_v1) + cgrp = BPF_CORE_READ(t, cgroups, subsys[perf_event_cgrp_id], cgroup); + else + cgrp = BPF_CORE_READ(t, cgroups, dfl_cgrp); + + return BPF_CORE_READ(cgrp, kn, id); +} + +static inline int can_record(struct task_struct *t, int state) +{ + /* kernel threads don't have user stack */ + if (t->flags & PF_KTHREAD) + return 0; + + if (state != TASK_INTERRUPTIBLE && + state != TASK_UNINTERRUPTIBLE) + return 0; + + if (has_cpu) { + __u32 cpu = bpf_get_smp_processor_id(); + __u8 *ok; + + ok = bpf_map_lookup_elem(&cpu_filter, &cpu); + if (!ok) + return 0; + } + + if (has_task) { + __u8 *ok; + __u32 pid = t->pid; + + ok = bpf_map_lookup_elem(&task_filter, &pid); + if (!ok) + return 0; + } + + if (has_cgroup) { + __u8 *ok; + __u64 cgrp_id = get_cgroup_id(t); + + ok = bpf_map_lookup_elem(&cgroup_filter, &cgrp_id); + if (!ok) + return 0; + } + + return 1; +} + +static int off_cpu_stat(u64 *ctx, struct task_struct *prev, + struct task_struct *next, int state) +{ + __u64 ts; + __u32 stack_id; + struct tstamp_data *pelem; + + ts = bpf_ktime_get_ns(); + + if (!can_record(prev, state)) + goto next; + + stack_id = bpf_get_stackid(ctx, &stacks, + BPF_F_FAST_STACK_CMP | BPF_F_USER_STACK); + + pelem = bpf_task_storage_get(&tstamp, prev, NULL, + BPF_LOCAL_STORAGE_GET_F_CREATE); + if (!pelem) + goto next; + + pelem->timestamp = ts; + pelem->state = state; + pelem->stack_id = stack_id; + +next: + pelem = bpf_task_storage_get(&tstamp, next, NULL, 0); + + if (pelem && pelem->timestamp) { + struct offcpu_key key = { + .pid = next->pid, + .tgid = next->tgid, + .stack_id = pelem->stack_id, + .state = pelem->state, + .cgroup_id = needs_cgroup ? get_cgroup_id(next) : 0, + }; + __u64 delta = ts - pelem->timestamp; + __u64 *total; + + total = bpf_map_lookup_elem(&off_cpu, &key); + if (total) + *total += delta; + else + bpf_map_update_elem(&off_cpu, &key, &delta, BPF_ANY); + + /* prevent to reuse the timestamp later */ + pelem->timestamp = 0; + } + + return 0; +} + +SEC("tp_btf/sched_switch") +int on_switch(u64 *ctx) +{ + struct task_struct *prev, *next; + int prev_state; + + if (!enabled) + return 0; + + prev = (struct task_struct *)ctx[1]; + next = (struct task_struct *)ctx[2]; + + if (has_prev_state) + prev_state = (int)ctx[3]; + else + prev_state = get_task_state(prev); + + return off_cpu_stat(ctx, prev, next, prev_state); +} + +char LICENSE[] SEC("license") = "Dual BSD/GPL"; diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 7f9f588e88c63c29d5b3cbe1d8f3bcef413f69a5..48af7d379d822881745393a0904b3e7589b02ae4 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -242,14 +242,20 @@ int __evlist__add_default(struct evlist *evlist, bool precise) return 0; } -int evlist__add_dummy(struct evlist *evlist) +static struct evsel *evlist__dummy_event(struct evlist *evlist) { struct perf_event_attr attr = { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_DUMMY, .size = sizeof(attr), /* to capture ABI version */ }; - struct evsel *evsel = evsel__new_idx(&attr, evlist->core.nr_entries); + + return evsel__new_idx(&attr, evlist->core.nr_entries); +} + +int evlist__add_dummy(struct evlist *evlist) +{ + struct evsel *evsel = evlist__dummy_event(evlist); if (evsel == NULL) return -ENOMEM; @@ -258,6 +264,51 @@ int evlist__add_dummy(struct evlist *evlist) return 0; } +static void evlist__add_on_all_cpus(struct evlist *evlist, struct evsel *evsel) +{ + evsel->core.system_wide = true; + + /* + * All CPUs. + * + * Note perf_event_open() does not accept CPUs that are not online, so + * in fact this CPU list will include only all online CPUs. + */ + perf_cpu_map__put(evsel->core.own_cpus); + evsel->core.own_cpus = perf_cpu_map__new(NULL); + perf_cpu_map__put(evsel->core.cpus); + evsel->core.cpus = perf_cpu_map__get(evsel->core.own_cpus); + + /* No threads */ + perf_thread_map__put(evsel->core.threads); + evsel->core.threads = perf_thread_map__new_dummy(); + + evlist__add(evlist, evsel); +} + +struct evsel *evlist__add_aux_dummy(struct evlist *evlist, bool system_wide) +{ + struct evsel *evsel = evlist__dummy_event(evlist); + + if (!evsel) + return NULL; + + evsel->core.attr.exclude_kernel = 1; + evsel->core.attr.exclude_guest = 1; + evsel->core.attr.exclude_hv = 1; + evsel->core.attr.freq = 0; + evsel->core.attr.sample_period = 1; + evsel->no_aux_samples = true; + evsel->name = strdup("dummy:u"); + + if (system_wide) + evlist__add_on_all_cpus(evlist, evsel); + else + evlist__add(evlist, evsel); + + return evsel; +} + static int evlist__add_attrs(struct evlist *evlist, struct perf_event_attr *attrs, size_t nr_attrs) { struct evsel *evsel, *n; @@ -747,15 +798,15 @@ static struct mmap *evlist__alloc_mmap(struct evlist *evlist, static void perf_evlist__mmap_cb_idx(struct perf_evlist *_evlist, - struct perf_evsel *_evsel __maybe_unused, + struct perf_evsel *_evsel, struct perf_mmap_param *_mp, int idx) { struct evlist *evlist = container_of(_evlist, struct evlist, core); struct mmap_params *mp = container_of(_mp, struct mmap_params, core); - bool per_cpu = !perf_cpu_map__empty(_evlist->user_requested_cpus); + struct evsel *evsel = container_of(_evsel, struct evsel, core); - auxtrace_mmap_params__set_idx(&mp->auxtrace_mp, evlist, idx, per_cpu); + auxtrace_mmap_params__set_idx(&mp->auxtrace_mp, evlist, evsel, idx); } static struct perf_mmap* diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index 4062f5aebfc19f5f7ca93178020da8a36ec39425..1bde9ccf4e7da707cd3681dace86f027abf65add 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -114,6 +114,11 @@ int arch_evlist__add_default_attrs(struct evlist *evlist); struct evsel *arch_evlist__leader(struct list_head *list); int evlist__add_dummy(struct evlist *evlist); +struct evsel *evlist__add_aux_dummy(struct evlist *evlist, bool system_wide); +static inline struct evsel *evlist__add_dummy_on_all_cpus(struct evlist *evlist) +{ + return evlist__add_aux_dummy(evlist, true); +} int evlist__add_sb_event(struct evlist *evlist, struct perf_event_attr *attr, evsel__sb_cb_t cb, void *data); diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index ef169ad152364a18c27f1b87e819b81f4b3cdade..ce499c5da8d7be12c837f41bfa6b3bbff9169b38 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -296,8 +296,8 @@ struct evsel *evsel__new_idx(struct perf_event_attr *attr, int idx) return NULL; evsel__init(evsel, attr, idx); - if (evsel__is_bpf_output(evsel)) { - evsel->core.attr.sample_type |= (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | + if (evsel__is_bpf_output(evsel) && !attr->sample_type) { + evsel->core.attr.sample_type = (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD), evsel->core.attr.sample_period = 1; } @@ -409,6 +409,7 @@ struct evsel *evsel__clone(struct evsel *orig) evsel->core.threads = perf_thread_map__get(orig->core.threads); evsel->core.nr_members = orig->core.nr_members; evsel->core.system_wide = orig->core.system_wide; + evsel->core.requires_cpu = orig->core.requires_cpu; if (orig->name) { evsel->name = strdup(orig->name); @@ -896,7 +897,7 @@ static void __evsel__config_callchain(struct evsel *evsel, struct record_opts *o "specifying a subset with --user-regs may render DWARF unwinding unreliable, " "so the minimal registers set (IP, SP) is explicitly forced.\n"); } else { - attr->sample_regs_user |= PERF_REGS_MASK; + attr->sample_regs_user |= arch__user_reg_mask(); } attr->sample_stack_user = param->dump_size; attr->exclude_callchain_user = 1; diff --git a/tools/perf/util/libunwind/arm64.c b/tools/perf/util/libunwind/arm64.c index 15f60fd0942493ccaad3580276438d5ca83b8796..014d8215965639819eb5a76f0a27ef45b91de5c3 100644 --- a/tools/perf/util/libunwind/arm64.c +++ b/tools/perf/util/libunwind/arm64.c @@ -24,7 +24,7 @@ #include "unwind.h" #include "libunwind-aarch64.h" #define perf_event_arm_regs perf_event_arm64_regs -#include <../../../../arch/arm64/include/uapi/asm/perf_regs.h> +#include <../../../arch/arm64/include/uapi/asm/perf_regs.h> #undef perf_event_arm_regs #include "../../arch/arm64/util/unwind-libunwind.c" diff --git a/tools/perf/util/mmap.c b/tools/perf/util/mmap.c index 50502b4a7ca469c783c2eae3c8dac5ba465158e2..a4dff881be39b65f4d2b1f878b76ecb30f5b85d8 100644 --- a/tools/perf/util/mmap.c +++ b/tools/perf/util/mmap.c @@ -62,8 +62,8 @@ void __weak auxtrace_mmap_params__init(struct auxtrace_mmap_params *mp __maybe_u void __weak auxtrace_mmap_params__set_idx(struct auxtrace_mmap_params *mp __maybe_unused, struct evlist *evlist __maybe_unused, - int idx __maybe_unused, - bool per_cpu __maybe_unused) + struct evsel *evsel __maybe_unused, + int idx __maybe_unused) { } diff --git a/tools/perf/util/off_cpu.h b/tools/perf/util/off_cpu.h new file mode 100644 index 0000000000000000000000000000000000000000..548008f74d4200f692a466801967298f45c8ef3f --- /dev/null +++ b/tools/perf/util/off_cpu.h @@ -0,0 +1,29 @@ +#ifndef PERF_UTIL_OFF_CPU_H +#define PERF_UTIL_OFF_CPU_H + +struct evlist; +struct target; +struct perf_session; +struct record_opts; + +#define OFFCPU_EVENT "offcpu-time" + +#ifdef HAVE_BPF_SKEL +int off_cpu_prepare(struct evlist *evlist, struct target *target, + struct record_opts *opts); +int off_cpu_write(struct perf_session *session); +#else +static inline int off_cpu_prepare(struct evlist *evlist __maybe_unused, + struct target *target __maybe_unused, + struct record_opts *opts __maybe_unused) +{ + return -1; +} + +static inline int off_cpu_write(struct perf_session *session __maybe_unused) +{ + return -1; +} +#endif + +#endif /* PERF_UTIL_OFF_CPU_H */ diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 30a9d915853d0daab204328c1c103847b91884e1..7ed235740431624a5d280f7a9aa0afab067994d5 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -365,7 +365,7 @@ __add_event(struct list_head *list, int *idx, (*idx)++; evsel->core.cpus = cpus; evsel->core.own_cpus = perf_cpu_map__get(cpus); - evsel->core.system_wide = pmu ? pmu->is_uncore : false; + evsel->core.requires_cpu = pmu ? pmu->is_uncore : false; evsel->auto_merge_stats = auto_merge_stats; if (name) diff --git a/tools/perf/util/perf_regs.c b/tools/perf/util/perf_regs.c index a982e40ee5a91455cc1c0ba28172899635934b2d..872dd3d38782199841c3291e2ac2ced479e579a2 100644 --- a/tools/perf/util/perf_regs.c +++ b/tools/perf/util/perf_regs.c @@ -103,6 +103,8 @@ static const char *__perf_reg_name_arm64(int id) return "lr"; case PERF_REG_ARM64_PC: return "pc"; + case PERF_REG_ARM64_VG: + return "vg"; default: return NULL; } diff --git a/tools/perf/util/python-ext-sources b/tools/perf/util/python-ext-sources index a685d20165f785a13cbd30c2780dfa3f7d4be39d..aa5156c2bcff5cda3a9733951e0b2e5488d43703 100644 --- a/tools/perf/util/python-ext-sources +++ b/tools/perf/util/python-ext-sources @@ -38,5 +38,6 @@ util/units.c util/affinity.c util/rwsem.c util/hashmap.c +util/perf_regs.c util/pmu-hybrid.c util/fncache.c diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c index 659eb4e4b34ba3dca52e390e2a41970f7ceb88b4..adba01b7d9dd9401fc78935c8bbf9daacea187ce 100644 --- a/tools/perf/util/scripting-engines/trace-event-python.c +++ b/tools/perf/util/scripting-engines/trace-event-python.c @@ -755,12 +755,22 @@ static void set_regs_in_dict(PyObject *dict, } static void set_sym_in_dict(PyObject *dict, struct addr_location *al, - const char *dso_field, const char *sym_field, - const char *symoff_field) + const char *dso_field, const char *dso_bid_field, + const char *dso_map_start, const char *dso_map_end, + const char *sym_field, const char *symoff_field) { + char sbuild_id[SBUILD_ID_SIZE]; + if (al->map) { pydict_set_item_string_decref(dict, dso_field, _PyUnicode_FromString(al->map->dso->name)); + build_id__sprintf(&al->map->dso->bid, sbuild_id); + pydict_set_item_string_decref(dict, dso_bid_field, + _PyUnicode_FromString(sbuild_id)); + pydict_set_item_string_decref(dict, dso_map_start, + PyLong_FromUnsignedLong(al->map->start)); + pydict_set_item_string_decref(dict, dso_map_end, + PyLong_FromUnsignedLong(al->map->end)); } if (al->sym) { pydict_set_item_string_decref(dict, sym_field, @@ -840,7 +850,8 @@ static PyObject *get_perf_sample_dict(struct perf_sample *sample, (const char *)sample->raw_data, sample->raw_size)); pydict_set_item_string_decref(dict, "comm", _PyUnicode_FromString(thread__comm_str(al->thread))); - set_sym_in_dict(dict, al, "dso", "symbol", "symoff"); + set_sym_in_dict(dict, al, "dso", "dso_bid", "dso_map_start", "dso_map_end", + "symbol", "symoff"); pydict_set_item_string_decref(dict, "callchain", callchain); @@ -856,7 +867,9 @@ static PyObject *get_perf_sample_dict(struct perf_sample *sample, if (addr_al) { pydict_set_item_string_decref(dict_sample, "addr_correlates_sym", PyBool_FromLong(1)); - set_sym_in_dict(dict_sample, addr_al, "addr_dso", "addr_symbol", "addr_symoff"); + set_sym_in_dict(dict_sample, addr_al, "addr_dso", "addr_dso_bid", + "addr_dso_map_start", "addr_dso_map_end", + "addr_symbol", "addr_symoff"); } if (sample->flags) diff --git a/tools/testing/crypto/chacha20-s390/Makefile b/tools/testing/crypto/chacha20-s390/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..db81cd2fb9c5e539cd997a1b2b97b3ad849941e5 --- /dev/null +++ b/tools/testing/crypto/chacha20-s390/Makefile @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# Copyright (C) 2022 Red Hat, Inc. +# Author: Vladis Dronov + +obj-m += test_cipher.o +test_cipher-y := test-cipher.o + +all: + make -C /lib/modules/$(shell uname -r)/build/ M=$(PWD) modules +clean: + make -C /lib/modules/$(shell uname -r)/build/ M=$(PWD) clean diff --git a/tools/testing/crypto/chacha20-s390/run-tests.sh b/tools/testing/crypto/chacha20-s390/run-tests.sh new file mode 100644 index 0000000000000000000000000000000000000000..43108794b9969b233d1614b0d260e0f7d016137a --- /dev/null +++ b/tools/testing/crypto/chacha20-s390/run-tests.sh @@ -0,0 +1,34 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 +# +# Copyright (C) 2022 Red Hat, Inc. +# Author: Vladis Dronov +# +# This script runs (via instmod) test-cipher.ko module which invokes +# generic and s390-native ChaCha20 encryprion algorithms with different +# size of data. Check 'dmesg' for results. +# +# The insmod error is expected: +# insmod: ERROR: could not insert module test_cipher.ko: Operation not permitted + +lsmod | grep chacha | cut -f1 -d' ' | xargs rmmod +modprobe chacha_generic +modprobe chacha_s390 + +# run encryption for different data size, including whole block(s) +/- 1 +insmod test_cipher.ko size=63 +insmod test_cipher.ko size=64 +insmod test_cipher.ko size=65 +insmod test_cipher.ko size=127 +insmod test_cipher.ko size=128 +insmod test_cipher.ko size=129 +insmod test_cipher.ko size=511 +insmod test_cipher.ko size=512 +insmod test_cipher.ko size=513 +insmod test_cipher.ko size=4096 +insmod test_cipher.ko size=65611 +insmod test_cipher.ko size=6291456 +insmod test_cipher.ko size=62914560 + +# print test logs +dmesg | tail -170 diff --git a/tools/testing/crypto/chacha20-s390/test-cipher.c b/tools/testing/crypto/chacha20-s390/test-cipher.c new file mode 100644 index 0000000000000000000000000000000000000000..34e8b855266fcdb2b6987a01e31c0bcf80742bdb --- /dev/null +++ b/tools/testing/crypto/chacha20-s390/test-cipher.c @@ -0,0 +1,372 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2022 Red Hat, Inc. + * Author: Vladis Dronov + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static unsigned int data_size __read_mostly = 256; +static unsigned int debug __read_mostly = 0; + +/* tie all skcipher structures together */ +struct skcipher_def { + struct scatterlist sginp, sgout; + struct crypto_skcipher *tfm; + struct skcipher_request *req; + struct crypto_wait wait; +}; + +/* Perform cipher operations with the chacha lib */ +static int test_lib_chacha(u8 *revert, u8 *cipher, u8 *plain) +{ + u32 chacha_state[CHACHA_STATE_WORDS]; + u8 iv[16], key[32]; + u64 start, end; + + memset(key, 'X', sizeof(key)); + memset(iv, 'I', sizeof(iv)); + + if (debug) { + print_hex_dump(KERN_INFO, "key: ", DUMP_PREFIX_OFFSET, + 16, 1, key, 32, 1); + + print_hex_dump(KERN_INFO, "iv: ", DUMP_PREFIX_OFFSET, + 16, 1, iv, 16, 1); + } + + /* Encrypt */ + chacha_init_arch(chacha_state, (u32*)key, iv); + + start = ktime_get_ns(); + chacha_crypt_arch(chacha_state, cipher, plain, data_size, 20); + end = ktime_get_ns(); + + + if (debug) + print_hex_dump(KERN_INFO, "encr:", DUMP_PREFIX_OFFSET, + 16, 1, cipher, + (data_size > 64 ? 64 : data_size), 1); + + pr_info("lib encryption took: %lld nsec", end - start); + + /* Decrypt */ + chacha_init_arch(chacha_state, (u32 *)key, iv); + + start = ktime_get_ns(); + chacha_crypt_arch(chacha_state, revert, cipher, data_size, 20); + end = ktime_get_ns(); + + if (debug) + print_hex_dump(KERN_INFO, "decr:", DUMP_PREFIX_OFFSET, + 16, 1, revert, + (data_size > 64 ? 64 : data_size), 1); + + pr_info("lib decryption took: %lld nsec", end - start); + + return 0; +} + +/* Perform cipher operations with skcipher */ +static unsigned int test_skcipher_encdec(struct skcipher_def *sk, + int enc) +{ + int rc; + + if (enc) { + rc = crypto_wait_req(crypto_skcipher_encrypt(sk->req), + &sk->wait); + if (rc) + pr_info("skcipher encrypt returned with result" + "%d\n", rc); + } + else + { + rc = crypto_wait_req(crypto_skcipher_decrypt(sk->req), + &sk->wait); + if (rc) + pr_info("skcipher decrypt returned with result" + "%d\n", rc); + } + + return rc; +} + +/* Initialize and trigger cipher operations */ +static int test_skcipher(char *name, u8 *revert, u8 *cipher, u8 *plain) +{ + struct skcipher_def sk; + struct crypto_skcipher *skcipher = NULL; + struct skcipher_request *req = NULL; + u8 iv[16], key[32]; + u64 start, end; + int ret = -EFAULT; + + skcipher = crypto_alloc_skcipher(name, 0, 0); + if (IS_ERR(skcipher)) { + pr_info("could not allocate skcipher %s handle\n", name); + return PTR_ERR(skcipher); + } + + req = skcipher_request_alloc(skcipher, GFP_KERNEL); + if (!req) { + pr_info("could not allocate skcipher request\n"); + ret = -ENOMEM; + goto out; + } + + skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, + crypto_req_done, + &sk.wait); + + memset(key, 'X', sizeof(key)); + memset(iv, 'I', sizeof(iv)); + + if (crypto_skcipher_setkey(skcipher, key, 32)) { + pr_info("key could not be set\n"); + ret = -EAGAIN; + goto out; + } + + if (debug) { + print_hex_dump(KERN_INFO, "key: ", DUMP_PREFIX_OFFSET, + 16, 1, key, 32, 1); + + print_hex_dump(KERN_INFO, "iv: ", DUMP_PREFIX_OFFSET, + 16, 1, iv, 16, 1); + } + + sk.tfm = skcipher; + sk.req = req; + + /* Encrypt in one pass */ + sg_init_one(&sk.sginp, plain, data_size); + sg_init_one(&sk.sgout, cipher, data_size); + skcipher_request_set_crypt(req, &sk.sginp, &sk.sgout, + data_size, iv); + crypto_init_wait(&sk.wait); + + /* Encrypt data */ + start = ktime_get_ns(); + ret = test_skcipher_encdec(&sk, 1); + end = ktime_get_ns(); + + if (ret) + goto out; + + pr_info("%s tfm encryption successful, took %lld nsec\n", name, end - start); + + if (debug) + print_hex_dump(KERN_INFO, "encr:", DUMP_PREFIX_OFFSET, + 16, 1, cipher, + (data_size > 64 ? 64 : data_size), 1); + + /* Prepare for decryption */ + memset(iv, 'I', sizeof(iv)); + + sg_init_one(&sk.sginp, cipher, data_size); + sg_init_one(&sk.sgout, revert, data_size); + skcipher_request_set_crypt(req, &sk.sginp, &sk.sgout, + data_size, iv); + crypto_init_wait(&sk.wait); + + /* Decrypt data */ + start = ktime_get_ns(); + ret = test_skcipher_encdec(&sk, 0); + end = ktime_get_ns(); + + if (ret) + goto out; + + pr_info("%s tfm decryption successful, took %lld nsec\n", name, end - start); + + if (debug) + print_hex_dump(KERN_INFO, "decr:", DUMP_PREFIX_OFFSET, + 16, 1, revert, + (data_size > 64 ? 64 : data_size), 1); + + /* Dump some internal skcipher data */ + if (debug) + pr_info("skcipher %s: cryptlen %d blksize %d stride %d " + "ivsize %d alignmask 0x%x\n", + name, sk.req->cryptlen, + crypto_skcipher_blocksize(sk.tfm), + crypto_skcipher_alg(sk.tfm)->walksize, + crypto_skcipher_ivsize(sk.tfm), + crypto_skcipher_alignmask(sk.tfm)); + +out: + if (skcipher) + crypto_free_skcipher(skcipher); + if (req) + skcipher_request_free(req); + return ret; +} + +static int __init chacha_s390_test_init(void) +{ + u8 *plain = NULL, *revert = NULL; + u8 *cipher_generic = NULL, *cipher_s390 = NULL; + int ret = -1; + + pr_info("s390 ChaCha20 test module: size=%d debug=%d\n", + data_size, debug); + + /* Allocate and fill buffers */ + plain = vmalloc(data_size); + if (!plain) { + pr_info("could not allocate plain buffer\n"); + ret = -2; + goto out; + } + memset(plain, 'a', data_size); + get_random_bytes(plain, (data_size > 256 ? 256 : data_size)); + + cipher_generic = vmalloc(data_size); + if (!cipher_generic) { + pr_info("could not allocate cipher_generic buffer\n"); + ret = -2; + goto out; + } + memset(cipher_generic, 0, data_size); + + cipher_s390 = vmalloc(data_size); + if (!cipher_s390) { + pr_info("could not allocate cipher_s390 buffer\n"); + ret = -2; + goto out; + } + memset(cipher_s390, 0, data_size); + + revert = vmalloc(data_size); + if (!revert) { + pr_info("could not allocate revert buffer\n"); + ret = -2; + goto out; + } + memset(revert, 0, data_size); + + if (debug) + print_hex_dump(KERN_INFO, "src: ", DUMP_PREFIX_OFFSET, + 16, 1, plain, + (data_size > 64 ? 64 : data_size), 1); + + /* Use chacha20 generic */ + ret = test_skcipher("chacha20-generic", revert, cipher_generic, plain); + if (ret) + goto out; + + if (memcmp(plain, revert, data_size)) { + pr_info("generic en/decryption check FAILED\n"); + ret = -2; + goto out; + } + else + pr_info("generic en/decryption check OK\n"); + + memset(revert, 0, data_size); + + /* Use chacha20 s390 */ + ret = test_skcipher("chacha20-s390", revert, cipher_s390, plain); + if (ret) + goto out; + + if (memcmp(plain, revert, data_size)) { + pr_info("s390 en/decryption check FAILED\n"); + ret = -2; + goto out; + } + else + pr_info("s390 en/decryption check OK\n"); + + if (memcmp(cipher_generic, cipher_s390, data_size)) { + pr_info("s390 vs generic check FAILED\n"); + ret = -2; + goto out; + } + else + pr_info("s390 vs generic check OK\n"); + + memset(cipher_s390, 0, data_size); + memset(revert, 0, data_size); + + /* Use chacha20 lib */ + test_lib_chacha(revert, cipher_s390, plain); + + if (memcmp(plain, revert, data_size)) { + pr_info("lib en/decryption check FAILED\n"); + ret = -2; + goto out; + } + else + pr_info("lib en/decryption check OK\n"); + + if (memcmp(cipher_generic, cipher_s390, data_size)) { + pr_info("lib vs generic check FAILED\n"); + ret = -2; + goto out; + } + else + pr_info("lib vs generic check OK\n"); + + pr_info("--- chacha20 s390 test end ---\n"); + +out: + if (plain) + vfree(plain); + if (cipher_generic) + vfree(cipher_generic); + if (cipher_s390) + vfree(cipher_s390); + if (revert) + vfree(revert); + + return -1; +} + +static void __exit chacha_s390_test_exit(void) +{ + pr_info("s390 ChaCha20 test module exit\n"); +} + +module_param_named(size, data_size, uint, 0660); +module_param(debug, int, 0660); +MODULE_PARM_DESC(size, "Size of a plaintext"); +MODULE_PARM_DESC(debug, "Debug level (0=off,1=on)"); + +module_init(chacha_s390_test_init); +module_exit(chacha_s390_test_exit); + +MODULE_DESCRIPTION("s390 ChaCha20 self-test"); +MODULE_AUTHOR("Vladis Dronov "); +MODULE_LICENSE("GPL v2"); diff --git a/tools/testing/cxl/Kbuild b/tools/testing/cxl/Kbuild index 82e49ab0937d5a0a3dd0c850b5f455d510711cd7..33543231d453dbbd5aab4ef24aa7ac84d40e9b94 100644 --- a/tools/testing/cxl/Kbuild +++ b/tools/testing/cxl/Kbuild @@ -8,6 +8,8 @@ ldflags-y += --wrap=devm_cxl_port_enumerate_dports ldflags-y += --wrap=devm_cxl_setup_hdm ldflags-y += --wrap=devm_cxl_add_passthrough_decoder ldflags-y += --wrap=devm_cxl_enumerate_decoders +ldflags-y += --wrap=cxl_await_media_ready +ldflags-y += --wrap=cxl_hdm_decode_init DRIVERS := ../../../drivers CXL_SRC := $(DRIVERS)/cxl @@ -34,7 +36,6 @@ cxl_port-y += config_check.o obj-m += cxl_mem.o cxl_mem-y := $(CXL_SRC)/mem.o -cxl_mem-y += mock_mem.o cxl_mem-y += config_check.o obj-m += cxl_core.o diff --git a/tools/testing/cxl/mock_mem.c b/tools/testing/cxl/mock_mem.c deleted file mode 100644 index d1dec5845139dfdabaa2dff2e49938f74821ea4f..0000000000000000000000000000000000000000 --- a/tools/testing/cxl/mock_mem.c +++ /dev/null @@ -1,10 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* Copyright(c) 2022 Intel Corporation. All rights reserved. */ - -#include - -struct cxl_dev_state; -bool cxl_dvsec_decode_init(struct cxl_dev_state *cxlds) -{ - return true; -} diff --git a/tools/testing/cxl/test/mem.c b/tools/testing/cxl/test/mem.c index b6b726eff3e2565e660bc8f14a4ae288606879e5..6b9239b2afd4e5dce6e10cd410f352609d10ff87 100644 --- a/tools/testing/cxl/test/mem.c +++ b/tools/testing/cxl/test/mem.c @@ -237,25 +237,11 @@ static int cxl_mock_mbox_send(struct cxl_dev_state *cxlds, struct cxl_mbox_cmd * return rc; } -static int cxl_mock_wait_media_ready(struct cxl_dev_state *cxlds) -{ - msleep(100); - return 0; -} - static void label_area_release(void *lsa) { vfree(lsa); } -static void mock_validate_dvsec_ranges(struct cxl_dev_state *cxlds) -{ - struct cxl_endpoint_dvsec_info *info; - - info = &cxlds->info; - info->mem_enabled = true; -} - static int cxl_mock_mem_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -278,7 +264,6 @@ static int cxl_mock_mem_probe(struct platform_device *pdev) cxlds->serial = pdev->id; cxlds->mbox_send = cxl_mock_mbox_send; - cxlds->wait_media_ready = cxl_mock_wait_media_ready; cxlds->payload_size = SZ_4K; rc = cxl_enumerate_cmds(cxlds); @@ -293,8 +278,6 @@ static int cxl_mock_mem_probe(struct platform_device *pdev) if (rc) return rc; - mock_validate_dvsec_ranges(cxlds); - cxlmd = devm_cxl_add_memdev(cxlds); if (IS_ERR(cxlmd)) return PTR_ERR(cxlmd); diff --git a/tools/testing/cxl/test/mock.c b/tools/testing/cxl/test/mock.c index 6e8c9d63c92d983e2a907c509620f881d0c8d3e2..f1f8c40948c5c61a64a34250e9735f82e19c860a 100644 --- a/tools/testing/cxl/test/mock.c +++ b/tools/testing/cxl/test/mock.c @@ -193,6 +193,35 @@ int __wrap_devm_cxl_port_enumerate_dports(struct cxl_port *port) } EXPORT_SYMBOL_NS_GPL(__wrap_devm_cxl_port_enumerate_dports, CXL); +int __wrap_cxl_await_media_ready(struct cxl_dev_state *cxlds) +{ + int rc, index; + struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); + + if (ops && ops->is_mock_dev(cxlds->dev)) + rc = 0; + else + rc = cxl_await_media_ready(cxlds); + put_cxl_mock_ops(index); + + return rc; +} +EXPORT_SYMBOL_NS_GPL(__wrap_cxl_await_media_ready, CXL); + +bool __wrap_cxl_hdm_decode_init(struct cxl_dev_state *cxlds, + struct cxl_hdm *cxlhdm) +{ + int rc = 0, index; + struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); + + if (!ops || !ops->is_mock_dev(cxlds->dev)) + rc = cxl_hdm_decode_init(cxlds, cxlhdm); + put_cxl_mock_ops(index); + + return rc; +} +EXPORT_SYMBOL_NS_GPL(__wrap_cxl_hdm_decode_init, CXL); + MODULE_LICENSE("GPL v2"); MODULE_IMPORT_NS(ACPI); MODULE_IMPORT_NS(CXL); diff --git a/tools/testing/nvdimm/pmem-dax.c b/tools/testing/nvdimm/pmem-dax.c index af19c85558e74c9dd7a693bb2aa4be93c10b69fc..c1ec099a3b1d0515f552d16a7934618f4fdcd944 100644 --- a/tools/testing/nvdimm/pmem-dax.c +++ b/tools/testing/nvdimm/pmem-dax.c @@ -4,11 +4,13 @@ */ #include "test/nfit_test.h" #include +#include #include #include long __pmem_direct_access(struct pmem_device *pmem, pgoff_t pgoff, - long nr_pages, void **kaddr, pfn_t *pfn) + long nr_pages, enum dax_access_mode mode, void **kaddr, + pfn_t *pfn) { resource_size_t offset = PFN_PHYS(pgoff) + pmem->data_offset; diff --git a/tools/testing/nvdimm/test/iomap.c b/tools/testing/nvdimm/test/iomap.c index b752ce47ead3c9599c01f5c476c26ac8431a42b6..ea956082e6a4a79814d19161bb540263d3de4ddd 100644 --- a/tools/testing/nvdimm/test/iomap.c +++ b/tools/testing/nvdimm/test/iomap.c @@ -62,16 +62,14 @@ struct nfit_test_resource *get_nfit_res(resource_size_t resource) } EXPORT_SYMBOL(get_nfit_res); -static void __iomem *__nfit_test_ioremap(resource_size_t offset, unsigned long size, - void __iomem *(*fallback_fn)(resource_size_t, unsigned long)) -{ - struct nfit_test_resource *nfit_res = get_nfit_res(offset); - - if (nfit_res) - return (void __iomem *) nfit_res->buf + offset - - nfit_res->res.start; - return fallback_fn(offset, size); -} +#define __nfit_test_ioremap(offset, size, fallback_fn) ({ \ + struct nfit_test_resource *nfit_res = get_nfit_res(offset); \ + nfit_res ? \ + (void __iomem *) nfit_res->buf + (offset) \ + - nfit_res->res.start \ + : \ + fallback_fn((offset), (size)) ; \ +}) void __iomem *__wrap_devm_ioremap(struct device *dev, resource_size_t offset, unsigned long size) diff --git a/tools/testing/nvdimm/test/nfit.c b/tools/testing/nvdimm/test/nfit.c index 1da76ccde448f894a81fcc58a315a864d28577bc..c75abb497a1ac6798bde371a56f63b04d1085c58 100644 --- a/tools/testing/nvdimm/test/nfit.c +++ b/tools/testing/nvdimm/test/nfit.c @@ -23,8 +23,6 @@ #include "nfit_test.h" #include "../watermark.h" -#include - /* * Generate an NFIT table to describe the following topology: * @@ -3375,7 +3373,6 @@ static __exit void nfit_test_exit(void) { int i; - flush_workqueue(nfit_wq); destroy_workqueue(nfit_wq); for (i = 0; i < NUM_NFITS; i++) platform_device_unregister(&instances[i]->pdev); diff --git a/tools/testing/selftests/ftrace/test.d/kprobe/multiple_kprobes.tc b/tools/testing/selftests/ftrace/test.d/kprobe/multiple_kprobes.tc index 312d237800969e67432468e06baead6f82287c5e..be754f5bcf79fe874bd558d444b52b75b474d137 100644 --- a/tools/testing/selftests/ftrace/test.d/kprobe/multiple_kprobes.tc +++ b/tools/testing/selftests/ftrace/test.d/kprobe/multiple_kprobes.tc @@ -25,6 +25,8 @@ if [ $L -ne 256 ]; then exit_fail fi +cat kprobe_events >> $testlog + echo 1 > events/kprobes/enable echo 0 > events/kprobes/enable echo > kprobe_events diff --git a/tools/testing/selftests/powerpc/include/utils.h b/tools/testing/selftests/powerpc/include/utils.h index b7d188fc87c745fb856e1ecdcc9faec2c364c2d7..b9fa9cd709df4c5ec4fc509cd0a3808250b39f55 100644 --- a/tools/testing/selftests/powerpc/include/utils.h +++ b/tools/testing/selftests/powerpc/include/utils.h @@ -135,6 +135,11 @@ do { \ #define PPC_FEATURE2_ARCH_3_1 0x00040000 #endif +/* POWER10 features */ +#ifndef PPC_FEATURE2_MMA +#define PPC_FEATURE2_MMA 0x00020000 +#endif + #if defined(__powerpc64__) #define UCONTEXT_NIA(UC) (UC)->uc_mcontext.gp_regs[PT_NIP] #define UCONTEXT_MSR(UC) (UC)->uc_mcontext.gp_regs[PT_MSR] diff --git a/tools/testing/selftests/powerpc/math/Makefile b/tools/testing/selftests/powerpc/math/Makefile index fcc91c2059841f360fd60563832553a9ec2c6e39..3948f7c510aa7470edcaceda13cc397f415f3310 100644 --- a/tools/testing/selftests/powerpc/math/Makefile +++ b/tools/testing/selftests/powerpc/math/Makefile @@ -1,5 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 -TEST_GEN_PROGS := fpu_syscall fpu_preempt fpu_signal fpu_denormal vmx_syscall vmx_preempt vmx_signal vsx_preempt +TEST_GEN_PROGS := fpu_syscall fpu_preempt fpu_signal fpu_denormal vmx_syscall vmx_preempt vmx_signal vsx_preempt mma top_srcdir = ../../../../.. include ../../lib.mk @@ -17,3 +17,5 @@ $(OUTPUT)/vmx_signal: vmx_asm.S ../utils.c $(OUTPUT)/vsx_preempt: CFLAGS += -mvsx $(OUTPUT)/vsx_preempt: vsx_asm.S ../utils.c + +$(OUTPUT)/mma: mma.c mma.S ../utils.c diff --git a/tools/testing/selftests/powerpc/math/mma.S b/tools/testing/selftests/powerpc/math/mma.S new file mode 100644 index 0000000000000000000000000000000000000000..8528c98495659404addd841478a2bd9b22cb0df2 --- /dev/null +++ b/tools/testing/selftests/powerpc/math/mma.S @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * + * Test basic matrix multiply assist (MMA) functionality if available. + * + * Copyright 2020, Alistair Popple, IBM Corp. + */ + .global test_mma +test_mma: + /* Load accumulator via VSX registers from image passed in r3 */ + lxvh8x 4,0,3 + lxvh8x 5,0,4 + + /* Clear and prime the accumulator (xxsetaccz) */ + .long 0x7c030162 + + /* Prime the accumulator with MMA VSX move to accumulator + * X-form (xxmtacc) (not needed due to above zeroing) */ + //.long 0x7c010162 + + /* xvi16ger2s */ + .long 0xec042958 + + /* Store result in image passed in r5 */ + stxvw4x 0,0,5 + addi 5,5,16 + stxvw4x 1,0,5 + addi 5,5,16 + stxvw4x 2,0,5 + addi 5,5,16 + stxvw4x 3,0,5 + addi 5,5,16 + + blr diff --git a/tools/testing/selftests/powerpc/math/mma.c b/tools/testing/selftests/powerpc/math/mma.c new file mode 100644 index 0000000000000000000000000000000000000000..3a71808c993f4b33583e8b854dd3cf21f35b3796 --- /dev/null +++ b/tools/testing/selftests/powerpc/math/mma.c @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Test basic matrix multiply assist (MMA) functionality if available. + * + * Copyright 2020, Alistair Popple, IBM Corp. + */ +#include +#include + +#include "utils.h" + +extern void test_mma(uint16_t (*)[8], uint16_t (*)[8], uint32_t (*)[4*4]); + +static int mma(void) +{ + int i; + int rc = 0; + uint16_t x[] = {1, 0, 2, 0, 3, 0, 4, 0}; + uint16_t y[] = {1, 0, 2, 0, 3, 0, 4, 0}; + uint32_t z[4*4]; + uint32_t exp[4*4] = {1, 2, 3, 4, + 2, 4, 6, 8, + 3, 6, 9, 12, + 4, 8, 12, 16}; + + SKIP_IF_MSG(!have_hwcap2(PPC_FEATURE2_ARCH_3_1), "Need ISAv3.1"); + SKIP_IF_MSG(!have_hwcap2(PPC_FEATURE2_MMA), "Need MMA"); + + test_mma(&x, &y, &z); + + for (i = 0; i < 16; i++) { + printf("MMA[%d] = %d ", i, z[i]); + + if (z[i] == exp[i]) { + printf(" (Correct)\n"); + } else { + printf(" (Incorrect)\n"); + rc = 1; + } + } + + return rc; +} + +int main(int argc, char *argv[]) +{ + return test_harness(mma, "mma"); +} diff --git a/tools/testing/selftests/powerpc/mm/.gitignore b/tools/testing/selftests/powerpc/mm/.gitignore index aac4a59f9e2813c460953413e74fa3bd5aaa7e39..4e1a294eec3551d23b95fa127677538f6b74afe5 100644 --- a/tools/testing/selftests/powerpc/mm/.gitignore +++ b/tools/testing/selftests/powerpc/mm/.gitignore @@ -12,3 +12,4 @@ pkey_exec_prot pkey_siginfo stack_expansion_ldst stack_expansion_signal +large_vm_gpr_corruption diff --git a/tools/testing/selftests/powerpc/mm/Makefile b/tools/testing/selftests/powerpc/mm/Makefile index 40253abc62089b23b55ca35487a82347212b99b7..27dc09d0bfeed287cd6e1aa0f6b73a5a402f6912 100644 --- a/tools/testing/selftests/powerpc/mm/Makefile +++ b/tools/testing/selftests/powerpc/mm/Makefile @@ -4,7 +4,8 @@ noarg: TEST_GEN_PROGS := hugetlb_vs_thp_test subpage_prot prot_sao segv_errors wild_bctr \ large_vm_fork_separation bad_accesses pkey_exec_prot \ - pkey_siginfo stack_expansion_signal stack_expansion_ldst + pkey_siginfo stack_expansion_signal stack_expansion_ldst \ + large_vm_gpr_corruption TEST_PROGS := stress_code_patching.sh TEST_GEN_PROGS_EXTENDED := tlbie_test @@ -19,6 +20,7 @@ $(OUTPUT)/prot_sao: ../utils.c $(OUTPUT)/wild_bctr: CFLAGS += -m64 $(OUTPUT)/large_vm_fork_separation: CFLAGS += -m64 +$(OUTPUT)/large_vm_gpr_corruption: CFLAGS += -m64 $(OUTPUT)/bad_accesses: CFLAGS += -m64 $(OUTPUT)/pkey_exec_prot: CFLAGS += -m64 $(OUTPUT)/pkey_siginfo: CFLAGS += -m64 diff --git a/tools/testing/selftests/powerpc/mm/large_vm_gpr_corruption.c b/tools/testing/selftests/powerpc/mm/large_vm_gpr_corruption.c new file mode 100644 index 0000000000000000000000000000000000000000..927bfae99ed90b8b8c8936ab65eb20348ce6202c --- /dev/null +++ b/tools/testing/selftests/powerpc/mm/large_vm_gpr_corruption.c @@ -0,0 +1,156 @@ +// SPDX-License-Identifier: GPL-2.0+ +// +// Copyright 2022, Michael Ellerman, IBM Corp. +// +// Test that the 4PB address space SLB handling doesn't corrupt userspace registers +// (r9-r13) due to a SLB fault while saving the PPR. +// +// The bug was introduced in f384796c4 ("powerpc/mm: Add support for handling > 512TB +// address in SLB miss") and fixed in 4c2de74cc869 ("powerpc/64: Interrupts save PPR on +// stack rather than thread_struct"). +// +// To hit the bug requires the task struct and kernel stack to be in different segments. +// Usually that requires more than 1TB of RAM, or if that's not practical, boot the kernel +// with "disable_1tb_segments". +// +// The test works by creating mappings above 512TB, to trigger the large address space +// support. It creates 64 mappings, double the size of the SLB, to cause SLB faults on +// each access (assuming naive replacement). It then loops over those mappings touching +// each, and checks that r9-r13 aren't corrupted. +// +// It then forks another child and tries again, because a new child process will get a new +// kernel stack and thread struct allocated, which may be more optimally placed to trigger +// the bug. It would probably be better to leave the previous child processes hanging +// around, so that kernel stack & thread struct allocations are not reused, but that would +// amount to a 30 second fork bomb. The current design reliably triggers the bug on +// unpatched kernels. + +#include +#include +#include +#include +#include +#include +#include + +#include "utils.h" + +#ifndef MAP_FIXED_NOREPLACE +#define MAP_FIXED_NOREPLACE MAP_FIXED // "Should be safe" above 512TB +#endif + +#define BASE_ADDRESS (1ul << 50) // 1PB +#define STRIDE (2ul << 40) // 2TB +#define SLB_SIZE 32 +#define NR_MAPPINGS (SLB_SIZE * 2) + +static volatile sig_atomic_t signaled; + +static void signal_handler(int sig) +{ + signaled = 1; +} + +#define CHECK_REG(_reg) \ + if (_reg != _reg##_orig) { \ + printf(str(_reg) " corrupted! Expected 0x%lx != 0x%lx\n", _reg##_orig, \ + _reg); \ + _exit(1); \ + } + +static int touch_mappings(void) +{ + unsigned long r9_orig, r10_orig, r11_orig, r12_orig, r13_orig; + unsigned long r9, r10, r11, r12, r13; + unsigned long addr, *p; + int i; + + for (i = 0; i < NR_MAPPINGS; i++) { + addr = BASE_ADDRESS + (i * STRIDE); + p = (unsigned long *)addr; + + asm volatile("mr %0, %%r9 ;" // Read original GPR values + "mr %1, %%r10 ;" + "mr %2, %%r11 ;" + "mr %3, %%r12 ;" + "mr %4, %%r13 ;" + "std %10, 0(%11) ;" // Trigger SLB fault + "mr %5, %%r9 ;" // Save possibly corrupted values + "mr %6, %%r10 ;" + "mr %7, %%r11 ;" + "mr %8, %%r12 ;" + "mr %9, %%r13 ;" + "mr %%r9, %0 ;" // Restore original values + "mr %%r10, %1 ;" + "mr %%r11, %2 ;" + "mr %%r12, %3 ;" + "mr %%r13, %4 ;" + : "=&b"(r9_orig), "=&b"(r10_orig), "=&b"(r11_orig), + "=&b"(r12_orig), "=&b"(r13_orig), "=&b"(r9), "=&b"(r10), + "=&b"(r11), "=&b"(r12), "=&b"(r13) + : "b"(i), "b"(p) + : "r9", "r10", "r11", "r12", "r13"); + + CHECK_REG(r9); + CHECK_REG(r10); + CHECK_REG(r11); + CHECK_REG(r12); + CHECK_REG(r13); + } + + return 0; +} + +static int test(void) +{ + unsigned long page_size, addr, *p; + struct sigaction action; + bool hash_mmu; + int i, status; + pid_t pid; + + // This tests a hash MMU specific bug. + FAIL_IF(using_hash_mmu(&hash_mmu)); + SKIP_IF(!hash_mmu); + + page_size = sysconf(_SC_PAGESIZE); + + for (i = 0; i < NR_MAPPINGS; i++) { + addr = BASE_ADDRESS + (i * STRIDE); + + p = mmap((void *)addr, page_size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED_NOREPLACE, -1, 0); + if (p == MAP_FAILED) { + perror("mmap"); + printf("Error: couldn't mmap(), confirm kernel has 4PB support?\n"); + return 1; + } + } + + action.sa_handler = signal_handler; + action.sa_flags = SA_RESTART; + FAIL_IF(sigaction(SIGALRM, &action, NULL) < 0); + + // Seen to always crash in under ~10s on affected kernels. + alarm(30); + + while (!signaled) { + // Fork new processes, to increase the chance that we hit the case where + // the kernel stack and task struct are in different segments. + pid = fork(); + if (pid == 0) + exit(touch_mappings()); + + FAIL_IF(waitpid(-1, &status, 0) == -1); + FAIL_IF(WIFSIGNALED(status)); + FAIL_IF(!WIFEXITED(status)); + FAIL_IF(WEXITSTATUS(status)); + } + + return 0; +} + +int main(void) +{ + return test_harness(test, "large_vm_gpr_corruption"); +} diff --git a/tools/testing/selftests/powerpc/pmu/ebb/fixed_instruction_loop.S b/tools/testing/selftests/powerpc/pmu/ebb/fixed_instruction_loop.S deleted file mode 100644 index 08a7b5f133b9a9c143212b9dcbd7669824a0b9c9..0000000000000000000000000000000000000000 --- a/tools/testing/selftests/powerpc/pmu/ebb/fixed_instruction_loop.S +++ /dev/null @@ -1,43 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright 2014, Michael Ellerman, IBM Corp. - */ - -#include - - .text - -FUNC_START(thirty_two_instruction_loop) - cmpwi r3,0 - beqlr - addi r4,r3,1 - addi r4,r4,1 - addi r4,r4,1 - addi r4,r4,1 - addi r4,r4,1 - addi r4,r4,1 - addi r4,r4,1 - addi r4,r4,1 - addi r4,r4,1 - addi r4,r4,1 - addi r4,r4,1 - addi r4,r4,1 - addi r4,r4,1 - addi r4,r4,1 - addi r4,r4,1 - addi r4,r4,1 - addi r4,r4,1 - addi r4,r4,1 - addi r4,r4,1 - addi r4,r4,1 - addi r4,r4,1 - addi r4,r4,1 - addi r4,r4,1 - addi r4,r4,1 - addi r4,r4,1 - addi r4,r4,1 - addi r4,r4,1 - addi r4,r4,1 # 28 addi's - subi r3,r3,1 - b FUNC_NAME(thirty_two_instruction_loop) -FUNC_END(thirty_two_instruction_loop) diff --git a/tools/testing/selftests/powerpc/pmu/sampling_tests/misc.c b/tools/testing/selftests/powerpc/pmu/sampling_tests/misc.c index fca054bbc0945371dfc4e1b9b275387c0111ac7b..c01a31d5f4eeedbdf74e061c08ebc4f2bc545b39 100644 --- a/tools/testing/selftests/powerpc/pmu/sampling_tests/misc.c +++ b/tools/testing/selftests/powerpc/pmu/sampling_tests/misc.c @@ -274,7 +274,7 @@ u64 *get_intr_regs(struct event *event, void *sample_buff) return intr_regs; } -static const unsigned int __perf_reg_mask(const char *register_name) +static const int __perf_reg_mask(const char *register_name) { if (!strcmp(register_name, "R0")) return 0; diff --git a/tools/testing/selftests/powerpc/security/spectre_v2.c b/tools/testing/selftests/powerpc/security/spectre_v2.c index d42ca8c676c3a9ffbc73126a8c9232326ed0ec10..5b2abb719ef2e3740912bca30374fb9a2689986b 100644 --- a/tools/testing/selftests/powerpc/security/spectre_v2.c +++ b/tools/testing/selftests/powerpc/security/spectre_v2.c @@ -182,17 +182,23 @@ int spectre_v2_test(void) case COUNT_CACHE_FLUSH_HW: // These should all not affect userspace branch prediction if (miss_percent > 15) { - printf("Branch misses > 15%% unexpected in this configuration!\n"); - printf("Possible mis-match between reported & actual mitigation\n"); - /* - * Such a mismatch may be caused by a guest system - * reporting as vulnerable when the host is mitigated. - * Return skip code to avoid detecting this as an error. - * We are not vulnerable and reporting otherwise, so - * missing such a mismatch is safe. - */ - if (miss_percent > 95) + if (miss_percent > 95) { + /* + * Such a mismatch may be caused by a system being unaware + * the count cache is disabled. This may be to enable + * guest migration between hosts with different settings. + * Return skip code to avoid detecting this as an error. + * We are not vulnerable and reporting otherwise, so + * missing such a mismatch is safe. + */ + printf("Branch misses > 95%% unexpected in this configuration.\n"); + printf("Count cache likely disabled without Linux knowing.\n"); + if (state == COUNT_CACHE_FLUSH_SW) + printf("WARNING: Kernel performing unnecessary flushes.\n"); return 4; + } + printf("Branch misses > 15%% unexpected in this configuration!\n"); + printf("Possible mismatch between reported & actual mitigation\n"); return 1; } @@ -201,14 +207,14 @@ int spectre_v2_test(void) // This seems to affect userspace branch prediction a bit? if (miss_percent > 25) { printf("Branch misses > 25%% unexpected in this configuration!\n"); - printf("Possible mis-match between reported & actual mitigation\n"); + printf("Possible mismatch between reported & actual mitigation\n"); return 1; } break; case COUNT_CACHE_DISABLED: if (miss_percent < 95) { - printf("Branch misses < 20%% unexpected in this configuration!\n"); - printf("Possible mis-match between reported & actual mitigation\n"); + printf("Branch misses < 95%% unexpected in this configuration!\n"); + printf("Possible mismatch between reported & actual mitigation\n"); return 1; } break; diff --git a/tools/tracing/rtla/Makefile b/tools/tracing/rtla/Makefile index 11fb417abb42f51f289456043f8db1ed60dc159b..3822f4ea5f495dde9252cb9a6e115a3aba75f177 100644 --- a/tools/tracing/rtla/Makefile +++ b/tools/tracing/rtla/Makefile @@ -23,6 +23,7 @@ $(call allow-override,LD_SO_CONF_PATH,/etc/ld.so.conf.d/) $(call allow-override,LDCONFIG,ldconfig) INSTALL = install +MKDIR = mkdir FOPTS := -flto=auto -ffat-lto-objects -fexceptions -fstack-protector-strong \ -fasynchronous-unwind-tables -fstack-clash-protection WOPTS := -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -Wno-maybe-uninitialized @@ -31,7 +32,7 @@ TRACEFS_HEADERS := $$($(PKG_CONFIG) --cflags libtracefs) CFLAGS := -O -g -DVERSION=\"$(VERSION)\" $(FOPTS) $(MOPTS) $(WOPTS) $(TRACEFS_HEADERS) LDFLAGS := -ggdb -LIBS := $$($(PKG_CONFIG) --libs libtracefs) -lprocps +LIBS := $$($(PKG_CONFIG) --libs libtracefs) SRC := $(wildcard src/*.c) HDR := $(wildcard src/*.h) @@ -57,6 +58,41 @@ else DOCSRC = $(SRCTREE)/../../../Documentation/tools/rtla/ endif +LIBTRACEEVENT_MIN_VERSION = 1.5 +LIBTRACEFS_MIN_VERSION = 1.3 + +TEST_LIBTRACEEVENT = $(shell sh -c "$(PKG_CONFIG) --atleast-version $(LIBTRACEEVENT_MIN_VERSION) libtraceevent > /dev/null 2>&1 || echo n") +ifeq ("$(TEST_LIBTRACEEVENT)", "n") +.PHONY: warning_traceevent +warning_traceevent: + @echo "********************************************" + @echo "** NOTICE: libtraceevent version $(LIBTRACEEVENT_MIN_VERSION) or higher not found" + @echo "**" + @echo "** Consider installing the latest libtraceevent from your" + @echo "** distribution, e.g., 'dnf install libtraceevent' on Fedora," + @echo "** or from source:" + @echo "**" + @echo "** https://git.kernel.org/pub/scm/libs/libtrace/libtraceevent.git/ " + @echo "**" + @echo "********************************************" +endif + +TEST_LIBTRACEFS = $(shell sh -c "$(PKG_CONFIG) --atleast-version $(LIBTRACEFS_MIN_VERSION) libtracefs > /dev/null 2>&1 || echo n") +ifeq ("$(TEST_LIBTRACEFS)", "n") +.PHONY: warning_tracefs +warning_tracefs: + @echo "********************************************" + @echo "** NOTICE: libtracefs version $(LIBTRACEFS_MIN_VERSION) or higher not found" + @echo "**" + @echo "** Consider installing the latest libtracefs from your" + @echo "** distribution, e.g., 'dnf install libtracefs' on Fedora," + @echo "** or from source:" + @echo "**" + @echo "** https://git.kernel.org/pub/scm/libs/libtrace/libtracefs.git/ " + @echo "**" + @echo "********************************************" +endif + .PHONY: all all: rtla @@ -68,7 +104,7 @@ static: $(OBJ) .PHONY: install install: doc_install - $(INSTALL) -d -m 755 $(DESTDIR)$(BINDIR) + $(MKDIR) -p $(DESTDIR)$(BINDIR) $(INSTALL) rtla -m 755 $(DESTDIR)$(BINDIR) $(STRIP) $(DESTDIR)$(BINDIR)/rtla @test ! -f $(DESTDIR)$(BINDIR)/osnoise || rm $(DESTDIR)$(BINDIR)/osnoise diff --git a/tools/tracing/rtla/README.txt b/tools/tracing/rtla/README.txt index 6c88446f7e74aa5237bec42d1edfe866eb18d663..4af3fd40f17163669df58dc04f392745ea576b20 100644 --- a/tools/tracing/rtla/README.txt +++ b/tools/tracing/rtla/README.txt @@ -1,19 +1,16 @@ RTLA: Real-Time Linux Analysis tools -The rtla is a meta-tool that includes a set of commands that -aims to analyze the real-time properties of Linux. But, instead of -testing Linux as a black box, rtla leverages kernel tracing -capabilities to provide precise information about the properties -and root causes of unexpected results. +The rtla meta-tool includes a set of commands that aims to analyze +the real-time properties of Linux. Instead of testing Linux as a black box, +rtla leverages kernel tracing capabilities to provide precise information +about the properties and root causes of unexpected results. Installing RTLA -RTLA depends on some libraries and tools. More precisely, it depends on the -following libraries: +RTLA depends on the following libraries and tools: - libtracefs - libtraceevent - - procps It also depends on python3-docutils to compile man pages. diff --git a/tools/tracing/rtla/src/osnoise_hist.c b/tools/tracing/rtla/src/osnoise_hist.c index b4380d45cacd4545754dd258581a70f976104c39..5d7ea479ac89f9000a6bd20211110efb1f5c1ea4 100644 --- a/tools/tracing/rtla/src/osnoise_hist.c +++ b/tools/tracing/rtla/src/osnoise_hist.c @@ -809,7 +809,7 @@ int osnoise_hist_main(int argc, char *argv[]) retval = set_comm_sched_attr("osnoise/", ¶ms->sched_param); if (retval) { err_msg("Failed to set sched parameters\n"); - goto out_hist; + goto out_free; } } @@ -819,7 +819,7 @@ int osnoise_hist_main(int argc, char *argv[]) record = osnoise_init_trace_tool("osnoise"); if (!record) { err_msg("Failed to enable the trace instance\n"); - goto out_hist; + goto out_free; } if (params->events) { @@ -869,6 +869,7 @@ int osnoise_hist_main(int argc, char *argv[]) out_hist: trace_events_destroy(&record->trace, params->events); params->events = NULL; +out_free: osnoise_free_histogram(tool->data); out_destroy: osnoise_destroy_tool(record); diff --git a/tools/tracing/rtla/src/osnoise_top.c b/tools/tracing/rtla/src/osnoise_top.c index 72c2fd6ce005d6c6d0a05eb960ea4d1ac60a62df..76479bfb292244b0e61fc4b79ffdfe694e770193 100644 --- a/tools/tracing/rtla/src/osnoise_top.c +++ b/tools/tracing/rtla/src/osnoise_top.c @@ -572,7 +572,7 @@ int osnoise_top_main(int argc, char **argv) retval = osnoise_top_apply_config(tool, params); if (retval) { err_msg("Could not apply config\n"); - goto out_top; + goto out_free; } trace = &tool->trace; @@ -580,14 +580,14 @@ int osnoise_top_main(int argc, char **argv) retval = enable_osnoise(trace); if (retval) { err_msg("Failed to enable osnoise tracer\n"); - goto out_top; + goto out_free; } if (params->set_sched) { retval = set_comm_sched_attr("osnoise/", ¶ms->sched_param); if (retval) { err_msg("Failed to set sched parameters\n"); - goto out_top; + goto out_free; } } @@ -597,7 +597,7 @@ int osnoise_top_main(int argc, char **argv) record = osnoise_init_trace_tool("osnoise"); if (!record) { err_msg("Failed to enable the trace instance\n"); - goto out_top; + goto out_free; } if (params->events) { @@ -649,6 +649,7 @@ int osnoise_top_main(int argc, char **argv) out_top: trace_events_destroy(&record->trace, params->events); params->events = NULL; +out_free: osnoise_free_top(tool->data); osnoise_destroy_tool(record); osnoise_destroy_tool(tool); diff --git a/tools/tracing/rtla/src/timerlat_hist.c b/tools/tracing/rtla/src/timerlat_hist.c index dc908126c610d1ef230a116ee425f8a596f78b0e..f3ec628f5e5196ffb47461d0234aa680a4982f68 100644 --- a/tools/tracing/rtla/src/timerlat_hist.c +++ b/tools/tracing/rtla/src/timerlat_hist.c @@ -821,7 +821,7 @@ int timerlat_hist_main(int argc, char *argv[]) retval = timerlat_hist_apply_config(tool, params); if (retval) { err_msg("Could not apply config\n"); - goto out_hist; + goto out_free; } trace = &tool->trace; @@ -829,14 +829,14 @@ int timerlat_hist_main(int argc, char *argv[]) retval = enable_timerlat(trace); if (retval) { err_msg("Failed to enable timerlat tracer\n"); - goto out_hist; + goto out_free; } if (params->set_sched) { retval = set_comm_sched_attr("timerlat/", ¶ms->sched_param); if (retval) { err_msg("Failed to set sched parameters\n"); - goto out_hist; + goto out_free; } } @@ -844,7 +844,7 @@ int timerlat_hist_main(int argc, char *argv[]) dma_latency_fd = set_cpu_dma_latency(params->dma_latency); if (dma_latency_fd < 0) { err_msg("Could not set /dev/cpu_dma_latency.\n"); - goto out_hist; + goto out_free; } } @@ -854,7 +854,7 @@ int timerlat_hist_main(int argc, char *argv[]) record = osnoise_init_trace_tool("timerlat"); if (!record) { err_msg("Failed to enable the trace instance\n"); - goto out_hist; + goto out_free; } if (params->events) { @@ -904,6 +904,7 @@ out_hist: close(dma_latency_fd); trace_events_destroy(&record->trace, params->events); params->events = NULL; +out_free: timerlat_free_histogram(tool->data); osnoise_destroy_tool(record); osnoise_destroy_tool(tool); diff --git a/tools/tracing/rtla/src/timerlat_top.c b/tools/tracing/rtla/src/timerlat_top.c index 1f754c3df53f2a2083ed5205320c020f35c37bd0..35452a1d45e9fbff6a97b3c3de4b71842661748b 100644 --- a/tools/tracing/rtla/src/timerlat_top.c +++ b/tools/tracing/rtla/src/timerlat_top.c @@ -612,7 +612,7 @@ int timerlat_top_main(int argc, char *argv[]) retval = timerlat_top_apply_config(top, params); if (retval) { err_msg("Could not apply config\n"); - goto out_top; + goto out_free; } trace = &top->trace; @@ -620,14 +620,14 @@ int timerlat_top_main(int argc, char *argv[]) retval = enable_timerlat(trace); if (retval) { err_msg("Failed to enable timerlat tracer\n"); - goto out_top; + goto out_free; } if (params->set_sched) { retval = set_comm_sched_attr("timerlat/", ¶ms->sched_param); if (retval) { err_msg("Failed to set sched parameters\n"); - goto out_top; + goto out_free; } } @@ -635,7 +635,7 @@ int timerlat_top_main(int argc, char *argv[]) dma_latency_fd = set_cpu_dma_latency(params->dma_latency); if (dma_latency_fd < 0) { err_msg("Could not set /dev/cpu_dma_latency.\n"); - goto out_top; + goto out_free; } } @@ -645,7 +645,7 @@ int timerlat_top_main(int argc, char *argv[]) record = osnoise_init_trace_tool("timerlat"); if (!record) { err_msg("Failed to enable the trace instance\n"); - goto out_top; + goto out_free; } if (params->events) { @@ -699,6 +699,7 @@ out_top: close(dma_latency_fd); trace_events_destroy(&record->trace, params->events); params->events = NULL; +out_free: timerlat_free_top(top->data); osnoise_destroy_tool(record); osnoise_destroy_tool(top); diff --git a/tools/tracing/rtla/src/utils.c b/tools/tracing/rtla/src/utils.c index da2b590edaede1d8227d63a8890e93a37bcd84d5..5352167a1e751d297d3b5888d0e6e4a205fc892a 100644 --- a/tools/tracing/rtla/src/utils.c +++ b/tools/tracing/rtla/src/utils.c @@ -3,7 +3,7 @@ * Copyright (C) 2021 Red Hat Inc, Daniel Bristot de Oliveira */ -#include +#include #include #include #include @@ -255,50 +255,114 @@ int __set_sched_attr(int pid, struct sched_attr *attr) retval = sched_setattr(pid, attr, flags); if (retval < 0) { - err_msg("boost_with_deadline failed to boost pid %d: %s\n", + err_msg("Failed to set sched attributes to the pid %d: %s\n", pid, strerror(errno)); return 1; } return 0; } + +/* + * procfs_is_workload_pid - check if a procfs entry contains a comm_prefix* comm + * + * Check if the procfs entry is a directory of a process, and then check if the + * process has a comm with the prefix set in char *comm_prefix. As the + * current users of this function only check for kernel threads, there is no + * need to check for the threads for the process. + * + * Return: True if the proc_entry contains a comm file with comm_prefix*. + * Otherwise returns false. + */ +static int procfs_is_workload_pid(const char *comm_prefix, struct dirent *proc_entry) +{ + char buffer[MAX_PATH]; + int comm_fd, retval; + char *t_name; + + if (proc_entry->d_type != DT_DIR) + return 0; + + if (*proc_entry->d_name == '.') + return 0; + + /* check if the string is a pid */ + for (t_name = proc_entry->d_name; t_name; t_name++) { + if (!isdigit(*t_name)) + break; + } + + if (*t_name != '\0') + return 0; + + snprintf(buffer, MAX_PATH, "/proc/%s/comm", proc_entry->d_name); + comm_fd = open(buffer, O_RDONLY); + if (comm_fd < 0) + return 0; + + memset(buffer, 0, MAX_PATH); + retval = read(comm_fd, buffer, MAX_PATH); + + close(comm_fd); + + if (retval <= 0) + return 0; + + retval = strncmp(comm_prefix, buffer, strlen(comm_prefix)); + if (retval) + return 0; + + /* comm already have \n */ + debug_msg("Found workload pid:%s comm:%s", proc_entry->d_name, buffer); + + return 1; +} + /* - * set_comm_sched_attr - set sched params to threads starting with char *comm + * set_comm_sched_attr - set sched params to threads starting with char *comm_prefix * - * This function uses procps to list the currently running threads and then - * set the sched_attr *attr to the threads that start with char *comm. It is + * This function uses procfs to list the currently running threads and then set the + * sched_attr *attr to the threads that start with char *comm_prefix. It is * mainly used to set the priority to the kernel threads created by the * tracers. */ -int set_comm_sched_attr(const char *comm, struct sched_attr *attr) +int set_comm_sched_attr(const char *comm_prefix, struct sched_attr *attr) { - int flags = PROC_FILLCOM | PROC_FILLSTAT; - PROCTAB *ptp; - proc_t task; + struct dirent *proc_entry; + DIR *procfs; int retval; - ptp = openproc(flags); - if (!ptp) { - err_msg("error openproc()\n"); - return -ENOENT; + if (strlen(comm_prefix) >= MAX_PATH) { + err_msg("Command prefix is too long: %d < strlen(%s)\n", + MAX_PATH, comm_prefix); + return 1; } - memset(&task, 0, sizeof(task)); + procfs = opendir("/proc"); + if (!procfs) { + err_msg("Could not open procfs\n"); + return 1; + } - while (readproc(ptp, &task)) { - retval = strncmp(comm, task.cmd, strlen(comm)); - if (retval) + while ((proc_entry = readdir(procfs))) { + + retval = procfs_is_workload_pid(comm_prefix, proc_entry); + if (!retval) continue; - retval = __set_sched_attr(task.tid, attr); - if (retval) + + /* procfs_is_workload_pid confirmed it is a pid */ + retval = __set_sched_attr(atoi(proc_entry->d_name), attr); + if (retval) { + err_msg("Error setting sched attributes for pid:%s\n", proc_entry->d_name); goto out_err; - } + } - closeproc(ptp); + debug_msg("Set sched attributes for pid:%s\n", proc_entry->d_name); + } return 0; out_err: - closeproc(ptp); + closedir(procfs); return 1; } diff --git a/tools/tracing/rtla/src/utils.h b/tools/tracing/rtla/src/utils.h index fa08e374870ac8b0fd7e64f6507710ac9d263f9f..5571afd3b549863922df3d71e8c68a732867c0c2 100644 --- a/tools/tracing/rtla/src/utils.h +++ b/tools/tracing/rtla/src/utils.h @@ -6,6 +6,7 @@ * '18446744073709551615\0' */ #define BUFF_U64_STR_SIZE 24 +#define MAX_PATH 1024 #define container_of(ptr, type, member)({ \ const typeof(((type *)0)->member) *__mptr = (ptr); \ @@ -53,5 +54,5 @@ struct sched_attr { }; int parse_prio(char *arg, struct sched_attr *sched_param); -int set_comm_sched_attr(const char *comm, struct sched_attr *attr); +int set_comm_sched_attr(const char *comm_prefix, struct sched_attr *attr); int set_cpu_dma_latency(int32_t latency);